Introduce number unificator for evaluators

This commit is contained in:
2020-03-07 18:47:19 +01:00
parent a28a98080d
commit f71b59f51e
3 changed files with 20 additions and 38 deletions

View File

@@ -1,6 +1,5 @@
package io.smnp.evaluation.evaluator
import io.smnp.data.enumeration.DataType
import io.smnp.data.model.Value
import io.smnp.dsl.ast.model.node.Node
import io.smnp.dsl.ast.model.node.ProductOperatorNode
@@ -10,6 +9,7 @@ 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 ProductOperatorEvaluator : Evaluator() {
override fun supportedNodes() = listOf(ProductOperatorNode::class)
@@ -27,26 +27,10 @@ class ProductOperatorEvaluator : Evaluator() {
return EvaluatorOutput.value(
when (operator) {
TokenType.ASTERISK -> product(lhs, rhs)
TokenType.SLASH -> quotient(lhs, rhs)
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) })
else -> throw ShouldNeverReachThisLineException()
}
)
}
private fun product(lhs: Value, rhs: Value): Value {
if(listOf(lhs.type, rhs.type).contains(DataType.FLOAT)) {
return Value.float((lhs.value as Number).toFloat() * (rhs.value as Number).toFloat())
}
return Value.int((lhs.value as Int) * (rhs.value as Int))
}
private fun quotient(lhs: Value, rhs: Value): Value {
if(listOf(lhs.type, rhs.type).contains(DataType.FLOAT)) {
return Value.float((lhs.value as Number).toFloat() / (rhs.value as Number).toFloat())
}
return Value.int((lhs.value as Int) / (rhs.value as Int))
}
}

View File

@@ -1,6 +1,5 @@
package io.smnp.evaluation.evaluator
import io.smnp.data.enumeration.DataType
import io.smnp.data.model.Value
import io.smnp.dsl.ast.model.node.Node
import io.smnp.dsl.ast.model.node.SumOperatorNode
@@ -10,6 +9,7 @@ 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 SumOperatorEvaluator : Evaluator() {
override fun supportedNodes() = listOf(SumOperatorNode::class)
@@ -26,25 +26,9 @@ class SumOperatorEvaluator : Evaluator() {
}
return EvaluatorOutput.value(when(operator) {
TokenType.PLUS -> sum(lhs, rhs)
TokenType.MINUS -> difference(lhs, rhs)
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) })
else -> throw ShouldNeverReachThisLineException()
})
}
private fun sum(lhs: Value, rhs: Value): Value {
if(listOf(lhs.type, rhs.type).contains(DataType.FLOAT)) {
return Value.float((lhs.value as Number).toFloat() + (rhs.value as Number).toFloat())
}
return Value.int((lhs.value as Int) + (rhs.value as Int))
}
private fun difference(lhs: Value, rhs: Value): Value {
if(listOf(lhs.type, rhs.type).contains(DataType.FLOAT)) {
return Value.float((lhs.value as Number).toFloat() - (rhs.value as Number).toFloat())
}
return Value.int((lhs.value as Int) - (rhs.value as Int))
}
}

View File

@@ -0,0 +1,14 @@
package io.smnp.evaluation.util
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 {
if(numbers.any { it.type == DataType.FLOAT }) {
return floatConsumer(numbers.map { (it.value as Number).toFloat() })
}
return intConsumer(numbers.map { (it.value as Number).toInt() })
}
}