diff options
-rw-r--r-- | README.md | 21 | ||||
l--------- | common.ml | 1 | ||||
-rw-r--r-- | common.mli | 24 | ||||
-rw-r--r-- | instptr.ml | 51 | ||||
-rw-r--r-- | instptr.mli | 29 | ||||
-rw-r--r-- | main.ml | 10 | ||||
-rw-r--r-- | makefile | 11 | ||||
-rw-r--r-- | parser.ml | 24 | ||||
-rw-r--r-- | parser.mli | 15 | ||||
-rw-r--r-- | projet.ml | 122 | ||||
-rw-r--r-- | reg.ml | 16 | ||||
-rw-r--r-- | reg.mli | 23 | ||||
-rw-r--r-- | urm.ml | 34 | ||||
-rw-r--r-- | urm.mli | 17 |
14 files changed, 275 insertions, 123 deletions
@@ -1 +1,20 @@ | |||
1 | # upem-progfunc-projet \ No newline at end of file | 1 | # UPEM / L3 Info / Functional programming / Project: URM |
2 | |||
3 | Unlimited Register Machine in OCaml. | ||
4 | |||
5 | ## Usage | ||
6 | |||
7 | * Requirements: ocaml, GNU Make, OCaml Makefile | ||
8 | * Build: `make nc` produces a binary named `urm` | ||
9 | * Clean: `make clean` | ||
10 | |||
11 | |||
12 | ## Authors | ||
13 | |||
14 | * Pacien TRAN-GIRARD | ||
15 | * Adam NAILI | ||
16 | |||
17 | |||
18 | ## License | ||
19 | |||
20 | Project distributed under the terms of the Creative Commons BY-NC-SA 3.0 license. | ||
diff --git a/common.ml b/common.ml new file mode 120000 index 0000000..ed50e6f --- /dev/null +++ b/common.ml | |||
@@ -0,0 +1 @@ | |||
common.mli \ No newline at end of file | |||
diff --git a/common.mli b/common.mli new file mode 100644 index 0000000..a62b083 --- /dev/null +++ b/common.mli | |||
@@ -0,0 +1,24 @@ | |||
1 | (* | ||
2 | * UPEM / L3 / Functional programming / Project: URM | ||
3 | * Pacien TRAN-GIRARD, Adam NAILI | ||
4 | *) | ||
5 | |||
6 | type line = int | ||
7 | type regidx = int | ||
8 | type regval = int | ||
9 | type reg = Reg of regidx * regval | ||
10 | |||
11 | type urmcmd = | ||
12 | | Copy of regidx * regidx | ||
13 | | Jump of regidx * regidx * line | ||
14 | | Succ of regidx | ||
15 | | Zero of regidx | ||
16 | |||
17 | type instptr = InstPtr of (line * urmcmd) list * (line * urmcmd) list | ||
18 | |||
19 | type urm = { | ||
20 | instptr : instptr; | ||
21 | regs : reg list | ||
22 | } | ||
23 | |||
24 | exception Syntax_error | ||
diff --git a/instptr.ml b/instptr.ml new file mode 100644 index 0000000..9e472c4 --- /dev/null +++ b/instptr.ml | |||
@@ -0,0 +1,51 @@ | |||
1 | (* | ||
2 | * UPEM / L3 / Functional programming / Project: URM | ||
3 | * Pacien TRAN-GIRARD, Adam NAILI | ||
4 | *) | ||
5 | |||
6 | open Common | ||
7 | |||
8 | (* Creates a pointer of instruction from an urm command list *) | ||
9 | let instptr_mk urmcmd_list = | ||
10 | let rec aux urmcmd_list count acc = | ||
11 | match urmcmd_list with | ||
12 | | [] -> acc | ||
13 | | instr :: tail -> aux tail (count + 1) ((count, instr) :: acc) | ||
14 | in InstPtr([], List.rev (aux urmcmd_list 0 [])) | ||
15 | |||
16 | (* Moves the pointer to the previous instruction *) | ||
17 | let instptr_move_up = function | ||
18 | | InstPtr([], list2) -> InstPtr([], list2) | ||
19 | | InstPtr(instr :: list1, list2) -> InstPtr(list1, instr :: list2) | ||
20 | |||
21 | (* Moves the pointer to the next instruction *) | ||
22 | let instptr_move_down = function | ||
23 | | InstPtr(list1, []) -> InstPtr(list1, []) | ||
24 | | InstPtr(list1, instr :: list2) -> InstPtr(instr :: list1, list2) | ||
25 | |||
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 | ||
28 | | InstPtr(list1, (l, Zero(a)) :: tail)-> (l, Zero(a)) | ||
29 | | InstPtr(list1, (l, Succ(a)) :: tail) -> (l, Succ(a)) | ||
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 | |||
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 = | ||
36 | let aux = function | ||
37 | | l, Zero(a) -> (string_of_int l) ^ ": Zero " ^ (string_of_int a) | ||
38 | | l, Succ(a) -> (string_of_int l) ^ ": Succ " ^ (string_of_int a) | ||
39 | | l, Copy(a, b) -> (string_of_int l) ^ ": 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) | ||
41 | in try aux (instptr_get instptr) with _ -> "null" | ||
42 | |||
43 | (* Returns true if the instruction pointer is not pointing on any instruction (end of the instruction list) *) | ||
44 | let instptr_end = function | ||
45 | | InstPtr(_, []) -> true | ||
46 | | _ -> false | ||
47 | |||
48 | let rec instptr_jump ptr offset = match offset with | ||
49 | | 0 -> ptr | ||
50 | | _ when offset > 0 -> instptr_jump (instptr_move_up ptr) (offset - 1) | ||
51 | | _ -> instptr_jump (instptr_move_down ptr) (offset + 1) | ||
diff --git a/instptr.mli b/instptr.mli new file mode 100644 index 0000000..f1252b5 --- /dev/null +++ b/instptr.mli | |||
@@ -0,0 +1,29 @@ | |||
1 | (* | ||
2 | * UPEM / L3 / Functional programming / Project: URM | ||
3 | * Pacien TRAN-GIRARD, Adam NAILI | ||
4 | *) | ||
5 | |||
6 | open Common | ||
7 | |||
8 | (* Create an instruction pointer for an URM program. *) | ||
9 | val instptr_mk : urmcmd list -> instptr | ||
10 | |||
11 | (* Move the instruction pointer up. Do nothing if this is not possible. *) | ||
12 | val instptr_move_up : instptr -> instptr | ||
13 | |||
14 | (* Move the instruction pointer down. Do nothing if this is not possible. *) | ||
15 | val instptr_move_down : instptr -> instptr | ||
16 | |||
17 | (* Get the current command from the instruction pointer. | ||
18 | * Fail if the command pointer is not set on a valid command. *) | ||
19 | val instptr_get : instptr -> line * urmcmd | ||
20 | |||
21 | (* Get the current instruction as a string. | ||
22 | * Returns "null" is the instruction pointer is not valid. *) | ||
23 | val instptr_string : instptr -> string | ||
24 | |||
25 | (* Returns the pointer of instruction after a jump decided by the given offse t *) | ||
26 | val instptr_jump : instptr -> int -> instptr | ||
27 | |||
28 | (* Returns true if the instruction pointer is not pointing on any instruction (end of the instruction list) *) | ||
29 | val instptr_end : instptr -> bool | ||
@@ -0,0 +1,10 @@ | |||
1 | (* | ||
2 | * UPEM / L3 / Functional programming / Project: URM | ||
3 | * Pacien TRAN-GIRARD, Adam NAILI | ||
4 | *) | ||
5 | |||
6 | open Common | ||
7 | open Parser | ||
8 | open Instptr | ||
9 | open Reg | ||
10 | open Urm | ||
diff --git a/makefile b/makefile new file mode 100644 index 0000000..f027be5 --- /dev/null +++ b/makefile | |||
@@ -0,0 +1,11 @@ | |||
1 | RESULT = urm | ||
2 | LIBS = str | ||
3 | SOURCES = \ | ||
4 | common.ml \ | ||
5 | parser.mli parser.ml \ | ||
6 | instptr.mli instptr.ml \ | ||
7 | reg.mli reg.ml \ | ||
8 | urm.mli urm.ml | ||
9 | |||
10 | OCAMLMAKEFILE = /usr/share/ocamlmakefile/OCamlMakefile | ||
11 | include $(OCAMLMAKEFILE) | ||
diff --git a/parser.ml b/parser.ml new file mode 100644 index 0000000..e01208f --- /dev/null +++ b/parser.ml | |||
@@ -0,0 +1,24 @@ | |||
1 | (* | ||
2 | * UPEM / L3 / Functional programming / Project: URM | ||
3 | * Pacien TRAN-GIRARD, Adam NAILI | ||
4 | *) | ||
5 | |||
6 | open Common | ||
7 | |||
8 | let rec string_of_file f = | ||
9 | try | ||
10 | let str = input_line f | ||
11 | in str ^ " " ^ (string_of_file f) | ||
12 | with End_of_file -> "" | ||
13 | |||
14 | let rec program_of_lex = function | ||
15 | | [] -> [] | ||
16 | | "zero" :: arg_1 :: tail -> (Zero (int_of_string arg_1)) :: (program_of_lex tail) | ||
17 | | "succ" :: arg_1 :: tail -> (Succ (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) | ||
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) | ||
20 | | _ -> raise Syntax_error | ||
21 | |||
22 | let program_of_string str = | ||
23 | let lex = Str.split (Str.regexp "[\t\n(),]+") str | ||
24 | in List.iter (fun s -> print_string s; print_newline ()) lex; program_of_lex lex | ||
diff --git a/parser.mli b/parser.mli new file mode 100644 index 0000000..d210396 --- /dev/null +++ b/parser.mli | |||
@@ -0,0 +1,15 @@ | |||
1 | (* | ||
2 | * UPEM / L3 / Functional programming / Project: URM | ||
3 | * Pacien TRAN-GIRARD, Adam NAILI | ||
4 | *) | ||
5 | |||
6 | open Common | ||
7 | |||
8 | (* Reads a file into a string. *) | ||
9 | val string_of_file : in_channel -> string | ||
10 | |||
11 | (* Converts lexemes into instructions. *) | ||
12 | val program_of_lex : string list -> urmcmd list | ||
13 | |||
14 | (* Parses the string representation of a program. *) | ||
15 | val program_of_string : string -> urmcmd list | ||
diff --git a/projet.ml b/projet.ml deleted file mode 100644 index 67e6221..0000000 --- a/projet.ml +++ /dev/null | |||
@@ -1,122 +0,0 @@ | |||
1 | #load "str.cma" | ||
2 | |||
3 | type line = int | ||
4 | type regidx = int | ||
5 | type regval = int | ||
6 | type reg = Reg of regidx * regval | ||
7 | |||
8 | type urmcmd = | ||
9 | | Copy of regidx * regidx | ||
10 | | Jump of regidx * regidx * line | ||
11 | | Succ of regidx | ||
12 | | Zero of regidx | ||
13 | |||
14 | type instptr = InstPtr of (line * urmcmd) list * (line * urmcmd) list | ||
15 | |||
16 | type urm = { | ||
17 | instptr : instptr; | ||
18 | regs : reg list | ||
19 | } | ||
20 | |||
21 | exception Syntax_error | ||
22 | |||
23 | let rec string_of_file f = | ||
24 | try | ||
25 | let str = input_line f | ||
26 | in str ^ " " ^ (string_of_file f) | ||
27 | with End_of_file -> "" | ||
28 | |||
29 | let rec program_of_lex = function | ||
30 | | [] -> [] | ||
31 | | "zero" :: arg_1 :: tail -> (Zero (int_of_string arg_1)) :: (program_of_lex tail) | ||
32 | | "succ" :: arg_1 :: tail -> (Succ (int_of_string arg_1)) :: (program_of_lex tail) | ||
33 | | "copy" :: arg_1 :: arg_2 :: tail -> (Copy ((int_of_string arg_1), (int_of_string arg_2))) :: (program_of_lex tail) | ||
34 | | "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) | ||
35 | | _ -> raise Syntax_error | ||
36 | |||
37 | let program_of_string str = | ||
38 | let lex = Str.split (Str.regexp "[\t\n(),]+") str | ||
39 | in List.iter (fun s -> print_string s; print_newline ()) lex; program_of_lex lex | ||
40 | |||
41 | (* Creates a pointer of instruction from an urm command list *) | ||
42 | let instptr_mk urmcmd_list = | ||
43 | let rec aux urmcmd_list count acc = | ||
44 | match urmcmd_list with | ||
45 | | [] -> acc | ||
46 | | instr :: tail -> aux tail (count + 1) ((count, instr) :: acc) | ||
47 | in InstPtr([], List.rev (aux urmcmd_list 0 [])) | ||
48 | |||
49 | (* Moves the pointer to the previous instruction *) | ||
50 | let instptr_move_up = function | ||