Enforce checking function and method names if they're exist before creating new ones

This commit is contained in:
Bartłomiej Pluta
2019-07-08 22:53:32 +02:00
parent d4b4aa48ee
commit a3dfae73f1
5 changed files with 39 additions and 12 deletions

View File

@@ -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):

View File

@@ -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))

View File

@@ -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))

View File

@@ -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):

View File

@@ -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):