Get or2 working again via the assembler

This commit is contained in:
Reid 'arrdem' McKenzie 2022-08-17 00:07:09 -06:00
parent 5a3a6bc96f
commit 2c92447947
5 changed files with 115 additions and 40 deletions

View file

@ -26,6 +26,7 @@ class FuncBuilder(object):
if not self._straightline: if not self._straightline:
return return
start_stack = self._stack
match op: match op:
case isa.Label(_): case isa.Label(_):
# Labels abort # Labels abort
@ -35,6 +36,15 @@ class FuncBuilder(object):
# Control ops abort # Control ops abort
self._straightline = False self._straightline = False
case isa.CLOSUREC(n) | isa.CLOSUREF(n):
self._stack -= n
case isa.TYPEREF():
pass
case isa.ARMREF():
self._stack -= 1
case isa.DROP(n): case isa.DROP(n):
self._stack -= n self._stack -= n
@ -48,6 +58,8 @@ class FuncBuilder(object):
self._stack -= getattr(op, "nargs", 0) self._stack -= getattr(op, "nargs", 0)
self._stack += 1 self._stack += 1
print(op, "pre", start_stack, "post", self._stack)
def write(self, op: Union[isa.Opcode, isa.Label, Sequence[isa.Opcode]]): def write(self, op: Union[isa.Opcode, isa.Label, Sequence[isa.Opcode]]):
def flatten(o): def flatten(o):
@ -58,15 +70,24 @@ class FuncBuilder(object):
yield from flatten(e) yield from flatten(e)
if isinstance(op, (isa.Opcode, isa.Label)): if isinstance(op, (isa.Opcode, isa.Label)):
self._opcodes.append(op) self._write(op)
else: else:
for e in op: for e in flatten(op):
self.write(e) self.write(e)
def make_label(self, prefix: Optional[str] = ""): def make_label(self, prefix: Optional[str] = ""):
return gensym(prefix) return gensym(prefix)
def mark_argument(self, prefix: Optional[str] = ""):
if not self._opcodes:
s = gensym(prefix)
self._stack += 1
self._slots[s] = self._stack - 1
return s
else:
raise Exception("Cannot mark arguments after writing opcodes")
def mark_label(self, prefix: Optional[str] = ""): def mark_label(self, prefix: Optional[str] = ""):
l = self.make_label(prefix=prefix) l = self.make_label(prefix=prefix)
self.write(l) self.write(l)
@ -80,7 +101,8 @@ class FuncBuilder(object):
elif self._straightline: elif self._straightline:
s = gensym(prefix) s = gensym(prefix)
self._slots[s] = self._stack assert self._stack > 0
self._slots[s] = self._stack - 1
return s return s
else: else:

View file

@ -5,6 +5,7 @@ Hopefully no "real" interpreter ever uses this code, since it's obviously replac
""" """
from ichor import isa from ichor import isa
from ichor.assembler import FuncBuilder
from ichor.state import Module, Variant from ichor.state import Module, Variant
@ -42,45 +43,87 @@ NOT1 = BOOTSTRAP.define_function(
], ],
) )
_b = FuncBuilder()
# Capture args
_x = _b.mark_argument()
_y = _b.mark_argument()
# Const
_b.write(isa.IDENTIFIERC("bool"))
_b.write(isa.TYPEREF())
_bool_t = _b.mark_slot()
_b.write(isa.SLOT(_bool_t))
_b.write(isa.IDENTIFIERC("true"))
_b.write(isa.ARMREF())
_true_t = _b.mark_slot()
_b.write(isa.SLOT(_bool_t))
_b.write(isa.IDENTIFIERC("false"))
_b.write(isa.ARMREF())
_false_t = _b.mark_slot()
# x: Bool, x: Bool -> Bool
_true_l = _b.make_label()
_b.write(isa.SLOT(_x))
_b.write(isa.SLOT(_true_t))
_b.write(isa.ATEST(_true_l))
_b.write(isa.SLOT(_y))
_b.write(isa.SLOT(_true_t))
_b.write(isa.ATEST(_true_l))
_b.write(isa.SLOT(_false_t))
_b.write(isa.ARM(0))
_b.write(isa.RETURN())
_b.write(_true_l)
_b.write(isa.SLOT(_true_t))
_b.write(isa.ARM(0))
_b.write(isa.RETURN())
OR2 = BOOTSTRAP.define_function( OR2 = BOOTSTRAP.define_function(
f";or;{BOOL},{BOOL};{BOOL}", f";or;{BOOL},{BOOL};{BOOL}",
[ _b.build()
isa.BREAK(),
],
) )
_b = FuncBuilder()
_b.write(isa.BREAK())
OR3 = BOOTSTRAP.define_function( OR3 = BOOTSTRAP.define_function(
f";or;{BOOL},{BOOL},{BOOL};{BOOL}", f";or;{BOOL},{BOOL},{BOOL};{BOOL}",
[ _b.build()
isa.BREAK(),
]
) )
_b = FuncBuilder()
_b.write(isa.BREAK())
AND2 = BOOTSTRAP.define_function( AND2 = BOOTSTRAP.define_function(
f";and;{BOOL},{BOOL};{BOOL}", f";and;{BOOL},{BOOL};{BOOL}",
[ _b.build()
isa.BREAK(),
],
) )
_b = FuncBuilder()
_b.write(isa.BREAK())
AND3 = BOOTSTRAP.define_function( AND3 = BOOTSTRAP.define_function(
f";and;{BOOL},{BOOL},{BOOL};{BOOL}", f";and;{BOOL},{BOOL},{BOOL};{BOOL}",
[ _b.build()
isa.BREAK(),
],
) )
_b = FuncBuilder()
_b.write(isa.BREAK())
XOR2 = BOOTSTRAP.define_function( XOR2 = BOOTSTRAP.define_function(
f";xor;{BOOL},{BOOL};{BOOL}", f";xor;{BOOL},{BOOL};{BOOL}",
[ _b.build()
isa.BREAK(),
],
) )
_b = FuncBuilder()
_b.write(isa.BREAK())
XOR3 = BOOTSTRAP.define_function( XOR3 = BOOTSTRAP.define_function(
f";xor;{BOOL},{BOOL},{BOOL};{BOOL}", f";xor;{BOOL},{BOOL},{BOOL};{BOOL}",
[ _b.build()
# A^B|B^C
isa.BREAK(),
]
) )

View file

@ -264,11 +264,11 @@ class Interpreter(BaseInterpreter):
def handle_atest(self, state: InterpreterState, opcode: isa.ATEST) -> InterpreterState: def handle_atest(self, state: InterpreterState, opcode: isa.ATEST) -> InterpreterState:
armref: VariantRef = state.stackframe.pop() armref: VariantRef = state.stackframe.pop()
if not isinstance(armref, VariantRef): if not isinstance(armref, VariantRef):
return self.handle_fault(state, opcode, "VTEST must be given a variant reference") return self.handle_fault(state, opcode, "ATEST must be given a variant reference")
inst: Variant = state.stackframe.pop() inst: Variant = state.stackframe.pop()
if not isinstance(inst, Variant): if not isinstance(inst, Variant):
return self.handle_fault(state, opcode, "VTEST must be given an instance of a variant") return self.handle_fault(state, opcode, "ATEST must be given an instance of a variant")
if inst.type == armref.type.name and inst.variant == armref.arm: if inst.type == armref.type.name and inst.variant == armref.arm:
state.stackframe.goto(opcode.target) state.stackframe.goto(opcode.target)

View file

@ -19,8 +19,9 @@ class LoggingInterpreter(Interpreter):
b.append(" stack:") b.append(" stack:")
for offset, it in zip(range(0, len(state.stackframe), 1), state.stackframe): for offset, it in zip(range(0, len(state.stackframe), 1), state.stackframe):
b.append(f" {offset: <3} {it}") b.append(f" {offset: <3} {it}")
b.append(f" op: {opcode}")
print(indent("\n".join(b), " " * state.stackframe.depth)) b.append(f" op: {opcode}")
print(indent("\n".join(b), " " * state.stackframe.depth))
return state return state

View file

@ -3,7 +3,13 @@
from .fixtures import * # noqa from .fixtures import * # noqa
from ichor import isa from ichor import isa
from ichor.bootstrap import FALSE, NOT1, TRUE from ichor.bootstrap import (
FALSE,
NOT1,
OR2,
OR2_INSTRS,
TRUE,
)
import pytest import pytest
@ -20,19 +26,22 @@ def test_not(vm, stack, ret):
], stack = stack) == ret ], stack = stack) == ret
# @pytest.mark.parametrize("stack,ret", [ @pytest.mark.parametrize("stack,ret", [
# [[False, False], [False]], [[FALSE, FALSE], [FALSE]],
# [[True, False], [True]], [[TRUE, FALSE], [TRUE]],
# [[False, True], [True]], [[FALSE, TRUE], [TRUE]],
# [[True, True], [True]], [[TRUE, TRUE], [TRUE]],
# ]) ])
# def test_or(vm, stack, ret): def test_or(vm, stack, ret):
# assert vm.run([ for idx, i in zip(range(512), OR2_INSTRS):
# isa.IDENTIFIERC(OR2), print(f"{idx:>3} {i}")
# isa.FUNREF(),
# isa.CALLF(2), assert vm.run([
# isa.RETURN(1) isa.IDENTIFIERC(OR2),
# ], stack = stack) == ret isa.FUNREF(),
isa.CALLF(2),
isa.RETURN()
], stack = stack) == ret
# @pytest.mark.parametrize("stack,ret", [ # @pytest.mark.parametrize("stack,ret", [