diff options
-rw-r--r-- | README.md | 6 | ||||
-rw-r--r-- | examples/add.reg | 2 | ||||
-rw-r--r-- | examples/add.urm | 11 | ||||
-rw-r--r-- | instptr.ml | 36 | ||||
-rw-r--r-- | main.ml | 19 | ||||
-rw-r--r-- | makefile | 3 | ||||
-rw-r--r-- | parser.ml | 22 | ||||
-rw-r--r-- | parser.mli | 7 | ||||
-rw-r--r-- | reg.ml | 12 | ||||
-rw-r--r-- | reg.mli | 6 | ||||
-rw-r--r-- | urm.ml | 15 | ||||
-rw-r--r-- | urm_test.ml | 7 |
12 files changed, 101 insertions, 45 deletions
@@ -19,7 +19,11 @@ Unlimited Register Machine in OCaml. | |||
19 | 19 | ||
20 | ## Usage | 20 | ## Usage |
21 | 21 | ||
22 | TODO: describe usage of the `urm` program. | 22 | ``` |
23 | ./urm <run | trace> <program file> <initial register state file> | ||
24 | ``` | ||
25 | |||
26 | Examples programs are provided in the `examples` folder. | ||
23 | 27 | ||
24 | 28 | ||
25 | ## Authors | 29 | ## Authors |
diff --git a/examples/add.reg b/examples/add.reg new file mode 100644 index 0000000..c24e1f9 --- /dev/null +++ b/examples/add.reg | |||
@@ -0,0 +1,2 @@ | |||
1 | 1 2 | ||
2 | 2 3 | ||
diff --git a/examples/add.urm b/examples/add.urm new file mode 100644 index 0000000..d11eff7 --- /dev/null +++ b/examples/add.urm | |||
@@ -0,0 +1,11 @@ | |||
1 | ZERO 0 | ||
2 | ZERO 3 | ||
3 | JUMP 1 3 6 | ||
4 | SUCC 0 | ||
5 | SUCC 3 | ||
6 | JUMP 3 3 2 | ||
7 | ZERO 3 | ||
8 | JUMP 2 3 11 | ||
9 | SUCC 0 | ||
10 | SUCC 3 | ||
11 | JUMP 3 3 7 | ||
@@ -5,42 +5,33 @@ | |||
5 | 5 | ||
6 | open Common | 6 | open Common |
7 | 7 | ||
8 | (* Creates a pointer of instruction from an urm command list *) | ||
9 | let instptr_mk urmcmd_list = | 8 | let instptr_mk urmcmd_list = |
10 | let rec aux urmcmd_list count acc = | 9 | let rec aux urmcmd_list count acc = match urmcmd_list with |
11 | match urmcmd_list with | ||
12 | | [] -> acc | 10 | | [] -> acc |
13 | | instr :: tail -> aux tail (count + 1) ((count, instr) :: acc) | 11 | | instr :: tail -> aux tail (count + 1) ((count, instr) :: acc) |
14 | in InstPtr([], List.rev (aux urmcmd_list 0 [])) | 12 | in InstPtr([], List.rev (aux urmcmd_list 0 [])) |
15 | 13 | ||
16 | (* Moves the pointer to the previous instruction *) | ||
17 | let instptr_move_up = function | 14 | let instptr_move_up = function |
18 | | InstPtr([], list2) -> InstPtr([], list2) | ||
19 | | InstPtr(instr :: list1, list2) -> InstPtr(list1, instr :: list2) | 15 | | InstPtr(instr :: list1, list2) -> InstPtr(list1, instr :: list2) |
16 | | x -> x | ||
20 | 17 | ||
21 | (* Moves the pointer to the next instruction *) | ||
22 | let instptr_move_down = function | 18 | let instptr_move_down = function |
23 | | InstPtr(list1, []) -> InstPtr(list1, []) | ||
24 | | InstPtr(list1, instr :: list2) -> InstPtr(instr :: list1, list2) | 19 | | InstPtr(list1, instr :: list2) -> InstPtr(instr :: list1, list2) |
20 | | x -> x | ||
25 | 21 | ||
26 | (* Returns the couple from the current pointer position : (line, instruction) where instruction is an urm command or fails if there is no instruction pointed *) | ||
27 | let instptr_get = function | 22 | let instptr_get = function |
28 | | InstPtr(list1, (l, Zero(a)) :: tail)-> (l, Zero(a)) | 23 | | InstPtr(_, x :: _) -> x |
29 | | InstPtr(list1, (l, Succ(a)) :: tail) -> (l, Succ(a)) | 24 | | InstPtr(_, []) -> failwith "No instruction left" |
30 | | InstPtr(list1, (l, Copy(a, b)) :: tail) -> (l, Copy(a, b)) | ||
31 | | InstPtr(list1, (l, Jump(a, b, c)) :: tail) -> (l, Jump(a, b, c)) | ||
32 | | InstPtr(_, [])-> failwith "No instruction left" | ||
33 | 25 | ||
34 | (* Converts the current instruction pointed into a string (line and instruction formatted). If there is no instruction, returns "null" *) | ||
35 | let instptr_string instptr = | 26 | let instptr_string instptr = |
36 | let aux = function | 27 | let string_of_inst = function |
37 | | l, Zero(a) -> (string_of_int l) ^ ": Zero " ^ (string_of_int a) | 28 | | Zero(a) -> "Zero " ^ (string_of_int a) |
38 | | l, Succ(a) -> (string_of_int l) ^ ": Succ " ^ (string_of_int a) | 29 | | Succ(a) -> "Succ " ^ (string_of_int a) |
39 | | l, Copy(a, b) -> (string_of_int l) ^ ": Copy " ^ (string_of_int a) ^ " " ^ (string_of_int b) | 30 | | Copy(a, b) -> "Copy " ^ (string_of_int a) ^ " " ^ (string_of_int b) |
40 | | l, Jump(a, b, c) -> (string_of_int l) ^ ": Jump " ^ (string_of_int a) ^ " " ^ (string_of_int b) ^ " " ^ (string_of_int c) | 31 | | Jump(a, b, c) -> "Jump " ^ (string_of_int a) ^ " " ^ (string_of_int b) ^ " " ^ (string_of_int c) |
41 | in try aux (instptr_get instptr) with _ -> "null" | 32 | in let string_of_instptr (l, inst) = (string_of_int l) ^ ": " ^ string_of_inst inst |
42 | 33 | in try string_of_instptr (instptr_get instptr) with _ -> "null" | |
43 | (* Returns true if the instruction pointer is not pointing on any instruction (end of the instruction list) *) | 34 | |
44 | let instptr_end = function | 35 | let instptr_end = function |
45 | | InstPtr(_, []) -> true | 36 | | InstPtr(_, []) -> true |
46 | | _ -> false | 37 | | _ -> false |
@@ -49,3 +40,4 @@ let rec instptr_jump ptr offset = match offset with | |||
49 | | 0 -> ptr | 40 | | 0 -> ptr |
50 | | _ when offset > 0 -> instptr_jump (instptr_move_up ptr) (offset - 1) | 41 | | _ when offset > 0 -> instptr_jump (instptr_move_up ptr) (offset - 1) |
51 | | _ -> instptr_jump (instptr_move_down ptr) (offset + 1) | 42 | | _ -> instptr_jump (instptr_move_down ptr) (offset + 1) |
43 | |||
@@ -9,3 +9,22 @@ open Instptr | |||
9 | open Reg | 9 | open Reg |
10 | open Urm | 10 | open Urm |
11 | 11 | ||
12 | let exec_with_resource func filename = | ||
13 | let file = open_in filename in | ||
14 | let res = func file in | ||
15 | close_in file; res | ||
16 | |||
17 | let read_prgm = exec_with_resource (fun f -> string_of_file f |> program_of_string) | ||
18 | let read_regs = exec_with_resource (fun f -> string_of_file f |> regs_of_string) | ||
19 | let run run_func prgm regs = urm_mk prgm regs |> run_func |> regs_string |> print_endline | ||
20 | |||
21 | let run_mode_of_string = function | ||
22 | | "run" -> urm_run | ||
23 | | "trace" -> urm_run_trace | ||
24 | | _ -> failwith "Invalid run mode" | ||
25 | |||
26 | let () = match Sys.argv with | ||
27 | | [| _; "run-tests" |] -> () (* handled in test files *) | ||
28 | | [| _; mode; prgm; regs |] -> run (run_mode_of_string mode) (read_prgm prgm) (read_regs regs) | ||
29 | | _ -> print_endline "Usage: urm <run-tests | run <prgmfile> <regfile> | trace <prgmfile> <regfile>>" | ||
30 | |||
@@ -7,7 +7,8 @@ SOURCES = \ | |||
7 | instptr.mli instptr.ml \ | 7 | instptr.mli instptr.ml \ |
8 | reg.mli reg.ml \ | 8 | reg.mli reg.ml \ |
9 | urm.mli urm.ml urm_test.ml \ | 9 | urm.mli urm.ml urm_test.ml \ |
10 | eurm.mli eurm.ml eurm_test.ml | 10 | eurm.mli eurm.ml eurm_test.ml \ |
11 | main.ml | ||
11 | 12 | ||
12 | OCAMLMAKEFILE = /usr/share/ocamlmakefile/OCamlMakefile | 13 | OCAMLMAKEFILE = /usr/share/ocamlmakefile/OCamlMakefile |
13 | include $(OCAMLMAKEFILE) | 14 | include $(OCAMLMAKEFILE) |
@@ -13,12 +13,20 @@ let rec string_of_file f = | |||
13 | 13 | ||
14 | let rec program_of_lex = function | 14 | let rec program_of_lex = function |
15 | | [] -> [] | 15 | | [] -> [] |
16 | | "zero" :: arg_1 :: tail -> (Zero (int_of_string arg_1)) :: (program_of_lex tail) | 16 | | instr :: tail -> match (String.lowercase_ascii instr) :: tail with |
17 | | "succ" :: arg_1 :: tail -> (Succ (int_of_string arg_1)) :: (program_of_lex tail) | 17 | | "zero" :: arg_1 :: tail -> (Zero (int_of_string arg_1)) :: (program_of_lex tail) |
18 | | "copy" :: arg_1 :: arg_2 :: tail -> (Copy ((int_of_string arg_1), (int_of_string arg_2))) :: (program_of_lex tail) | 18 | | "succ" :: arg_1 :: tail -> (Succ (int_of_string arg_1)) :: (program_of_lex tail) |
19 | | "jump" :: arg_1 :: arg_2 :: arg_3 :: tail -> (Jump ((int_of_string arg_1), (int_of_string arg_2), (int_of_string arg_3))) :: (program_of_lex tail) | 19 | | "copy" :: arg_1 :: arg_2 :: tail -> (Copy ((int_of_string arg_1), (int_of_string arg_2))) :: (program_of_lex tail) |
20 | | "jump" :: arg_1 :: arg_2 :: arg_3 :: tail -> (Jump ((int_of_string arg_1), (int_of_string arg_2), (int_of_string arg_3))) :: (program_of_lex tail) | ||
21 | | _ -> raise Syntax_error | ||
22 | |||
23 | (* FIXME: reject multiple definition of a single register *) | ||
24 | let rec regs_of_lex = function | ||
25 | | [] -> [] | ||
26 | | regnum :: regvalue :: tail -> Reg (int_of_string regnum, int_of_string regvalue) :: (regs_of_lex tail) | ||
20 | | _ -> raise Syntax_error | 27 | | _ -> raise Syntax_error |
21 | 28 | ||
22 | let program_of_string str = | 29 | let seq_from_string lexer_func str = Str.split (Str.regexp "[\t\n(), ]+") str |> lexer_func |
23 | let lex = Str.split (Str.regexp "[\t\n(),]+") str | 30 | let program_of_string = seq_from_string program_of_lex |
24 | in List.iter (fun s -> print_string s; print_newline ()) lex; program_of_lex lex | 31 | let regs_of_string = seq_from_string regs_of_lex |
32 | |||
@@ -11,5 +11,12 @@ val string_of_file : in_channel -> string | |||
11 | (* Converts lexemes into instructions. *) | 11 | (* Converts lexemes into instructions. *) |
12 | val program_of_lex : string list -> urmcmd list | 12 | val program_of_lex : string list -> urmcmd list |
13 | 13 | ||
14 | (* Converts lexemes into registers. *) | ||
15 | val regs_of_lex : string list -> reg list | ||
16 | |||
14 | (* Parses the string representation of a program. *) | 17 | (* Parses the string representation of a program. *) |
15 | val program_of_string : string -> urmcmd list | 18 | val program_of_string : string -> urmcmd list |
19 | |||
20 | (* Parses the string representation of serialized registers. *) | ||
21 | val regs_of_string : string -> reg list | ||
22 | |||
@@ -7,10 +7,10 @@ open Common | |||
7 | 7 | ||
8 | let reg_idx (Reg(idx, _)) = idx | 8 | let reg_idx (Reg(idx, _)) = idx |
9 | let reg_val (Reg(_, value)) = value | 9 | let reg_val (Reg(_, value)) = value |
10 | let reg_compar reg1 reg2 = (reg_val reg1) - (reg_val reg2) | 10 | let reg_compar l r = (reg_val l) - (reg_val r) |
11 | let reg_string (Reg (index, value)) = "(" ^ (string_of_int index) ^ "," ^ (string_of_int value) ^ ")" | ||
11 | 12 | ||
12 | let regs_get reglist idx = | 13 | let regs_get reglist index = List.find (fun (Reg(idx, _)) -> idx = index) reglist |> reg_val |
13 | List.find (fun (Reg(x,v)) -> x = idx) reglist |> reg_val | 14 | let regs_set reglist index value = Reg(index, value) :: List.filter (fun (Reg(idx, _)) -> idx != index) reglist |
14 | 15 | let regs_sort = List.sort (fun (Reg(l, _)) (Reg(r, _)) -> compare l r) | |
15 | let regs_set reglist index value = | 16 | let regs_string reglist = regs_sort reglist |> List.map (reg_string) |> String.concat "," |
16 | Reg(index, value) :: List.filter (fun (Reg(x, v)) -> x != index) reglist | ||
@@ -21,3 +21,9 @@ val regs_get : reg list -> regidx -> regval | |||
21 | (* Set the value of the register to value, | 21 | (* Set the value of the register to value, |
22 | * or creates it to the value specified if it does not exist *) | 22 | * or creates it to the value specified if it does not exist *) |
23 | val regs_set : reg list -> regidx -> regval -> reg list | 23 | val regs_set : reg list -> regidx -> regval -> reg list |
24 | |||
25 | (* Sorts a list of registers in ascending index order *) | ||
26 | val regs_sort : reg list -> reg list | ||
27 | |||
28 | (* Returns the string representation of a register list. *) | ||
29 | val regs_string : reg list -> string | ||
@@ -23,12 +23,19 @@ let urm_apply urm = | |||
23 | | _, _ -> { instptr = urm.instptr ; regs = urm.regs } |> urm_move_down | 23 | | _, _ -> { instptr = urm.instptr ; regs = urm.regs } |> urm_move_down |
24 | in if instptr_end urm.instptr then urm else aux (instptr_get urm.instptr) | 24 | in if instptr_end urm.instptr then urm else aux (instptr_get urm.instptr) |
25 | 25 | ||
26 | (* Launches the URM *) | 26 | let rec urm_run_pre pre = function |
27 | let rec urm_run = function | ||
28 | | { instptr = InstPtr(_, []) ; regs = reg_list } -> reg_list | 27 | | { instptr = InstPtr(_, []) ; regs = reg_list } -> reg_list |
29 | | urm -> urm_apply urm |> urm_run | 28 | | urm -> pre urm; urm_apply urm |> urm_run_pre pre |
30 | 29 | ||
31 | let urm_run_trace = urm_run (* TODO *) | 30 | let urm_run = urm_run_pre (fun _ -> ()) |
31 | |||
32 | let urm_run_trace = | ||
33 | let print_func u = | ||
34 | print_endline (instptr_string u.instptr); | ||
35 | print_endline (regs_string u.regs); | ||
36 | print_newline () | ||
37 | in urm_run_pre (print_func) | ||
32 | 38 | ||
33 | (* Creates an URM from a command list and a register list *) |