From 24f5fd49fac03ead3fe716c7d6a2a79308b0c4a6 Mon Sep 17 00:00:00 2001
From: Jeeves <guydoodlesdev@gmail.com>
Date: Tue, 4 Mar 2025 23:17:45 -0700
Subject: [PATCH] fix stack peek/poke, tests, improve debugging via colors

---
 src/uxn.zig | 75 +++++++++++++++++++++++++++++++++--------------------
 1 file changed, 47 insertions(+), 28 deletions(-)

diff --git a/src/uxn.zig b/src/uxn.zig
index f324685..1a032e2 100644
--- a/src/uxn.zig
+++ b/src/uxn.zig
@@ -40,11 +40,42 @@ const Memory = struct {
     }
 };
 
+test "memory peek/poke" {
+    var mem = Memory{ .m = undefined };
+    mem.poke(u16, 0, 0xABCD);
+    mem.poke(u8, 2, 0x69);
+    try std.testing.expectEqual(0xABCD, mem.peek(u16, 0));
+    try std.testing.expectEqual(0x69, mem.peek(u8, 2));
+}
+
 const Stack = struct {
     s: [0x100]u8,
     sp: u8 = 0,
 
     pub fn peek(self: *Stack, comptime T: type) T {
+        std.debug.print("\x1b[1;32mstack peek:\x1b[0m sp {d}, type {s}\n", .{ self.sp, @typeName(T) });
+        return switch (T) {
+            u8 => self.s[self.sp -% 1],
+            u16 => @as(u16, @intCast(self.s[self.sp -% 2])) << 8 | self.s[self.sp -% 1],
+            else => @compileError("expected u8 or u16, got " + @typeName(T)),
+        };
+    }
+
+    pub fn poke(self: *Stack, comptime T: type, v: T) void {
+        std.debug.print("\x1b[1;32mstack poke:\x1b[0m sp {d}, type {s}\n", .{ self.sp, @typeName(T) });
+        switch (T) {
+            u8 => self.s[self.sp -% 1] = v,
+            u16 => {
+                self.s[self.sp -% 2] = @truncate(v >> 8);
+                self.s[self.sp -% 1] = @truncate(v & 0xFF);
+            },
+            else => @compileError("expected u8 or u16, got " + @typeName(T)),
+        }
+    }
+
+    pub fn pop(self: *Stack, comptime T: type) T {
+        self.sp -%= @intCast(@divExact(@typeInfo(T).int.bits, 8));
+        std.debug.print("\x1b[1;32mstack pop:\x1b[0m sp {d}, type {s}\n", .{ self.sp, @typeName(T) });
         return switch (T) {
             u8 => self.s[self.sp],
             u16 => @as(u16, @intCast(self.s[self.sp])) << 8 | self.s[self.sp +% 1],
@@ -52,7 +83,8 @@ const Stack = struct {
         };
     }
 
-    pub fn poke(self: *Stack, comptime T: type, v: T) void {
+    pub fn push(self: *Stack, comptime T: type, v: T) void {
+        std.debug.print("\x1b[1;32mstack push:\x1b[0m sp {d}, type {s}\n", .{ self.sp, @typeName(T) });
         switch (T) {
             u8 => self.s[self.sp] = v,
             u16 => {
@@ -61,19 +93,24 @@ const Stack = struct {
             },
             else => @compileError("expected u8 or u16, got " + @typeName(T)),
         }
-    }
-
-    pub fn pop(self: *Stack, comptime T: type) T {
-        self.sp -%= @intCast(@divExact(@typeInfo(T).int.bits, 8));
-        return self.peek(T);
-    }
-
-    pub fn push(self: *Stack, comptime T: type, v: T) void {
-        self.poke(T, v);
         self.sp +%= @intCast(@divExact(@typeInfo(T).int.bits, 8));
     }
 };
 
+test "stack poke/peek/push/pop" {
+    var stack = Stack{ .s = undefined };
+    stack.push(u16, 0xABCD);
+    stack.push(u8, 0x69);
+    try std.testing.expectEqual(0x69, stack.peek(u8));
+    try std.testing.expectEqual(0x69, stack.pop(u8));
+    try std.testing.expectEqual(0xABCD, stack.peek(u16));
+    try std.testing.expectEqual(0xABCD, stack.pop(u16));
+    stack.poke(u8, 0xBF);
+    try std.testing.expectEqual(0xBF, stack.peek(u8));
+    stack.poke(u16, 0xBEEF);
+    try std.testing.expectEqual(0xBEEF, stack.peek(u16));
+}
+
 pub fn eval(self: *Uxn) bool {
     switch (self.mem.m[self.pc]) {
         0x00 => return true, // BRK
@@ -603,24 +640,6 @@ fn sft(stack: *Stack, comptime T: type, comptime keep: bool) void {
     }
 }
 
-// TODO move the mem/stack to just below their respective definitions
-
-test "memory peek/poke" {
-    var mem = Memory{ .m = undefined };
-    mem.poke(u16, 0, 0xABCD);
-    mem.poke(u8, 2, 0xAA);
-    try std.testing.expectEqual(0xABCD, mem.peek(u16, 0));
-    try std.testing.expectEqual(0xAA, mem.peek(u8, 2));
-}
-
-test "stack push/pop" {
-    var stack = Stack{ .s = undefined };
-    stack.push(u16, 0xABCD);
-    stack.push(u8, 0xAA);
-    try std.testing.expectEqual(0xAA, stack.pop(u8));
-    try std.testing.expectEqual(0xABCD, stack.pop(u16));
-}
-
 // test "arithmetic instructions" {
 //     var uxn = Uxn{
 //         .mem = .{ .m = undefined },