Create evaluator for access operator

This commit is contained in:
Bartłomiej Pluta
2019-07-12 19:40:37 +02:00
parent 94666aca79
commit a1273896e4
5 changed files with 73 additions and 42 deletions

View File

@@ -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)

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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)