Create evaluator for function call

This commit is contained in:
Bartłomiej Pluta
2019-07-08 14:10:10 +02:00
parent 6e42ac0f91
commit 1e634180d6
10 changed files with 81 additions and 62 deletions

View File

@@ -64,11 +64,11 @@ class EvaluationResult():
def evaluate(node, environment):
from smnp.runtime.evaluators.program import ProgramEvaluator
from smnp.runtime.evaluators.expression import evaluateExpression
from smnp.runtime.evaluators.expression import expressionEvaluator
result = Evaluator.oneOf(
Evaluator.forNodes(ProgramEvaluator.evaluate, Program),
evaluateExpression
expressionEvaluator()
)(node, environment)
if not result.result:

View File

@@ -1,22 +1,36 @@
from smnp.ast.node.identifier import IdentifierNode
from smnp.ast.node.integer import IntegerLiteralNode
from smnp.ast.node.invocation import FunctionCallNode
from smnp.ast.node.list import ListNode
from smnp.ast.node.note import NoteLiteralNode
from smnp.ast.node.string import StringLiteralNode
from smnp.error.runtime import RuntimeException
from smnp.runtime.evaluator import Evaluator
from smnp.type.model import Type
def evaluateExpression(node, environment):
from smnp.runtime.evaluators.string import StringEvaluator
from smnp.runtime.evaluators.integer import IntegerEvaluator
from smnp.runtime.evaluators.note import NoteEvaluator
from smnp.runtime.evaluators.identifier import IdentifierEvaluator
from smnp.runtime.evaluators.list import ListEvaluator
def expressionEvaluator(doAssert=False):
def evaluateExpression(node, environment):
from smnp.runtime.evaluators.string import StringEvaluator
from smnp.runtime.evaluators.integer import IntegerEvaluator
from smnp.runtime.evaluators.note import NoteEvaluator
from smnp.runtime.evaluators.identifier import IdentifierEvaluator
from smnp.runtime.evaluators.list import ListEvaluator
from smnp.runtime.evaluators.function import FunctionCallEvaluator
result = Evaluator.oneOf(
Evaluator.forNodes(StringEvaluator.evaluate, StringLiteralNode),
Evaluator.forNodes(IntegerEvaluator.evaluate, IntegerLiteralNode),
Evaluator.forNodes(NoteEvaluator.evaluate, NoteLiteralNode),
Evaluator.forNodes(IdentifierEvaluator.evaluate, IdentifierNode),
Evaluator.forNodes(ListEvaluator.evaluate, ListNode),
Evaluator.forNodes(FunctionCallEvaluator.evaluate, FunctionCallNode)
)(node, environment)
if doAssert and result.result and result.value.type == Type.VOID:
raise RuntimeException(f"Expected expression", node.pos)
return result
return evaluateExpression
return Evaluator.oneOf(
Evaluator.forNodes(StringEvaluator.evaluate, StringLiteralNode),
Evaluator.forNodes(IntegerEvaluator.evaluate, IntegerLiteralNode),
Evaluator.forNodes(NoteEvaluator.evaluate, NoteLiteralNode),
Evaluator.forNodes(IdentifierEvaluator.evaluate, IdentifierNode),
Evaluator.forNodes(ListEvaluator.evaluate, ListNode)
)(node, environment)

View File

@@ -1,40 +1,45 @@
from smnp.ast.node.identifier import IdentifierNode
from smnp.ast.node.program import Program
from smnp.error.base import SmnpException
from smnp.error.runtime import RuntimeException
from smnp.runtime.evaluators.list import evaluateList
from smnp.runtime.tools import flatListNode
from smnp.runtime.evaluator import Evaluator
from smnp.runtime.evaluators.expression import expressionEvaluator
from smnp.runtime.evaluators.iterable import abstractIterableEvaluator
def evaluateFunctionDefinition(definition, environment):
name = definition.name
params = list([p for p in flatListNode(definition.parameters)])
body = definition.body
class FunctionCallEvaluator(Evaluator):
if not isinstance(definition.parent, Program):
raise RuntimeException(f"Functions can be defined only on the top level of script", name.pos)
for p in params:
if not isinstance(p, IdentifierNode):
raise RuntimeException("Parameter of function definition must be an identifier", p.pos, )
if name.identifier in environment.customFunctions or name.identifier in environment.functions:
raise RuntimeException(f"Function '{name.identifier}' already exists", name.pos)
environment.customFunctions[name.identifier] = {
'params': params,
'body': flatListNode(body)
}
def evaluateFunctionCall(functionCall, environment):
try:
functionName = functionCall.identifier.identifier
arguments = evaluateList(functionCall.arguments, environment).value
return environment.invokeFunction(functionName, arguments)
except SmnpException as e:
e.pos = functionCall.pos
raise e
@classmethod
def evaluator(cls, node, environment):
name = node.name.value
arguments = abstractIterableEvaluator(expressionEvaluator(True))(node.arguments, environment)
return environment.invokeFunction(name, arguments)
#
# def evaluateFunctionDefinition(definition, environment):
# name = definition.name
# params = list([p for p in flatListNode(definition.parameters)])
# body = definition.body
#
# if not isinstance(definition.parent, Program):
# raise RuntimeException(f"Functions can be defined only on the top level of script", name.pos)
#
# for p in params:
# if not isinstance(p, IdentifierNode):
# raise RuntimeException("Parameter of function definition must be an identifier", p.pos, )
#
# if name.identifier in environment.customFunctions or name.identifier in environment.functions:
# raise RuntimeException(f"Function '{name.identifier}' already exists", name.pos)
#
# environment.customFunctions[name.identifier] = {
# 'params': params,
# 'body': flatListNode(body)
# }
#
#
# def evaluateFunctionCall(functionCall, environment):
# try:
# functionName = functionCall.identifier.identifier
# arguments = evaluateList(functionCall.arguments, environment).value
# return environment.invokeFunction(functionName, arguments)
# except SmnpException as e:
# e.pos = functionCall.pos
# raise e
# def evaluateFunctionCall(functionCall, environment):

View File

@@ -1,5 +1,5 @@
from smnp.runtime.evaluator import Evaluator
from smnp.runtime.evaluators.expression import evaluateExpression
from smnp.runtime.evaluators.expression import expressionEvaluator
from smnp.runtime.evaluators.iterable import abstractIterableEvaluator
from smnp.type.model import Type
from smnp.type.value import Value
@@ -9,5 +9,5 @@ class ListEvaluator(Evaluator):
@classmethod
def evaluator(cls, node, environment):
list = abstractIterableEvaluator(evaluateExpression)(node, environment)
list = abstractIterableEvaluator(expressionEvaluator(doAssert=True))(node, environment)
return Value(Type.LIST, list)