[broken] Almost to a reworked Function model
This commit is contained in:
parent
197dfd0089
commit
d926a5e404
2 changed files with 47 additions and 42 deletions
|
@ -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):
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in a new issue