Migrate product operator evaluator to Kotlin

This commit is contained in:
2020-03-07 18:00:49 +01:00
parent 1406a3fa6f
commit 81cd0f25a7
4 changed files with 68 additions and 1 deletions

View File

@@ -2,6 +2,7 @@ package io.smnp.data.model
import io.smnp.data.entity.Note
import io.smnp.data.enumeration.DataType
import io.smnp.error.ShouldNeverReachThisLineException
class Value private constructor(val type: DataType, val value: Any?, val properties: Map<String, Value> = emptyMap()) {
init {
@@ -23,6 +24,14 @@ class Value private constructor(val type: DataType, val value: Any?, val propert
return Value(DataType.FLOAT, value)
}
fun numeric(value: Number): Value {
return when(value::class) {
Int::class -> int(value.toInt())
Float::class -> float(value.toFloat())
else -> throw ShouldNeverReachThisLineException()
}
}
fun string(value: String): Value {
return Value(DataType.STRING, value, hashMapOf(
Pair("length", int(value.length))

View File

@@ -0,0 +1,5 @@
package io.smnp.error
class ShouldNeverReachThisLineException : Exception(
"This exception should never be thrown. Please check stack trace and investigate the source of error."
)

View File

@@ -19,7 +19,8 @@ class DefaultEvaluator : Evaluator() {
MinusOperatorEvaluator(),
NotOperatorEvaluator(),
PowerOperatorEvaluator()
PowerOperatorEvaluator(),
ProductOperatorEvaluator()
).evaluate(node, environment)
}
}

View File

@@ -0,0 +1,52 @@
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
import io.smnp.dsl.ast.model.node.TokenNode
import io.smnp.dsl.token.model.enumeration.TokenType
import io.smnp.error.EvaluationException
import io.smnp.error.ShouldNeverReachThisLineException
import io.smnp.evaluation.environment.Environment
import io.smnp.evaluation.model.entity.EvaluatorOutput
class ProductOperatorEvaluator : Evaluator() {
override fun supportedNodes() = listOf(ProductOperatorNode::class)
override fun tryToEvaluate(node: Node, environment: Environment): EvaluatorOutput {
val evaluator = DefaultEvaluator()
val (lhsNode, opNode, rhsNode) = (node as ProductOperatorNode)
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 supports only numeric types", node.position)
}
return EvaluatorOutput.value(
when (operator) {
TokenType.ASTERISK -> product(lhs, rhs)
TokenType.SLASH -> quotient(lhs, rhs)
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))
}
}