Simplify wrapping with decorator pattern evaluation exceptions
This commit is contained in:
@@ -16,10 +16,10 @@ import kotlin.system.exitProcess
|
||||
|
||||
fun main(args: Array<String>): Unit = mainBody {
|
||||
ArgParser(args).parseInto(::Arguments).run {
|
||||
try {
|
||||
val interpreter = DefaultInterpreter()
|
||||
val environment = DefaultEnvironment()
|
||||
val interpreter = DefaultInterpreter()
|
||||
val environment = DefaultEnvironment()
|
||||
|
||||
try {
|
||||
environment.setVariable("__param__", Value.wrap(parameters.toMap()))
|
||||
|
||||
when {
|
||||
@@ -51,6 +51,10 @@ fun main(args: Array<String>): Unit = mainBody {
|
||||
System.err.println("\nStack trace:\n${it.environment.stackTrace()}")
|
||||
}
|
||||
exitProcess(1)
|
||||
} finally {
|
||||
if(!environment.disposed) {
|
||||
environment.dispose()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,11 +2,10 @@ package io.smnp.evaluation.evaluator
|
||||
|
||||
import io.smnp.dsl.ast.model.node.*
|
||||
import io.smnp.environment.Environment
|
||||
import io.smnp.error.EnvironmentException
|
||||
import io.smnp.error.EvaluationException
|
||||
import io.smnp.error.PositionException
|
||||
import io.smnp.error.SmnpException
|
||||
import io.smnp.evaluation.model.entity.EvaluatorOutput
|
||||
import io.smnp.evaluation.util.ContextExceptionFactory
|
||||
import io.smnp.evaluation.util.ContextExceptionFactory.contextEvaluationException
|
||||
|
||||
class AccessOperatorEvaluator : Evaluator() {
|
||||
override fun supportedNodes() = listOf(AccessOperatorNode::class)
|
||||
@@ -20,12 +19,10 @@ class AccessOperatorEvaluator : Evaluator() {
|
||||
is IdentifierNode -> {
|
||||
val rhs = rhsNode.token.rawValue
|
||||
EvaluatorOutput.value(
|
||||
lhs.properties[rhs] ?: throw PositionException(
|
||||
EnvironmentException(
|
||||
EvaluationException("Unknown property $rhs of type ${lhs.typeName}"),
|
||||
environment
|
||||
),
|
||||
rhsNode.position
|
||||
lhs.properties[rhs] ?: throw contextEvaluationException(
|
||||
"Unknown property $rhs of type ${lhs.typeName}",
|
||||
rhsNode.position,
|
||||
environment
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -36,16 +33,15 @@ class AccessOperatorEvaluator : Evaluator() {
|
||||
(argsNode as FunctionCallArgumentsNode).items.map { evaluator.evaluate(it, environment).value }
|
||||
try {
|
||||
return EvaluatorOutput.value(environment.invokeMethod(lhs, identifier, arguments))
|
||||
} catch(e: SmnpException) {
|
||||
throw PositionException(EnvironmentException(e, environment), identifierNode.position)
|
||||
} catch (e: SmnpException) {
|
||||
throw ContextExceptionFactory.wrapWithContext(e, identifierNode.position, environment)
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
throw PositionException(
|
||||
EnvironmentException(
|
||||
EvaluationException("Invalid property access type - only property name and method call are allowed"),
|
||||
environment
|
||||
), rhsNode.position
|
||||
throw contextEvaluationException(
|
||||
"Invalid property access type - only property name and method call are allowed",
|
||||
rhsNode.position,
|
||||
environment
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,10 +4,8 @@ import io.smnp.dsl.ast.model.node.AssignmentOperatorNode
|
||||
import io.smnp.dsl.ast.model.node.IdentifierNode
|
||||
import io.smnp.dsl.ast.model.node.Node
|
||||
import io.smnp.environment.Environment
|
||||
import io.smnp.error.EnvironmentException
|
||||
import io.smnp.error.EvaluationException
|
||||
import io.smnp.error.PositionException
|
||||
import io.smnp.evaluation.model.entity.EvaluatorOutput
|
||||
import io.smnp.evaluation.util.ContextExceptionFactory.contextEvaluationException
|
||||
import io.smnp.type.enumeration.DataType
|
||||
|
||||
class AssignmentOperatorEvaluator : Evaluator() {
|
||||
@@ -21,12 +19,10 @@ class AssignmentOperatorEvaluator : Evaluator() {
|
||||
val value = evaluator.evaluate(valueNode, environment).value
|
||||
|
||||
if (value.type == DataType.VOID) {
|
||||
throw PositionException(
|
||||
EnvironmentException(
|
||||
EvaluationException("Right hand side expression of assignment operation has returned nothing"),
|
||||
environment
|
||||
),
|
||||
valueNode.position
|
||||
throw contextEvaluationException(
|
||||
"Right hand side expression of assignment operation has returned nothing",
|
||||
valueNode.position,
|
||||
environment
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -4,10 +4,8 @@ import io.smnp.dsl.ast.model.node.ConditionNode
|
||||
import io.smnp.dsl.ast.model.node.Node
|
||||
import io.smnp.dsl.ast.model.node.NoneNode
|
||||
import io.smnp.environment.Environment
|
||||
import io.smnp.error.EnvironmentException
|
||||
import io.smnp.error.EvaluationException
|
||||
import io.smnp.error.PositionException
|
||||
import io.smnp.evaluation.model.entity.EvaluatorOutput
|
||||
import io.smnp.evaluation.util.ContextExceptionFactory.contextEvaluationException
|
||||
import io.smnp.type.enumeration.DataType
|
||||
|
||||
class ConditionEvaluator : Evaluator() {
|
||||
@@ -21,12 +19,10 @@ class ConditionEvaluator : Evaluator() {
|
||||
val condition = expressionEvaluator.evaluate(conditionNode, environment).value
|
||||
|
||||
if (condition.type != DataType.BOOL) {
|
||||
throw PositionException(
|
||||
EnvironmentException(
|
||||
EvaluationException("Condition should be of bool type, found '${condition.value}'"),
|
||||
environment
|
||||
),
|
||||
conditionNode.position
|
||||
throw contextEvaluationException(
|
||||
"Condition should be of bool type, found '${condition.value}'",
|
||||
conditionNode.position,
|
||||
environment
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -2,11 +2,9 @@ package io.smnp.evaluation.evaluator
|
||||
|
||||
import io.smnp.dsl.ast.model.node.Node
|
||||
import io.smnp.environment.Environment
|
||||
import io.smnp.error.EnvironmentException
|
||||
import io.smnp.error.EvaluationException
|
||||
import io.smnp.error.PositionException
|
||||
import io.smnp.evaluation.model.entity.EvaluatorOutput
|
||||
import io.smnp.evaluation.model.enumeration.EvaluationResult
|
||||
import io.smnp.evaluation.util.ContextExceptionFactory.contextEvaluationException
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
abstract class Evaluator {
|
||||
@@ -64,10 +62,7 @@ abstract class Evaluator {
|
||||
val output = evaluator.evaluate(node, environment)
|
||||
|
||||
if (output.result == EvaluationResult.FAILED) {
|
||||
throw PositionException(
|
||||
EnvironmentException(EvaluationException("Expected $expected"), environment),
|
||||
node.position
|
||||
)
|
||||
throw contextEvaluationException("Expected $expected", node.position, environment)
|
||||
}
|
||||
|
||||
return output
|
||||
|
||||
@@ -7,10 +7,9 @@ import io.smnp.dsl.ast.model.node.FunctionDefinitionNode
|
||||
import io.smnp.dsl.ast.model.node.Node
|
||||
import io.smnp.dsl.ast.model.node.SingleTypeNode
|
||||
import io.smnp.environment.Environment
|
||||
import io.smnp.error.EnvironmentException
|
||||
import io.smnp.error.PositionException
|
||||
import io.smnp.error.SmnpException
|
||||
import io.smnp.evaluation.model.entity.EvaluatorOutput
|
||||
import io.smnp.evaluation.util.ContextExceptionFactory.wrapWithContext
|
||||
|
||||
class ExtendEvaluator : Evaluator() {
|
||||
override fun supportedNodes() = listOf(ExtendNode::class)
|
||||
@@ -25,7 +24,7 @@ class ExtendEvaluator : Evaluator() {
|
||||
try {
|
||||
environment.defineMethod(it.second)
|
||||
} catch (e: SmnpException) {
|
||||
throw PositionException(EnvironmentException(e, environment), it.first.position)
|
||||
throw wrapWithContext(e, it.first.position, environment)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,24 +5,23 @@ import io.smnp.dsl.ast.model.node.FunctionCallNode
|
||||
import io.smnp.dsl.ast.model.node.IdentifierNode
|
||||
import io.smnp.dsl.ast.model.node.Node
|
||||
import io.smnp.environment.Environment
|
||||
import io.smnp.error.EnvironmentException
|
||||
import io.smnp.error.PositionException
|
||||
import io.smnp.error.SmnpException
|
||||
import io.smnp.evaluation.model.entity.EvaluatorOutput
|
||||
import io.smnp.evaluation.util.ContextExceptionFactory.wrapWithContext
|
||||
|
||||
class FunctionCallEvaluator : Evaluator() {
|
||||
override fun supportedNodes() = listOf(FunctionCallNode::class)
|
||||
override fun supportedNodes() = listOf(FunctionCallNode::class)
|
||||
|
||||
override fun tryToEvaluate(node: Node, environment: Environment): EvaluatorOutput {
|
||||
val evaluator = assert(ExpressionEvaluator(), "expression")
|
||||
val (identifierNode, argsNode) = node as FunctionCallNode
|
||||
val identifier = (identifierNode as IdentifierNode).token.rawValue
|
||||
val arguments = (argsNode as FunctionCallArgumentsNode).items.map { evaluator.evaluate(it, environment).value }
|
||||
override fun tryToEvaluate(node: Node, environment: Environment): EvaluatorOutput {
|
||||
val evaluator = assert(ExpressionEvaluator(), "expression")
|
||||
val (identifierNode, argsNode) = node as FunctionCallNode
|
||||
val identifier = (identifierNode as IdentifierNode).token.rawValue
|
||||
val arguments = (argsNode as FunctionCallArgumentsNode).items.map { evaluator.evaluate(it, environment).value }
|
||||
|
||||
try {
|
||||
return EvaluatorOutput.value(environment.invokeFunction(identifier, arguments))
|
||||
} catch(e: SmnpException) {
|
||||
throw PositionException(EnvironmentException(e, environment), identifierNode.position)
|
||||
}
|
||||
}
|
||||
try {
|
||||
return EvaluatorOutput.value(environment.invokeFunction(identifier, arguments))
|
||||
} catch (e: SmnpException) {
|
||||
throw wrapWithContext(e, identifierNode.position, environment)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,23 +4,22 @@ import io.smnp.callable.function.CustomFunction
|
||||
import io.smnp.dsl.ast.model.node.FunctionDefinitionNode
|
||||
import io.smnp.dsl.ast.model.node.Node
|
||||
import io.smnp.environment.Environment
|
||||
import io.smnp.error.EnvironmentException
|
||||
import io.smnp.error.PositionException
|
||||
import io.smnp.error.SmnpException
|
||||
import io.smnp.evaluation.model.entity.EvaluatorOutput
|
||||
import io.smnp.evaluation.util.ContextExceptionFactory.wrapWithContext
|
||||
|
||||
class FunctionDefinitionEvaluator : Evaluator() {
|
||||
override fun supportedNodes() = listOf(FunctionDefinitionNode::class)
|
||||
override fun supportedNodes() = listOf(FunctionDefinitionNode::class)
|
||||
|
||||
override fun tryToEvaluate(node: Node, environment: Environment): EvaluatorOutput {
|
||||
val function = CustomFunction.create(node as FunctionDefinitionNode)
|
||||
override fun tryToEvaluate(node: Node, environment: Environment): EvaluatorOutput {
|
||||
val function = CustomFunction.create(node as FunctionDefinitionNode)
|
||||
|
||||
try {
|
||||
environment.defineFunction(function)
|
||||
} catch(e: SmnpException) {
|
||||
throw PositionException(EnvironmentException(e, environment), node.position)
|
||||
}
|
||||
try {
|
||||
environment.defineFunction(function)
|
||||
} catch (e: SmnpException) {
|
||||
throw wrapWithContext(e, node.position, environment)
|
||||
}
|
||||
|
||||
return EvaluatorOutput.ok()
|
||||
}
|
||||
return EvaluatorOutput.ok()
|
||||
}
|
||||
}
|
||||
@@ -3,21 +3,20 @@ package io.smnp.evaluation.evaluator
|
||||
import io.smnp.dsl.ast.model.node.IdentifierNode
|
||||
import io.smnp.dsl.ast.model.node.Node
|
||||
import io.smnp.environment.Environment
|
||||
import io.smnp.error.EnvironmentException
|
||||
import io.smnp.error.EvaluationException
|
||||
import io.smnp.error.PositionException
|
||||
import io.smnp.evaluation.model.entity.EvaluatorOutput
|
||||
import io.smnp.evaluation.util.ContextExceptionFactory.wrapWithContext
|
||||
|
||||
class IdentifierEvaluator : Evaluator() {
|
||||
override fun supportedNodes() = listOf(IdentifierNode::class)
|
||||
override fun supportedNodes() = listOf(IdentifierNode::class)
|
||||
|
||||
override fun tryToEvaluate(node: Node, environment: Environment): EvaluatorOutput {
|
||||
val identifier = (node as IdentifierNode).token.rawValue
|
||||
override fun tryToEvaluate(node: Node, environment: Environment): EvaluatorOutput {
|
||||
val identifier = (node as IdentifierNode).token.rawValue
|
||||
|
||||
try {
|
||||
return EvaluatorOutput.value(environment.getVariable(identifier))
|
||||
} catch (e: EvaluationException) {
|
||||
throw PositionException(EnvironmentException(e, environment), node.position)
|
||||
}
|
||||
}
|
||||
try {
|
||||
return EvaluatorOutput.value(environment.getVariable(identifier))
|
||||
} catch (e: EvaluationException) {
|
||||
throw wrapWithContext(e, node.position, environment)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,23 +4,22 @@ import io.smnp.dsl.ast.model.node.IdentifierNode
|
||||
import io.smnp.dsl.ast.model.node.ImportNode
|
||||
import io.smnp.dsl.ast.model.node.Node
|
||||
import io.smnp.environment.Environment
|
||||
import io.smnp.error.EnvironmentException
|
||||
import io.smnp.error.PositionException
|
||||
import io.smnp.error.SmnpException
|
||||
import io.smnp.evaluation.model.entity.EvaluatorOutput
|
||||
import io.smnp.evaluation.util.ContextExceptionFactory.wrapWithContext
|
||||
|
||||
class ImportEvaluator : Evaluator() {
|
||||
override fun supportedNodes() = listOf(ImportNode::class)
|
||||
override fun supportedNodes() = listOf(ImportNode::class)
|
||||
|
||||
override fun tryToEvaluate(node: Node, environment: Environment): EvaluatorOutput {
|
||||
val path = (node as ImportNode).path.joinToString(".") { (it as IdentifierNode).token.rawValue }
|
||||
override fun tryToEvaluate(node: Node, environment: Environment): EvaluatorOutput {
|
||||
val path = (node as ImportNode).path.joinToString(".") { (it as IdentifierNode).token.rawValue }
|
||||
|
||||
try {
|
||||
environment.loadModule(path)
|
||||
} catch(e: SmnpException) {
|
||||
throw PositionException(EnvironmentException(e, environment), node.position)
|
||||
}
|
||||
try {
|
||||
environment.loadModule(path)
|
||||
} catch (e: SmnpException) {
|
||||
throw wrapWithContext(e, node.position, environment)
|
||||
}
|
||||
|
||||
return EvaluatorOutput.ok()
|
||||
}
|
||||
return EvaluatorOutput.ok()
|
||||
}
|
||||
}
|
||||
@@ -5,11 +5,9 @@ import io.smnp.dsl.ast.model.node.Node
|
||||
import io.smnp.dsl.ast.model.node.TokenNode
|
||||
import io.smnp.dsl.token.model.enumeration.TokenType
|
||||
import io.smnp.environment.Environment
|
||||
import io.smnp.error.EnvironmentException
|
||||
import io.smnp.error.EvaluationException
|
||||
import io.smnp.error.PositionException
|
||||
import io.smnp.error.ShouldNeverReachThisLineException
|
||||
import io.smnp.evaluation.model.entity.EvaluatorOutput
|
||||
import io.smnp.evaluation.util.ContextExceptionFactory.contextEvaluationException
|
||||
import io.smnp.type.enumeration.DataType
|
||||
import io.smnp.type.model.Value
|
||||
|
||||
@@ -24,8 +22,16 @@ class LogicOperatorEvaluator : Evaluator() {
|
||||
return EvaluatorOutput.value(
|
||||
Value.bool(
|
||||
when (operator) {
|
||||
TokenType.AND -> if(evalOperand(lhsNode, operator, environment)) evalOperand(rhsNode, operator, environment) else false
|
||||
TokenType.OR -> if (evalOperand(lhsNode, operator, environment)) true else evalOperand(rhsNode, operator, environment)
|
||||
TokenType.AND -> if (evalOperand(lhsNode, operator, environment)) evalOperand(
|
||||
rhsNode,
|
||||
operator,
|
||||
environment
|
||||
) else false
|
||||
TokenType.OR -> if (evalOperand(lhsNode, operator, environment)) true else evalOperand(
|
||||
rhsNode,
|
||||
operator,
|
||||
environment
|
||||
)
|
||||
else -> throw ShouldNeverReachThisLineException()
|
||||
}
|
||||
)
|
||||
@@ -36,12 +42,10 @@ class LogicOperatorEvaluator : Evaluator() {
|
||||
val value = evaluator.evaluate(operand, environment).value
|
||||
|
||||
if (value.type != DataType.BOOL) {
|
||||
throw PositionException(
|
||||
EnvironmentException(
|
||||
EvaluationException("Operator '${operator.token}' supports only bool types, found ${value.typeName}"),
|
||||
environment
|
||||
),
|
||||
operand.position
|
||||
throw contextEvaluationException(
|
||||
"Operator '${operator.token}' supports only bool types, found ${value.typeName}",
|
||||
operand.position,
|
||||
environment
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -4,11 +4,9 @@ import io.smnp.dsl.ast.model.node.IdentifierNode
|
||||
import io.smnp.dsl.ast.model.node.LoopNode
|
||||
import io.smnp.dsl.ast.model.node.Node
|
||||
import io.smnp.environment.Environment
|
||||
import io.smnp.error.EnvironmentException
|
||||
import io.smnp.error.EvaluationException
|
||||
import io.smnp.error.PositionException
|
||||
import io.smnp.evaluation.model.entity.EvaluatorOutput
|
||||
import io.smnp.evaluation.model.enumeration.EvaluationResult
|
||||
import io.smnp.evaluation.util.ContextExceptionFactory.contextEvaluationException
|
||||
import io.smnp.type.enumeration.DataType.*
|
||||
import io.smnp.type.model.Value
|
||||
|
||||
@@ -28,13 +26,10 @@ class LoopEvaluator : Evaluator() {
|
||||
LIST -> evaluateForList(iterator, parametersNode, statementNode, filterNode, environment)
|
||||
MAP -> evaluateForMap(iterator, parametersNode, statementNode, filterNode, environment)
|
||||
BOOL -> evaluateForBool(iteratorNode, parametersNode, statementNode, filterNode, environment)
|
||||
else -> throw PositionException(
|
||||
EnvironmentException(
|
||||
EvaluationException(
|
||||
"Expected for-loop with int iterator or foreach-loop with string, list or map iterator or while-loop with bool iterator, found ${iterator.typeName}"
|
||||
),
|
||||
environment
|
||||
), iteratorNode.position
|
||||
else -> throw contextEvaluationException(
|
||||
"Expected for-loop with int iterator or foreach-loop with string, list or map iterator or while-loop with bool iterator, found ${iterator.typeName}",
|
||||
iteratorNode.position,
|
||||
environment
|
||||
)
|
||||
}
|
||||
environment.popScope()
|
||||
@@ -140,21 +135,18 @@ class LoopEvaluator : Evaluator() {
|
||||
environment: Environment
|
||||
): EvaluatorOutput {
|
||||
if (parametersNode != Node.NONE) {
|
||||
throw PositionException(
|
||||
EnvironmentException(
|
||||
EvaluationException("Parameters are not supported in the while-loop"),
|
||||
environment
|
||||
),
|
||||
parametersNode.position
|
||||
throw contextEvaluationException(
|
||||
"Parameters are not supported in the while-loop",
|
||||
parametersNode.position,
|
||||
environment
|
||||
)
|
||||
}
|
||||
|
||||
if (filterNode != Node.NONE) {
|
||||
throw PositionException(
|
||||
EnvironmentException(
|
||||
EvaluationException("Filter is not supported in the while-loop"),
|
||||
environment
|
||||
), filterNode.position
|
||||
throw contextEvaluationException(
|
||||
"Filter is not supported in the while-loop",
|
||||
filterNode.position,
|
||||
environment
|
||||
)
|
||||
}
|
||||
|
||||
@@ -179,14 +171,10 @@ class LoopEvaluator : Evaluator() {
|
||||
if (filterNode != Node.NONE) {
|
||||
val condition = expressionEvaluator.evaluate(filterNode, environment).value
|
||||
if (condition.type != BOOL) {
|
||||
throw PositionException(
|
||||
EnvironmentException(
|
||||
EvaluationException(
|
||||
"Filter condition should be evaluated to bool type"
|
||||
),
|
||||
environment
|
||||
),
|
||||
filterNode.position
|
||||
throw contextEvaluationException(
|
||||
"Filter condition should be evaluated to bool type",
|
||||
filterNode.position,
|
||||
environment
|
||||
)
|
||||
}
|
||||
return condition.value as Boolean
|
||||
|
||||
@@ -5,10 +5,8 @@ import io.smnp.dsl.ast.model.node.MapEntryNode
|
||||
import io.smnp.dsl.ast.model.node.MapNode
|
||||
import io.smnp.dsl.ast.model.node.Node
|
||||
import io.smnp.environment.Environment
|
||||
import io.smnp.error.EnvironmentException
|
||||
import io.smnp.error.EvaluationException
|
||||
import io.smnp.error.PositionException
|
||||
import io.smnp.evaluation.model.entity.EvaluatorOutput
|
||||
import io.smnp.evaluation.util.ContextExceptionFactory.contextEvaluationException
|
||||
import io.smnp.type.enumeration.DataType.*
|
||||
import io.smnp.type.model.Value
|
||||
|
||||
@@ -33,13 +31,7 @@ class MapEvaluator : Evaluator() {
|
||||
}
|
||||
|
||||
if (key.type !in listOf(BOOL, INT, NOTE, STRING)) {
|
||||
throw PositionException(
|
||||
EnvironmentException(
|
||||
EvaluationException("Invalid map key's type ${key.typeName}"),
|
||||
environment
|
||||
),
|
||||
keyNode.position
|
||||
)
|
||||
throw contextEvaluationException("Invalid map key's type ${key.typeName}", keyNode.position, environment)
|
||||
}
|
||||
|
||||
return key
|
||||
|
||||
@@ -3,10 +3,8 @@ package io.smnp.evaluation.evaluator
|
||||
import io.smnp.dsl.ast.model.node.MinusOperatorNode
|
||||
import io.smnp.dsl.ast.model.node.Node
|
||||
import io.smnp.environment.Environment
|
||||
import io.smnp.error.EnvironmentException
|
||||
import io.smnp.error.EvaluationException
|
||||
import io.smnp.error.PositionException
|
||||
import io.smnp.evaluation.model.entity.EvaluatorOutput
|
||||
import io.smnp.evaluation.util.ContextExceptionFactory.contextEvaluationException
|
||||
import io.smnp.type.enumeration.DataType
|
||||
import io.smnp.type.model.Value
|
||||
|
||||
@@ -24,12 +22,10 @@ class MinusOperatorEvaluator : Evaluator() {
|
||||
DataType.FLOAT -> Value.float(-1.0f * operand.value.value as Float)
|
||||
DataType.STRING -> Value.string((operand.value.value as String).reversed())
|
||||
DataType.LIST -> Value.list((operand.value.value as List<Value>).reversed())
|
||||
else -> throw PositionException(
|
||||
EnvironmentException(
|
||||
EvaluationException("Type ${operand.value.typeName} does not support minus operator"),
|
||||
environment
|
||||
),
|
||||
node.position
|
||||
else -> throw contextEvaluationException(
|
||||
"Type ${operand.value.typeName} does not support minus operator",
|
||||
node.position,
|
||||
environment
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
@@ -3,10 +3,8 @@ package io.smnp.evaluation.evaluator
|
||||
import io.smnp.dsl.ast.model.node.Node
|
||||
import io.smnp.dsl.ast.model.node.NotOperatorNode
|
||||
import io.smnp.environment.Environment
|
||||
import io.smnp.error.EnvironmentException
|
||||
import io.smnp.error.EvaluationException
|
||||
import io.smnp.error.PositionException
|
||||
import io.smnp.evaluation.model.entity.EvaluatorOutput
|
||||
import io.smnp.evaluation.util.ContextExceptionFactory.contextEvaluationException
|
||||
import io.smnp.type.enumeration.DataType
|
||||
import io.smnp.type.model.Value
|
||||
|
||||
@@ -19,13 +17,7 @@ class NotOperatorEvaluator : Evaluator() {
|
||||
val operand = evaluator.evaluate(operandNode, environment).value
|
||||
|
||||
if (operand.type != DataType.BOOL) {
|
||||
throw PositionException(
|
||||
EnvironmentException(
|
||||
EvaluationException("Only bool types can be negated"),
|
||||
environment
|
||||
),
|
||||
operandNode.position
|
||||
)
|
||||
throw contextEvaluationException("Only bool types can be negated", operandNode.position, environment)
|
||||
}
|
||||
|
||||
return EvaluatorOutput.value(Value.bool(!(operand.value as Boolean)))
|
||||
|
||||
@@ -3,10 +3,8 @@ package io.smnp.evaluation.evaluator
|
||||
import io.smnp.dsl.ast.model.node.Node
|
||||
import io.smnp.dsl.ast.model.node.PowerOperatorNode
|
||||
import io.smnp.environment.Environment
|
||||
import io.smnp.error.EnvironmentException
|
||||
import io.smnp.error.EvaluationException
|
||||
import io.smnp.error.PositionException
|
||||
import io.smnp.evaluation.model.entity.EvaluatorOutput
|
||||
import io.smnp.evaluation.util.ContextExceptionFactory.contextEvaluationException
|
||||
import io.smnp.type.model.Value
|
||||
import kotlin.math.pow
|
||||
|
||||
@@ -20,13 +18,7 @@ class PowerOperatorEvaluator : Evaluator() {
|
||||
val rhs = evaluator.evaluate(rhsNode, environment).value
|
||||
|
||||
if (!lhs.type.isNumeric() || !rhs.type.isNumeric()) {
|
||||
throw PositionException(
|
||||
EnvironmentException(
|
||||
EvaluationException("Operator ** supports only numeric types"),
|
||||
environment
|
||||
),
|
||||
node.position
|
||||
)
|
||||
throw contextEvaluationException("Operator ** supports only numeric types", node.position, environment)
|
||||
}
|
||||
|
||||
return EvaluatorOutput.value(Value.float((lhs.value as Number).toFloat().pow((rhs.value as Number).toFloat())))
|
||||
|
||||
@@ -5,11 +5,9 @@ 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.environment.Environment
|
||||
import io.smnp.error.EnvironmentException
|
||||
import io.smnp.error.EvaluationException
|
||||
import io.smnp.error.PositionException
|
||||
import io.smnp.error.ShouldNeverReachThisLineException
|
||||
import io.smnp.evaluation.model.entity.EvaluatorOutput
|
||||
import io.smnp.evaluation.util.ContextExceptionFactory.contextEvaluationException
|
||||
import io.smnp.evaluation.util.NumberUnification.unify
|
||||
import io.smnp.type.model.Value
|
||||
|
||||
@@ -24,12 +22,10 @@ class ProductOperatorEvaluator : Evaluator() {
|
||||
val operator = (opNode as TokenNode).token.type
|
||||
|
||||
if (!lhs.type.isNumeric() || !rhs.type.isNumeric()) {
|
||||
throw PositionException(
|
||||
EnvironmentException(
|
||||
EvaluationException("Operator ${operator.token} supports only numeric types"),
|
||||
environment
|
||||
),
|
||||
node.position
|
||||
throw contextEvaluationException(
|
||||
"Operator ${operator.token} supports only numeric types",
|
||||
node.position,
|
||||
environment
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -4,11 +4,9 @@ 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.environment.Environment
|
||||
import io.smnp.error.EnvironmentException
|
||||
import io.smnp.error.EvaluationException
|
||||
import io.smnp.error.PositionException
|
||||
import io.smnp.error.ShouldNeverReachThisLineException
|
||||
import io.smnp.evaluation.model.entity.EvaluatorOutput
|
||||
import io.smnp.evaluation.util.ContextExceptionFactory.contextEvaluationException
|
||||
import io.smnp.evaluation.util.NumberUnification.unify
|
||||
import io.smnp.type.model.Value
|
||||
|
||||
@@ -32,13 +30,7 @@ class RelationOperatorEvaluator : Evaluator() {
|
||||
}
|
||||
|
||||
if (!lhs.type.isNumeric() || !rhs.type.isNumeric()) {
|
||||
throw PositionException(
|
||||
EnvironmentException(
|
||||
EvaluationException("Operator $operator supports only numeric types"),
|
||||
environment
|
||||
),
|
||||
node.position
|
||||
)
|
||||
throw contextEvaluationException("Operator $operator supports only numeric types", node.position, environment)
|
||||
}
|
||||
|
||||
return EvaluatorOutput.value(
|
||||
|
||||
@@ -3,10 +3,8 @@ package io.smnp.evaluation.evaluator
|
||||
import io.smnp.data.entity.Note
|
||||
import io.smnp.dsl.ast.model.node.*
|
||||
import io.smnp.environment.Environment
|
||||
import io.smnp.error.EnvironmentException
|
||||
import io.smnp.error.EvaluationException
|
||||
import io.smnp.error.PositionException
|
||||
import io.smnp.evaluation.model.entity.EvaluatorOutput
|
||||
import io.smnp.evaluation.util.ContextExceptionFactory.contextEvaluationException
|
||||
import io.smnp.math.Fraction
|
||||
import io.smnp.type.enumeration.DataType
|
||||
import io.smnp.type.model.Value
|
||||
@@ -49,11 +47,10 @@ class StaffEvaluator : Evaluator() {
|
||||
it: Node
|
||||
) {
|
||||
if (index != 0) {
|
||||
throw PositionException(
|
||||
EnvironmentException(
|
||||
EvaluationException("Time signature can be placed only at the beginning of measure"),
|
||||
environment
|
||||
), it.position
|
||||
throw contextEvaluationException(
|
||||
"Time signature can be placed only at the beginning of measure",
|
||||
it.position,
|
||||
environment
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -69,11 +66,10 @@ class StaffEvaluator : Evaluator() {
|
||||
currentSignature?.let {
|
||||
if (evaluatedSignature != it) {
|
||||
val simplified = evaluatedSignature.simplified
|
||||
throw PositionException(
|
||||
EnvironmentException(
|
||||
EvaluationException("Invalid time signature: expected ${it.numerator}/${it.denominator}, got ${simplified.numerator}/${simplified.denominator}"),
|
||||
environment
|
||||
), measure.position
|
||||
throw contextEvaluationException(
|
||||
"Invalid time signature: expected ${it.numerator}/${it.denominator}, got ${simplified.numerator}/${simplified.denominator}",
|
||||
measure.position,
|
||||
environment
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,11 +6,9 @@ import io.smnp.dsl.ast.model.node.SumOperatorNode
|
||||
import io.smnp.dsl.ast.model.node.TokenNode
|
||||
import io.smnp.dsl.token.model.enumeration.TokenType
|
||||
import io.smnp.environment.Environment
|
||||
import io.smnp.error.EnvironmentException
|
||||
import io.smnp.error.EvaluationException
|
||||
import io.smnp.error.PositionException
|
||||
import io.smnp.error.ShouldNeverReachThisLineException
|
||||
import io.smnp.evaluation.model.entity.EvaluatorOutput
|
||||
import io.smnp.evaluation.util.ContextExceptionFactory.contextEvaluationException
|
||||
import io.smnp.evaluation.util.NumberUnification.unify
|
||||
import io.smnp.math.Fraction
|
||||
import io.smnp.type.enumeration.DataType.*
|
||||
@@ -40,17 +38,18 @@ class SumOperatorEvaluator : Evaluator() {
|
||||
|
||||
private fun plus(lhs: Value, plusNode: Node, rhs: Value, environment: Environment): Value {
|
||||
return when {
|
||||
areNumeric(lhs, rhs) -> unify(lhs, rhs, int = { (l, r) -> Value.int(l + r) }, float = { (l, r) -> Value.float(l + r) })
|
||||
areNumeric(lhs, rhs) -> unify(
|
||||
lhs,
|
||||
rhs,
|
||||
int = { (l, r) -> Value.int(l + r) },
|
||||
float = { (l, r) -> Value.float(l + r) })
|
||||
lhs.type == STRING -> string(lhs.value as String + rhs.value.toString())
|
||||
areLists(lhs, rhs) -> list(lhs.value as List<Value> + rhs.value as List<Value>)
|
||||
lhs.type == NOTE && rhs.type == INT -> note(lhs.value as Note + Fraction(1, rhs.value as Int))
|
||||
else -> throw PositionException(
|
||||
EnvironmentException(
|
||||
EvaluationException(
|
||||
"The ${lhs.typeName} and ${rhs.typeName} are not supported by + operator"
|
||||
),
|
||||
environment
|
||||
), plusNode.position
|
||||
else -> throw contextEvaluationException(
|
||||
"The ${lhs.typeName} and ${rhs.typeName} are not supported by + operator",
|
||||
plusNode.position,
|
||||
environment
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -63,12 +62,10 @@ class SumOperatorEvaluator : Evaluator() {
|
||||
int = { (l, r) -> Value.int(l - r) },
|
||||
float = { (l, r) -> Value.float(l - r) }
|
||||
)
|
||||
else throw PositionException(
|
||||
EnvironmentException(
|
||||
EvaluationException("The - operator supports only numeric values"),
|
||||
environment
|
||||
),
|
||||
minusNode.position
|
||||
else throw contextEvaluationException(
|
||||
"The - operator supports only numeric values",
|
||||
minusNode.position,
|
||||
environment
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package io.smnp.evaluation.util
|
||||
|
||||
import io.smnp.dsl.token.model.entity.TokenPosition
|
||||
import io.smnp.environment.Environment
|
||||
import io.smnp.error.EnvironmentException
|
||||
import io.smnp.error.EvaluationException
|
||||
import io.smnp.error.PositionException
|
||||
import io.smnp.error.SmnpException
|
||||
|
||||
object ContextExceptionFactory {
|
||||
fun contextEvaluationException(message: String, position: TokenPosition, environment: Environment): SmnpException {
|
||||
return wrapWithContext(
|
||||
EvaluationException(
|
||||
message
|
||||
), position, environment
|
||||
)
|
||||
}
|
||||
|
||||
fun wrapWithContext(exception: SmnpException, position: TokenPosition, environment: Environment): SmnpException {
|
||||
return PositionException(
|
||||
EnvironmentException(
|
||||
exception,
|
||||
environment
|
||||
), position
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user