2022-06-14 03:11:15 +00:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
|
|
|
|
"""The core VM/interpreter model."""
|
|
|
|
|
|
|
|
|
|
|
|
import typing as t
|
|
|
|
|
|
|
|
from ichor.isa import Opcode
|
2022-06-15 07:12:22 +00:00
|
|
|
from lark import Lark, Transformer, v_args, Token
|
2022-06-14 03:11:15 +00:00
|
|
|
|
|
|
|
|
|
|
|
class Identifier(t.NamedTuple):
|
|
|
|
name: str
|
|
|
|
|
|
|
|
|
2022-06-14 07:19:30 +00:00
|
|
|
GRAMMAR = r"""
|
|
|
|
fun: constraints ";" name ";" arguments ";" ret
|
|
|
|
|
|
|
|
arguments: (type ","?)*
|
|
|
|
ret: (type ","?)*
|
|
|
|
constraints: (constraint ","?)*
|
|
|
|
constraint: type
|
|
|
|
|
|
|
|
var: constraints ";" name ";" arms
|
2022-06-15 07:12:22 +00:00
|
|
|
arms: (arm ","?)+
|
2022-06-14 07:19:30 +00:00
|
|
|
arm: name "(" bindings ")"
|
|
|
|
|
|
|
|
bindings: (binding ","?)*
|
|
|
|
binding: name ":" type
|
|
|
|
|
|
|
|
type: NAME
|
|
|
|
name: NAME
|
2022-06-15 07:46:32 +00:00
|
|
|
NAME: /[^;,:⊢(){}|]+/
|
2022-06-14 07:19:30 +00:00
|
|
|
"""
|
|
|
|
|
2022-06-15 07:46:32 +00:00
|
|
|
|
2022-06-15 07:12:22 +00:00
|
|
|
class FuncT(Transformer):
|
|
|
|
@v_args(inline=True)
|
|
|
|
def fun(self, constraints, name, arguments, ret):
|
|
|
|
return (constraints, name, arguments, ret)
|
|
|
|
|
|
|
|
def constraints(self, args):
|
|
|
|
return (*args,)
|
|
|
|
|
|
|
|
def arguments(self, args):
|
|
|
|
return tuple(args)
|
|
|
|
|
|
|
|
def ret(self, args):
|
|
|
|
return tuple(args)
|
|
|
|
|
|
|
|
@v_args(inline=True)
|
|
|
|
def NAME(self, name: Token):
|
|
|
|
return name.value
|
|
|
|
|
|
|
|
@v_args(inline=True)
|
|
|
|
def name(self, name):
|
|
|
|
return name
|
|
|
|
|
|
|
|
@v_args(inline=True)
|
|
|
|
def type(self, name):
|
|
|
|
return name
|
|
|
|
|
|
|
|
|
|
|
|
FUNC = Lark(GRAMMAR, start="fun", parser='lalr', transformer=FuncT())
|
2022-06-14 07:19:30 +00:00
|
|
|
|
2022-06-14 03:11:15 +00:00
|
|
|
|
|
|
|
class FunctionRef(t.NamedTuple):
|
|
|
|
name: str
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def parse(cls, raw: str):
|
2022-06-15 07:46:32 +00:00
|
|
|
return cls(raw)
|
2022-06-14 03:11:15 +00:00
|
|
|
|
|
|
|
|
|
|
|
class Function(t.NamedTuple):
|
|
|
|
name: str
|
2022-06-14 07:19:30 +00:00
|
|
|
arguments: t.List[str]
|
|
|
|
returns: t.List[str]
|
|
|
|
instructions: t.List[Opcode]
|
|
|
|
typevars: t.List[t.Any] = []
|
|
|
|
typeconstraints: t.List[t.Any] = []
|
|
|
|
metadata: dict = {}
|
|
|
|
|
2022-06-15 07:12:22 +00:00
|
|
|
@classmethod
|
|
|
|
def build(cls, name: str, instructions: t.List[Opcode]):
|
2022-06-15 07:46:32 +00:00
|
|
|
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)}"
|
2022-06-15 07:12:22 +00:00
|
|
|
|
|
|
|
|
|
|
|
class VarT(FuncT):
|
|
|
|
@v_args(inline=True)
|
|
|
|
def var(self, constraints, name, arms):
|
|
|
|
return (constraints, name, arms)
|
|
|
|
|
|
|
|
@v_args(inline=True)
|
|
|
|
def constraint(self, name):
|
|
|
|
return name
|
|
|
|
|
|
|
|
def arms(self, arms):
|
|
|
|
return tuple(arms)
|
|
|
|
|
|
|
|
def binding(self, binding):
|
|
|
|
return tuple(binding)
|
|
|
|
|
|
|
|
def bindings(self, bindings):
|
|
|
|
return tuple(bindings)
|
|
|
|
|
|
|
|
@v_args(inline=True)
|
|
|
|
def arm(self, name, bindings):
|
|
|
|
return (name, bindings)
|
|
|
|
|
|
|
|
|
2022-06-14 07:19:30 +00:00
|
|
|
|
2022-06-15 07:12:22 +00:00
|
|
|
VAR = Lark(GRAMMAR, start="var", parser='lalr', transformer=VarT())
|
2022-06-14 07:19:30 +00:00
|
|
|
|
2022-06-15 07:46:32 +00:00
|
|
|
|
2022-06-14 07:19:30 +00:00
|
|
|
class Type(t.NamedTuple):
|
|
|
|
name: str
|
|
|
|
constructors: t.List[t.Tuple[str, t.List[str]]]
|
|
|
|
typevars: t.List[t.Any] = []
|
|
|
|
typeconstraints: t.List[t.Any] = []
|
|
|
|
metadata: dict = {}
|
2022-06-14 03:11:15 +00:00
|
|
|
|
2022-06-15 07:46:32 +00:00
|
|
|
@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)
|
|
|
|
|
2022-06-14 03:11:15 +00:00
|
|
|
|
|
|
|
class Closure(t.NamedTuple):
|
|
|
|
# Note that a closure over a closure is equivalent to a single closure which extends the captured stack fragment, so
|
|
|
|
# there's no need for a union here as we can simply convert nested closures.
|
|
|
|
funref: FunctionRef
|
|
|
|
frag: t.List[t.Any]
|
|
|
|
|
|
|
|
|
|
|
|
class Struct(t.NamedTuple):
|
|
|
|
name: str
|
|
|
|
type_params: list
|
|
|
|
children: t.Mapping[str, t.Any]
|
|
|
|
|
|
|
|
|
|
|
|
class Module(t.NamedTuple):
|
2022-06-15 07:46:32 +00:00
|
|
|
functions: t.Dict[str, Function] = {}
|
|
|
|
labels: t.Dict[str, int] = {}
|
2022-06-14 03:11:15 +00:00
|
|
|
codepage: list = []
|
2022-06-15 07:46:32 +00:00
|
|
|
types: t.Dict[str, Type] = {}
|
2022-06-14 03:11:15 +00:00
|
|
|
constants: dict = {}
|
|
|
|
|
|
|
|
def copy(self) -> "Module":
|
|
|
|
return Module(
|
|
|
|
self.functions.copy(),
|
2022-06-15 07:46:32 +00:00
|
|
|
self.labels.copy(),
|
|
|
|
self.codepage.copy(),
|
2022-06-14 03:11:15 +00:00
|
|
|
self.types.copy(),
|
|
|
|
self.constants.copy(),
|
|
|
|
)
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def translate(start: int, end: int, i: Opcode):
|
|
|
|
# FIXME: Consolidate bounds checks somehow
|
|
|
|
match i:
|
|
|
|
case Opcode.IF(t):
|
|
|
|
d = t + start
|
|
|
|
assert start <= d < end
|
|
|
|
return Opcode.IF(d)
|
|
|
|
|
|
|
|
case Opcode.GOTO(t):
|
|
|
|
d = t + start
|
|
|
|
assert start <= d < end
|
|
|
|
return Opcode.GOTO(d)
|
|
|
|
|
|
|
|
case _:
|
|
|
|
return i
|
|
|
|
|
|
|
|
def define_function(self, name, opcodes):
|
|
|
|
"""Enter a function into module.
|
|
|
|
|
|
|
|
Side-effects the codepage and name table.
|
|
|
|
|
|
|
|
"""
|
2022-06-15 07:46:32 +00:00
|
|
|
func = Function.build(name, opcodes)
|
|
|
|
self.functions[func.signature] = func
|
|
|
|
self.labels[func.signature] = start = len(self.codepage)
|
2022-06-14 03:11:15 +00:00
|
|
|
for op in opcodes:
|
|
|
|
self.codepage.append(self.translate(start, start + len(opcodes), op))
|
2022-06-15 07:46:32 +00:00
|
|
|
return func.signature
|
2022-06-14 03:11:15 +00:00
|
|
|
|
|
|
|
def define_type(self, name, signature):
|
|
|
|
self.types[name] = signature
|
|
|
|
return name
|
|
|
|
|
|
|
|
def __str__(self):
|
|
|
|
b = []
|
2022-06-15 07:46:32 +00:00
|
|
|
marks = {v: k for k, v in self.labels.items()}
|
2022-06-14 03:11:15 +00:00
|
|
|
for i, o in zip(range(1<<64), self.codepage):
|
|
|
|
if(i in marks):
|
|
|
|
b.append(f"{marks[i]}:")
|
2022-06-15 07:46:32 +00:00
|
|
|
b.append(f"{i: >10}: {o}")
|
2022-06-14 03:11:15 +00:00
|
|
|
return "\n".join(b)
|