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.atom import AtomParser
from smnp.ast.node.operator import BinaryOperator, UnaryOperator, Operator from smnp.ast.node.operator import BinaryOperator, UnaryOperator, Operator
from smnp.ast.node.valuable import Valuable
from smnp.ast.parser import Parser from smnp.ast.parser import Parser
from smnp.token.type import TokenType from smnp.token.type import TokenType
class Unit(Valuable): class MinusOperator(UnaryOperator):
pass pass
class MinusOperator(UnaryOperator): class Access(BinaryOperator):
pass pass
@@ -31,7 +30,7 @@ def UnitParser(input):
atom2, atom2,
[TokenType.DOT], [TokenType.DOT],
Parser.doAssert(atom2, "atom"), 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" name="unit"
)(input) )(input)

View File

@@ -1,5 +1,4 @@
from smnp.ast.node.identifier import Identifier from smnp.ast.node.identifier import Identifier, FunctionCall
from smnp.ast.node.invocation import FunctionCallNode
from smnp.error.runtime import RuntimeException from smnp.error.runtime import RuntimeException
from smnp.runtime.evaluator import Evaluator from smnp.runtime.evaluator import Evaluator
from smnp.runtime.evaluators.expression import expressionEvaluator from smnp.runtime.evaluators.expression import expressionEvaluator
@@ -20,9 +19,9 @@ class AccessEvaluator(Evaluator):
except KeyError: except KeyError:
raise RuntimeException(f"Unknown property '{right.value}' of type '{left.type.name.lower()}'", right.pos) raise RuntimeException(f"Unknown property '{right.value}' of type '{left.type.name.lower()}'", right.pos)
if type(right) == FunctionCallNode: if type(right) == FunctionCall:
try: try:
arguments = abstractIterableEvaluator(expressionEvaluator(True))(right.arguments, environment) arguments = abstractIterableEvaluator(expressionEvaluator(doAssert=True))(right.arguments, environment)
return environment.invokeMethod(left, right.name.value, arguments) return environment.invokeMethod(left, right.name.value, arguments)
except RuntimeException as e: except RuntimeException as e:
raise updatePos(e, right) 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.error.runtime import RuntimeException
from smnp.runtime.evaluator import Evaluator from smnp.runtime.evaluator import Evaluator
from smnp.runtime.evaluators.expression import expressionEvaluator from smnp.runtime.evaluators.expression import expressionEvaluator
@@ -61,3 +64,18 @@ class MapEvaluator(Evaluator):
map[key] = exprEvaluator(entry.value, environment).value map[key] = exprEvaluator(entry.value, environment).value
return Type.map(map) 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.identifier import FunctionCall
from smnp.ast.node.list import List from smnp.ast.node.unit import MinusOperator, Access
from smnp.ast.node.map import Map
from smnp.ast.node.unit import MinusOperator
from smnp.error.runtime import RuntimeException from smnp.error.runtime import RuntimeException
from smnp.runtime.evaluator import Evaluator from smnp.runtime.evaluator import Evaluator
from smnp.type.model import Type from smnp.type.model import Type
@@ -10,32 +7,16 @@ from smnp.type.model import Type
def expressionEvaluator(doAssert=False): def expressionEvaluator(doAssert=False):
def evaluateExpression(node, environment): 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.function import FunctionCallEvaluator
from smnp.runtime.evaluators.atom import ListEvaluator
from smnp.runtime.evaluators.atom import MapEvaluator
from smnp.runtime.evaluators.minus import MinusEvaluator from smnp.runtime.evaluators.minus import MinusEvaluator
from smnp.runtime.evaluators.atom import AtomEvaluator
from smnp.runtime.evaluators.access import AccessEvaluator
result = Evaluator.oneOf( result = Evaluator.oneOf(
Evaluator.forNodes(FunctionCallEvaluator.evaluate, FunctionCall), Evaluator.forNodes(FunctionCallEvaluator.evaluate, FunctionCall),
Evaluator.forNodes(StringEvaluator.evaluate, StringLiteral), Evaluator.forNodes(MinusEvaluator.evaluate, MinusOperator),
Evaluator.forNodes(IntegerEvaluator.evaluate, IntegerLiteral), Evaluator.forNodes(AccessEvaluator.evaluate, Access),
Evaluator.forNodes(NoteEvaluator.evaluate, NoteLiteral), AtomEvaluator.evaluate
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) )(node, environment)
if doAssert and result.result and result.value.type == Type.VOID: if doAssert and result.result and result.value.type == Type.VOID:
@@ -43,5 +24,5 @@ def expressionEvaluator(doAssert=False):
return result return result
return evaluateExpression
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)