[broken] Almost to a reworked Function model

This commit is contained in:
Reid 'arrdem' McKenzie 2022-06-15 01:46:32 -06:00
parent 197dfd0089
commit d926a5e404
2 changed files with 47 additions and 42 deletions

View file

@ -10,9 +10,10 @@ context (a virtual machine) which DOES have an easily introspected and serialize
from copy import deepcopy from copy import deepcopy
import typing as t
from ichor.isa import Opcode from ichor.isa import Opcode
from ichor.state import Closure, FunctionRef, Identifier, Module from ichor.state import Closure, FunctionRef, Identifier, Module, Function
def rotate(l): def rotate(l):
@ -20,7 +21,10 @@ def rotate(l):
class Stackframe(object): class Stackframe(object):
def __init__(self, stack=None, name=None, ip=None, parent=None, depth=0): def __init__(self,
stack=None,
fun: t.Optional[Function] = None,
ip=None, parent=None, depth=0):
self.stack = stack or [] self.stack = stack or []
self.name = name or ";unknown;;" self.name = name or ";unknown;;"
self.ip = ip or 0 self.ip = ip or 0
@ -33,13 +37,13 @@ class Stackframe(object):
def pop(self): def pop(self):
return self.stack.pop(0) return self.stack.pop(0)
def call(self, signature: FunctionRef, ip) -> "Stackframe": def call(self, fun: Function, ip) -> "Stackframe":
self.ip += 1 self.ip += 1
nargs = len(signature.args) 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(
stack=args, stack=args,
name=signature.raw, name=fun.signature,
ip=ip, ip=ip,
parent=self, parent=self,
depth=self.depth+1 depth=self.depth+1
@ -84,7 +88,7 @@ class Interpreter(object):
stackframe = Stackframe(stack=stack) stackframe = Stackframe(stack=stack)
mod = self.bootstrap.copy() mod = self.bootstrap.copy()
stackframe.ip = mod.functions[mod.define_function(";<main>;;", opcodes)] stackframe.ip = mod.labels[mod.define_function(";<main>;;", opcodes)]
print(mod) print(mod)
@ -168,17 +172,18 @@ class Interpreter(object):
sig = stackframe.pop() sig = stackframe.pop()
if not isinstance(sig, FunctionRef): if not isinstance(sig, FunctionRef):
_error("CALLF requires a funref at top of stack") _error("CALLF requires a funref at top of stack")
if n != len(sig.args): fun = mod.functions[sig.name]
if n != len(fun.arguments):
_error("CALLF target violation; argument count missmatch") _error("CALLF target violation; argument count missmatch")
if n > len(stackframe): if n > len(stackframe):
_error("Stack size violation") _error("Stack size violation")
try: try:
ip = mod.functions[sig.raw] ip = mod.codepage[sig.raw]
except KeyError: except KeyError:
_error("Unknown target") _error("Unknown target")
stackframe = stackframe.call(sig, ip) stackframe = stackframe.call(fun, ip)
continue continue
case Opcode.RETURN(n): case Opcode.RETURN(n):

View file

@ -30,9 +30,10 @@ binding: name ":" type
type: NAME type: NAME
name: NAME name: NAME
NAME: /[^;,:()<>\[\]{}|]+/ NAME: /[^;,:(){}|]+/
""" """
class FuncT(Transformer): class FuncT(Transformer):
@v_args(inline=True) @v_args(inline=True)
def fun(self, constraints, name, arguments, ret): def fun(self, constraints, name, arguments, ret):
@ -64,26 +65,11 @@ FUNC = Lark(GRAMMAR, start="fun", parser='lalr', transformer=FuncT())
class FunctionRef(t.NamedTuple): class FunctionRef(t.NamedTuple):
raw: str
type_params: list
name: str name: str
args: list
ret: list
@staticmethod
def parse_list(l):
return [e for e in l.split(",") if e]
@classmethod @classmethod
def parse(cls, raw: str): def parse(cls, raw: str):
vars, name, args, ret = raw.split(";") return cls(raw)
return cls(
raw,
cls.parse_list(vars),
name,
cls.parse_list(args),
cls.parse_list(ret)
)
class Function(t.NamedTuple): class Function(t.NamedTuple):
@ -97,7 +83,16 @@ class Function(t.NamedTuple):
@classmethod @classmethod
def build(cls, name: str, instructions: t.List[Opcode]): def build(cls, name: str, instructions: t.List[Opcode]):
pass constraints, name, args, rets = FUNC.parse(name)
# FIXME: Constraints probably needs some massaging
# FIXME: Need to get typevars from somewhere
# They both probably live in the same list
return cls(name, args, rets, instructions, typeconstraints=constraints)
@property
def signature(self):
# FIXME: This should be more meaningful - likely including a type and code fingerprint
return f"{self.name};{len(self.arguments)};{len(self.returns)}"
class VarT(FuncT): class VarT(FuncT):
@ -126,6 +121,7 @@ class VarT(FuncT):
VAR = Lark(GRAMMAR, start="var", parser='lalr', transformer=VarT()) VAR = Lark(GRAMMAR, start="var", parser='lalr', transformer=VarT())
class Type(t.NamedTuple): class Type(t.NamedTuple):
name: str name: str
constructors: t.List[t.Tuple[str, t.List[str]]] constructors: t.List[t.Tuple[str, t.List[str]]]
@ -133,6 +129,14 @@ class Type(t.NamedTuple):
typeconstraints: t.List[t.Any] = [] typeconstraints: t.List[t.Any] = []
metadata: dict = {} metadata: dict = {}
@classmethod
def build(cls, name: str):
constraints, name, arms = VAR.parse(name)
# FIXME: Constraints probably needs some massaging
# FIXME: Need to get typevars from somewhere
# They both probably live in the same list
return cls(name, arms, typeconstraints=constraints)
class Closure(t.NamedTuple): class Closure(t.NamedTuple):
# Note that a closure over a closure is equivalent to a single closure which extends the captured stack fragment, so # Note that a closure over a closure is equivalent to a single closure which extends the captured stack fragment, so
@ -148,15 +152,17 @@ class Struct(t.NamedTuple):
class Module(t.NamedTuple): class Module(t.NamedTuple):
functions: t.Dict[str, Function] = {}
labels: t.Dict[str, int] = {}
codepage: list = [] codepage: list = []
functions: dict = {} types: t.Dict[str, Type] = {}
types: dict = {}
constants: dict = {} constants: dict = {}
def copy(self) -> "Module": def copy(self) -> "Module":
return Module( return Module(
self.codepage.copy(),
self.functions.copy(), self.functions.copy(),
self.labels.copy(),
self.codepage.copy(),
self.types.copy(), self.types.copy(),
self.constants.copy(), self.constants.copy(),
) )
@ -184,18 +190,12 @@ class Module(t.NamedTuple):
Side-effects the codepage and name table. Side-effects the codepage and name table.
""" """
func = Function.build(name, opcodes)
try: self.functions[func.signature] = func
sig = FunctionRef.parse(name) self.labels[func.signature] = start = len(self.codepage)
assert sig.name
except:
raise ValueError("Illegal name provided")
start = len(self.codepage)
self.functions[name] = start
for op in opcodes: for op in opcodes:
self.codepage.append(self.translate(start, start + len(opcodes), op)) self.codepage.append(self.translate(start, start + len(opcodes), op))
return name return func.signature
def define_type(self, name, signature): def define_type(self, name, signature):
self.types[name] = signature self.types[name] = signature
@ -203,9 +203,9 @@ class Module(t.NamedTuple):
def __str__(self): def __str__(self):
b = [] b = []
marks = {v: k for k, v in self.functions.items()} marks = {v: k for k, v in self.labels.items()}
for i, o in zip(range(1<<64), self.codepage): for i, o in zip(range(1<<64), self.codepage):
if(i in marks): if(i in marks):
b.append(f"{marks[i]}:") b.append(f"{marks[i]}:")
b.append(f"{i: >10}: {o}") b.append(f"{i: >10}: {o}")
return "\n".join(b) return "\n".join(b)