Get or2 working again via the assembler
This commit is contained in:
parent
5a3a6bc96f
commit
2c92447947
5 changed files with 115 additions and 40 deletions
|
@ -26,6 +26,7 @@ class FuncBuilder(object):
|
|||
if not self._straightline:
|
||||
return
|
||||
|
||||
start_stack = self._stack
|
||||
match op:
|
||||
case isa.Label(_):
|
||||
# Labels abort
|
||||
|
@ -35,6 +36,15 @@ class FuncBuilder(object):
|
|||
# Control ops abort
|
||||
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):
|
||||
self._stack -= n
|
||||
|
||||
|
@ -48,6 +58,8 @@ class FuncBuilder(object):
|
|||
self._stack -= getattr(op, "nargs", 0)
|
||||
self._stack += 1
|
||||
|
||||
print(op, "pre", start_stack, "post", self._stack)
|
||||
|
||||
def write(self, op: Union[isa.Opcode, isa.Label, Sequence[isa.Opcode]]):
|
||||
|
||||
def flatten(o):
|
||||
|
@ -58,15 +70,24 @@ class FuncBuilder(object):
|
|||
yield from flatten(e)
|
||||
|
||||
if isinstance(op, (isa.Opcode, isa.Label)):
|
||||
self._opcodes.append(op)
|
||||
self._write(op)
|
||||
|
||||
else:
|
||||
for e in op:
|
||||
for e in flatten(op):
|
||||
self.write(e)
|
||||
|
||||
def make_label(self, prefix: Optional[str] = ""):
|
||||
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] = ""):
|
||||
l = self.make_label(prefix=prefix)
|
||||
self.write(l)
|
||||
|
@ -80,7 +101,8 @@ class FuncBuilder(object):
|
|||
|
||||
elif self._straightline:
|
||||
s = gensym(prefix)
|
||||
self._slots[s] = self._stack
|
||||
assert self._stack > 0
|
||||
self._slots[s] = self._stack - 1
|
||||
return s
|
||||
|
||||
else:
|
||||
|
|
|
@ -5,6 +5,7 @@ Hopefully no "real" interpreter ever uses this code, since it's obviously replac
|
|||
"""
|
||||
|
||||
from ichor import isa
|
||||
from ichor.assembler import FuncBuilder
|
||||
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(
|
||||
f";or;{BOOL},{BOOL};{BOOL}",
|
||||
[
|
||||
isa.BREAK(),
|
||||
],
|
||||
_b.build()
|
||||
)
|
||||
|
||||
_b = FuncBuilder()
|
||||
_b.write(isa.BREAK())
|
||||
|
||||
OR3 = BOOTSTRAP.define_function(
|
||||
f";or;{BOOL},{BOOL},{BOOL};{BOOL}",
|
||||
[
|
||||
isa.BREAK(),
|
||||
]
|
||||
_b.build()
|
||||
)
|
||||
|
||||
_b = FuncBuilder()
|
||||
_b.write(isa.BREAK())
|
||||
|
||||
AND2 = BOOTSTRAP.define_function(
|
||||
f";and;{BOOL},{BOOL};{BOOL}",
|
||||
[
|
||||
isa.BREAK(),
|
||||
],
|
||||
_b.build()
|
||||
)
|
||||
|
||||
_b = FuncBuilder()
|
||||
_b.write(isa.BREAK())
|
||||
|
||||
AND3 = BOOTSTRAP.define_function(
|
||||
f";and;{BOOL},{BOOL},{BOOL};{BOOL}",
|
||||
[
|
||||
isa.BREAK(),
|
||||
],
|
||||
_b.build()
|
||||
)
|
||||
|
||||
_b = FuncBuilder()
|
||||
_b.write(isa.BREAK())
|
||||
|
||||
XOR2 = BOOTSTRAP.define_function(
|
||||
f";xor;{BOOL},{BOOL};{BOOL}",
|
||||
[
|
||||
isa.BREAK(),
|
||||
],
|
||||
_b.build()
|
||||
)
|
||||
|
||||
_b = FuncBuilder()
|
||||
_b.write(isa.BREAK())
|
||||
|
||||
XOR3 = BOOTSTRAP.define_function(
|
||||
f";xor;{BOOL},{BOOL},{BOOL};{BOOL}",
|
||||
[
|
||||
# A^B|B^C
|
||||
isa.BREAK(),
|
||||
]
|
||||
_b.build()
|
||||
)
|
||||
|
|
|
@ -264,11 +264,11 @@ class Interpreter(BaseInterpreter):
|
|||
def handle_atest(self, state: InterpreterState, opcode: isa.ATEST) -> InterpreterState:
|
||||
armref: VariantRef = state.stackframe.pop()
|
||||
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()
|
||||
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:
|
||||
state.stackframe.goto(opcode.target)
|
||||
|
|
|
@ -19,8 +19,9 @@ class LoggingInterpreter(Interpreter):
|
|||
b.append(" stack:")
|
||||
for offset, it in zip(range(0, len(state.stackframe), 1), state.stackframe):
|
||||
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
|
||||
|
||||
|
|
|
@ -3,7 +3,13 @@
|
|||
from .fixtures import * # noqa
|
||||
|
||||
from ichor import isa
|
||||
from ichor.bootstrap import FALSE, NOT1, TRUE
|
||||
from ichor.bootstrap import (
|
||||
FALSE,
|
||||
NOT1,
|
||||
OR2,
|
||||
OR2_INSTRS,
|
||||
TRUE,
|
||||
)
|
||||
import pytest
|
||||
|
||||
|
||||
|
@ -20,19 +26,22 @@ def test_not(vm, stack, ret):
|
|||
], stack = stack) == ret
|
||||
|
||||
|
||||
# @pytest.mark.parametrize("stack,ret", [
|
||||
# [[False, False], [False]],
|
||||
# [[True, False], [True]],
|
||||
# [[False, True], [True]],
|
||||
# [[True, True], [True]],
|
||||
# ])
|
||||
# def test_or(vm, stack, ret):
|
||||
# assert vm.run([
|
||||
# isa.IDENTIFIERC(OR2),
|
||||
# isa.FUNREF(),
|
||||
# isa.CALLF(2),
|
||||
# isa.RETURN(1)
|
||||
# ], stack = stack) == ret
|
||||
@pytest.mark.parametrize("stack,ret", [
|
||||
[[FALSE, FALSE], [FALSE]],
|
||||
[[TRUE, FALSE], [TRUE]],
|
||||
[[FALSE, TRUE], [TRUE]],
|
||||
[[TRUE, TRUE], [TRUE]],
|
||||
])
|
||||
def test_or(vm, stack, ret):
|
||||
for idx, i in zip(range(512), OR2_INSTRS):
|
||||
print(f"{idx:>3} {i}")
|
||||
|
||||
assert vm.run([
|
||||
isa.IDENTIFIERC(OR2),
|
||||
isa.FUNREF(),
|
||||
isa.CALLF(2),
|
||||
isa.RETURN()
|
||||
], stack = stack) == ret
|
||||
|
||||
|
||||
# @pytest.mark.parametrize("stack,ret", [
|
||||
|
|
Loading…
Reference in a new issue