···88 | X
99 | T
1010 | F
1111+ | M
11121213and r_n =
1314 | R of register
···4142 | HOST of register
4243 (* Communication *)
4344 | MODE
4545+ | VOID_M
4446 (* File Manipulation *)
4547 | MAKE
4648 | GRAB of r_n
+11
lib/OpCode.ml
···4455type t = Common.op_code
6677+let is_m_op (op : t) =
88+ match op with
99+ | COPY (R M, _)
1010+ | COPY (_, M)
1111+ | VOID_M ->
1212+ true
1313+ | _ -> false
1414+715let regInstruction name r = Printf.sprintf "%s %s" name (Register.show r)
816917let rnInstruction name rn = Printf.sprintf "%s %s" name (Register.show_r_n rn)
···4856 | LINK dest -> rnInstruction "LINK" dest
4957 | HOST dest -> regInstruction "HOST" dest
5058 | MODE -> "MODE"
5959+ | VOID_M -> "VOID M"
5160 | MAKE -> "MAKE"
5261 | GRAB file -> rnInstruction "GRAB" file
5362 | FILE dest -> regInstruction "FILE" dest
···112121 | HOST _, _ -> false
113122 | MODE, MODE -> true
114123 | MODE, _ -> false
124124+ | VOID_M, VOID_M -> true
125125+ | VOID_M, _ -> false
115126 | MAKE, MAKE -> true
116127 | MAKE, _ -> false
117128 | GRAB f1, GRAB f2 -> Register.equal_r_n f1 f2
+5-1
lib/Reader.ml
···2525 | [ rn ] -> Result.bind (parse_r_n rn) (fun _ -> Error "NOT ENOUGH ARGS")
2626 | [ rn; r ] ->
2727 Result.bind (parse_r_n rn) (fun rn ->
2828- Result.bind (parse_register r) (fun r -> Ok (COPY (rn, r))))
2828+ Result.bind (parse_register r) (fun r ->
2929+ match (rn, r) with
3030+ | R src, dest when Register.equal src dest ->
3131+ Error "CANNOT REPEAT REGISTERS"
3232+ | _ -> Ok (COPY (rn, r))))
2933 | _ -> Error "TOO MANY ARGS"
30343135let math_op op src i dest =
+2
lib/Register.ml
···99 | X -> "X"
1010 | T -> "T"
1111 | F -> "F"
1212+ | M -> "M"
12131314let pp ppf t = Format.fprintf ppf "%s" (show t)
1415···1718 | X, X -> true
1819 | T, T -> true
1920 | F, F -> true
2121+ | M, M -> true
2022 | _ -> false
21232224type r_n = Common.r_n
+29-30
lib/Vm.ml
···9090 | X -> ret exa.x
9191 | T -> ret exa.t
9292 | F -> read_file exa
9393+ | M -> raise Unimplemented
93949495let set_register (exa : Exa.t) (reg : register) (value : Value.t) : inst_result =
9596 match reg with
···100101 exa.t <- value;
101102 pass ()
102103 | F -> raise Unimplemented
104104+ | M -> raise Unimplemented
103105104106let value_of_r_n (exa : Exa.t) (rn : Register.r_n) : (Value.t, error_t) result =
105107 match rn with
···131133 match dest with
132134 | X -> set_register exa dest value
133135 | T -> set_register exa dest value
134134- | F -> write_file exa value)
136136+ | F -> write_file exa value
137137+ | M -> raise Unimplemented)
135138136139let clamp (i : Value.t) : Value.t =
137140 match i with
···331334 match (exa.f, reg) with
332335 | None, _ -> runtime_error "NO CURRENT FILE"
333336 | Some f, F ->
334334- if exa.f_pos >= File.length f then runtime_error "CANNNOT VOID PAST END OF FILE"
337337+ if exa.f_pos >= File.length f then runtime_error "CANNOT VOID PAST END OF FILE"
335338 else begin
336339 File.void f exa.f_pos;
337340 if exa.f_pos > File.length f then exa.f_pos <- File.length f;
···394397 | LINK dest -> link exa dest
395398 | HOST dest -> host exa dest
396399 | MODE -> mode exa
400400+ | VOID_M -> pass ()
397401 | MAKE -> make vm exa
398402 | GRAB id -> grab exa id
399403 | FILE dest -> fname exa dest
···409413 Dynarray.iter Debugger.disassembleExa vm.exas;
410414 print_newline ()
411415412412-let tick (vm : t) : (bool, error_t) result =
416416+let tick ?(live = ref false) (vm : t) : unit =
417417+ live := false;
413418 vm.tick <- vm.tick + 1;
414419 if vm.debug then debug_print vm;
415415- let live = ref (Ok false) in
416420 let i = ref 0 in
417417- with_return (fun return ->
418418- Array.iter
419419- (fun exa ->
420420- match exa with
421421- | None -> i := !i + 1
422422- | Some exa -> (
423423- if exa.dead then (
424424- ignore (drop exa);
425425- Dynarray.set vm.exas !i None;
426426- Host.remove exa.host exa.name)
427427- else
428428- match execute vm exa with
429429- | Ok _ ->
430430- i := !i + 1;
431431- live := Ok true
432432- | Error _ as e ->
433433- exa.dead <- true;
434434- return e))
435435- (vm.exas |> Dynarray.to_array);
436436- !live)
421421+ Array.iter
422422+ (fun exa ->
423423+ match exa with
424424+ | None -> i := !i + 1
425425+ | Some exa -> (
426426+ if exa.dead then (
427427+ ignore (drop exa);
428428+ Dynarray.set vm.exas !i None;
429429+ Host.remove exa.host exa.name)
430430+ else
431431+ match execute vm exa with
432432+ | Ok _ ->
433433+ i := !i + 1;
434434+ live := true
435435+ | Error _ -> exa.dead <- true))
436436+ (vm.exas |> Dynarray.to_array)
437437438438-let run (vm : t) : (unit, error_t) result =
439439- let live = ref (Ok true) in
440440- while Result.is_ok !live && Result.get_ok !live = true do
441441- live := tick vm
442442- done;
443443- Result.map ignore !live
438438+let run (vm : t) : unit =
439439+ let live = ref true in
440440+ while !live do
441441+ tick vm ~live
442442+ done
+6-5
test/End_to_end_test.ml
···3535 (match Vm.create_exa vm home "A" code with
3636 | Error _err -> Alcotest.(check string) "" "" (string_of_int (Random.bits ()))
3737 | Ok _exa ->
3838- test_run vm (fun () ->
3939- let f2 =
4040- File.create "200" ~contents:[ Int 72; Int 52; Int 4; Int 60; Int 436 ]
4141- in
4242- Alcotest.check t_file "file has been changed" f2 file));
3838+ Vm.run vm;
3939+ let f2 =
4040+ File.create "200" ~contents:[ Int 72; Int 52; Int 4; Int 60; Int 436 ]
4141+ in
4242+ Alcotest.check t_file "file has been changed" f2 file;
4343+ ());
4344 ())
-7
test/Helpers.ml
···14141515let t_error_t = Alcotest.testable InstResult.pp_error_t InstResult.equal_error_t
16161717-let test_run (vm : Vm.t) f =
1818- match Vm.run vm with
1919- | Ok () -> f ()
2020- | Error (RUNTIME_ERROR e)
2121- | Error (COMPILE_ERROR e) ->
2222- Alcotest.(check string) "" (string_of_int (Random.bits ())) e
2323-2417let context_strs : string list ref = ref []
25182619(** [set_context doc] sets a top-level context for all tests in the current file.
+6
test/Reader_test.ml
···9191 Alcotest.check t_parse_result "parse_code" lines expected;
92929393 ());
9494+9595+ specify "repeated registers in COPY" (fun () ->
9696+ let lines = parse_code "COPY X X" in
9797+ let expected = Error "CANNOT REPEAT REGISTERS" in
9898+ Alcotest.check t_parse_result "" lines expected;
9999+ ());
94100 ())
+5-5
test/Vm_test.ml
···5959 match Vm.create_exa vm host "A" "LINK 800" with
6060 | Error _err -> Alcotest.(check string) "" "" (string_of_int (Random.bits ()))
6161 | Ok exa ->
6262- ignore (Vm.tick vm);
6262+ Vm.tick vm;
6363 Alcotest.(check string) "" exa.host.name "other")
64646565let () =
···9191 match Vm.create_exa vm host "A" code with
9292 | Error _ -> Alcotest.(check string) "" "" (string_of_int (Random.bits ()))
9393 | Ok _ ->
9494- test_run vm (fun () ->
9595- let f2 = File.create "200" ~contents:[ Int 100 ] in
9696- Alcotest.check t_file "file has been changed" f2 f1;
9797- ()))
9494+ Vm.run vm;
9595+ let f2 = File.create "200" ~contents:[ Int 100 ] in
9696+ Alcotest.check t_file "file has been changed" f2 f1;
9797+ ())