Create evaluators for optional arguments in function and method definitions

This commit is contained in:
Bartłomiej Pluta
2019-07-13 23:52:15 +02:00
parent 69bac69946
commit 460deb4981
6 changed files with 41 additions and 18 deletions

View File

@@ -1,7 +1,8 @@
from smnp.ast.node.none import NoneNode
from smnp.function.signature import signature
from smnp.runtime.evaluator import Evaluator
from smnp.runtime.tools.signature import argumentsNodeToMethodSignature, listSpecifier, mapSpecifier
from smnp.runtime.tools.signature import argumentsNodeToMethodSignature, listSpecifier, mapSpecifier, \
evaluateDefaultArguments
from smnp.type.model import Type
from smnp.type.signature.matcher.type import ofType
@@ -34,6 +35,7 @@ class ExtendEvaluator(Evaluator):
name = node.name.value
signature = argumentsNodeToMethodSignature(node.arguments)
arguments = [arg.variable.value for arg in node.arguments]
defaultArguments = evaluateDefaultArguments(node.arguments, environment)
body = node.body
environment.addCustomMethod(type, variable, name, signature, arguments, body)
environment.addCustomMethod(type, variable, name, signature, arguments, body, defaultArguments)

View File

@@ -3,7 +3,7 @@ from smnp.runtime.evaluator import Evaluator, evaluate
from smnp.runtime.evaluators.expression import expressionEvaluator
from smnp.runtime.evaluators.iterable import abstractIterableEvaluator
from smnp.runtime.tools.error import updatePos
from smnp.runtime.tools.signature import argumentsNodeToMethodSignature
from smnp.runtime.tools.signature import argumentsNodeToMethodSignature, evaluateDefaultArguments
from smnp.type.model import Type
@@ -27,8 +27,9 @@ class FunctionDefinitionEvaluator(Evaluator):
name = node.name.value
signature = argumentsNodeToMethodSignature(node.arguments)
arguments = [ arg.variable.value for arg in node.arguments ]
defaultArguments = evaluateDefaultArguments(node.arguments, environment)
body = node.body
environment.addCustomFunction(name, signature, arguments, body)
environment.addCustomFunction(name, signature, arguments, body, defaultArguments)
except RuntimeException as e:
raise updatePos(e, node)

View File

@@ -2,7 +2,8 @@ from smnp.ast.node import type as ast
from smnp.ast.node.none import NoneNode
from smnp.ast.node.type import TypesList
from smnp.error.runtime import RuntimeException
from smnp.function.signature import varargSignature, signature
from smnp.function.signature import varargSignature, signature, optional
from smnp.runtime.evaluators.expression import expressionEvaluator
from smnp.runtime.tools.error import updatePos
from smnp.type.model import Type
from smnp.type.signature.matcher.list import listOfMatchers
@@ -10,11 +11,17 @@ from smnp.type.signature.matcher.map import mapOfMatchers
from smnp.type.signature.matcher.type import allTypes, oneOf, ofType
def evaluateDefaultArguments(node, environment):
defaultValues = { arg.variable.value: expressionEvaluator(doAssert=True)(arg.optionalValue, environment).value for arg in node.children if type(arg.optionalValue) != NoneNode }
return defaultValues
def argumentsNodeToMethodSignature(node):
try:
sign = []
vararg = None
argumentsCount = len(node.children)
checkPositionOfOptionalArguments(node)
for i, child in enumerate(node.children):
matchers = {
ast.Type: (lambda c: c.type, typeMatcher),
@@ -27,6 +34,8 @@ def argumentsNodeToMethodSignature(node):
raise RuntimeException("Vararg must be the last argument in signature", child.pos)
vararg = evaluatedMatcher
else:
if type(child.optionalValue) != NoneNode:
evaluatedMatcher = optional(evaluatedMatcher)
sign.append(evaluatedMatcher)
@@ -35,6 +44,14 @@ def argumentsNodeToMethodSignature(node):
raise updatePos(e, node)
def checkPositionOfOptionalArguments(node):
firstOptional = next((i for i, v in enumerate(node.children) if type(v.optionalValue) != NoneNode), None) #next(filter(lambda arg: type(arg.optionalValue) != NoneNode, node.children), None)
if firstOptional is not None:
regularAfterOptional = next((i for i, v in enumerate(node.children[firstOptional:]) if type(v.optionalValue) == NoneNode), None)
if regularAfterOptional is not None:
raise RuntimeException(f"Optional arguments should be declared at the end of the arguments list", node.children[regularAfterOptional].pos)
def multipleTypeMatcher(typeNode):
subSignature = []