Improve AssignmentOperatorEvaluator and SumOperatorEvaluator

This commit is contained in:
2020-03-13 07:44:40 +01:00
parent 7008bc626c
commit e9ddb92ee2
2 changed files with 60 additions and 25 deletions

View File

@@ -4,10 +4,12 @@ import io.smnp.dsl.ast.model.node.AssignmentOperatorNode
import io.smnp.dsl.ast.model.node.IdentifierNode import io.smnp.dsl.ast.model.node.IdentifierNode
import io.smnp.dsl.ast.model.node.Node import io.smnp.dsl.ast.model.node.Node
import io.smnp.environment.Environment import io.smnp.environment.Environment
import io.smnp.error.EvaluationException
import io.smnp.evaluation.model.entity.EvaluatorOutput import io.smnp.evaluation.model.entity.EvaluatorOutput
import io.smnp.type.enumeration.DataType
class AssignmentOperatorEvaluator : Evaluator() { 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)
@@ -16,6 +18,13 @@ class AssignmentOperatorEvaluator : Evaluator() {
val identifier = (identifierNode as IdentifierNode).token.rawValue val identifier = (identifierNode as IdentifierNode).token.rawValue
val value = evaluator.evaluate(valueNode, environment).value!! val value = evaluator.evaluate(valueNode, environment).value!!
if (value.type == DataType.VOID) {
throw EvaluationException(
"Right hand side expression of assignment operation has returned nothing",
valueNode.position
)
}
environment.setVariable(identifier, value) environment.setVariable(identifier, value)
return EvaluatorOutput.value(value) return EvaluatorOutput.value(value)

View File

@@ -9,6 +9,7 @@ import io.smnp.error.EvaluationException
import io.smnp.error.ShouldNeverReachThisLineException import io.smnp.error.ShouldNeverReachThisLineException
import io.smnp.evaluation.model.entity.EvaluatorOutput import io.smnp.evaluation.model.entity.EvaluatorOutput
import io.smnp.evaluation.util.NumberUnification.unify import io.smnp.evaluation.util.NumberUnification.unify
import io.smnp.type.enumeration.DataType
import io.smnp.type.model.Value import io.smnp.type.model.Value
class SumOperatorEvaluator : Evaluator() { class SumOperatorEvaluator : Evaluator() {
@@ -21,14 +22,39 @@ class SumOperatorEvaluator : Evaluator() {
val rhs = evaluator.evaluate(rhsNode, environment).value!! val rhs = evaluator.evaluate(rhsNode, environment).value!!
val operator = (opNode as TokenNode).token.type val operator = (opNode as TokenNode).token.type
if(!lhs.type.isNumeric() || !rhs.type.isNumeric()) { return EvaluatorOutput.value(
throw EvaluationException("Operator ${operator.token} supports only numeric types", node.position) when (operator) {
TokenType.PLUS -> plus(lhs, opNode, rhs)
TokenType.MINUS -> minus(lhs, opNode, rhs)
else -> throw ShouldNeverReachThisLineException()
}
)
} }
return EvaluatorOutput.value(when(operator) { private fun plus(lhs: Value, plusNode: Node, rhs: Value): Value {
TokenType.PLUS -> unify(lhs, rhs, int = { (l, r) -> Value.int(l + r) }, float = { (l, r) -> Value.float(l + r) }) return if (areNumeric(lhs, rhs))
TokenType.MINUS -> unify(lhs, rhs, int = { (l, r) -> Value.int(l - r) }, float = { (l, r) -> Value.float(l - r) }) unify(lhs, rhs, int = { (l, r) -> Value.int(l + r) }, float = { (l, r) -> Value.float(l + r) })
else -> throw ShouldNeverReachThisLineException() 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<Value> + rhs.value!! as List<Value>)
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
} }