Enable executing custom functions
This commit is contained in:
@@ -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))
|
||||||
|
|||||||
@@ -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))}>"
|
||||||
@@ -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:
|
||||||
|
|||||||
@@ -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([])
|
||||||
|
|||||||
Reference in New Issue
Block a user