205 lines
5.1 KiB
OCaml
205 lines
5.1 KiB
OCaml
open Sequence
|
|
|
|
let example_program =
|
|
[|
|
|
Instr.PUSH (Instr.Int 5);
|
|
Instr.PUSH (Instr.Int 3);
|
|
Instr.ADD;
|
|
Instr.DUP;
|
|
Instr.PUSH (Instr.Int 2);
|
|
Instr.MUL;
|
|
Instr.ADD;
|
|
Instr.HALT;
|
|
|]
|
|
|
|
let arithmetic_program =
|
|
[|
|
|
Instr.PUSH (Instr.Int 10);
|
|
Instr.PUSH (Instr.Int 7);
|
|
Instr.SUB;
|
|
Instr.PUSH (Instr.Int 2);
|
|
Instr.MUL;
|
|
Instr.HALT;
|
|
|]
|
|
|
|
let conditional_program =
|
|
[|
|
|
Instr.PUSH (Instr.Int 5);
|
|
Instr.PUSH (Instr.Int 3);
|
|
Instr.LT;
|
|
Instr.JMP_IF 2;
|
|
Instr.PUSH (Instr.Int 100);
|
|
Instr.JMP 1;
|
|
Instr.PUSH (Instr.Int 200);
|
|
Instr.HALT;
|
|
|]
|
|
|
|
let comparison_program =
|
|
[|
|
|
Instr.PUSH (Instr.Int 10);
|
|
Instr.PUSH (Instr.Int 5);
|
|
Instr.GT;
|
|
Instr.PUSH (Instr.Int 5);
|
|
Instr.PUSH (Instr.Int 10);
|
|
Instr.LE;
|
|
Instr.AND;
|
|
Instr.HALT;
|
|
|]
|
|
|
|
let division_program =
|
|
[|
|
|
Instr.PUSH (Instr.Int 20);
|
|
Instr.PUSH (Instr.Int 4);
|
|
Instr.DIV;
|
|
Instr.PUSH (Instr.Int 3);
|
|
Instr.MOD;
|
|
Instr.HALT;
|
|
|]
|
|
|
|
let stack_ops_program =
|
|
[|
|
|
Instr.PUSH (Instr.Int 1);
|
|
Instr.PUSH (Instr.Int 2);
|
|
Instr.PUSH (Instr.Int 3);
|
|
Instr.ROT;
|
|
Instr.SWAP;
|
|
Instr.OVER;
|
|
Instr.ADD;
|
|
Instr.HALT;
|
|
|]
|
|
|
|
let logical_program =
|
|
[|
|
|
Instr.PUSH (Instr.Bool true);
|
|
Instr.PUSH (Instr.Bool false);
|
|
Instr.OR;
|
|
Instr.PUSH (Instr.Bool true);
|
|
Instr.AND;
|
|
Instr.NOT;
|
|
Instr.HALT;
|
|
|]
|
|
|
|
let negation_program =
|
|
[|
|
|
Instr.PUSH (Instr.Int 42);
|
|
Instr.NEG;
|
|
Instr.PUSH (Instr.Int 10);
|
|
Instr.ADD;
|
|
Instr.HALT;
|
|
|]
|
|
|
|
let closure_program =
|
|
[|
|
|
Instr.PUSH (Instr.Int 100);
|
|
Instr.MK_CLOSURE 10;
|
|
Instr.CALL;
|
|
Instr.HALT;
|
|
Instr.PUSH (Instr.Int 200);
|
|
Instr.RET;
|
|
|]
|
|
|
|
let exception_program =
|
|
[|
|
|
Instr.TRY 3;
|
|
Instr.PUSH (Instr.Int 42);
|
|
Instr.PUSH (Instr.Int 0);
|
|
Instr.DIV;
|
|
Instr.HALT;
|
|
Instr.POP;
|
|
Instr.PUSH (Instr.Int 999);
|
|
Instr.HALT;
|
|
|]
|
|
|
|
let complex_program =
|
|
[|
|
|
Instr.PUSH (Instr.Int 15);
|
|
Instr.PUSH (Instr.Int 3);
|
|
Instr.DIV;
|
|
Instr.DUP;
|
|
Instr.PUSH (Instr.Int 2);
|
|
Instr.MUL;
|
|
Instr.SWAP;
|
|
Instr.ADD;
|
|
Instr.PUSH (Instr.Int 10);
|
|
Instr.GT;
|
|
Instr.JMP_IF 2;
|
|
Instr.PUSH (Instr.Int 0);
|
|
Instr.JMP 1;
|
|
Instr.PUSH (Instr.Int 1);
|
|
Instr.HALT;
|
|
|]
|
|
|
|
let run_test name program expected =
|
|
Printf.printf "Test: %s\n" name;
|
|
match Vm.execute_program program with
|
|
| Vm.Success (Some (Instr.Int result)) ->
|
|
if result = expected then
|
|
Printf.printf " ✓ Pass: %d (expected %d)\n\n" result expected
|
|
else
|
|
Printf.printf " ✗ Fail: got %d, expected %d\n\n" result expected
|
|
| Vm.Success (Some (Instr.Bool result)) ->
|
|
Printf.printf " Result: %b\n\n" result
|
|
| Vm.Success None ->
|
|
Printf.printf " ✗ Fail: No result\n\n"
|
|
| Vm.Failure e ->
|
|
Printf.printf " ✗ Error: %s\n\n" (State.show_error e)
|
|
|
|
let run_trace_test name program =
|
|
Printf.printf "Trace test: %s\n" name;
|
|
let result, trace = Vm.execute_with_trace program in
|
|
(match result with
|
|
| Vm.Success (Some (Instr.Int n)) ->
|
|
Printf.printf " Result: %d\n" n
|
|
| Vm.Success (Some (Instr.Bool b)) ->
|
|
Printf.printf " Result: %b\n" b
|
|
| Vm.Success None ->
|
|
Printf.printf " Result: None\n"
|
|
| Vm.Failure e ->
|
|
Printf.printf " Error: %s\n" (State.show_error e));
|
|
Printf.printf " Trace entries: %d\n" (List.length trace);
|
|
if List.length trace > 0 then
|
|
(let last = List.hd (List.rev trace) in
|
|
Printf.printf " Final: pc=%d, stack_len=%d, cont_depth=%d\n"
|
|
last.Trampoline.pc last.Trampoline.stack_len last.Trampoline.cont_depth);
|
|
Printf.printf "\n"
|
|
|
|
let () =
|
|
run_test "Basic arithmetic" example_program 24;
|
|
run_test "Subtraction and multiplication" arithmetic_program 6;
|
|
run_test "Conditional branching" conditional_program 200;
|
|
run_test "Comparison operations" comparison_program 1;
|
|
run_test "Division and modulo" division_program 2;
|
|
run_test "Stack operations" stack_ops_program 5;
|
|
run_test "Logical operations" logical_program 0;
|
|
run_test "Negation" negation_program (-32);
|
|
run_test "Complex expression" complex_program 1;
|
|
|
|
let invalid_jump = [|
|
|
Instr.PUSH (Instr.Int 1);
|
|
Instr.JMP 1000;
|
|
Instr.HALT;
|
|
|] in
|
|
let errors = Vm.validate invalid_jump in
|
|
Printf.printf "Invalid jump validation: %d errors found\n" (List.length errors);
|
|
List.iter (fun (pc, err) ->
|
|
Printf.printf " PC %d: %s\n" pc (State.show_error err))
|
|
errors;
|
|
Printf.printf "\n";
|
|
|
|
let disasm = Vm.disassemble example_program in
|
|
List.iter (fun (pc, instr) ->
|
|
Printf.printf " %d: %s\n" pc instr)
|
|
disasm;
|
|
Printf.printf "\n";
|
|
|
|
run_trace_test "Traced execution" arithmetic_program;
|
|
|
|
match Vm.execute_program exception_program with
|
|
| Vm.Success (Some (Instr.Int n)) ->
|
|
Printf.printf "Exception caught, result: %d\n" n
|
|
| Vm.Success None ->
|
|
Printf.printf "Exception caught, no result\n"
|
|
| Vm.Failure e ->
|
|
Printf.printf "Exception not caught: %s\n" (State.show_error e);
|
|
Printf.printf "\n"
|