aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md6
-rw-r--r--examples/add.reg2
-rw-r--r--examples/add.urm11
-rw-r--r--instptr.ml36
-rw-r--r--main.ml19
-rw-r--r--makefile3
-rw-r--r--parser.ml22
-rw-r--r--parser.mli7
-rw-r--r--reg.ml12
-rw-r--r--reg.mli6
-rw-r--r--urm.ml15
-rw-r--r--urm_test.ml7
12 files changed, 101 insertions, 45 deletions
diff --git a/README.md b/README.md
index 2971b4c..2cce7bf 100644
--- a/README.md
+++ b/README.md
@@ -19,7 +19,11 @@ Unlimited Register Machine in OCaml.
19 19
20## Usage 20## Usage
21 21
22TODO: describe usage of the `urm` program. 22```
23./urm <run | trace> <program file> <initial register state file>
24```
25
26Examples 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 @@
11 2
22 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 @@
1ZERO 0
2ZERO 3
3JUMP 1 3 6
4SUCC 0
5SUCC 3
6JUMP 3 3 2
7ZERO 3
8JUMP 2 3 11
9SUCC 0
10SUCC 3
11JUMP 3 3 7
diff --git a/instptr.ml b/instptr.ml
index 9e472c4..0311a00 100644
--- a/instptr.ml
+++ b/instptr.ml
@@ -5,42 +5,33 @@
5 5
6open Common 6open Common
7 7
8(* Creates a pointer of instruction from an urm command list *)
9let instptr_mk urmcmd_list = 8let 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 *)
17let instptr_move_up = function 14let 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 *)
22let instptr_move_down = function 18let 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 *)
27let instptr_get = function 22let 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" *)
35let instptr_string instptr = 26let 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
44let instptr_end = function 35let 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
diff --git a/main.ml b/main.ml
index 1bb6704..2f8d57c 100644
--- a/main.ml
+++ b/main.ml
@@ -9,3 +9,22 @@ open Instptr
9open Reg 9open Reg
10open Urm 10open Urm
11 11
12let exec_with_resource func filename =
13 let file = open_in filename in
14 let res = func file in
15 close_in file; res
16
17let read_prgm = exec_with_resource (fun f -> string_of_file f |> program_of_string)
18let read_regs = exec_with_resource (fun f -> string_of_file f |> regs_of_string)
19let run run_func prgm regs = urm_mk prgm regs |> run_func |> regs_string |> print_endline
20
21let run_mode_of_string = function
22 | "run" -> urm_run
23 | "trace" -> urm_run_trace
24 | _ -> failwith "Invalid run mode"
25
26let () = 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
diff --git a/makefile b/makefile
index 4179bf2..6aceab8 100644
--- a/makefile
+++ b/makefile
@@ -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
12OCAMLMAKEFILE = /usr/share/ocamlmakefile/OCamlMakefile 13OCAMLMAKEFILE = /usr/share/ocamlmakefile/OCamlMakefile
13include $(OCAMLMAKEFILE) 14include $(OCAMLMAKEFILE)
diff --git a/parser.ml b/parser.ml
index e01208f..1f367d1 100644
--- a/parser.ml
+++ b/parser.ml
@@ -13,12 +13,20 @@ let rec string_of_file f =
13 13
14let rec program_of_lex = function 14let 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 *)
24let 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
22let program_of_string str = 29let 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 30let 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 31let regs_of_string = seq_from_string regs_of_lex
32
diff --git a/parser.mli b/parser.mli
index d210396..f7609f9 100644
--- a/parser.mli
+++ b/parser.mli
@@ -11,5 +11,12 @@ val string_of_file : in_channel -> string
11(* Converts lexemes into instructions. *) 11(* Converts lexemes into instructions. *)
12val program_of_lex : string list -> urmcmd list 12val program_of_lex : string list -> urmcmd list
13 13
14(* Converts lexemes into registers. *)
15val regs_of_lex : string list -> reg list
16
14(* Parses the string representation of a program. *) 17(* Parses the string representation of a program. *)
15val program_of_string : string -> urmcmd list 18val program_of_string : string -> urmcmd list
19
20(* Parses the string representation of serialized registers. *)
21val regs_of_string : string -> reg list
22
diff --git a/reg.ml b/reg.ml
index b27a868..56c4ae6 100644
--- a/reg.ml
+++ b/reg.ml
@@ -7,10 +7,10 @@ open Common
7 7
8let reg_idx (Reg(idx, _)) = idx 8let reg_idx (Reg(idx, _)) = idx
9let reg_val (Reg(_, value)) = value 9let reg_val (Reg(_, value)) = value
10let reg_compar reg1 reg2 = (reg_val reg1) - (reg_val reg2) 10let reg_compar l r = (reg_val l) - (reg_val r)
11let reg_string (Reg (index, value)) = "(" ^ (string_of_int index) ^ "," ^ (string_of_int value) ^ ")"
11 12
12let regs_get reglist idx = 13let 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 14let regs_set reglist index value = Reg(index, value) :: List.filter (fun (Reg(idx, _)) -> idx != index) reglist
14 15let regs_sort = List.sort (fun (Reg(l, _)) (Reg(r, _)) -> compare l r)
15let regs_set reglist index value = 16let 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
diff --git a/reg.mli b/reg.mli
index 15d53de..6e81259 100644
--- a/reg.mli
+++ b/reg.mli
@@ -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 *)
23val regs_set : reg list -> regidx -> regval -> reg list 23val regs_set : reg list -> regidx -> regval -> reg list
24
25(* Sorts a list of registers in ascending index order *)
26val regs_sort : reg list -> reg list
27
28(* Returns the string representation of a register list. *)
29val regs_string : reg list -> string
diff --git a/urm.ml b/urm.ml
index 49e970b..3b7068b 100644
--- a/urm.ml
+++ b/urm.ml
@@ -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 *) 26let rec urm_run_pre pre = function
27let 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
31let urm_run_trace = urm_run (* TODO *) 30let urm_run = urm_run_pre (fun _ -> ())
31
32let 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 *)