Migrate relation operators evaluator to Kotlin

This commit is contained in:
2020-03-07 19:37:58 +01:00
parent 0bf2a98102
commit 97cb3d3017
5 changed files with 55 additions and 8 deletions

View File

@@ -23,7 +23,8 @@ class DefaultEvaluator : Evaluator() {
ProductOperatorEvaluator(),
SumOperatorEvaluator(),
AccessOperatorEvaluator(),
LogicOperatorEvaluator()
LogicOperatorEvaluator(),
RelationOperatorEvaluator()
).evaluate(node, environment)
}
}

View File

@@ -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()
}
)

View File

@@ -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()
}
)
}
}

View File

@@ -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()
})
}

View File

@@ -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<Int>) -> Value, floatConsumer: (List<Float>) -> Value): Value {
fun unify(vararg numbers: Value, int: (List<Int>) -> Value, float: (List<Float>) -> 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() })
}
}