From ab82ee8628f342fe81873fb4d0166f84911f369d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Przemys=C5=82aw=20Pluta?= Date: Tue, 10 Mar 2020 22:16:40 +0100 Subject: [PATCH] Add support for function/methods invocation on Evaluator --- .../dsl/ast/model/node/FunctionCallNode.kt | 3 +++ .../evaluator/AccessOperatorEvaluator.kt | 11 +++++----- .../evaluator/ExpressionEvaluator.kt | 4 +++- .../evaluator/FunctionCallEvaluator.kt | 21 +++++++++++++++++++ 4 files changed, 32 insertions(+), 7 deletions(-) create mode 100644 app/src/main/kotlin/io/smnp/evaluation/evaluator/FunctionCallEvaluator.kt diff --git a/app/src/main/kotlin/io/smnp/dsl/ast/model/node/FunctionCallNode.kt b/app/src/main/kotlin/io/smnp/dsl/ast/model/node/FunctionCallNode.kt index bc61c0f..387cdfc 100644 --- a/app/src/main/kotlin/io/smnp/dsl/ast/model/node/FunctionCallNode.kt +++ b/app/src/main/kotlin/io/smnp/dsl/ast/model/node/FunctionCallNode.kt @@ -1,6 +1,9 @@ package io.smnp.dsl.ast.model.node class FunctionCallNode(identifier: Node, arguments: Node) : Node(2, identifier.position) { + operator fun component1() = children[0] + operator fun component2() = children[1] + val identifier: Node get() = children[0] diff --git a/app/src/main/kotlin/io/smnp/evaluation/evaluator/AccessOperatorEvaluator.kt b/app/src/main/kotlin/io/smnp/evaluation/evaluator/AccessOperatorEvaluator.kt index 981b25a..03eb8d6 100644 --- a/app/src/main/kotlin/io/smnp/evaluation/evaluator/AccessOperatorEvaluator.kt +++ b/app/src/main/kotlin/io/smnp/evaluation/evaluator/AccessOperatorEvaluator.kt @@ -1,9 +1,6 @@ package io.smnp.evaluation.evaluator -import io.smnp.dsl.ast.model.node.AccessOperatorNode -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.dsl.ast.model.node.* import io.smnp.environment.Environment import io.smnp.error.EvaluationException import io.smnp.evaluation.model.entity.EvaluatorOutput @@ -22,8 +19,10 @@ class AccessOperatorEvaluator : Evaluator() { EvaluatorOutput.value(lhs.properties[rhs] ?: throw EvaluationException("Unknown property $rhs of type ${lhs.type.name.toLowerCase()}", rhsNode.position)) } is FunctionCallNode -> { - // todo Implement when methods become available - EvaluatorOutput.fail() + val (identifierNode, argsNode) = rhsNode + val identifier = (identifierNode as IdentifierNode).token.rawValue + val arguments = (argsNode as FunctionCallArgumentsNode).items.map { evaluator.evaluate(it, environment).value!! } + return EvaluatorOutput.value(environment.invokeMethod(lhs, identifier, arguments)) } else -> { throw EvaluationException("Invalid property access type - only property name and method call are allowed", rhsNode.position) diff --git a/app/src/main/kotlin/io/smnp/evaluation/evaluator/ExpressionEvaluator.kt b/app/src/main/kotlin/io/smnp/evaluation/evaluator/ExpressionEvaluator.kt index 0dfd4d2..3b46fcd 100644 --- a/app/src/main/kotlin/io/smnp/evaluation/evaluator/ExpressionEvaluator.kt +++ b/app/src/main/kotlin/io/smnp/evaluation/evaluator/ExpressionEvaluator.kt @@ -25,7 +25,9 @@ class ExpressionEvaluator : Evaluator() { SumOperatorEvaluator(), AccessOperatorEvaluator(), LogicOperatorEvaluator(), - RelationOperatorEvaluator() + RelationOperatorEvaluator(), + + FunctionCallEvaluator() ).evaluate(node, environment) if(output.result == EvaluationResult.OK) { diff --git a/app/src/main/kotlin/io/smnp/evaluation/evaluator/FunctionCallEvaluator.kt b/app/src/main/kotlin/io/smnp/evaluation/evaluator/FunctionCallEvaluator.kt new file mode 100644 index 0000000..51ca64a --- /dev/null +++ b/app/src/main/kotlin/io/smnp/evaluation/evaluator/FunctionCallEvaluator.kt @@ -0,0 +1,21 @@ +package io.smnp.evaluation.evaluator + +import io.smnp.dsl.ast.model.node.FunctionCallArgumentsNode +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.evaluation.model.entity.EvaluatorOutput + +class FunctionCallEvaluator : Evaluator() { + 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!! } + + return EvaluatorOutput.value(environment.invokeFunction(identifier, arguments)) + } +} \ No newline at end of file