perl: Remove step 0.5.
[jackhill/mal.git] / ocaml / step4_if_fn_do.ml
index 6580dd6..0e0cbaf 100644 (file)
@@ -1,16 +1,32 @@
+module T = Types.Types
+
 let repl_env = Env.make (Some Core.ns)
 
 let rec eval_ast ast env =
   match ast with
-    | Types.Symbol s -> Env.get env ast
-    | Types.MalList xs -> Types.MalList (List.map (fun x -> eval x env) xs)
+    | T.Symbol s -> Env.get env ast
+    | 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 =
   match ast with
-    | Types.MalList [(Types.Symbol "def!"); key; expr] ->
+    | T.List { T.value = [] } -> ast
+    | T.List { T.value = [(T.Symbol { T.value = "def!" }); key; expr] } ->
         let value = (eval expr env) in
           Env.set env key value; value
-    | Types.MalList [(Types.Symbol "let*"); (Types.MalList bindings); body] ->
+    | T.List { T.value = [(T.Symbol { T.value = "let*" }); (T.Vector { T.value = bindings }); body] }
+    | T.List { T.value = [(T.Symbol { T.value = "let*" }); (T.List   { T.value = bindings }); body] } ->
         (let sub_env = Env.make (Some env) in
           let rec bind_pairs = (function
             | sym :: expr :: more ->
@@ -20,19 +36,20 @@ and eval ast env =
             | [] -> ())
             in bind_pairs bindings;
           eval body sub_env)
-    | Types.MalList ((Types.Symbol "do") :: body) ->
-        List.fold_left (fun x expr -> eval expr env) Types.Nil body
-    | Types.MalList [Types.Symbol "if"; test; then_expr; else_expr] ->
+    | T.List { T.value = ((T.Symbol { T.value = "do" }) :: body) } ->
+        List.fold_left (fun x expr -> eval expr env) T.Nil body
+    | T.List { T.value = [T.Symbol { T.value = "if" }; test; then_expr; else_expr] } ->
         if Types.to_bool (eval test env) then (eval then_expr env) else (eval else_expr env)
-    | Types.MalList [Types.Symbol "if"; test; then_expr] ->
-        if Types.to_bool (eval test env) then (eval then_expr env) else Types.Nil
-    | Types.MalList [Types.Symbol "fn*"; Types.MalList arg_names; expr] ->
-        Types.Fn
+    | T.List { T.value = [T.Symbol { T.value = "if" }; test; then_expr] } ->
+        if Types.to_bool (eval test env) then (eval then_expr env) else T.Nil
+    | T.List { T.value = [T.Symbol { T.value = "fn*" }; T.Vector { T.value = arg_names }; expr] }
+    | T.List { T.value = [T.Symbol { T.value = "fn*" }; T.List   { T.value = arg_names }; expr] } ->
+        Types.fn
           (function args ->
             let sub_env = Env.make (Some env) in
               let rec bind_args a b =
                 (match a, b with
-                  | [Types.Symbol "&"; name], args -> Env.set sub_env name (Types.MalList args);
+                  | [T.Symbol { T.value = "&" }; name], args -> Env.set sub_env name (Types.list args);
                   | (name :: names), (arg :: args) ->
                       Env.set sub_env name arg;
                       bind_args names args;
@@ -40,9 +57,9 @@ and eval ast env =
                   | _ -> raise (Invalid_argument "Bad param count in fn call"))
               in bind_args arg_names args;
               eval expr sub_env)
-    | Types.MalList _ ->
+    | T.List _ ->
       (match eval_ast ast env with
-         | Types.MalList ((Types.Fn f) :: args) -> f args
+         | T.List { T.value = ((T.Fn { T.value = f }) :: args) } -> f args
          | _ -> raise (Invalid_argument "Cannot invoke non-function"))
     | _ -> eval_ast ast env