Enable executing custom functions

This commit is contained in:
Bartłomiej Pluta
2019-07-08 16:01:20 +02:00
parent 606d93c319
commit 8b7e1432b6
4 changed files with 49 additions and 9 deletions

View File

@@ -1,5 +1,7 @@
from smnp.error.function import FunctionNotFoundException, MethodNotFoundException from smnp.error.function import FunctionNotFoundException, MethodNotFoundException, IllegalFunctionInvocationException
from smnp.error.runtime import RuntimeException from smnp.error.runtime import RuntimeException
from smnp.library.model import types
from smnp.runtime.evaluators.function import BodyEvaluator
class Environment(): class Environment():
@@ -19,13 +21,37 @@ class Environment():
raise MethodNotFoundException(object.type, name) # TODO method not found raise MethodNotFoundException(object.type, name) # TODO method not found
def invokeFunction(self, name, args): def invokeFunction(self, name, args):
for function in self.functions: # TODO to działa tylko dla wbudowanych funkcji builtinFunctionResult = self._invokeFunction(name, args)
if builtinFunctionResult[0]:
return builtinFunctionResult[1]
customFunctionResult = self._invokeCustomFunction(name, args)
if customFunctionResult[0]:
return customFunctionResult[1]
raise FunctionNotFoundException(name)
def _invokeFunction(self, name, args):
for function in self.functions:
if function.name == name: if function.name == name:
ret = function.call(self, args) ret = function.call(self, args)
if ret is not None: if ret is not None:
return ret return (True, ret)
raise FunctionNotFoundException(name)
# TODO raise nie znaleziono funkcji return (False, None)
def _invokeCustomFunction(self, name, args):
for function in self.customFunctions:
if function.name == name:
signatureCheckresult = function.signature.check(args)
if signatureCheckresult[0]:
self.scopes.append({ argName: argValue for argName, argValue in zip(function.arguments, args) })
result = BodyEvaluator.evaluate(function.body, self).value #TODO check if it isn't necessary to verify 'result' attr of EvaluatioNResult
self.scopes.pop(-1)
return (True, result)
raise IllegalFunctionInvocationException(f"{function.name}{function.signature.string}", f"{name}{types(args)}")
return (False, None)
def addCustomFunction(self, name, signature, arguments, body): def addCustomFunction(self, name, signature, arguments, body):
self.customFunctions.append(CustomFunction(name, signature, arguments, body)) self.customFunctions.append(CustomFunction(name, signature, arguments, body))

View File

@@ -59,10 +59,12 @@ def types(args):
return f"({', '.join(output)})" return f"({', '.join(output)})"
def listTypes(l, output=[]): def listTypes(l, output=None):
if output is None:
output = []
for item in l: for item in l:
if item.type == Type.LIST: if item.type == Type.LIST:
output.append(listTypes(item.value, [])) output.append(listTypes(item.value, []))
else: else:
output.append(item.type.name.lower()) output.append(item.type.name.lower())
return f"{Type.LIST.name.lower()}<{'|'.join(set(output))}>" return f"{Type.LIST.name.lower()}<{', '.join(set(output))}>"

View File

@@ -19,12 +19,12 @@ def expressionEvaluator(doAssert=False):
from smnp.runtime.evaluators.function import FunctionCallEvaluator from smnp.runtime.evaluators.function import FunctionCallEvaluator
result = Evaluator.oneOf( result = Evaluator.oneOf(
Evaluator.forNodes(FunctionCallEvaluator.evaluate, FunctionCallNode),
Evaluator.forNodes(StringEvaluator.evaluate, StringLiteralNode), Evaluator.forNodes(StringEvaluator.evaluate, StringLiteralNode),
Evaluator.forNodes(IntegerEvaluator.evaluate, IntegerLiteralNode), Evaluator.forNodes(IntegerEvaluator.evaluate, IntegerLiteralNode),
Evaluator.forNodes(NoteEvaluator.evaluate, NoteLiteralNode), Evaluator.forNodes(NoteEvaluator.evaluate, NoteLiteralNode),
Evaluator.forNodes(IdentifierEvaluator.evaluate, IdentifierNode), Evaluator.forNodes(IdentifierEvaluator.evaluate, IdentifierNode),
Evaluator.forNodes(ListEvaluator.evaluate, ListNode), Evaluator.forNodes(ListEvaluator.evaluate, ListNode),
Evaluator.forNodes(FunctionCallEvaluator.evaluate, FunctionCallNode)
)(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:

View File

@@ -1,7 +1,8 @@
from smnp.ast.node.none import NoneNode from smnp.ast.node.none import NoneNode
from smnp.ast.node.ret import ReturnNode
from smnp.ast.node.variable import TypedVariableNode from smnp.ast.node.variable import TypedVariableNode
from smnp.library.signature import signature, listOfMatchers, ofType from smnp.library.signature import signature, listOfMatchers, ofType
from smnp.runtime.evaluator import Evaluator from smnp.runtime.evaluator import Evaluator, evaluate
from smnp.runtime.evaluators.expression import expressionEvaluator from smnp.runtime.evaluators.expression import expressionEvaluator
from smnp.runtime.evaluators.iterable import abstractIterableEvaluator from smnp.runtime.evaluators.iterable import abstractIterableEvaluator
from smnp.type.model import Type from smnp.type.model import Type
@@ -52,6 +53,17 @@ def listSpecifier(specifier):
return listOfMatchers(*subSignature) return listOfMatchers(*subSignature)
class BodyEvaluator(Evaluator):
@classmethod
def evaluator(cls, node, environment):
for child in node.children:
if type(child) == ReturnNode:
x = expressionEvaluator(doAssert=True)(child.value, environment).value #TODO check if it isn't necessary to verify 'result' attr of EvaluatioNResult
return x
else:
evaluate(child, environment)
# if node.type.specifier is not NoneNode: # if node.type.specifier is not NoneNode:
# if Type[node.type.upper()] == Type.LIST: # if Type[node.type.upper()] == Type.LIST:
# return listOf([]) # return listOf([])