caml-urm

A OCaml module for manipulating unlimited register machines

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

Diffstat

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