module IntexInterp = struct open Intex exception EvalError of string let rec run (Pgm(n,body)) ints = let len = List.length ints in if n = len then eval body ints else raise (EvalError ("Program expected " ^ (string_of_int n) ^ " arguments but got " ^ (string_of_int len))) (* direct version *) and eval exp args = match exp with Lit i -> i | Arg index -> if (index <= 0) || (index > List.length args) then raise (EvalError("Illegal arg index: " ^ (string_of_int index))) else List.nth args (index - 1) | BinApp(op,rand1,rand2) -> primApply op (eval rand1 args) (eval rand2 args) (* (* fold-based version *) and eval exp = fold (fun i -> (fun args -> i)) (fun index -> (fun args -> if (index <= 0) || (index > List.length args) then raise (EvalError("Illegal arg index: " ^ (string_of_int index))) else List.nth args (index - 1))) (fun op fun1 fun2 -> (fun args -> primApply op (fun1 args) (fun2 args))) exp *) and primApply binop x y = match binop with Add -> x + y | Sub -> x - y | Mul -> x * y | Div -> if y = 0 then raise (EvalError ("Division by 0: " ^ (string_of_int x))) else x / y | Rem -> if y = 0 then raise (EvalError ("Remainder by 0: " ^ (string_of_int x))) else x mod y (* An interactive read-eval-print loop (REPL) for Intex expressions. By default, assumes zero arguments, but this can be changed with the #args directive (see below). The following directives are supported: + (#args i_1 ... i_n): Install the n integers i_ 1 ... i_n as the current program arguments + (#quit): Exit the interpreter *) let repl () = let print = StringUtils.print in let sexpToint sexp = (* sexpToint : sexp -> int *) match sexp with Sexp.Int(i) -> i | _ -> raise (Failure "Not an int!") in let rec loop args = let _ = print "\n\nintex> " in let line = read_line () in match (Sexp.stringToSexp line) with Sexp.Seq [Sexp.Sym "#quit"] -> print "\ndone\n" | Sexp.Seq ((Sexp.Sym "#args") :: ints) -> loop (List.map sexpToint ints) | _ -> try (print (string_of_int (eval (stringToExp line) args)); loop args) with EvalError s -> (print ("Error: " ^ s); loop args) | SyntaxError s -> (print ("Error: " ^ s); loop args) in loop [] end