Enable checking matching optional arguments with declared types

This commit is contained in:
Bartłomiej Pluta
2019-07-14 00:10:20 +02:00
parent 460deb4981
commit c5435e66ff
4 changed files with 27 additions and 11 deletions

View File

@@ -3,7 +3,7 @@ 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, optional
from smnp.runtime.evaluators.expression import expressionEvaluator
from smnp.runtime.evaluators.expression import expressionEvaluator, expressionEvaluatorWithMatcher
from smnp.runtime.tools.error import updatePos
from smnp.type.model import Type
from smnp.type.signature.matcher.list import listOfMatchers
@@ -13,15 +13,17 @@ 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):
def argumentsNodeToMethodSignature(node, environment):
try:
sign = []
vararg = None
argumentsCount = len(node.children)
checkPositionOfOptionalArguments(node)
defaultArgs = {}
for i, child in enumerate(node.children):
matchers = {
ast.Type: (lambda c: c.type, typeMatcher),
@@ -29,17 +31,22 @@ def argumentsNodeToMethodSignature(node):
TypesList: (lambda c: c, multipleTypeMatcher)
}
evaluatedMatcher = matchers[type(child.type)][1](matchers[type(child.type)][0](child))
if child.vararg:
if i != argumentsCount - 1:
raise RuntimeException("Vararg must be the last argument in signature", child.pos)
vararg = evaluatedMatcher
else:
if type(child.optionalValue) != NoneNode:
defaultArgs[child.variable.value] = expressionEvaluatorWithMatcher(
evaluatedMatcher,
exceptionProvider=lambda value: RuntimeException(
f"Value '{value.stringify()}' doesn't match declared type: {evaluatedMatcher.string}", child.optionalValue.pos)
)(child.optionalValue, environment)
evaluatedMatcher = optional(evaluatedMatcher)
sign.append(evaluatedMatcher)
return varargSignature(vararg, *sign, wrapVarargInValue=True) if vararg is not None else signature(*sign)
return defaultArgs, (varargSignature(vararg, *sign, wrapVarargInValue=True) if vararg is not None else signature(*sign))
except RuntimeException as e:
raise updatePos(e, node)