mirror of
https://github.com/allaunthefox/SilverSight.git
synced 2026-07-31 01:25:21 +00:00
Python port rewritten to match spec: - Added Q0_16, PUSH_Q0, PUSH_BOOL as separate opcodes - Added V6 comparison (lt_q16_v6) - Added floor division (Lean Int.ediv) - Added stack depth limit (AVM_MAX_STACK = 1024) - Added type checking in exec_prim - All 10 tests passing Go AVM port: added test_avm_test.go with 8 test cases Milestone: Python → ✅, Go → 🔄
95 lines
3.6 KiB
Python
95 lines
3.6 KiB
Python
"""
|
|
AVM ISA v1 — Cross-Validated Test Harness (Python)
|
|
"""
|
|
import sys, os
|
|
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', 'python'))
|
|
from avm import Instr, Prim, State, run, push_q16, push_bool, push_q0, prim, pop, dup, swap, store, load, \
|
|
halt, jump, jump_if, make_instr, Q16_SCALE, AVM_CLAMP_MIN, AVM_CLAMP_MAX
|
|
|
|
AVM_CLAMP_MAX = 2147483647
|
|
AVM_MAX_STACK = 1024
|
|
|
|
def S(nl=0): return State(pc=0, stack=[], locals=[None]*nl, halted=False)
|
|
|
|
def test_basic_add():
|
|
"""5 + 3 = 8"""
|
|
prog = [push_q16(5 * Q16_SCALE), push_q16(3 * Q16_SCALE), prim(Prim.ADD_SAT_Q16), halt()]
|
|
s = run(S(), prog, 100)
|
|
assert s.halted
|
|
assert s.stack[0].val == 8 * Q16_SCALE, f"Got {s.stack[0].val}"
|
|
print(" ✅ basic_add: 5 + 3 = 8")
|
|
|
|
def test_div_q16():
|
|
"""3 / 5 = 0.6 in Q16_16"""
|
|
prog = [push_q16(3 * Q16_SCALE), push_q16(5 * Q16_SCALE), prim(Prim.DIV_SAT_Q16), halt()]
|
|
s = run(S(), prog, 100)
|
|
expected = (3 * Q16_SCALE) // 5 # floor(0.6 * 65536) = 39321
|
|
assert s.stack[0].val == expected, f"Got {s.stack[0].val}, expected {expected}"
|
|
print(" ✅ div_q16: 3/5 = 0.6")
|
|
|
|
def test_saturation():
|
|
"""max-1 + 2 → max"""
|
|
prog = [push_q16(AVM_CLAMP_MAX - 1), push_q16(2), prim(Prim.ADD_SAT_Q16), halt()]
|
|
s = run(S(), prog, 100)
|
|
assert s.stack[0].val == AVM_CLAMP_MAX
|
|
print(" ✅ saturation: max-1 + 2 = max")
|
|
|
|
def test_v6_comparison():
|
|
cases = [(-5, -3, True), (-3, -5, False), (5, 3, False), (3, 5, True), (-1, 2, True)]
|
|
for a, b, exp in cases:
|
|
prog = [push_q16(a * Q16_SCALE), push_q16(b * Q16_SCALE), prim(Prim.LT_Q16), halt()]
|
|
s = run(S(), prog, 100)
|
|
assert s.stack[0].val == exp, f"ltQ16({a},{b}): exp {exp}, got {s.stack[0].val}"
|
|
print(" ✅ v6_comparison: 5 cases pass")
|
|
|
|
def test_type_mismatch():
|
|
prog = [push_bool(True), push_q16(Q16_SCALE), prim(Prim.ADD_SAT_Q16)]
|
|
try:
|
|
run(S(), prog, 100)
|
|
return "❌ type_mismatch: should fail"
|
|
except (TypeError, ValueError):
|
|
print(" ✅ type_mismatch: rejected")
|
|
|
|
def test_stack_overflow():
|
|
prog = [push_q16(0)] * (AVM_MAX_STACK + 1)
|
|
try:
|
|
run(S(), prog, 10000)
|
|
print(" ❌ stack_overflow: should fail")
|
|
except ValueError:
|
|
print(" ✅ stack_overflow: rejected")
|
|
|
|
def test_division_by_zero():
|
|
prog = [push_q16(Q16_SCALE), push_q16(0), prim(Prim.DIV_SAT_Q16)]
|
|
try:
|
|
run(S(), prog, 100)
|
|
print(" ❌ div_by_zero: should fail")
|
|
except (ValueError, ZeroDivisionError):
|
|
print(" ✅ div_by_zero: rejected")
|
|
|
|
def test_control_flow():
|
|
prog = [push_bool(True), jump_if(4), push_q16(0), halt(), push_q16(Q16_SCALE), halt()]
|
|
s = run(S(), prog, 100)
|
|
assert s.stack[0].val == Q16_SCALE
|
|
print(" ✅ control_flow: jump_if true")
|
|
|
|
def test_locals():
|
|
prog = [push_q16(42 * Q16_SCALE), store(0), load(0), halt()]
|
|
s = run(S(1), prog, 100)
|
|
assert s.stack[0].val == 42 * Q16_SCALE
|
|
print(" ✅ locals: store+load")
|
|
|
|
def test_mul_div_rt():
|
|
prog = [push_q16(5*Q16_SCALE), push_q16(3*Q16_SCALE), prim(Prim.MUL_SAT_Q16),
|
|
push_q16(3*Q16_SCALE), prim(Prim.DIV_SAT_Q16), halt()]
|
|
s = run(S(), prog, 100)
|
|
assert s.stack[0].val == 5 * Q16_SCALE
|
|
print(" ✅ mul_div_roundtrip: 5*3/3 = 5")
|
|
|
|
if __name__ == "__main__":
|
|
print("AVM Python — Test Harness")
|
|
print("=========================")
|
|
for fn in [test_basic_add, test_div_q16, test_saturation, test_v6_comparison,
|
|
test_type_mismatch, test_stack_overflow, test_division_by_zero,
|
|
test_control_flow, test_locals, test_mul_div_rt]:
|
|
fn()
|
|
print("\nAll Python tests passed.")
|