- Commit
- 7784b59ebcd514fc5fa7ae0d2be0196327fcbeba
- Parent
- c880518b3ea9533417583163713f60129c63f8d5
- Author
- Pablo <pablo-escobar@riseup.net>
- Date
Created a binary interpreter
Using the OCaml library I wrote a simple interpreter for URM assembly
A OCaml module for manipulating unlimited register machines
Created a binary interpreter
Using the OCaml library I wrote a simple interpreter for URM assembly
3 files changed, 88 insertions, 0 deletions
Status | File Name | N° Changes | Insertions | Deletions |
Modified | .gitignore | 1 | 1 | 0 |
Modified | Makefile | 8 | 8 | 0 |
Added | main.ml | 79 | 79 | 0 |
diff --git a/.gitignore b/.gitignore @@ -1,3 +1,4 @@ *.cmi *.cmx *.o +urm
diff --git a/Makefile b/Makefile @@ -1,5 +1,13 @@ +.PHONY: clean + +urm: urm.mli urm.ml main.ml + ocamlfind ocamlopt -o urm -linkpkg $^ + docs.pdf: urm.mli ocamldoc -latex -o docs.tex urm.mli latexmk -pdflatex docs.tex texclear docs.tex rm docs.tex ocamldoc.sty + +clean: + find . -type f -name '*.cmi' -or -name '*.cmx' -or -name '*.o' | xargs -r rm
diff --git a/main.ml b/main.ml @@ -0,0 +1,79 @@ +open List + +let usage = "USAGE: urm [-i ITERS] REGS FILE" + +let default_max_iters = 1000 + +let seq (xs : 'a option list) : 'a list option = + let f x acc = + Option.join (Option.map (fun y -> Option.map (fun ys -> y :: ys) acc) x) + in List.fold_right f xs (Some []) + +let exec_file (iters : int) (regs : int array) (file : in_channel) : unit = + let contents = really_input_string file (in_channel_length file) in + try + let program = Urm.parse contents + and regs_fn = (fun i -> if i < Array.length regs then regs.(i) else 0) in + match Urm.nexec iters program (Urm.of_registers regs_fn) with + | Some m -> + let final_regs = List.init (Array.length regs) (Urm.register m) in + Printf.printf "%s\n" + (String.concat " " (map (Printf.sprintf "%d") final_regs)) + | None -> + Printf.eprintf + "ERROR: the input program did not halt after %d iterations\n" + iters; + Printf.eprintf "The input program may not halt\n"; + exit 1 + with Urm.Syntax_error err -> Printf.eprintf "ERROR: %s\n" err + + + +let (iters, regs_str, filepath) : int * string * string = + let parse_iters iters_str = + match int_of_string_opt iters_str with + | Some n when n > 0 -> + n + | Some n -> + Printf.eprintf + "ERROR: negative number of maximum iterations provided: %d\n" n; + Printf.eprintf "Expected a positive integers\n"; + exit 1 + | None -> + Printf.eprintf + "ERROR: invalid number of maximum iterations provided: '%s'\n" + iters_str; + Printf.eprintf "Expected a positive integers\n"; + exit 1 + in + match Sys.argv with + | [| _ ; "-i" ; iters_str ; regs ; filepath |] -> + (parse_iters iters_str, regs, filepath) + | [| _ ; regs ; filepath |] -> + (default_max_iters, regs, filepath) + | argv when Array.length argv < 3 -> + Printf.eprintf "ERROR: not enought arguments provided\n"; + exit 1 + | _ -> + Printf.eprintf "ERROR: invalid arguments provided\n"; + exit 1 + +let regs = + match seq (map int_of_string_opt (String.split_on_char ' ' regs_str)) with + | Some regs -> + regs + | None -> + Printf.eprintf + "ERROR: invalid initial values for the registers provided: '%s'\n" + regs_str; + Printf.eprintf "Expected a list of integers separated by spaces\n"; + exit 1 + +let file = + try + open_in filepath + with Sys_error err -> + Printf.eprintf "ERROR: %s\n" err; + exit 1 + +let () = exec_file iters (Array.of_list regs) file