Create evaluator for custom functions definition (but invocation doesn't work yet)
This commit is contained in:
@@ -3,6 +3,7 @@ from smnp.ast.node.iterable import abstractIterableParser
|
||||
from smnp.ast.node.model import Node
|
||||
from smnp.ast.parser import Parser
|
||||
from smnp.token.type import TokenType
|
||||
from smnp.type.model import Type
|
||||
|
||||
|
||||
class TypeSpecifier(Node):
|
||||
@@ -44,7 +45,7 @@ class TypeNode(AccessNode):
|
||||
def _parse(cls, input):
|
||||
def createNode(type, specifier):
|
||||
node = TypeNode(type.pos)
|
||||
node.type = type.value
|
||||
node.type = Type[type.value.upper()]
|
||||
node.specifier = specifier
|
||||
return node
|
||||
|
||||
|
||||
@@ -7,8 +7,8 @@ class Environment():
|
||||
self.scopes = scopes
|
||||
self.functions = functions
|
||||
self.methods = methods
|
||||
self.customFunctions = {}
|
||||
self.callStack = [] #TODO remove
|
||||
self.customFunctions = []
|
||||
self.customMethods = []
|
||||
|
||||
def invokeMethod(self, name, object, args):
|
||||
for method in self.methods: # TODO to działa tylko dla wbudowanych funkcji
|
||||
@@ -27,6 +27,9 @@ class Environment():
|
||||
raise FunctionNotFoundException(name)
|
||||
# TODO raise nie znaleziono funkcji
|
||||
|
||||
def addCustomFunction(self, name, signature, arguments, body):
|
||||
self.customFunctions.append(CustomFunction(name, signature, arguments, body))
|
||||
|
||||
def findVariable(self, name, type=None, pos=None):
|
||||
for scope in reversed(self.scopes):
|
||||
if name in scope:
|
||||
@@ -54,12 +57,26 @@ class Environment():
|
||||
def functionsToString(self):
|
||||
return "Functions:\n" + ("\n".join([ f" {function.name}(...)" for function in self.functions ]))
|
||||
|
||||
def customFunctionsToString(self):
|
||||
return "Custom Functions:\n" + ("\n".join([ f" {function.name}(...)" for function in self.customFunctions ]))
|
||||
|
||||
def methodsToString(self):
|
||||
return "Methods:\n" + ("\n".join([f" {function.name}(...)" for function in self.methods]))
|
||||
|
||||
def customMethodsToString(self):
|
||||
return "Custom Methods:\n" + ("\n".join([ f" {function.name}(...)" for function in self.customMethods ]))
|
||||
|
||||
|
||||
def __str__(self):
|
||||
return self.scopesToString() + self.functionsToString() + self.methodsToString()
|
||||
return self.scopesToString() + self.functionsToString() + self.methodsToString() + self.customFunctionsToString() + self.customMethodsToString()
|
||||
|
||||
def __repr__(self):
|
||||
return self.__str__()
|
||||
return self.__str__()
|
||||
|
||||
|
||||
class CustomFunction:
|
||||
def __init__(self, name, signature, arguments, body):
|
||||
self.name = name
|
||||
self.signature = signature
|
||||
self.arguments = arguments
|
||||
self.body = body
|
||||
@@ -94,6 +94,11 @@ def ofTypes(*types):
|
||||
return value.type in types
|
||||
return Matcher(None, check, f"<{', '.join([t.name.lower() for t in types])}>")
|
||||
|
||||
def ofType(type):
|
||||
def check(value):
|
||||
return value.type == type
|
||||
|
||||
return Matcher(None, check, type.name.lower())
|
||||
|
||||
def listOf(*types):
|
||||
def check(value):
|
||||
@@ -101,6 +106,15 @@ def listOf(*types):
|
||||
|
||||
return Matcher(Type.LIST, check, f"{Type.LIST.name.lower()}<{', '.join([t.name.lower() for t in types])}>")
|
||||
|
||||
def listOfMatchers(*matchers):
|
||||
def check(value):
|
||||
matched = 0
|
||||
for item in value.value:
|
||||
matched += 1 if any(matcher.match(item) for matcher in matchers) else 0
|
||||
|
||||
return matched == len(value.value)
|
||||
|
||||
return Matcher(Type.LIST, check, f"{Type.LIST.name.lower()}<{', '.join([m.string for m in matchers])}>")
|
||||
|
||||
def listMatches(*pattern):
|
||||
def check(value):
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
from smnp.ast.node.function import FunctionDefinitionNode
|
||||
from smnp.ast.node.program import Program
|
||||
from smnp.error.runtime import RuntimeException
|
||||
from smnp.type.model import Type
|
||||
@@ -66,8 +67,10 @@ def evaluate(node, environment):
|
||||
from smnp.runtime.evaluators.program import ProgramEvaluator
|
||||
from smnp.runtime.evaluators.expression import expressionEvaluator
|
||||
|
||||
from smnp.runtime.evaluators.function import FunctionDefinitionEvaluator
|
||||
result = Evaluator.oneOf(
|
||||
Evaluator.forNodes(ProgramEvaluator.evaluate, Program),
|
||||
Evaluator.forNodes(FunctionDefinitionEvaluator.evaluate, FunctionDefinitionNode),
|
||||
expressionEvaluator()
|
||||
)(node, environment)
|
||||
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
from smnp.ast.node.none import NoneNode
|
||||
from smnp.ast.node.variable import TypedVariableNode
|
||||
from smnp.library.signature import signature, listOfMatchers, ofType
|
||||
from smnp.runtime.evaluator import Evaluator
|
||||
from smnp.runtime.evaluators.expression import expressionEvaluator
|
||||
from smnp.runtime.evaluators.iterable import abstractIterableEvaluator
|
||||
from smnp.type.model import Type
|
||||
|
||||
|
||||
class FunctionCallEvaluator(Evaluator):
|
||||
@@ -10,6 +14,48 @@ class FunctionCallEvaluator(Evaluator):
|
||||
name = node.name.value
|
||||
arguments = abstractIterableEvaluator(expressionEvaluator(True))(node.arguments, environment)
|
||||
return environment.invokeFunction(name, arguments)
|
||||
|
||||
|
||||
class FunctionDefinitionEvaluator(Evaluator):
|
||||
|
||||
@classmethod
|
||||
def evaluator(cls, node, environment):
|
||||
name = node.name.value
|
||||
signature = argumentsNodeToMethodSignature(node.arguments)
|
||||
arguments = [ arg.variable.value for arg in node.arguments ]
|
||||
body = node.body
|
||||
environment.addCustomFunction(name, signature, arguments, body)
|
||||
|
||||
|
||||
def argumentsNodeToMethodSignature(node):
|
||||
sign = []
|
||||
|
||||
for child in node.children:
|
||||
if type(child) == TypedVariableNode:
|
||||
if type(child.type.specifier) == NoneNode:
|
||||
sign.append(ofType(child.type.type))
|
||||
elif child.type.type == Type.LIST:
|
||||
sign.append(listSpecifier(child.type.specifier))
|
||||
|
||||
return signature(*sign)
|
||||
|
||||
|
||||
def listSpecifier(specifier):
|
||||
subSignature = []
|
||||
|
||||
for child in specifier.children:
|
||||
if type(child.specifier) == NoneNode:
|
||||
subSignature.append(ofType(child.type))
|
||||
elif child.type == Type.LIST:
|
||||
subSignature.append(listSpecifier(child.specifier))
|
||||
|
||||
return listOfMatchers(*subSignature)
|
||||
|
||||
|
||||
# if node.type.specifier is not NoneNode:
|
||||
# if Type[node.type.upper()] == Type.LIST:
|
||||
# return listOf([])
|
||||
|
||||
#
|
||||
# def evaluateFunctionDefinition(definition, environment):
|
||||
# name = definition.name
|
||||
|
||||
Reference in New Issue
Block a user