Enable invoking builtin methods

This commit is contained in:
Bartłomiej Pluta
2019-07-08 17:15:54 +02:00
parent 8b7e1432b6
commit d8cdafe293
3 changed files with 72 additions and 31 deletions

View File

@@ -12,16 +12,41 @@ class Environment():
self.customFunctions = [] self.customFunctions = []
self.customMethods = [] self.customMethods = []
def invokeMethod(self, name, object, args): def invokeMethod(self, object, name, args):
for method in self.methods: # TODO to działa tylko dla wbudowanych funkcji builtinMethodResult = self._invokeBuiltinMethod(object, name, args)
if builtinMethodResult[0]:
return builtinMethodResult[1]
customMethodResult = self._invokeCustomMethod(object, name, args)
if customMethodResult[0]:
return customMethodResult[1]
raise MethodNotFoundException(object.type, name)
def _invokeBuiltinMethod(self, object, name, args):
for method in self.methods:
if method.name == name: if method.name == name:
ret = method.call(self, [object, *args.value]) ret = method.call(self, [object, *args])
if ret is not None: if ret is not None:
return ret return (True, ret)
raise MethodNotFoundException(object.type, name) # TODO method not found
return (False, None)
def _invokeCustomMethod(self, object, name, args):
for function in self.customMethods:
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 invokeFunction(self, name, args): def invokeFunction(self, name, args):
builtinFunctionResult = self._invokeFunction(name, args) builtinFunctionResult = self._invokeBuiltinFunction(name, args)
if builtinFunctionResult[0]: if builtinFunctionResult[0]:
return builtinFunctionResult[1] return builtinFunctionResult[1]
@@ -31,7 +56,7 @@ class Environment():
raise FunctionNotFoundException(name) raise FunctionNotFoundException(name)
def _invokeFunction(self, name, args): def _invokeBuiltinFunction(self, name, args):
for function in self.functions: for function in self.functions:
if function.name == name: if function.name == name:
ret = function.call(self, args) ret = function.call(self, args)
@@ -45,7 +70,6 @@ class Environment():
if function.name == name: if function.name == name:
signatureCheckresult = function.signature.check(args) signatureCheckresult = function.signature.check(args)
if signatureCheckresult[0]: if signatureCheckresult[0]:
self.scopes.append({ argName: argValue for argName, argValue in zip(function.arguments, args) }) 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 result = BodyEvaluator.evaluate(function.body, self).value #TODO check if it isn't necessary to verify 'result' attr of EvaluatioNResult
self.scopes.pop(-1) self.scopes.pop(-1)

View File

@@ -1,32 +1,46 @@
from smnp.ast.node.access import AccessNode from smnp.ast.node.identifier import IdentifierNode
from smnp.ast.node.function import FunctionCallNode from smnp.ast.node.invocation import FunctionCallNode
from smnp.error.base import SmnpException from smnp.runtime.evaluator import Evaluator
from smnp.error.runtime import RuntimeException from smnp.runtime.evaluators.expression import expressionEvaluator
from smnp.runtime.evaluator import evaluate from smnp.runtime.evaluators.iterable import abstractIterableEvaluator
from smnp.runtime.evaluators.list import evaluateList
def evaluateAccess(access, environment): class AccessEvaluator(Evaluator):
element = evaluate(access.element, environment)
if type(access.property) == FunctionCallNode:
return evaluateMethodCall(element, access.property, environment)
if type(access.property) == AccessNode:
return evaluateAccess(access.property, environment)
raise RuntimeException("Not implemented yet", access.property.pos) @classmethod
# TODO only methods can be handled so far def evaluator(cls, node, environment):
left = expressionEvaluator(doAssert=True)(node.left, environment).value #TODO check if it isn't necessary to verify 'result' attr of EvaluatioNResult
right = node.right
if type(node.right) == IdentifierNode:
raise RuntimeError("Accessing properties is not implemented yet")
def evaluateMethodCall(element, methodCall, environment): if type(node.right) == FunctionCallNode:
try: arguments = abstractIterableEvaluator(expressionEvaluator(True))(right.arguments, environment)
methodName = methodCall.identifier.identifier return environment.invokeMethod(left, right.name.value, arguments)
arguments = evaluateList(methodCall.arguments, environment)
return environment.invokeMethod(methodName, element, arguments) #
# def evaluateAccess(access, environment):
except SmnpException as e: # element = evaluate(access.element, environment)
e.pos = methodCall.pos # if type(access.property) == FunctionCallNode:
raise e # return evaluateMethodCall(element, access.property, environment)
# if type(access.property) == AccessNode:
# return evaluateAccess(access.property, environment)
#
# raise RuntimeException("Not implemented yet", access.property.pos)
# # TODO only methods can be handled so far
#
#
# def evaluateMethodCall(element, methodCall, environment):
# try:
# methodName = methodCall.identifier.identifier
# arguments = evaluateList(methodCall.arguments, environment)
#
# return environment.invokeMethod(methodName, element, arguments)
#
# except SmnpException as e:
# e.pos = methodCall.pos
# raise e
# for name, library in environment.customFunctions.items(): # for name, library in environment.customFunctions.items():
# if funcName == name: # if funcName == name:
# if len(library['params']) != len(arguments): # if len(library['params']) != len(arguments):

View File

@@ -1,3 +1,4 @@
from smnp.ast.node.access import AccessNode
from smnp.ast.node.identifier import IdentifierNode from smnp.ast.node.identifier import IdentifierNode
from smnp.ast.node.integer import IntegerLiteralNode from smnp.ast.node.integer import IntegerLiteralNode
from smnp.ast.node.invocation import FunctionCallNode from smnp.ast.node.invocation import FunctionCallNode
@@ -18,6 +19,7 @@ def expressionEvaluator(doAssert=False):
from smnp.runtime.evaluators.list import ListEvaluator from smnp.runtime.evaluators.list import ListEvaluator
from smnp.runtime.evaluators.function import FunctionCallEvaluator from smnp.runtime.evaluators.function import FunctionCallEvaluator
from smnp.runtime.evaluators.access import AccessEvaluator
result = Evaluator.oneOf( result = Evaluator.oneOf(
Evaluator.forNodes(FunctionCallEvaluator.evaluate, FunctionCallNode), Evaluator.forNodes(FunctionCallEvaluator.evaluate, FunctionCallNode),
Evaluator.forNodes(StringEvaluator.evaluate, StringLiteralNode), Evaluator.forNodes(StringEvaluator.evaluate, StringLiteralNode),
@@ -25,6 +27,7 @@ def expressionEvaluator(doAssert=False):
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(AccessEvaluator.evaluate, AccessNode)
)(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: