Create evaluator for custom functions definition (but invocation doesn't work yet)

This commit is contained in:
Bartłomiej Pluta
2019-07-08 15:36:13 +02:00
parent 1e634180d6
commit 606d93c319
5 changed files with 86 additions and 5 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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):

View File

@@ -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)

View File

@@ -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