Enforce checking function and method names if they're exist before creating new ones
This commit is contained in:
@@ -79,9 +79,27 @@ class Environment():
|
||||
return (False, None)
|
||||
|
||||
def addCustomFunction(self, name, signature, arguments, body):
|
||||
if len([fun for fun in self.functions + self.customFunctions if fun.name == name]) > 0:
|
||||
raise RuntimeException(f"Cannot redeclare function '{name}'", None)
|
||||
|
||||
self.customFunctions.append(CustomFunction(name, signature, arguments, body))
|
||||
|
||||
# TODO:
|
||||
# There is still problem with checking existing of generic types, like lists:
|
||||
# extend list as l {
|
||||
# function foo() { return 1 }
|
||||
# }
|
||||
# extend list<integer> as l {
|
||||
# function foo() { return 2 }
|
||||
# }
|
||||
# Then calling [1, 2, 3, 4].foo() will produce 1, when the second method is more suitable
|
||||
def addCustomMethod(self, typeSignature, alias, name, signature, arguments, body):
|
||||
if len([m for m in self.methods if m.name == name and m.signature.matchers[0] == typeSignature.matchers[0]]) > 0:
|
||||
raise RuntimeException(f"Cannot redeclare method '{name}' for type '{typeSignature.matchers[0]}'", None)
|
||||
|
||||
if len([m for m in self.customMethods if m.name == name and m.typeSignature.matchers[0] == typeSignature.matchers[0]]) > 0:
|
||||
raise RuntimeException(f"Cannot redeclare method '{name}' for type '{typeSignature.matchers[0]}'", None)
|
||||
|
||||
self.customMethods.append(CustomMethod(typeSignature, alias, name, signature, arguments, body))
|
||||
|
||||
def findVariable(self, name, type=None, pos=None):
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
from smnp.library.model import Function
|
||||
from smnp.library.signature import signature, ofTypes
|
||||
from smnp.library.signature import signature, ofType
|
||||
from smnp.type.model import Type
|
||||
|
||||
_signature = signature(ofTypes(Type.NOTE), ofTypes(Type.INTEGER))
|
||||
_signature = signature(ofType(Type.NOTE), ofType(Type.INTEGER))
|
||||
def _function(env, note, duration):
|
||||
return Type.note(note.value.withDuration(duration.value))
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
from smnp.library.model import Function
|
||||
from smnp.library.signature import signature, ofTypes
|
||||
from smnp.library.signature import signature, ofType
|
||||
from smnp.type.model import Type
|
||||
|
||||
_signature = signature(ofTypes(Type.NOTE), ofTypes(Type.INTEGER))
|
||||
_signature = signature(ofType(Type.NOTE), ofType(Type.INTEGER))
|
||||
def _function(env, note, octave):
|
||||
return Type.note(note.value.withOctave(octave.value))
|
||||
|
||||
|
||||
@@ -24,6 +24,9 @@ class Matcher:
|
||||
string = f"[{self.string} or {matcher.string}]"
|
||||
return Matcher(None, lambda x: self.match(x) or matcher.match(x), string)
|
||||
|
||||
def __eq__(self, other):
|
||||
return self.type == other.type and self.string == other.string
|
||||
|
||||
|
||||
|
||||
def __str__(self):
|
||||
@@ -34,9 +37,10 @@ class Matcher:
|
||||
|
||||
|
||||
class Signature:
|
||||
def __init__(self, check, string):
|
||||
def __init__(self, check, string, matchers):
|
||||
self.check = check
|
||||
self.string = string
|
||||
self.matchers = matchers
|
||||
|
||||
|
||||
def varargSignature(varargMatcher, *basicSignature):
|
||||
@@ -56,7 +60,7 @@ def varargSignature(varargMatcher, *basicSignature):
|
||||
|
||||
string = f"({', '.join([str(m) for m in basicSignature])}{', ' if len(basicSignature) > 0 else ''}{str(varargMatcher)}...)"
|
||||
|
||||
return Signature(check, string)
|
||||
return Signature(check, string, [varargMatcher, *basicSignature])
|
||||
|
||||
|
||||
def doesNotMatchVararg(basicSignature):
|
||||
@@ -77,7 +81,7 @@ def signature(*signature):
|
||||
|
||||
string = f"({', '.join([str(m) for m in signature])})"
|
||||
|
||||
return Signature(check, string)
|
||||
return Signature(check, string, signature)
|
||||
|
||||
|
||||
def doesNotMatch(sign):
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
from smnp.ast.node.none import NoneNode
|
||||
from smnp.ast.node.ret import ReturnNode
|
||||
from smnp.ast.node.variable import TypedVariableNode
|
||||
from smnp.error.runtime import RuntimeException
|
||||
from smnp.library.signature import signature, listOfMatchers, ofType
|
||||
from smnp.runtime.evaluator import Evaluator, evaluate
|
||||
from smnp.runtime.evaluators.expression import expressionEvaluator
|
||||
@@ -21,11 +22,15 @@ 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)
|
||||
try:
|
||||
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)
|
||||
except RuntimeException as e:
|
||||
e.pos = node.pos
|
||||
raise e
|
||||
|
||||
|
||||
def argumentsNodeToMethodSignature(node):
|
||||
|
||||
Reference in New Issue
Block a user