3 let repl_env = Env.make
(Some
Core.ns
)
5 let rec eval_ast ast env
=
7 | T.Symbol s
-> Env.get env ast
8 | T.List
{ T.value = xs
; T.meta
= meta
}
9 -> T.List
{ T.value = (List.map
(fun x
-> eval x env
) xs
);
11 | T.Vector
{ T.value = xs
; T.meta
= meta
}
12 -> T.Vector
{ T.value = (List.map
(fun x
-> eval x env
) xs
);
14 | T.Map
{ T.value = xs
; T.meta
= meta
}
15 -> T.Map
{T.meta
= meta
;
16 T.value = (Types.MalMap.fold
18 -> Types.MalMap.add
(eval k env
) (eval v env
) m
)
24 | T.List
{ T.value = [(T.Symbol
{ T.value = "def!" }); key
; expr
] } ->
25 let value = (eval expr env
) in
26 Env.set env key
value; value
27 | T.List
{ T.value = [(T.Symbol
{ T.value = "let*" }); (T.Vector
{ T.value = bindings
}); body
] }
28 | T.List
{ T.value = [(T.Symbol
{ T.value = "let*" }); (T.List
{ T.value = bindings
}); body
] } ->
29 (let sub_env = Env.make
(Some env
) in
30 let rec bind_pairs = (function
31 | sym
:: expr
:: more
->
32 Env.set
sub_env sym
(eval expr
sub_env);
34 | _
::[] -> raise
(Invalid_argument
"let* bindings must be an even number of forms")
36 in bind_pairs bindings
;
38 | T.List
{ T.value = ((T.Symbol
{ T.value = "do" }) :: body
) } ->
39 List.fold_left
(fun x expr
-> eval expr env
) T.Nil body
40 | T.List
{ T.value = [T.Symbol
{ T.value = "if" }; test
; then_expr
; else_expr
] } ->
41 if Types.to_bool
(eval test env
) then (eval then_expr env
) else (eval else_expr env
)
42 | T.List
{ T.value = [T.Symbol
{ T.value = "if" }; test
; then_expr
] } ->
43 if Types.to_bool
(eval test env
) then (eval then_expr env
) else T.Nil
44 | T.List
{ T.value = [T.Symbol
{ T.value = "fn*" }; T.Vector
{ T.value = arg_names
}; expr
] }
45 | T.List
{ T.value = [T.Symbol
{ T.value = "fn*" }; T.List
{ T.value = arg_names
}; expr
] } ->
48 let sub_env = Env.make
(Some env
) in
49 let rec bind_args a b
=
51 | [T.Symbol
{ T.value = "&" }; name
], args
-> Env.set
sub_env name
(Types.list args
);
52 | (name
:: names
), (arg
:: args
) ->
53 Env.set
sub_env name arg
;
56 | _
-> raise
(Invalid_argument
"Bad param count in fn call"))
57 in bind_args arg_names args
;
60 (match eval_ast ast env
with
61 | T.List
{ T.value = ((T.Fn
{ T.value = f
}) :: args
) } -> f args
62 | _
-> raise
(Invalid_argument
"Cannot invoke non-function"))
63 | _
-> eval_ast ast env
65 let read str
= Reader.read_str str
66 let print exp
= Printer.pr_str exp
true
67 let rep str env
= print (eval
(read str
) env
)
72 ignore
(rep "(def! not (fn* (a) (if a false true)))" repl_env);
74 print_string
"user> ";
75 let line = read_line
() in
77 print_endline
(rep line repl_env);
78 with End_of_file
-> ()
79 | Invalid_argument x
->
80 output_string stderr
("Invalid_argument exception: " ^ x ^
"\n");
83 with End_of_file
-> ()