Get CLOSUREC working

This commit is contained in:
Reid D. 'arrdem' McKenzie 2022-06-01 00:09:59 -06:00
parent 3debddf0b2
commit af65fbb6f6
4 changed files with 44 additions and 5 deletions

View file

@ -11,12 +11,13 @@ def main():
vm = Interpreter(BOOTSTRAP)
ret = vm.run(
[
Opcode.FUNREF(XOR2),
Opcode.FUNREF(XOR3),
Opcode.CLOSUREF(1),
Opcode.CLOSUREC(1),
Opcode.CALLC(1),
Opcode.RETURN(1),
],
stack = [True, False]
stack = [True, True, False]
)
print(ret)

View file

@ -11,11 +11,12 @@ context (a virtual machine) which DOES have an easily introspected and serialize
import sys
assert sys.version_info > (3, 10, 0), "`match` support is required"
from copy import deepcopy
from .isa import FunctionRef, Opcode, Closure
from .isa import Closure, FunctionRef, Opcode
def rotate(l):
@ -87,8 +88,9 @@ class Interpreter(object):
stack = Stackframe(stack=stack)
mod = self.bootstrap.copy()
mod.define_function(";<entry>;;", opcodes)
stack.ip = mod.functions[";<entry>;;"]
stack.ip = mod.functions[mod.define_function(";<main>;;", opcodes)]
print(mod)
def _error(msg=None):
# Note this is pretty expensive because we have to snapshot the stack BEFORE we do anything
@ -211,6 +213,22 @@ class Interpreter(object):
stack.drop(n)
stack.push(c)
case Opcode.CLOSUREC(n):
c = stack.pop()
if not isinstance(c, Closure):
_error("CLOSUREC requires a closure at top of stack")
if n + len(c.frag) > len(c.funref.args):
_error("CLOSUREC target violation; too many parameters provided")
if n > len(stack):
_error("Stack size violation")
c = Closure(
c.funref,
stack.stack[:n] + c.frag
)
stack.drop(n)
stack.push(c)
case Opcode.CALLC(n):
c = stack.pop()
if not isinstance(c, Closure):

View file

@ -129,6 +129,7 @@ class Opcode:
Further close over the closure at the top of the stack.
This may produce nullary closures.
"""
nargs: int = 0
class CALLC(t.NamedTuple):
"""(`CLOSURE<... A to ... B>`, ... A) -> (... B)

View file

@ -84,3 +84,22 @@ def test_callc(vm, stack, ret):
Opcode.CALLC(1),
Opcode.RETURN(1),
], stack = stack) == ret
@pytest.mark.parametrize("stack,ret", [
[[False, False, False], [False]],
[[True, False, False], [True]],
[[False, True, False], [True]],
[[True, True, False], [True]],
[[True, True, True], [False]],
[[False, True, True], [True]],
[[False, False, True], [True]],
])
def test_closurec(vm, stack, ret):
assert vm.run([
Opcode.FUNREF(XOR3),
Opcode.CLOSUREF(1),
Opcode.CLOSUREC(1),
Opcode.CALLC(1),
Opcode.RETURN(1),
], stack = stack) == ret