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.customMethods = []
def invokeMethod(self, name, object, args):
for method in self.methods: # TODO to działa tylko dla wbudowanych funkcji
def invokeMethod(self, object, name, args):
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:
ret = method.call(self, [object, *args.value])
ret = method.call(self, [object, *args])
if ret is not None:
return ret
raise MethodNotFoundException(object.type, name) # TODO method not found
return (True, ret)
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):
builtinFunctionResult = self._invokeFunction(name, args)
builtinFunctionResult = self._invokeBuiltinFunction(name, args)
if builtinFunctionResult[0]:
return builtinFunctionResult[1]
@@ -31,7 +56,7 @@ class Environment():
raise FunctionNotFoundException(name)
def _invokeFunction(self, name, args):
def _invokeBuiltinFunction(self, name, args):
for function in self.functions:
if function.name == name:
ret = function.call(self, args)
@@ -45,7 +70,6 @@ class Environment():
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)

View File

@@ -1,32 +1,46 @@
from smnp.ast.node.access import AccessNode
from smnp.ast.node.function import FunctionCallNode
from smnp.error.base import SmnpException
from smnp.error.runtime import RuntimeException
from smnp.runtime.evaluator import evaluate
from smnp.runtime.evaluators.list import evaluateList
from smnp.ast.node.identifier import IdentifierNode
from smnp.ast.node.invocation import FunctionCallNode
from smnp.runtime.evaluator import Evaluator
from smnp.runtime.evaluators.expression import expressionEvaluator
from smnp.runtime.evaluators.iterable import abstractIterableEvaluator
def evaluateAccess(access, environment):
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)
class AccessEvaluator(Evaluator):
raise RuntimeException("Not implemented yet", access.property.pos)
# TODO only methods can be handled so far
@classmethod
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):
try:
methodName = methodCall.identifier.identifier
arguments = evaluateList(methodCall.arguments, environment)
if type(node.right) == FunctionCallNode:
arguments = abstractIterableEvaluator(expressionEvaluator(True))(right.arguments, environment)
return environment.invokeMethod(left, right.name.value, arguments)
return environment.invokeMethod(methodName, element, arguments)
except SmnpException as e:
e.pos = methodCall.pos
raise e
#
# def evaluateAccess(access, environment):
# 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)
# # 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():
# if funcName == name:
# 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.integer import IntegerLiteralNode
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.function import FunctionCallEvaluator
from smnp.runtime.evaluators.access import AccessEvaluator
result = Evaluator.oneOf(
Evaluator.forNodes(FunctionCallEvaluator.evaluate, FunctionCallNode),
Evaluator.forNodes(StringEvaluator.evaluate, StringLiteralNode),
@@ -25,6 +27,7 @@ def expressionEvaluator(doAssert=False):
Evaluator.forNodes(NoteEvaluator.evaluate, NoteLiteralNode),
Evaluator.forNodes(IdentifierEvaluator.evaluate, IdentifierNode),
Evaluator.forNodes(ListEvaluator.evaluate, ListNode),
Evaluator.forNodes(AccessEvaluator.evaluate, AccessNode)
)(node, environment)
if doAssert and result.result and result.value.type == Type.VOID: