From 97cb3d30171a07496289b80e87908cd61ccccd74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Przemys=C5=82aw=20Pluta?= Date: Sat, 7 Mar 2020 19:37:58 +0100 Subject: [PATCH] Migrate relation operators evaluator to Kotlin --- .../evaluation/evaluator/DefaultEvaluator.kt | 3 +- .../evaluator/ProductOperatorEvaluator.kt | 4 +- .../evaluator/RelationOperatorEvaluator.kt | 46 +++++++++++++++++++ .../evaluator/SumOperatorEvaluator.kt | 4 +- .../smnp/evaluation/util/NumberUnification.kt | 6 +-- 5 files changed, 55 insertions(+), 8 deletions(-) create mode 100644 src/main/kotlin/io/smnp/evaluation/evaluator/RelationOperatorEvaluator.kt diff --git a/src/main/kotlin/io/smnp/evaluation/evaluator/DefaultEvaluator.kt b/src/main/kotlin/io/smnp/evaluation/evaluator/DefaultEvaluator.kt index 0d91fd6..40e4f1c 100644 --- a/src/main/kotlin/io/smnp/evaluation/evaluator/DefaultEvaluator.kt +++ b/src/main/kotlin/io/smnp/evaluation/evaluator/DefaultEvaluator.kt @@ -23,7 +23,8 @@ class DefaultEvaluator : Evaluator() { ProductOperatorEvaluator(), SumOperatorEvaluator(), AccessOperatorEvaluator(), - LogicOperatorEvaluator() + LogicOperatorEvaluator(), + RelationOperatorEvaluator() ).evaluate(node, environment) } } \ No newline at end of file diff --git a/src/main/kotlin/io/smnp/evaluation/evaluator/ProductOperatorEvaluator.kt b/src/main/kotlin/io/smnp/evaluation/evaluator/ProductOperatorEvaluator.kt index 08c7634..087bc76 100644 --- a/src/main/kotlin/io/smnp/evaluation/evaluator/ProductOperatorEvaluator.kt +++ b/src/main/kotlin/io/smnp/evaluation/evaluator/ProductOperatorEvaluator.kt @@ -27,8 +27,8 @@ class ProductOperatorEvaluator : Evaluator() { return EvaluatorOutput.value( when (operator) { - TokenType.ASTERISK -> unify(lhs, rhs, intConsumer = { (l, r) -> Value.int(l * r) }, floatConsumer = { (l, r) -> Value.float(l * r) }) - TokenType.SLASH -> unify(lhs, rhs, intConsumer = { (l, r) -> Value.int(l / r) }, floatConsumer = { (l, r) -> Value.float(l / r) }) + TokenType.ASTERISK -> unify(lhs, rhs, int = { (l, r) -> Value.int(l * r) }, float = { (l, r) -> Value.float(l * r) }) + TokenType.SLASH -> unify(lhs, rhs, int = { (l, r) -> Value.int(l / r) }, float = { (l, r) -> Value.float(l / r) }) else -> throw ShouldNeverReachThisLineException() } ) diff --git a/src/main/kotlin/io/smnp/evaluation/evaluator/RelationOperatorEvaluator.kt b/src/main/kotlin/io/smnp/evaluation/evaluator/RelationOperatorEvaluator.kt new file mode 100644 index 0000000..0a98307 --- /dev/null +++ b/src/main/kotlin/io/smnp/evaluation/evaluator/RelationOperatorEvaluator.kt @@ -0,0 +1,46 @@ +package io.smnp.evaluation.evaluator + +import io.smnp.data.model.Value +import io.smnp.dsl.ast.model.node.Node +import io.smnp.dsl.ast.model.node.RelationOperatorNode +import io.smnp.dsl.ast.model.node.TokenNode +import io.smnp.error.EvaluationException +import io.smnp.error.ShouldNeverReachThisLineException +import io.smnp.evaluation.environment.Environment +import io.smnp.evaluation.model.entity.EvaluatorOutput +import io.smnp.evaluation.util.NumberUnification.unify + +class RelationOperatorEvaluator : Evaluator() { + override fun supportedNodes() = listOf(RelationOperatorNode::class) + + override fun tryToEvaluate(node: Node, environment: Environment): EvaluatorOutput { + val evaluator = DefaultEvaluator() + val (lhsNode, opNode, rhsNode) = (node as RelationOperatorNode) + val lhs = evaluator.evaluate(lhsNode, environment).value!! + val rhs = evaluator.evaluate(rhsNode, environment).value!! + val operator = (opNode as TokenNode).token.rawValue + + if (operator in listOf("==", "!=")) { + return EvaluatorOutput.value( + Value.bool( + if (operator == "==") lhs.value == rhs.value + else lhs.value != rhs.value + ) + ) + } + + if (!lhs.type.isNumeric() || !rhs.type.isNumeric()) { + throw EvaluationException("Operator $operator supports only numeric types", node.position) + } + + return EvaluatorOutput.value( + when(operator) { + ">" -> unify(lhs, rhs, int = { (l, r) -> Value.bool(l > r) }, float = { (l, r) -> Value.bool(l > r) }) + "<" -> unify(lhs, rhs, int = { (l, r) -> Value.bool(l < r) }, float = { (l, r) -> Value.bool(l < r) }) + ">=" -> unify(lhs, rhs, int = { (l, r) -> Value.bool(l >= r) }, float = { (l, r) -> Value.bool(l >= r) }) + "<=" -> unify(lhs, rhs, int = { (l, r) -> Value.bool(l <= r) }, float = { (l, r) -> Value.bool(l <= r) }) + else -> throw ShouldNeverReachThisLineException() + } + ) + } +} \ No newline at end of file diff --git a/src/main/kotlin/io/smnp/evaluation/evaluator/SumOperatorEvaluator.kt b/src/main/kotlin/io/smnp/evaluation/evaluator/SumOperatorEvaluator.kt index ab3e400..e46f23a 100644 --- a/src/main/kotlin/io/smnp/evaluation/evaluator/SumOperatorEvaluator.kt +++ b/src/main/kotlin/io/smnp/evaluation/evaluator/SumOperatorEvaluator.kt @@ -26,8 +26,8 @@ class SumOperatorEvaluator : Evaluator() { } return EvaluatorOutput.value(when(operator) { - TokenType.PLUS -> unify(lhs, rhs, intConsumer = { (l, r) -> Value.int(l + r) }, floatConsumer = { (l, r) -> Value.float(l + r) }) - TokenType.MINUS -> unify(lhs, rhs, intConsumer = { (l, r) -> Value.int(l - r) }, floatConsumer = { (l, r) -> Value.float(l - r) }) + 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) }) else -> throw ShouldNeverReachThisLineException() }) } diff --git a/src/main/kotlin/io/smnp/evaluation/util/NumberUnification.kt b/src/main/kotlin/io/smnp/evaluation/util/NumberUnification.kt index 3144630..53bbce3 100644 --- a/src/main/kotlin/io/smnp/evaluation/util/NumberUnification.kt +++ b/src/main/kotlin/io/smnp/evaluation/util/NumberUnification.kt @@ -4,11 +4,11 @@ import io.smnp.data.enumeration.DataType import io.smnp.data.model.Value object NumberUnification { - fun unify(vararg numbers: Value, intConsumer: (List) -> Value, floatConsumer: (List) -> Value): Value { + fun unify(vararg numbers: Value, int: (List) -> Value, float: (List) -> Value): Value { if(numbers.any { it.type == DataType.FLOAT }) { - return floatConsumer(numbers.map { (it.value as Number).toFloat() }) + return float(numbers.map { (it.value as Number).toFloat() }) } - return intConsumer(numbers.map { (it.value as Number).toInt() }) + return int(numbers.map { (it.value as Number).toInt() }) } } \ No newline at end of file