Code better in the morning
This commit is contained in:
parent
366440a3b9
commit
7f3efc882a
1 changed files with 62 additions and 44 deletions
|
@ -22,51 +22,67 @@ def rotate(l):
|
||||||
|
|
||||||
class Stackframe(object):
|
class Stackframe(object):
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
stack=None,
|
fun: Function,
|
||||||
fun: t.Optional[Function] = None,
|
ip: int,
|
||||||
ip=None, parent=None, depth=0):
|
stack: t.Optional[t.List[t.Any]] = None,
|
||||||
self.stack = stack or []
|
parent: t.Optional["Stackframe"] = None):
|
||||||
self.name = name or ";unknown;;"
|
self._fun = fun
|
||||||
self.ip = ip or 0
|
self._ip = ip
|
||||||
self.parent = parent
|
self._stack = stack or []
|
||||||
self.depth = depth
|
self._parent = parent
|
||||||
|
|
||||||
def push(self, obj):
|
def push(self, obj):
|
||||||
self.stack.insert(0, obj)
|
self._stack.insert(0, obj)
|
||||||
|
|
||||||
def pop(self):
|
def pop(self):
|
||||||
return self.stack.pop(0)
|
return self._stack.pop(0)
|
||||||
|
|
||||||
def call(self, fun: Function, ip) -> "Stackframe":
|
def call(self, fun: Function, ip) -> "Stackframe":
|
||||||
self.ip += 1
|
assert isinstance(fun, Function)
|
||||||
|
assert isinstance(ip, int)
|
||||||
|
self._ip += 1
|
||||||
nargs = len(fun.arguments)
|
nargs = len(fun.arguments)
|
||||||
args, self.stack = self.stack[:nargs], self.stack[nargs:]
|
args, self._stack = self._stack[:nargs], self._stack[nargs:]
|
||||||
return Stackframe(
|
return Stackframe(
|
||||||
|
fun,
|
||||||
|
ip,
|
||||||
stack=args,
|
stack=args,
|
||||||
name=fun.signature,
|
|
||||||
ip=ip,
|
|
||||||
parent=self,
|
parent=self,
|
||||||
depth=self.depth+1
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def ret(self, nargs) -> "Stackframe":
|
def ret(self, nargs) -> "Stackframe":
|
||||||
self.parent.stack = self.stack[:nargs] + self.parent.stack
|
assert nargs >= 0
|
||||||
return self.parent
|
assert isinstance(self._parent, Stackframe)
|
||||||
|
self._parent._stack = self._stack[:nargs] + self._parent._stack
|
||||||
|
return self._parent
|
||||||
|
|
||||||
def dup(self, nargs):
|
def dup(self, nargs):
|
||||||
self.stack = self.stack[:nargs] + self.stack
|
self._stack = self._stack[:nargs] + self._stack
|
||||||
|
|
||||||
def drop(self, nargs):
|
def drop(self, nargs):
|
||||||
self.stack = self.stack[nargs:]
|
self._stack = self._stack[nargs:]
|
||||||
|
|
||||||
def rot(self, nargs):
|
def rot(self, nargs):
|
||||||
self.stack = rotate(self.stack[:nargs]) + self.stack[nargs:]
|
self._stack = rotate(self._stack[:nargs]) + self._stack[nargs:]
|
||||||
|
|
||||||
|
def slot(self, n):
|
||||||
|
self.push(self._stack[len(self) - n - 1])
|
||||||
|
|
||||||
|
def goto(self, target: int):
|
||||||
|
self._ip = target
|
||||||
|
|
||||||
|
@property
|
||||||
|
def depth(self):
|
||||||
|
if self._parent == None:
|
||||||
|
return 0
|
||||||
|
else:
|
||||||
|
return self._parent.depth + 1
|
||||||
|
|
||||||
def __getitem__(self, key):
|
def __getitem__(self, key):
|
||||||
return self.stack.__getitem__(key)
|
return self._stack.__getitem__(key)
|
||||||
|
|
||||||
def __len__(self):
|
def __len__(self):
|
||||||
return len(self.stack)
|
return len(self._stack)
|
||||||
|
|
||||||
|
|
||||||
class InterpreterError(Exception):
|
class InterpreterError(Exception):
|
||||||
|
@ -86,9 +102,11 @@ class Interpreter(object):
|
||||||
def run(self, opcodes, stack=[]):
|
def run(self, opcodes, stack=[]):
|
||||||
"""Directly interpret some opcodes in the configured environment."""
|
"""Directly interpret some opcodes in the configured environment."""
|
||||||
|
|
||||||
stackframe = Stackframe(stack=stack)
|
|
||||||
mod = self.bootstrap.copy()
|
mod = self.bootstrap.copy()
|
||||||
stackframe.ip = mod.labels[mod.define_function(";<main>;;", opcodes)]
|
main = mod.define_function(";<main>;;", opcodes)
|
||||||
|
main_fun = mod.functions[main]
|
||||||
|
main_ip = mod.labels[main]
|
||||||
|
stackframe = Stackframe(main_fun, main_ip, stack)
|
||||||
|
|
||||||
print(mod)
|
print(mod)
|
||||||
|
|
||||||
|
@ -98,8 +116,8 @@ class Interpreter(object):
|
||||||
raise InterpreterError(mod, deepcopy(stackframe), msg)
|
raise InterpreterError(mod, deepcopy(stackframe), msg)
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
op = mod.codepage[stackframe.ip]
|
op = mod.codepage[stackframe._ip]
|
||||||
print("{0}{1: <50} {2}: {3}".format(" " * stackframe.depth, str(stackframe.stack), stackframe.ip, op))
|
print("{0}{1: <50} {2}: {3}".format(" " * stackframe.depth, str(stackframe._stack), stackframe._ip, op))
|
||||||
|
|
||||||
match op:
|
match op:
|
||||||
case Opcode.TRUE():
|
case Opcode.TRUE():
|
||||||
|
@ -117,14 +135,13 @@ class Interpreter(object):
|
||||||
_error("Type violation")
|
_error("Type violation")
|
||||||
|
|
||||||
if val is False:
|
if val is False:
|
||||||
stackframe.ip = target
|
stackframe.goto(target)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
case Opcode.GOTO(n):
|
case Opcode.GOTO(n):
|
||||||
if (n < 0):
|
if (n < 0):
|
||||||
_error("Illegal branch target")
|
_error("Illegal branch target")
|
||||||
|
stackframe.goto(n)
|
||||||
stackframe.ip = n
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
case Opcode.DUP(n):
|
case Opcode.DUP(n):
|
||||||
|
@ -148,9 +165,9 @@ class Interpreter(object):
|
||||||
case Opcode.SLOT(n):
|
case Opcode.SLOT(n):
|
||||||
if (n < 0):
|
if (n < 0):
|
||||||
_error("SLOT must have a positive reference")
|
_error("SLOT must have a positive reference")
|
||||||
if (n > len(stackframe.stack) - 1):
|
if (n > len(stackframe) - 1):
|
||||||
_error("SLOT reference out of range")
|
_error("SLOT reference out of range")
|
||||||
stackframe.push(stackframe.stack[len(stackframe) - n - 1])
|
stackframe.slot(n)
|
||||||
|
|
||||||
case Opcode.IDENTIFIERC(name):
|
case Opcode.IDENTIFIERC(name):
|
||||||
if not (name in mod.functions or name in mod.types):
|
if not (name in mod.functions or name in mod.types):
|
||||||
|
@ -179,7 +196,7 @@ class Interpreter(object):
|
||||||
_error("Stack size violation")
|
_error("Stack size violation")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
ip = mod.codepage[sig.raw]
|
ip = mod.labels[fun.signature]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
_error("Unknown target")
|
_error("Unknown target")
|
||||||
|
|
||||||
|
@ -193,8 +210,7 @@ class Interpreter(object):
|
||||||
if stackframe.depth == 0:
|
if stackframe.depth == 0:
|
||||||
return stackframe[:n]
|
return stackframe[:n]
|
||||||
|
|
||||||
sig = FunctionRef.parse(stackframe.name)
|
if (len(stackframe._fun.returns) != n):
|
||||||
if (len(sig.ret) != n):
|
|
||||||
_error("Signature violation")
|
_error("Signature violation")
|
||||||
|
|
||||||
stackframe = stackframe.ret(n)
|
stackframe = stackframe.ret(n)
|
||||||
|
@ -204,14 +220,15 @@ class Interpreter(object):
|
||||||
sig = stackframe.pop()
|
sig = stackframe.pop()
|
||||||
if not isinstance(sig, FunctionRef):
|
if not isinstance(sig, FunctionRef):
|
||||||
_error("CLOSUREF requires a funref at top of stack")
|
_error("CLOSUREF requires a funref at top of stack")
|
||||||
if not n <= len(sig.args):
|
fun = mod.functions[sig.name]
|
||||||
|
if not n <= len(fun.arguments):
|
||||||
_error("CLOSUREF target violation; too many parameters provided")
|
_error("CLOSUREF target violation; too many parameters provided")
|
||||||
if n > len(stackframe):
|
if n > len(stackframe):
|
||||||
_error("Stack size violation")
|
_error("Stack size violation")
|
||||||
|
|
||||||
c = Closure(
|
c = Closure(
|
||||||
sig,
|
sig,
|
||||||
stackframe.stack[:n]
|
stackframe._stack[:n]
|
||||||
)
|
)
|
||||||
stackframe.drop(n)
|
stackframe.drop(n)
|
||||||
stackframe.push(c)
|
stackframe.push(c)
|
||||||
|
@ -220,14 +237,15 @@ class Interpreter(object):
|
||||||
c = stackframe.pop()
|
c = stackframe.pop()
|
||||||
if not isinstance(c, Closure):
|
if not isinstance(c, Closure):
|
||||||
_error("CLOSUREC requires a closure at top of stack")
|
_error("CLOSUREC requires a closure at top of stack")
|
||||||
if n + len(c.frag) > len(c.funref.args):
|
fun = mod.functions[c.funref.name]
|
||||||
|
if n + len(c.frag) > len(fun.arguments):
|
||||||
_error("CLOSUREC target violation; too many parameters provided")
|
_error("CLOSUREC target violation; too many parameters provided")
|
||||||
if n > len(stackframe):
|
if n > len(stackframe):
|
||||||
_error("Stack size violation")
|
_error("Stack size violation")
|
||||||
|
|
||||||
c = Closure(
|
c = Closure(
|
||||||
c.funref,
|
c.funref,
|
||||||
stackframe.stack[:n] + c.frag
|
stackframe._stack[:n] + c.frag
|
||||||
)
|
)
|
||||||
stackframe.drop(n)
|
stackframe.drop(n)
|
||||||
stackframe.push(c)
|
stackframe.push(c)
|
||||||
|
@ -236,27 +254,27 @@ class Interpreter(object):
|
||||||
c = stackframe.pop()
|
c = stackframe.pop()
|
||||||
if not isinstance(c, Closure):
|
if not isinstance(c, Closure):
|
||||||
_error("CALLC requires a closure at top of stack")
|
_error("CALLC requires a closure at top of stack")
|
||||||
if n + len(c.frag) != len(c.funref.args):
|
fun = mod.functions[c.funref.name]
|
||||||
|
if n + len(c.frag) != len(fun.arguments):
|
||||||
_error("CALLC target vionation; argument count missmatch")
|
_error("CALLC target vionation; argument count missmatch")
|
||||||
if n > len(stackframe):
|
if n > len(stackframe):
|
||||||
_error("Stack size violation")
|
_error("Stack size violation")
|
||||||
|
|
||||||
# Extract the function signature
|
# Extract the function signature
|
||||||
sig = c.funref
|
|
||||||
|
|
||||||
# Push the closure's stack fragment
|
# Push the closure's stack fragment
|
||||||
stackframe.stack = c.frag + stackframe.stack
|
stackframe._stack = c.frag + stackframe._stack
|
||||||
|
|
||||||
# Perform a "normal" funref call
|
# Perform a "normal" funref call
|
||||||
try:
|
try:
|
||||||
ip = mod.functions[sig.raw]
|
ip = mod.labels[fun.signature]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
_error("Unknown target")
|
_error("Unknown target")
|
||||||
|
|
||||||
stackframe = stackframe.call(sig, ip)
|
stackframe = stackframe.call(fun, ip)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
case _:
|
case _:
|
||||||
raise Exception(f"Unhandled interpreter state {op}")
|
raise Exception(f"Unhandled interpreter state {op}")
|
||||||
|
|
||||||
stackframe.ip += 1
|
stackframe._ip += 1
|
||||||
|
|
Loading…
Reference in a new issue