Improve AssignmentOperatorEvaluator and SumOperatorEvaluator
This commit is contained in:
@@ -4,20 +4,29 @@ 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)
|
||||||
|
|
||||||
override fun tryToEvaluate(node: Node, environment: Environment): EvaluatorOutput {
|
override fun tryToEvaluate(node: Node, environment: Environment): EvaluatorOutput {
|
||||||
val (identifierNode, _, valueNode) = node as AssignmentOperatorNode
|
val (identifierNode, _, valueNode) = node as AssignmentOperatorNode
|
||||||
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!!
|
||||||
|
|
||||||
environment.setVariable(identifier, value)
|
if (value.type == DataType.VOID) {
|
||||||
|
throw EvaluationException(
|
||||||
|
"Right hand side expression of assignment operation has returned nothing",
|
||||||
|
valueNode.position
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
return EvaluatorOutput.value(value)
|
environment.setVariable(identifier, value)
|
||||||
}
|
|
||||||
|
return EvaluatorOutput.value(value)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -9,26 +9,52 @@ 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() {
|
||||||
override fun supportedNodes() = listOf(SumOperatorNode::class)
|
override fun supportedNodes() = listOf(SumOperatorNode::class)
|
||||||
|
|
||||||
override fun tryToEvaluate(node: Node, environment: Environment): EvaluatorOutput {
|
override fun tryToEvaluate(node: Node, environment: Environment): EvaluatorOutput {
|
||||||
val evaluator = ExpressionEvaluator()
|
val evaluator = ExpressionEvaluator()
|
||||||
val (lhsNode, opNode, rhsNode) = (node as SumOperatorNode)
|
val (lhsNode, opNode, rhsNode) = (node as SumOperatorNode)
|
||||||
val lhs = evaluator.evaluate(lhsNode, environment).value!!
|
val lhs = evaluator.evaluate(lhsNode, environment).value!!
|
||||||
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)
|
||||||
return EvaluatorOutput.value(when(operator) {
|
|
||||||
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()
|
else -> throw ShouldNeverReachThisLineException()
|
||||||
})
|
}
|
||||||
}
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun plus(lhs: Value, plusNode: 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 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
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user