From 71a60ae07990ddd75a2fdf1e54aaa203ec2664fa Mon Sep 17 00:00:00 2001
From: Reid 'arrdem' McKenzie <me@arrdem.com>
Date: Wed, 17 Aug 2022 00:18:08 -0600
Subject: [PATCH] Get and2/3 working

---
 .../shoggoth/src/python/ichor/bootstrap.py    | 86 ++++++++++++++++++-
 .../test/python/ichor/test_bootstrap.py       | 44 +++++++---
 2 files changed, 113 insertions(+), 17 deletions(-)

diff --git a/projects/shoggoth/src/python/ichor/bootstrap.py b/projects/shoggoth/src/python/ichor/bootstrap.py
index 9806a67..373b10a 100644
--- a/projects/shoggoth/src/python/ichor/bootstrap.py
+++ b/projects/shoggoth/src/python/ichor/bootstrap.py
@@ -64,7 +64,7 @@ _b.write(isa.IDENTIFIERC("false"))
 _b.write(isa.ARMREF())
 _false_t = _b.mark_slot()
 
-# x: Bool, x: Bool -> Bool
+# x: Bool, y: Bool -> Bool
 _true_l = _b.make_label()
 _b.write(isa.SLOT(_x))
 _b.write(isa.SLOT(_true_t))
@@ -109,7 +109,7 @@ _b.write(isa.IDENTIFIERC("false"))
 _b.write(isa.ARMREF())
 _false_t = _b.mark_slot()
 
-# x: Bool, x: Bool -> Bool
+# x: Bool, y: Bool, z: Bool -> Bool
 _true_l = _b.make_label()
 _b.write(isa.SLOT(_x))
 _b.write(isa.SLOT(_true_t))
@@ -139,7 +139,43 @@ OR3 = BOOTSTRAP.define_function(
 )
 
 _b = FuncBuilder()
-_b.write(isa.BREAK())
+# 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
+_false_l = _b.make_label()
+_b.write(isa.SLOT(_x))
+_b.write(isa.SLOT(_false_t))
+_b.write(isa.ATEST(_false_l))
+
+_b.write(isa.SLOT(_y))
+_b.write(isa.SLOT(_false_t))
+_b.write(isa.ATEST(_false_l))
+
+_b.write(isa.SLOT(_true_t))
+_b.write(isa.ARM(0))
+_b.write(isa.RETURN())
+
+_b.write(_false_l)
+_b.write(isa.SLOT(_false_t))
+_b.write(isa.ARM(0))
+_b.write(isa.RETURN())
 
 AND2 = BOOTSTRAP.define_function(
     f";and;{BOOL},{BOOL};{BOOL}",
@@ -147,7 +183,49 @@ AND2 = BOOTSTRAP.define_function(
 )
 
 _b = FuncBuilder()
-_b.write(isa.BREAK())
+_b = FuncBuilder()
+# Capture args
+_x = _b.mark_argument()
+_y = _b.mark_argument()
+_z = _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
+_false_l = _b.make_label()
+_b.write(isa.SLOT(_x))
+_b.write(isa.SLOT(_false_t))
+_b.write(isa.ATEST(_false_l))
+
+_b.write(isa.SLOT(_y))
+_b.write(isa.SLOT(_false_t))
+_b.write(isa.ATEST(_false_l))
+
+_b.write(isa.SLOT(_z))
+_b.write(isa.SLOT(_false_t))
+_b.write(isa.ATEST(_false_l))
+
+_b.write(isa.SLOT(_true_t))
+_b.write(isa.ARM(0))
+_b.write(isa.RETURN())
+
+_b.write(_false_l)
+_b.write(isa.SLOT(_false_t))
+_b.write(isa.ARM(0))
+_b.write(isa.RETURN())
 
 AND3 = BOOTSTRAP.define_function(
     f";and;{BOOL},{BOOL},{BOOL};{BOOL}",
diff --git a/projects/shoggoth/test/python/ichor/test_bootstrap.py b/projects/shoggoth/test/python/ichor/test_bootstrap.py
index 3f7151a..c3f793d 100644
--- a/projects/shoggoth/test/python/ichor/test_bootstrap.py
+++ b/projects/shoggoth/test/python/ichor/test_bootstrap.py
@@ -9,6 +9,8 @@ from ichor.bootstrap import (
     OR2,
     OR3,
     TRUE,
+    AND2,
+    AND3
 )
 import pytest
 
@@ -60,19 +62,35 @@ def test_or3(vm, stack, ret):
     ], stack = stack) == ret
 
 
-# @pytest.mark.parametrize("stack,ret", [
-#     [[False, False], [False]],
-#     [[True, False], [False]],
-#     [[False, True], [False]],
-#     [[True, True], [True]],
-# ])
-# def test_and(vm, stack, ret):
-#     assert vm.run([
-#         isa.IDENTIFIERC(AND2),
-#         isa.FUNREF(),
-#         isa.CALLF(2),
-#         isa.RETURN(1)
-#     ], stack = stack) == ret
+@pytest.mark.parametrize("stack,ret", [
+    [[FALSE, FALSE], [FALSE]],
+    [[TRUE, FALSE], [FALSE]],
+    [[FALSE, TRUE], [FALSE]],
+    [[TRUE, TRUE], [TRUE]],
+])
+def test_and2(vm, stack, ret):
+    assert vm.run([
+        isa.IDENTIFIERC(AND2),
+        isa.FUNREF(),
+        isa.CALLF(2),
+        isa.RETURN()
+    ], stack = stack) == ret
+
+
+@pytest.mark.parametrize("stack,ret", [
+    [[FALSE, FALSE, FALSE], [FALSE]],
+    [[TRUE, FALSE, FALSE], [FALSE]],
+    [[FALSE, TRUE, FALSE], [FALSE]],
+    [[TRUE, TRUE, FALSE], [FALSE]],
+    [[TRUE, TRUE, TRUE], [TRUE]],
+])
+def test_and3(vm, stack, ret):
+    assert vm.run([
+        isa.IDENTIFIERC(AND3),
+        isa.FUNREF(),
+        isa.CALLF(3),
+        isa.RETURN()
+    ], stack = stack) == ret
 
 
 # @pytest.mark.parametrize("stack,ret", [