Add call stack to RuntimeException based errors
This commit is contained in:
@@ -27,9 +27,7 @@ class Environment():
|
||||
def _invokeBuiltinMethod(self, object, name, args):
|
||||
for method in self.methods:
|
||||
if method.name == name:
|
||||
self.callStack.append(CallStackItem(name))
|
||||
ret = method.call(self, [object, *args])
|
||||
self.callStack.pop(-1)
|
||||
if ret is not None:
|
||||
return (True, ret)
|
||||
|
||||
@@ -65,9 +63,7 @@ class Environment():
|
||||
def _invokeBuiltinFunction(self, name, args):
|
||||
for function in self.functions:
|
||||
if function.name == name:
|
||||
self.callStack.append(CallStackItem(name))
|
||||
ret = function.call(self, args)
|
||||
self.callStack.pop(-1)
|
||||
if ret is not None:
|
||||
return (True, ret)
|
||||
|
||||
|
||||
@@ -6,8 +6,11 @@ class SmnpException(Exception):
|
||||
def _title(self):
|
||||
pass
|
||||
|
||||
def _postMessage(self):
|
||||
return ""
|
||||
|
||||
def _position(self):
|
||||
return "" if self.pos is None else f" [line {self.pos[0]+1}, col {self.pos[1]+1}]"
|
||||
|
||||
def message(self):
|
||||
return f"{self._title()}{self._position()}:\n{self.msg}"
|
||||
return f"{self._title()}{self._position()}:\n{self.msg}\n{self._postMessage()}"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
from smnp.error.base import SmnpException
|
||||
from smnp.error.runtime import RuntimeException
|
||||
|
||||
|
||||
class IllegalFunctionInvocationException(SmnpException):
|
||||
class IllegalFunctionInvocationException(RuntimeException):
|
||||
def __init__(self, expected, found, pos=None):
|
||||
super().__init__(f"Expected signature:\n{expected}\n\nFound:\n{found}", pos)
|
||||
|
||||
@@ -9,7 +9,7 @@ class IllegalFunctionInvocationException(SmnpException):
|
||||
return "Invocation Error"
|
||||
|
||||
|
||||
class FunctionNotFoundException(SmnpException):
|
||||
class FunctionNotFoundException(RuntimeException):
|
||||
def __init__(self, function, pos=None):
|
||||
super().__init__(f"Function '{function}' not found", pos)
|
||||
|
||||
@@ -17,7 +17,7 @@ class FunctionNotFoundException(SmnpException):
|
||||
return "Invocation Error"
|
||||
|
||||
|
||||
class MethodNotFoundException(SmnpException):
|
||||
class MethodNotFoundException(RuntimeException):
|
||||
def __init__(self, object, method, pos=None):
|
||||
super().__init__(f"Method '{method}' of type '{object}' not found", pos)
|
||||
|
||||
@@ -25,7 +25,7 @@ class MethodNotFoundException(SmnpException):
|
||||
return "Invocation Error"
|
||||
|
||||
|
||||
class IllegalArgumentException(SmnpException):
|
||||
class IllegalArgumentException(RuntimeException):
|
||||
def __init__(self, msg, pos=None):
|
||||
super().__init__(msg, pos)
|
||||
|
||||
|
||||
@@ -9,6 +9,9 @@ class RuntimeException(SmnpException):
|
||||
def _title(self):
|
||||
return "Runtime Error"
|
||||
|
||||
def _postMessage(self):
|
||||
return "\n" + self.environment.callStackToString() if len(self.environment.callStack) > 0 else ""
|
||||
|
||||
# def message(self):
|
||||
# posStr = "" if self.pos is None else f" [line {self.pos[0] + 1}, col {self.pos[1] + 1}]"
|
||||
# return f"Runtime error{posStr}:\n{self.mmsg}"
|
||||
|
||||
@@ -19,9 +19,13 @@ class Function:
|
||||
return f"{self.name}{self.signature.string}"
|
||||
|
||||
def call(self, env, args):
|
||||
from smnp.environment.environment import CallStackItem
|
||||
|
||||
result = self.signature.check(args)
|
||||
if result[0]:
|
||||
env.callStack.append(CallStackItem(self.name))
|
||||
ret = self.function(env, *result[1:])
|
||||
env.callStack.pop(-1)
|
||||
if ret is None:
|
||||
return Type.void()
|
||||
return ret
|
||||
@@ -38,10 +42,14 @@ class CombinedFunction(Function):
|
||||
return "\nor\n".join([f"{self.name}{function.signature.string}" for function in self.functions])
|
||||
|
||||
def call(self, env, args):
|
||||
from smnp.environment.environment import CallStackItem
|
||||
|
||||
for function in self.functions:
|
||||
result = function.signature.check(args)
|
||||
if result[0]:
|
||||
env.callStack.append(CallStackItem(self.name))
|
||||
ret = function.function(env, *result[1:])
|
||||
env.callStack.pop(-1)
|
||||
if ret is None:
|
||||
return Type.void()
|
||||
return ret
|
||||
|
||||
@@ -2,9 +2,9 @@ from smnp.error.function import IllegalArgumentException
|
||||
from smnp.function.model import Function
|
||||
from smnp.function.signature import signature
|
||||
from smnp.type.model import Type
|
||||
from smnp.type.signature.matcher.type import ofTypes
|
||||
from smnp.type.signature.matcher.type import ofType
|
||||
|
||||
_signature = signature(ofTypes(Type.STRING))
|
||||
_signature = signature(ofType(Type.STRING))
|
||||
def _function(env, parameter):
|
||||
if parameter.value == "environment":
|
||||
print(env)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from smnp.ast.parser import parse
|
||||
from smnp.environment.factory import createEnvironment
|
||||
from smnp.error.runtime import RuntimeException
|
||||
from smnp.program.FileReader import readLines
|
||||
from smnp.runtime.evaluator import evaluate
|
||||
from smnp.token.tokenizer import tokenize
|
||||
@@ -9,18 +10,22 @@ class Interpreter:
|
||||
|
||||
@staticmethod
|
||||
def interpretFile(file, printTokens=False, printAst=False):
|
||||
lines = readLines(file)
|
||||
|
||||
tokens = tokenize(lines)
|
||||
if printTokens:
|
||||
print(tokens)
|
||||
|
||||
ast = parse(tokens)
|
||||
if printAst:
|
||||
ast.print()
|
||||
|
||||
environment = createEnvironment()
|
||||
|
||||
evaluate(ast, environment)
|
||||
try:
|
||||
lines = readLines(file)
|
||||
|
||||
return environment
|
||||
tokens = tokenize(lines)
|
||||
if printTokens:
|
||||
print(tokens)
|
||||
|
||||
ast = parse(tokens)
|
||||
if printAst:
|
||||
ast.print()
|
||||
|
||||
evaluate(ast, environment)
|
||||
|
||||
return environment
|
||||
except RuntimeException as e:
|
||||
e.environment = environment
|
||||
raise e
|
||||
Reference in New Issue
Block a user