Get or2 working again via the assembler
This commit is contained in:
parent
4ac9de366b
commit
96cbc75be2
5 changed files with 115 additions and 40 deletions
|
@ -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:
|
||||||
|
|
|
@ -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(),
|
|
||||||
]
|
|
||||||
)
|
)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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", [
|
||||||
|
|
Loading…
Reference in a new issue