aboutsummaryrefslogtreecommitdiff
path: root/ocaml/step2_eval.ml
diff options
context:
space:
mode:
authorJoel Martin <github@martintribe.org>2015-01-30 12:06:45 -0600
committerJoel Martin <github@martintribe.org>2015-01-30 12:06:45 -0600
commit644e5ff95e186094054221cf2f13048630f81fa0 (patch)
tree14f965eee633f4ea185f640c6130e54063056d6b /ocaml/step2_eval.ml
parentbf518367d0706b2fa727acc5326230ef8d3c812b (diff)
parentbc6448bce925d18ecb893e8e8ee10d2b2178b31a (diff)
downloadmal-644e5ff95e186094054221cf2f13048630f81fa0.tar.gz
mal-644e5ff95e186094054221cf2f13048630f81fa0.zip
Merge pull request #3 from Chouser/ocaml
Ocaml
Diffstat (limited to 'ocaml/step2_eval.ml')
-rw-r--r--ocaml/step2_eval.ml64
1 files changed, 64 insertions, 0 deletions
diff --git a/ocaml/step2_eval.ml b/ocaml/step2_eval.ml
new file mode 100644
index 0000000..3778292
--- /dev/null
+++ b/ocaml/step2_eval.ml
@@ -0,0 +1,64 @@
+module T = Types.Types
+
+module Env =
+ Map.Make (
+ String
+ (*(struct
+ type t = Types.Symbol
+ let compare (Types.Symbol a) (Types.Symbol b) = compare a b
+ end)*)
+ )
+
+let num_fun f = Types.fn
+ (function
+ | [(T.Int a); (T.Int b)] -> T.Int (f a b)
+ | _ -> raise (Invalid_argument "Numeric args required for this Mal builtin"))
+
+let repl_env = ref (List.fold_left (fun a b -> b a) Env.empty
+ [ Env.add "+" (num_fun ( + ));
+ Env.add "-" (num_fun ( - ));
+ Env.add "*" (num_fun ( * ));
+ Env.add "/" (num_fun ( / )) ])
+
+let rec eval_ast ast env =
+ match ast with
+ | T.Symbol { T.value = s } ->
+ (try Env.find s !env
+ with Not_found -> raise (Invalid_argument ("Symbol '" ^ s ^ "' not found")))
+ | T.List { T.value = xs; T.meta = meta }
+ -> T.List { T.value = (List.map (fun x -> eval x env) xs);
+ T.meta = meta }
+ | T.Vector { T.value = xs; T.meta = meta }
+ -> T.Vector { T.value = (List.map (fun x -> eval x env) xs);
+ T.meta = meta }
+ | T.Map { T.value = xs; T.meta = meta }
+ -> T.Map {T.meta = meta;
+ T.value = (Types.MalMap.fold
+ (fun k v m
+ -> Types.MalMap.add (eval k env) (eval v env) m)
+ xs
+ Types.MalMap.empty)}
+ | _ -> ast
+and eval ast env =
+ let result = eval_ast ast env in
+ match result with
+ | T.List { T.value = ((T.Fn { T.value = f }) :: args) } -> (f args)
+ | _ -> result
+
+let read str = Reader.read_str str
+let print exp = Printer.pr_str exp true
+let rep str env = print (eval (read str) env)
+
+let rec main =
+ try
+ while true do
+ print_string "user> ";
+ let line = read_line () in
+ try
+ print_endline (rep line repl_env);
+ with End_of_file -> ()
+ | Invalid_argument x ->
+ output_string stderr ("Invalid_argument exception: " ^ x ^ "\n");
+ flush stderr
+ done
+ with End_of_file -> ()