diff --git a/eval.ml b/eval.ml index 9b91817..21b8c1a 100644 --- a/eval.ml +++ b/eval.ml @@ -21,13 +21,13 @@ let rec binop op l r = end | Some f -> f l r -let eval ans ast = +let eval vars ast = let rec aux = function | Value v -> v - | Var v -> - if v = "ans" - then ans - else raise @@ No_such_variable v + | Var v -> begin match Hashtbl.find_opt vars v with + | None -> raise @@ No_such_variable v + | Some v -> v + end | Binop (l, op, r) -> let l = aux l and r = aux r in binop op l r diff --git a/main.ml b/main.ml index 1c0dbef..8bdcad8 100644 --- a/main.ml +++ b/main.ml @@ -18,8 +18,10 @@ let error_to_string e = let print_error e = printf "error: %s\n" @@ error_to_string e +let vars = Hashtbl.create 100 + (* read-eval-print *) -let rep ans : unit = +let rep vars : unit = printf "> "; let line = read_line () in if line = "quit" then raise Exit; @@ -27,27 +29,28 @@ let rep ans : unit = line |> Lex.tokenize |> Parser.parse - |> Eval.eval !ans + |> Eval.eval vars in match v with | Nop -> () | _ -> - ans := v; + Hashtbl.replace vars "ans" v; printf "%s\n" @@ Ast.Value.to_string v let init_repl () = + Hashtbl.replace vars "ans" (Ast.Value.Int 0); + (* treat Ctrl-C as to reset line *) let sigintf _ = raise Reset_line in Sys.(set_signal sigint (Signal_handle sigintf)) (* simple REPL with error handling *) -let rec repl ans : unit = - try rep ans; repl ans with +let rec repl vars : unit = + try rep vars; repl vars with | Exit | End_of_file -> () - | Reset_line -> printf "\n"; repl ans - | e -> print_error e; repl ans + | Reset_line -> printf "\n"; repl vars + | e -> print_error e; repl vars let () = - let ans = ref @@ Ast.Value.Int 0 in init_repl (); printf "Configurable Evaluator %s\n" version; (* banner *) - repl ans + repl vars