From a1273896e4928c02fe9cde95cb0e611a0bee5f9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Pluta?= Date: Fri, 12 Jul 2019 19:40:37 +0200 Subject: [PATCH] Create evaluator for access operator --- smnp/ast/node/unit.py | 7 ++-- smnp/runtime/evaluators/access.py | 7 ++-- smnp/runtime/evaluators/atom.py | 18 ++++++++++ smnp/runtime/evaluators/expression.py | 49 ++++++++------------------- smnp/runtime/evaluators/unit.py | 34 +++++++++++++++++++ 5 files changed, 73 insertions(+), 42 deletions(-) create mode 100644 smnp/runtime/evaluators/unit.py diff --git a/smnp/ast/node/unit.py b/smnp/ast/node/unit.py index aa897a2..2a1b6cd 100644 --- a/smnp/ast/node/unit.py +++ b/smnp/ast/node/unit.py @@ -1,15 +1,14 @@ from smnp.ast.node.atom import AtomParser from smnp.ast.node.operator import BinaryOperator, UnaryOperator, Operator -from smnp.ast.node.valuable import Valuable from smnp.ast.parser import Parser from smnp.token.type import TokenType -class Unit(Valuable): +class MinusOperator(UnaryOperator): pass -class MinusOperator(UnaryOperator): +class Access(BinaryOperator): pass @@ -31,7 +30,7 @@ def UnitParser(input): atom2, [TokenType.DOT], Parser.doAssert(atom2, "atom"), - createNode=lambda left, op, right: Unit.withValue(BinaryOperator.withValues(left, op, right)), + createNode=lambda left, op, right: Access.withValues(left, op, right), name="unit" )(input) diff --git a/smnp/runtime/evaluators/access.py b/smnp/runtime/evaluators/access.py index f737c73..85f5924 100644 --- a/smnp/runtime/evaluators/access.py +++ b/smnp/runtime/evaluators/access.py @@ -1,5 +1,4 @@ -from smnp.ast.node.identifier import Identifier -from smnp.ast.node.invocation import FunctionCallNode +from smnp.ast.node.identifier import Identifier, FunctionCall from smnp.error.runtime import RuntimeException from smnp.runtime.evaluator import Evaluator from smnp.runtime.evaluators.expression import expressionEvaluator @@ -20,9 +19,9 @@ class AccessEvaluator(Evaluator): except KeyError: raise RuntimeException(f"Unknown property '{right.value}' of type '{left.type.name.lower()}'", right.pos) - if type(right) == FunctionCallNode: + if type(right) == FunctionCall: try: - arguments = abstractIterableEvaluator(expressionEvaluator(True))(right.arguments, environment) + arguments = abstractIterableEvaluator(expressionEvaluator(doAssert=True))(right.arguments, environment) return environment.invokeMethod(left, right.name.value, arguments) except RuntimeException as e: raise updatePos(e, right) diff --git a/smnp/runtime/evaluators/atom.py b/smnp/runtime/evaluators/atom.py index 9ee3733..93c20ed 100644 --- a/smnp/runtime/evaluators/atom.py +++ b/smnp/runtime/evaluators/atom.py @@ -1,3 +1,6 @@ +from smnp.ast.node.atom import StringLiteral, IntegerLiteral, NoteLiteral, BoolLiteral, TypeLiteral +from smnp.ast.node.list import List +from smnp.ast.node.map import Map from smnp.error.runtime import RuntimeException from smnp.runtime.evaluator import Evaluator from smnp.runtime.evaluators.expression import expressionEvaluator @@ -61,3 +64,18 @@ class MapEvaluator(Evaluator): map[key] = exprEvaluator(entry.value, environment).value return Type.map(map) + + +class AtomEvaluator(Evaluator): + + @classmethod + def evaluator(cls, node, environment): + return Evaluator.oneOf( + Evaluator.forNodes(StringEvaluator.evaluate, StringLiteral), + Evaluator.forNodes(IntegerEvaluator.evaluate, IntegerLiteral), + Evaluator.forNodes(NoteEvaluator.evaluate, NoteLiteral), + Evaluator.forNodes(BoolEvaluator.evaluate, BoolLiteral), + Evaluator.forNodes(TypeEvaluator.evaluate, TypeLiteral), + Evaluator.forNodes(ListEvaluator.evaluate, List), + Evaluator.forNodes(MapEvaluator.evaluate, Map) + )(node, environment).value diff --git a/smnp/runtime/evaluators/expression.py b/smnp/runtime/evaluators/expression.py index e4935af..4d20707 100644 --- a/smnp/runtime/evaluators/expression.py +++ b/smnp/runtime/evaluators/expression.py @@ -1,8 +1,5 @@ -from smnp.ast.node.atom import StringLiteral, IntegerLiteral, NoteLiteral, BoolLiteral, TypeLiteral from smnp.ast.node.identifier import FunctionCall -from smnp.ast.node.list import List -from smnp.ast.node.map import Map -from smnp.ast.node.unit import MinusOperator +from smnp.ast.node.unit import MinusOperator, Access from smnp.error.runtime import RuntimeException from smnp.runtime.evaluator import Evaluator from smnp.type.model import Type @@ -10,38 +7,22 @@ from smnp.type.model import Type def expressionEvaluator(doAssert=False): def evaluateExpression(node, environment): - from smnp.runtime.evaluators.atom import StringEvaluator - from smnp.runtime.evaluators.atom import TypeEvaluator - from smnp.runtime.evaluators.atom import IntegerEvaluator - from smnp.runtime.evaluators.atom import NoteEvaluator - from smnp.runtime.evaluators.atom import BoolEvaluator + from smnp.runtime.evaluators.function import FunctionCallEvaluator + from smnp.runtime.evaluators.minus import MinusEvaluator - from smnp.runtime.evaluators.function import FunctionCallEvaluator - from smnp.runtime.evaluators.atom import ListEvaluator - from smnp.runtime.evaluators.atom import MapEvaluator - from smnp.runtime.evaluators.minus import MinusEvaluator - result = Evaluator.oneOf( - Evaluator.forNodes(FunctionCallEvaluator.evaluate, FunctionCall), - Evaluator.forNodes(StringEvaluator.evaluate, StringLiteral), - Evaluator.forNodes(IntegerEvaluator.evaluate, IntegerLiteral), - Evaluator.forNodes(NoteEvaluator.evaluate, NoteLiteral), - Evaluator.forNodes(BoolEvaluator.evaluate, BoolLiteral), - Evaluator.forNodes(TypeEvaluator.evaluate, TypeLiteral), - Evaluator.forNodes(ListEvaluator.evaluate, List), - Evaluator.forNodes(MapEvaluator.evaluate, Map), - Evaluator.forNodes(MinusEvaluator.evaluate, MinusOperator) - # Evaluator.forNodes(IdentifierEvaluator.evaluate, Identifier), - # Evaluator.forNodes(ListEvaluator.evaluate, List), - # Evaluator.forNodes(AccessEvaluator.evaluate, LeftAssociativeOperatorNode), - # Evaluator.forNodes(AssignmentEvaluator.evaluate, AssignmentNode), - # Evaluator.forNodes(AsteriskEvaluator.evaluate, AsteriskNode), - # Evaluator.forNodes(MapEvaluator.evaluate, MapNode) - )(node, environment) + from smnp.runtime.evaluators.atom import AtomEvaluator + from smnp.runtime.evaluators.access import AccessEvaluator + result = Evaluator.oneOf( + Evaluator.forNodes(FunctionCallEvaluator.evaluate, FunctionCall), + Evaluator.forNodes(MinusEvaluator.evaluate, MinusOperator), + Evaluator.forNodes(AccessEvaluator.evaluate, Access), + AtomEvaluator.evaluate + )(node, environment) - if doAssert and result.result and result.value.type == Type.VOID: - raise RuntimeException(f"Expected expression", node.pos) + if doAssert and result.result and result.value.type == Type.VOID: + raise RuntimeException(f"Expected expression", node.pos) + + return result - return result return evaluateExpression - diff --git a/smnp/runtime/evaluators/unit.py b/smnp/runtime/evaluators/unit.py new file mode 100644 index 0000000..d6a6a76 --- /dev/null +++ b/smnp/runtime/evaluators/unit.py @@ -0,0 +1,34 @@ +from smnp.ast.node.identifier import Identifier, FunctionCall +from smnp.error.runtime import RuntimeException +from smnp.runtime.evaluator import Evaluator +from smnp.runtime.evaluators.expression import expressionEvaluator +from smnp.runtime.evaluators.iterable import abstractIterableEvaluator +from smnp.runtime.tools.error import updatePos + + +class UnitEvaluator(Evaluator): + + @classmethod + def evaluator(cls, node, environment): + return + + +class AccessEvaluator(Evaluator): + + @classmethod + def evaluator(cls, node, environment): + left = expressionEvaluator(doAssert=True)(node.left, environment).value # TODO check if it isn't necessary to verify 'result' attr of EvaluatioNResult + right = node.right + + if type(right) == Identifier: + try: + return left.properties[right.value] + except KeyError: + raise RuntimeException(f"Unknown property '{right.value}' of type '{left.type.name.lower()}'", right.pos) + + if type(right) == FunctionCall: + try: + arguments = abstractIterableEvaluator(expressionEvaluator(doAssert=True))(right.arguments, environment) + return environment.invokeMethod(left, right.name.value, arguments) + except RuntimeException as e: + raise updatePos(e, right) \ No newline at end of file