From e9ddb92ee2f9bb330ac5dc168779ae99726eac2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Przemys=C5=82aw=20Pluta?= Date: Fri, 13 Mar 2020 07:44:40 +0100 Subject: [PATCH] Improve AssignmentOperatorEvaluator and SumOperatorEvaluator --- .../evaluator/AssignmentOperatorEvaluator.kt | 27 ++++++--- .../evaluator/SumOperatorEvaluator.kt | 58 ++++++++++++++----- 2 files changed, 60 insertions(+), 25 deletions(-) diff --git a/app/src/main/kotlin/io/smnp/evaluation/evaluator/AssignmentOperatorEvaluator.kt b/app/src/main/kotlin/io/smnp/evaluation/evaluator/AssignmentOperatorEvaluator.kt index 8aee960..1e12906 100644 --- a/app/src/main/kotlin/io/smnp/evaluation/evaluator/AssignmentOperatorEvaluator.kt +++ b/app/src/main/kotlin/io/smnp/evaluation/evaluator/AssignmentOperatorEvaluator.kt @@ -4,20 +4,29 @@ import io.smnp.dsl.ast.model.node.AssignmentOperatorNode import io.smnp.dsl.ast.model.node.IdentifierNode import io.smnp.dsl.ast.model.node.Node import io.smnp.environment.Environment +import io.smnp.error.EvaluationException import io.smnp.evaluation.model.entity.EvaluatorOutput +import io.smnp.type.enumeration.DataType class AssignmentOperatorEvaluator : Evaluator() { - private val evaluator = ExpressionEvaluator() + private val evaluator = assert(ExpressionEvaluator(), "expression") - override fun supportedNodes() = listOf(AssignmentOperatorNode::class) + override fun supportedNodes() = listOf(AssignmentOperatorNode::class) - override fun tryToEvaluate(node: Node, environment: Environment): EvaluatorOutput { - val (identifierNode, _, valueNode) = node as AssignmentOperatorNode - val identifier = (identifierNode as IdentifierNode).token.rawValue - val value = evaluator.evaluate(valueNode, environment).value!! + override fun tryToEvaluate(node: Node, environment: Environment): EvaluatorOutput { + val (identifierNode, _, valueNode) = node as AssignmentOperatorNode + val identifier = (identifierNode as IdentifierNode).token.rawValue + val value = evaluator.evaluate(valueNode, environment).value!! - environment.setVariable(identifier, value) + if (value.type == DataType.VOID) { + throw EvaluationException( + "Right hand side expression of assignment operation has returned nothing", + valueNode.position + ) + } - return EvaluatorOutput.value(value) - } + environment.setVariable(identifier, value) + + return EvaluatorOutput.value(value) + } } \ No newline at end of file diff --git a/app/src/main/kotlin/io/smnp/evaluation/evaluator/SumOperatorEvaluator.kt b/app/src/main/kotlin/io/smnp/evaluation/evaluator/SumOperatorEvaluator.kt index 590f040..75e27d7 100644 --- a/app/src/main/kotlin/io/smnp/evaluation/evaluator/SumOperatorEvaluator.kt +++ b/app/src/main/kotlin/io/smnp/evaluation/evaluator/SumOperatorEvaluator.kt @@ -9,26 +9,52 @@ import io.smnp.error.EvaluationException import io.smnp.error.ShouldNeverReachThisLineException import io.smnp.evaluation.model.entity.EvaluatorOutput import io.smnp.evaluation.util.NumberUnification.unify +import io.smnp.type.enumeration.DataType import io.smnp.type.model.Value class SumOperatorEvaluator : Evaluator() { - override fun supportedNodes() = listOf(SumOperatorNode::class) + override fun supportedNodes() = listOf(SumOperatorNode::class) - override fun tryToEvaluate(node: Node, environment: Environment): EvaluatorOutput { - val evaluator = ExpressionEvaluator() - val (lhsNode, opNode, rhsNode) = (node as SumOperatorNode) - val lhs = evaluator.evaluate(lhsNode, environment).value!! - val rhs = evaluator.evaluate(rhsNode, environment).value!! - val operator = (opNode as TokenNode).token.type + override fun tryToEvaluate(node: Node, environment: Environment): EvaluatorOutput { + val evaluator = ExpressionEvaluator() + val (lhsNode, opNode, rhsNode) = (node as SumOperatorNode) + val lhs = evaluator.evaluate(lhsNode, environment).value!! + val rhs = evaluator.evaluate(rhsNode, environment).value!! + val operator = (opNode as TokenNode).token.type - if(!lhs.type.isNumeric() || !rhs.type.isNumeric()) { - throw EvaluationException("Operator ${operator.token} supports only numeric types", node.position) - } - - return EvaluatorOutput.value(when(operator) { - TokenType.PLUS -> unify(lhs, rhs, int = { (l, r) -> Value.int(l + r) }, float = { (l, r) -> Value.float(l + r) }) - TokenType.MINUS -> unify(lhs, rhs, int = { (l, r) -> Value.int(l - r) }, float = { (l, r) -> Value.float(l - r) }) + return EvaluatorOutput.value( + when (operator) { + TokenType.PLUS -> plus(lhs, opNode, rhs) + TokenType.MINUS -> minus(lhs, opNode, rhs) else -> throw ShouldNeverReachThisLineException() - }) - } + } + ) + } + + private fun plus(lhs: Value, plusNode: Node, rhs: Value): Value { + return if (areNumeric(lhs, rhs)) + unify(lhs, rhs, int = { (l, r) -> Value.int(l + r) }, float = { (l, r) -> Value.float(l + r) }) + else if (lhs.type == DataType.STRING) + Value.string(lhs.value!! as String + rhs.value.toString()) + else if (areLists(lhs, rhs)) + Value.list(lhs.value!! as List + rhs.value!! as List) + else throw EvaluationException( + "The ${lhs.type.name.toLowerCase()} and ${rhs.type.name.toLowerCase()} are not supported by + operator", + plusNode.position + ) + } + + private fun minus(lhs: Value, minusNode: Node, rhs: Value): Value { + return if (areNumeric(lhs, rhs)) + unify( + lhs, + rhs, + int = { (l, r) -> Value.int(l - r) }, + float = { (l, r) -> Value.float(l - r) } + ) + else throw EvaluationException("The - operator supports only numeric values", minusNode.position) + } + + private fun areNumeric(lhs: Value, rhs: Value) = lhs.type.isNumeric() && rhs.type.isNumeric() + private fun areLists(lhs: Value, rhs: Value) = lhs.type == DataType.LIST && rhs.type == DataType.LIST } \ No newline at end of file