From b4394668875dff984d44c7152621e141ca7e0455 Mon Sep 17 00:00:00 2001 From: "Reid D. 'arrdem' McKenzie" Date: Wed, 1 Jun 2022 00:09:59 -0600 Subject: [PATCH] Get CLOSUREC working --- .../shoggoth/src/python/ichor/__main__.py | 5 ++-- projects/shoggoth/src/python/ichor/impl.py | 24 ++++++++++++++++--- projects/shoggoth/src/python/ichor/isa.py | 1 + .../test/python/ichor/test_bootstrap.py | 19 +++++++++++++++ 4 files changed, 44 insertions(+), 5 deletions(-) diff --git a/projects/shoggoth/src/python/ichor/__main__.py b/projects/shoggoth/src/python/ichor/__main__.py index b05259f..7aa87ad 100644 --- a/projects/shoggoth/src/python/ichor/__main__.py +++ b/projects/shoggoth/src/python/ichor/__main__.py @@ -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) diff --git a/projects/shoggoth/src/python/ichor/impl.py b/projects/shoggoth/src/python/ichor/impl.py index 9f49a5c..1da2a5a 100644 --- a/projects/shoggoth/src/python/ichor/impl.py +++ b/projects/shoggoth/src/python/ichor/impl.py @@ -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(";;;", opcodes) - stack.ip = mod.functions[";;;"] + stack.ip = mod.functions[mod.define_function(";
;;", 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): diff --git a/projects/shoggoth/src/python/ichor/isa.py b/projects/shoggoth/src/python/ichor/isa.py index e101a49..26e696c 100644 --- a/projects/shoggoth/src/python/ichor/isa.py +++ b/projects/shoggoth/src/python/ichor/isa.py @@ -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) diff --git a/projects/shoggoth/test/python/ichor/test_bootstrap.py b/projects/shoggoth/test/python/ichor/test_bootstrap.py index 6d7714b..9334b39 100644 --- a/projects/shoggoth/test/python/ichor/test_bootstrap.py +++ b/projects/shoggoth/test/python/ichor/test_bootstrap.py @@ -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