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.node.model import Node
|
||||||
from smnp.ast.parser import Parser
|
from smnp.ast.parser import Parser
|
||||||
from smnp.token.type import TokenType
|
from smnp.token.type import TokenType
|
||||||
|
from smnp.type.model import Type
|
||||||
|
|
||||||
|
|
||||||
class TypeSpecifier(Node):
|
class TypeSpecifier(Node):
|
||||||
@@ -44,7 +45,7 @@ class TypeNode(AccessNode):
|
|||||||
def _parse(cls, input):
|
def _parse(cls, input):
|
||||||
def createNode(type, specifier):
|
def createNode(type, specifier):
|
||||||
node = TypeNode(type.pos)
|
node = TypeNode(type.pos)
|
||||||
node.type = type.value
|
node.type = Type[type.value.upper()]
|
||||||
node.specifier = specifier
|
node.specifier = specifier
|
||||||
return node
|
return node
|
||||||
|
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ class Environment():
|
|||||||
self.scopes = scopes
|
self.scopes = scopes
|
||||||
self.functions = functions
|
self.functions = functions
|
||||||
self.methods = methods
|
self.methods = methods
|
||||||
self.customFunctions = {}
|
self.customFunctions = []
|
||||||
self.callStack = [] #TODO remove
|
self.customMethods = []
|
||||||
|
|
||||||
def invokeMethod(self, name, object, args):
|
def invokeMethod(self, name, object, args):
|
||||||
for method in self.methods: # TODO to działa tylko dla wbudowanych funkcji
|
for method in self.methods: # TODO to działa tylko dla wbudowanych funkcji
|
||||||
@@ -27,6 +27,9 @@ class Environment():
|
|||||||
raise FunctionNotFoundException(name)
|
raise FunctionNotFoundException(name)
|
||||||
# TODO raise nie znaleziono funkcji
|
# 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):
|
def findVariable(self, name, type=None, pos=None):
|
||||||
for scope in reversed(self.scopes):
|
for scope in reversed(self.scopes):
|
||||||
if name in scope:
|
if name in scope:
|
||||||
@@ -54,12 +57,26 @@ class Environment():
|
|||||||
def functionsToString(self):
|
def functionsToString(self):
|
||||||
return "Functions:\n" + ("\n".join([ f" {function.name}(...)" for function in self.functions ]))
|
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):
|
def methodsToString(self):
|
||||||
return "Methods:\n" + ("\n".join([f" {function.name}(...)" for function in self.methods]))
|
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):
|
def __str__(self):
|
||||||
return self.scopesToString() + self.functionsToString() + self.methodsToString()
|
return self.scopesToString() + self.functionsToString() + self.methodsToString() + self.customFunctionsToString() + self.customMethodsToString()
|
||||||
|
|
||||||
def __repr__(self):
|
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 value.type in types
|
||||||
return Matcher(None, check, f"<{', '.join([t.name.lower() for t 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 listOf(*types):
|
||||||
def check(value):
|
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])}>")
|
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 listMatches(*pattern):
|
||||||
def check(value):
|
def check(value):
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
from smnp.ast.node.function import FunctionDefinitionNode
|
||||||
from smnp.ast.node.program import Program
|
from smnp.ast.node.program import Program
|
||||||
from smnp.error.runtime import RuntimeException
|
from smnp.error.runtime import RuntimeException
|
||||||
from smnp.type.model import Type
|
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.program import ProgramEvaluator
|
||||||
from smnp.runtime.evaluators.expression import expressionEvaluator
|
from smnp.runtime.evaluators.expression import expressionEvaluator
|
||||||
|
|
||||||
|
from smnp.runtime.evaluators.function import FunctionDefinitionEvaluator
|
||||||
result = Evaluator.oneOf(
|
result = Evaluator.oneOf(
|
||||||
Evaluator.forNodes(ProgramEvaluator.evaluate, Program),
|
Evaluator.forNodes(ProgramEvaluator.evaluate, Program),
|
||||||
|
Evaluator.forNodes(FunctionDefinitionEvaluator.evaluate, FunctionDefinitionNode),
|
||||||
expressionEvaluator()
|
expressionEvaluator()
|
||||||
)(node, environment)
|
)(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.evaluator import Evaluator
|
||||||
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
|
||||||
|
|
||||||
|
|
||||||
class FunctionCallEvaluator(Evaluator):
|
class FunctionCallEvaluator(Evaluator):
|
||||||
@@ -10,6 +14,48 @@ class FunctionCallEvaluator(Evaluator):
|
|||||||
name = node.name.value
|
name = node.name.value
|
||||||
arguments = abstractIterableEvaluator(expressionEvaluator(True))(node.arguments, environment)
|
arguments = abstractIterableEvaluator(expressionEvaluator(True))(node.arguments, environment)
|
||||||
return environment.invokeFunction(name, arguments)
|
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):
|
# def evaluateFunctionDefinition(definition, environment):
|
||||||
# name = definition.name
|
# name = definition.name
|
||||||
|
|||||||
Reference in New Issue
Block a user