standalone exapunks vm in ocaml
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Prepare for M support

+68 -52
+1 -3
bin/main.ml
··· 42 42 if debug then 43 43 Printf.printf "%s\n" 44 44 (exa.labels |> StringMap.to_seq_keys |> List.of_seq |> String.concat ";"); 45 - Result.iter_error 46 - (fun (e : InstResult.error_t) -> print_string (InstResult.show (Error e))) 47 - (Vm.run vm)) 45 + Vm.run vm) 48 46 (); 49 47 print_newline (); 50 48 exit 0
+2
lib/Common.ml
··· 8 8 | X 9 9 | T 10 10 | F 11 + | M 11 12 12 13 and r_n = 13 14 | R of register ··· 41 42 | HOST of register 42 43 (* Communication *) 43 44 | MODE 45 + | VOID_M 44 46 (* File Manipulation *) 45 47 | MAKE 46 48 | GRAB of r_n
+11
lib/OpCode.ml
··· 4 4 5 5 type t = Common.op_code 6 6 7 + let is_m_op (op : t) = 8 + match op with 9 + | COPY (R M, _) 10 + | COPY (_, M) 11 + | VOID_M -> 12 + true 13 + | _ -> false 14 + 7 15 let regInstruction name r = Printf.sprintf "%s %s" name (Register.show r) 8 16 9 17 let rnInstruction name rn = Printf.sprintf "%s %s" name (Register.show_r_n rn) ··· 48 56 | LINK dest -> rnInstruction "LINK" dest 49 57 | HOST dest -> regInstruction "HOST" dest 50 58 | MODE -> "MODE" 59 + | VOID_M -> "VOID M" 51 60 | MAKE -> "MAKE" 52 61 | GRAB file -> rnInstruction "GRAB" file 53 62 | FILE dest -> regInstruction "FILE" dest ··· 112 121 | HOST _, _ -> false 113 122 | MODE, MODE -> true 114 123 | MODE, _ -> false 124 + | VOID_M, VOID_M -> true 125 + | VOID_M, _ -> false 115 126 | MAKE, MAKE -> true 116 127 | MAKE, _ -> false 117 128 | GRAB f1, GRAB f2 -> Register.equal_r_n f1 f2
+5 -1
lib/Reader.ml
··· 25 25 | [ rn ] -> Result.bind (parse_r_n rn) (fun _ -> Error "NOT ENOUGH ARGS") 26 26 | [ rn; r ] -> 27 27 Result.bind (parse_r_n rn) (fun rn -> 28 - Result.bind (parse_register r) (fun r -> Ok (COPY (rn, r)))) 28 + Result.bind (parse_register r) (fun r -> 29 + match (rn, r) with 30 + | R src, dest when Register.equal src dest -> 31 + Error "CANNOT REPEAT REGISTERS" 32 + | _ -> Ok (COPY (rn, r)))) 29 33 | _ -> Error "TOO MANY ARGS" 30 34 31 35 let math_op op src i dest =
+2
lib/Register.ml
··· 9 9 | X -> "X" 10 10 | T -> "T" 11 11 | F -> "F" 12 + | M -> "M" 12 13 13 14 let pp ppf t = Format.fprintf ppf "%s" (show t) 14 15 ··· 17 18 | X, X -> true 18 19 | T, T -> true 19 20 | F, F -> true 21 + | M, M -> true 20 22 | _ -> false 21 23 22 24 type r_n = Common.r_n
+29 -30
lib/Vm.ml
··· 90 90 | X -> ret exa.x 91 91 | T -> ret exa.t 92 92 | F -> read_file exa 93 + | M -> raise Unimplemented 93 94 94 95 let set_register (exa : Exa.t) (reg : register) (value : Value.t) : inst_result = 95 96 match reg with ··· 100 101 exa.t <- value; 101 102 pass () 102 103 | F -> raise Unimplemented 104 + | M -> raise Unimplemented 103 105 104 106 let value_of_r_n (exa : Exa.t) (rn : Register.r_n) : (Value.t, error_t) result = 105 107 match rn with ··· 131 133 match dest with 132 134 | X -> set_register exa dest value 133 135 | T -> set_register exa dest value 134 - | F -> write_file exa value) 136 + | F -> write_file exa value 137 + | M -> raise Unimplemented) 135 138 136 139 let clamp (i : Value.t) : Value.t = 137 140 match i with ··· 331 334 match (exa.f, reg) with 332 335 | None, _ -> runtime_error "NO CURRENT FILE" 333 336 | Some f, F -> 334 - if exa.f_pos >= File.length f then runtime_error "CANNNOT VOID PAST END OF FILE" 337 + if exa.f_pos >= File.length f then runtime_error "CANNOT VOID PAST END OF FILE" 335 338 else begin 336 339 File.void f exa.f_pos; 337 340 if exa.f_pos > File.length f then exa.f_pos <- File.length f; ··· 394 397 | LINK dest -> link exa dest 395 398 | HOST dest -> host exa dest 396 399 | MODE -> mode exa 400 + | VOID_M -> pass () 397 401 | MAKE -> make vm exa 398 402 | GRAB id -> grab exa id 399 403 | FILE dest -> fname exa dest ··· 409 413 Dynarray.iter Debugger.disassembleExa vm.exas; 410 414 print_newline () 411 415 412 - let tick (vm : t) : (bool, error_t) result = 416 + let tick ?(live = ref false) (vm : t) : unit = 417 + live := false; 413 418 vm.tick <- vm.tick + 1; 414 419 if vm.debug then debug_print vm; 415 - let live = ref (Ok false) in 416 420 let i = ref 0 in 417 - with_return (fun return -> 418 - Array.iter 419 - (fun exa -> 420 - match exa with 421 - | None -> i := !i + 1 422 - | Some exa -> ( 423 - if exa.dead then ( 424 - ignore (drop exa); 425 - Dynarray.set vm.exas !i None; 426 - Host.remove exa.host exa.name) 427 - else 428 - match execute vm exa with 429 - | Ok _ -> 430 - i := !i + 1; 431 - live := Ok true 432 - | Error _ as e -> 433 - exa.dead <- true; 434 - return e)) 435 - (vm.exas |> Dynarray.to_array); 436 - !live) 421 + Array.iter 422 + (fun exa -> 423 + match exa with 424 + | None -> i := !i + 1 425 + | Some exa -> ( 426 + if exa.dead then ( 427 + ignore (drop exa); 428 + Dynarray.set vm.exas !i None; 429 + Host.remove exa.host exa.name) 430 + else 431 + match execute vm exa with 432 + | Ok _ -> 433 + i := !i + 1; 434 + live := true 435 + | Error _ -> exa.dead <- true)) 436 + (vm.exas |> Dynarray.to_array) 437 437 438 - let run (vm : t) : (unit, error_t) result = 439 - let live = ref (Ok true) in 440 - while Result.is_ok !live && Result.get_ok !live = true do 441 - live := tick vm 442 - done; 443 - Result.map ignore !live 438 + let run (vm : t) : unit = 439 + let live = ref true in 440 + while !live do 441 + tick vm ~live 442 + done
+6 -5
test/End_to_end_test.ml
··· 35 35 (match Vm.create_exa vm home "A" code with 36 36 | Error _err -> Alcotest.(check string) "" "" (string_of_int (Random.bits ())) 37 37 | Ok _exa -> 38 - test_run vm (fun () -> 39 - let f2 = 40 - File.create "200" ~contents:[ Int 72; Int 52; Int 4; Int 60; Int 436 ] 41 - in 42 - Alcotest.check t_file "file has been changed" f2 file)); 38 + Vm.run vm; 39 + let f2 = 40 + File.create "200" ~contents:[ Int 72; Int 52; Int 4; Int 60; Int 436 ] 41 + in 42 + Alcotest.check t_file "file has been changed" f2 file; 43 + ()); 43 44 ())
-7
test/Helpers.ml
··· 14 14 15 15 let t_error_t = Alcotest.testable InstResult.pp_error_t InstResult.equal_error_t 16 16 17 - let test_run (vm : Vm.t) f = 18 - match Vm.run vm with 19 - | Ok () -> f () 20 - | Error (RUNTIME_ERROR e) 21 - | Error (COMPILE_ERROR e) -> 22 - Alcotest.(check string) "" (string_of_int (Random.bits ())) e 23 - 24 17 let context_strs : string list ref = ref [] 25 18 26 19 (** [set_context doc] sets a top-level context for all tests in the current file.
+6
test/Reader_test.ml
··· 91 91 Alcotest.check t_parse_result "parse_code" lines expected; 92 92 93 93 ()); 94 + 95 + specify "repeated registers in COPY" (fun () -> 96 + let lines = parse_code "COPY X X" in 97 + let expected = Error "CANNOT REPEAT REGISTERS" in 98 + Alcotest.check t_parse_result "" lines expected; 99 + ()); 94 100 ())
+5 -5
test/Vm_test.ml
··· 59 59 match Vm.create_exa vm host "A" "LINK 800" with 60 60 | Error _err -> Alcotest.(check string) "" "" (string_of_int (Random.bits ())) 61 61 | Ok exa -> 62 - ignore (Vm.tick vm); 62 + Vm.tick vm; 63 63 Alcotest.(check string) "" exa.host.name "other") 64 64 65 65 let () = ··· 91 91 match Vm.create_exa vm host "A" code with 92 92 | Error _ -> Alcotest.(check string) "" "" (string_of_int (Random.bits ())) 93 93 | Ok _ -> 94 - test_run vm (fun () -> 95 - let f2 = File.create "200" ~contents:[ Int 100 ] in 96 - Alcotest.check t_file "file has been changed" f2 f1; 97 - ())) 94 + Vm.run vm; 95 + let f2 = File.create "200" ~contents:[ Int 100 ] in 96 + Alcotest.check t_file "file has been changed" f2 f1; 97 + ())
+1 -1
test/dune
··· 13 13 utils_test 14 14 helpers) 15 15 (action 16 - (run %{test} --expert)) 16 + (run %{test} --expert -w)) 17 17 (libraries exapunks alcotest testo)) 18 18 19 19 (env