diff --git a/projects/shoggoth/src/python/ichor/__main__.py b/projects/shoggoth/src/python/ichor/__main__.py index 7aa87ad..8ba9303 100644 --- a/projects/shoggoth/src/python/ichor/__main__.py +++ b/projects/shoggoth/src/python/ichor/__main__.py @@ -17,7 +17,7 @@ def main(): Opcode.CALLC(1), Opcode.RETURN(1), ], - stack = [True, True, False] + stackframe = [True, True, False] ) print(ret) diff --git a/projects/shoggoth/src/python/ichor/impl.py b/projects/shoggoth/src/python/ichor/impl.py index 832e757..7569bb3 100644 --- a/projects/shoggoth/src/python/ichor/impl.py +++ b/projects/shoggoth/src/python/ichor/impl.py @@ -12,7 +12,7 @@ context (a virtual machine) which DOES have an easily introspected and serialize from copy import deepcopy from ichor.isa import Opcode -from ichor.typing import Closure, FunctionRef, Identifier +from ichor.state import Closure, FunctionRef, Identifier, Module def rotate(l): @@ -76,7 +76,7 @@ class InterpreterError(Exception): class Interpreter(object): """A shit simple instruction pointer based interpreter.""" - def __init__(self, bootstrap_module): + def __init__(self, bootstrap_module: Module): self.bootstrap = bootstrap_module def run(self, opcodes, stack=[]): @@ -94,7 +94,7 @@ class Interpreter(object): raise InterpreterError(mod, deepcopy(stackframe), msg) while True: - op = mod.opcodes[stackframe.ip] + op = mod.codepage[stackframe.ip] print("{0}{1: <50} {2}: {3}".format(" " * stackframe.depth, str(stackframe.stack), stackframe.ip, op)) match op: diff --git a/projects/shoggoth/src/python/ichor/state.py b/projects/shoggoth/src/python/ichor/state.py new file mode 100644 index 0000000..deb30a9 --- /dev/null +++ b/projects/shoggoth/src/python/ichor/state.py @@ -0,0 +1,139 @@ +#!/usr/bin/env python3 + +"""The core VM/interpreter model.""" + + +import typing as t + +from ichor.isa import Opcode + + +class Identifier(t.NamedTuple): + name: str + + +class FunctionSignature(t.NamedTuple): + raw: str + type_params: list + name: str + args: list + ret: list + + @staticmethod + def parse_list(l): + return [e for e in l.split(",") if e] + + @classmethod + def parse(cls, raw: str): + vars, name, args, ret = raw.split(";") + return cls( + raw, + cls.parse_list(vars), + name, + cls.parse_list(args), + cls.parse_list(ret) + ) + + +class FunctionRef(t.NamedTuple): + raw: str + type_params: list + name: str + args: list + ret: list + + @staticmethod + def parse_list(l): + return [e for e in l.split(",") if e] + + @classmethod + def parse(cls, raw: str): + vars, name, args, ret = raw.split(";") + return cls( + raw, + cls.parse_list(vars), + name, + cls.parse_list(args), + cls.parse_list(ret) + ) + + +class Function(t.NamedTuple): + name: str + + +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): + codepage: list = [] + functions: dict = {} + types: dict = {} + constants: dict = {} + + def copy(self) -> "Module": + return Module( + self.codepage.copy(), + self.functions.copy(), + 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. + + """ + + try: + sig = FunctionRef.parse(name) + assert sig.name + except: + raise ValueError("Illegal name provided") + + start = len(self.codepage) + self.functions[name] = start + for op in opcodes: + self.codepage.append(self.translate(start, start + len(opcodes), op)) + return name + + def define_type(self, name, signature): + self.types[name] = signature + return name + + def __str__(self): + b = [] + marks = {v: k for k, v in self.functions.items()} + for i, o in zip(range(1<<64), self.codepage): + if(i in marks): + b.append(f"{marks[i]}:") + b.append(f"{i: >10}: {o}") + return "\n".join(b) diff --git a/projects/shoggoth/src/python/ichor/typing.py b/projects/shoggoth/src/python/ichor/typing.py index 40516fa..6cd48fe 100644 --- a/projects/shoggoth/src/python/ichor/typing.py +++ b/projects/shoggoth/src/python/ichor/typing.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python3 + """The public interface for shoggoth's baked-in types.""" @@ -20,78 +22,3 @@ class SumExpr(t.NamedTuple): class ProductExpr(t.NamedTuple): children: t.Mapping[str, t.Any] - - -# FIXME: How exactly -class StructExpr(t.NamedTuple): - name: str - type_params: list - field_names: t.List[str] - children: t.List[t.Any] - - -#################################################################################################### -#################################################################################################### -#################################################################################################### - -class FunctionRef(t.NamedTuple): - raw: str - type_params: list - name: str - args: list - ret: list - - @staticmethod - def parse_list(l): - return [e for e in l.split(",") if e] - - @classmethod - def parse(cls, raw: str): - vars, name, args, ret = raw.split(";") - return cls( - raw, - cls.parse_list(vars), - name, - cls.parse_list(args), - cls.parse_list(ret) - ) - - -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 FunctionSignature(t.NamedTuple): - raw: str - type_params: list - name: str - args: list - ret: list - - @staticmethod - def parse_list(l): - return [e for e in l.split(",") if e] - - @classmethod - def parse(cls, raw: str): - vars, name, args, ret = raw.split(";") - return cls( - raw, - cls.parse_list(vars), - name, - cls.parse_list(args), - cls.parse_list(ret) - ) - - -class Struct(t.NamedTuple): - name: str - type_params: list - children: t.Mapping[str, t.Any] - - -class Identifier(t.NamedTuple): - name: str diff --git a/projects/shoggoth/test/python/ichor/fixtures.py b/projects/shoggoth/test/python/ichor/fixtures.py index 5257a3d..1f973b4 100644 --- a/projects/shoggoth/test/python/ichor/fixtures.py +++ b/projects/shoggoth/test/python/ichor/fixtures.py @@ -1,6 +1,7 @@ #!/usr/bin/env python3 from ichor import Interpreter, BOOTSTRAP + import pytest