% AVM ISA v1 — Octave/MATLAB Test Harness
% Run with: cd octave && octave --no-gui test_avm.m

function test_avm()
  test_basic_add();
  test_div();
  test_saturation();
  test_locals();
  fprintf(stdout, "\nAll Octave tests passed.\n");
end

function test_basic_add()
  QS = AVM.Q16_SCALE;
  prog{1} = struct('op', AVM.OP_PUSH_Q16, 'arg', int32(5*QS), 'arg2', false);
  prog{2} = struct('op', AVM.OP_PUSH_Q16, 'arg', int32(3*QS), 'arg2', false);
  prog{3} = struct('op', AVM.OP_PRIM, 'arg', int32(AVM.PRIM_ADD_Q16), 'arg2', false);
  prog{4} = struct('op', AVM.OP_HALT, 'arg', int32(0), 'arg2', false);
  s = AVM.run(AVM.init_state(0), prog, 100);
  if s.stack{1}.i == 8*QS; fprintf(stdout, "  ✅ basic_add: 5+3=8\n");
  else; fprintf(stdout, "  ❌ basic_add\n"); end
end

function test_div()
  QS = AVM.Q16_SCALE;
  prog{1} = struct('op', AVM.OP_PUSH_Q16, 'arg', int32(3*QS), 'arg2', false);
  prog{2} = struct('op', AVM.OP_PUSH_Q16, 'arg', int32(5*QS), 'arg2', false);
  prog{3} = struct('op', AVM.OP_PRIM, 'arg', int32(AVM.PRIM_DIV_Q16), 'arg2', false);
  prog{4} = struct('op', AVM.OP_HALT, 'arg', int32(0), 'arg2', false);
  s = AVM.run(AVM.init_state(0), prog, 100);
  expected = int32(idivide(int32(3)*int32(QS), int32(5), 'floor'));
  if s.stack{1}.i == expected; fprintf(stdout, "  ✅ div_q16: 3/5\n");
  else; fprintf(stdout, "  ❌ div_q16\n"); end
end

function test_saturation()
  QS = AVM.Q16_SCALE;
  prog{1} = struct('op', AVM.OP_PUSH_Q16, 'arg', int32(AVM.AVM_CLAMP_MAX - 1), 'arg2', false);
  prog{2} = struct('op', AVM.OP_PUSH_Q16, 'arg', int32(2), 'arg2', false);
  prog{3} = struct('op', AVM.OP_PRIM, 'arg', int32(AVM.PRIM_ADD_Q16), 'arg2', false);
  prog{4} = struct('op', AVM.OP_HALT, 'arg', int32(0), 'arg2', false);
  s = AVM.run(AVM.init_state(0), prog, 100);
  if s.stack{1}.i == AVM.AVM_CLAMP_MAX; fprintf(stdout, "  ✅ saturation\n");
  else; fprintf(stdout, "  ❌ saturation\n"); end
end

function test_locals()
  QS = AVM.Q16_SCALE;
  prog{1} = struct('op', AVM.OP_PUSH_Q16, 'arg', int32(42*QS), 'arg2', false);
  prog{2} = struct('op', AVM.OP_STORE, 'arg', int32(0), 'arg2', false);
  prog{3} = struct('op', AVM.OP_LOAD, 'arg', int32(0), 'arg2', false);
  prog{4} = struct('op', AVM.OP_HALT, 'arg', int32(0), 'arg2', false);
  s = AVM.run(AVM.init_state(1), prog, 100);
  if s.stack{1}.i == 42*QS; fprintf(stdout, "  ✅ locals: store+load\n");
  else; fprintf(stdout, "  ❌ locals\n"); end
end

fprintf(stdout, "AVM Octave Port — Test Harness\n");
fprintf(stdout, "===============================\n");
test_avm();
