diff --git a/main.ml b/main.ml
@@ -1,74 +1,90 @@
open List
-let usage = "USAGE: urm [-i ITERS] REGS FILE"
+let usage () =
+ Printf.printf "USAGE: urm [-i ITERS] 'R0 R1 ...' FILE\n";
+ Printf.printf "See urm.1 for additional information\n"
let default_max_iters = 1000
+(** An equivalent to Haskell's [sequence] *)
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 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 =
+
+(** Execute the program from [file] with initial register values given by
+ [regs] and the maximum number of allowed iterations set to [iters] *)
+let main iters regs file =
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))
+ let regs_strs =
+ List.map
+ (Printf.sprintf "%d")
+ (List.init (Array.length regs) (Urm.register m))
+ in Printf.printf "%s\n" (String.concat " " regs_strs)
| 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
+ 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
-
+(** Initial parsing of the command-line arguments: get the strings out *)
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
+ n
| Some n ->
- Printf.eprintf
- "ERROR: negative number of maximum iterations provided: %d\n" n;
- Printf.eprintf "Expected a positive integers\n";
- exit 1
+ Printf.eprintf
+ "ERROR: negative number of maximum iterations provided: %d\n" n;
+ Printf.eprintf "Expected a positive integers\n";
+ usage ();
+ 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
+ Printf.eprintf
+ "ERROR: invalid number of maximum iterations provided: '%s'\n"
+ iters_str;
+ Printf.eprintf "Expected a positive integers\n";
+ usage ();
+ exit 1
in
match Sys.argv with
| [| _ ; "-i" ; iters_str ; regs ; filepath |] ->
- (parse_iters iters_str, regs, filepath)
+ (parse_iters iters_str, regs, filepath)
| [| _ ; regs ; filepath |] ->
- (default_max_iters, regs, filepath)
+ (default_max_iters, regs, filepath)
| argv when Array.length argv < 3 ->
Printf.eprintf "ERROR: not enought arguments provided\n";
+ usage ();
exit 1
| _ ->
Printf.eprintf "ERROR: invalid arguments provided\n";
+ usage ();
exit 1
+(** Parse the initial values of the registers as a list of ints separated by
+ spaces *)
let regs =
match seq (map int_of_string_opt (String.split_on_char ' ' regs_str)) with
| Some regs ->
- 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
+ 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";
+ usage ();
+ exit 1
+(** Try to open the file with the contents of the program *)
let file =
try
open_in filepath
@@ -76,4 +92,5 @@ let file =
Printf.eprintf "ERROR: %s\n" err;
exit 1
-let () = exec_file iters (Array.of_list regs) file
+let () = main iters (Array.of_list regs) file
+