Commit | Line | Data |
---|---|---|
9115534d C |
1 | let repl_env = Env.make (Some Core.ns) |
2 | ||
3 | let rec eval_ast ast env = | |
4 | match ast with | |
5 | | Types.Symbol s -> Env.get env ast | |
f2f11f62 | 6 | | Types.List xs -> Types.List (List.map (fun x -> eval x env) xs) |
9115534d C |
7 | | _ -> ast |
8 | and eval ast env = | |
9 | match ast with | |
f2f11f62 | 10 | | Types.List [(Types.Symbol "def!"); key; expr] -> |
9115534d C |
11 | let value = (eval expr env) in |
12 | Env.set env key value; value | |
f2f11f62 | 13 | | Types.List [(Types.Symbol "let*"); (Types.List bindings); body] -> |
9115534d C |
14 | (let sub_env = Env.make (Some env) in |
15 | let rec bind_pairs = (function | |
16 | | sym :: expr :: more -> | |
17 | Env.set sub_env sym (eval expr sub_env); | |
18 | bind_pairs more | |
19 | | _::[] -> raise (Invalid_argument "let* bindings must be an even number of forms") | |
20 | | [] -> ()) | |
21 | in bind_pairs bindings; | |
22 | eval body sub_env) | |
f2f11f62 | 23 | | Types.List ((Types.Symbol "do") :: body) -> |
9115534d | 24 | List.fold_left (fun x expr -> eval expr env) Types.Nil body |
f2f11f62 | 25 | | Types.List [Types.Symbol "if"; test; then_expr; else_expr] -> |
9115534d | 26 | if Types.to_bool (eval test env) then (eval then_expr env) else (eval else_expr env) |
f2f11f62 | 27 | | Types.List [Types.Symbol "if"; test; then_expr] -> |
9115534d | 28 | if Types.to_bool (eval test env) then (eval then_expr env) else Types.Nil |
f2f11f62 | 29 | | Types.List [Types.Symbol "fn*"; Types.List arg_names; expr] -> |
9115534d C |
30 | Types.Fn |
31 | (function args -> | |
32 | let sub_env = Env.make (Some env) in | |
de04357c | 33 | let rec bind_args a b = |
9115534d | 34 | (match a, b with |
f2f11f62 | 35 | | [Types.Symbol "&"; name], args -> Env.set sub_env name (Types.List args); |
9115534d C |
36 | | (name :: names), (arg :: args) -> |
37 | Env.set sub_env name arg; | |
38 | bind_args names args; | |
39 | | [], [] -> () | |
de04357c C |
40 | | _ -> raise (Invalid_argument "Bad param count in fn call")) |
41 | in bind_args arg_names args; | |
9115534d | 42 | eval expr sub_env) |
f2f11f62 | 43 | | Types.List _ -> |
9115534d | 44 | (match eval_ast ast env with |
f2f11f62 | 45 | | Types.List ((Types.Fn f) :: args) -> f args |
9115534d C |
46 | | _ -> raise (Invalid_argument "Cannot invoke non-function")) |
47 | | _ -> eval_ast ast env | |
48 | ||
49 | let read str = Reader.read_str str | |
de04357c | 50 | let print exp = Printer.pr_str exp true |
9115534d C |
51 | let rep str env = print (eval (read str) env) |
52 | ||
53 | let rec main = | |
54 | try | |
55 | Core.init Core.ns; | |
56 | ignore (rep "(def! not (fn* (a) (if a false true)))" repl_env); | |
57 | while true do | |
58 | print_string "user> "; | |
59 | let line = read_line () in | |
60 | try | |
61 | print_endline (rep line repl_env); | |
62 | with End_of_file -> () | |
63 | | Invalid_argument x -> | |
64 | output_string stderr ("Invalid_argument exception: " ^ x ^ "\n"); | |
65 | flush stderr | |
66 | done | |
67 | with End_of_file -> () |