Commit | Line | Data |
---|---|---|
31690700 JM |
1 | (load-file "../mal/types.mal") |
2 | (load-file "../mal/env.mal") | |
3 | ||
4 | ;; read | |
5 | (def! READ (fn* [strng] | |
6 | (read-string strng))) | |
7 | ||
8 | ||
9 | ;; eval | |
10 | (def! eval-ast (fn* [ast env] (do | |
11 | ;;(do (prn "eval-ast" ast "/" (keys env)) ) | |
12 | (cond | |
13 | (symbol? ast) (env-get env ast) | |
14 | ||
15 | (list? ast) (map (fn* [exp] (EVAL exp env)) ast) | |
16 | ||
17 | (vector? ast) (apply vector (map (fn* [exp] (EVAL exp env)) ast)) | |
18 | ||
19 | (map? ast) (apply hash-map | |
20 | (apply concat | |
21 | (map (fn* [k] [k (EVAL (get ast k) env)]) | |
22 | (keys ast)))) | |
23 | ||
24 | "else" ast)))) | |
25 | ||
26 | (def! LET (fn* [env args] | |
27 | (if (> (count args) 0) | |
28 | (do | |
29 | (env-set env (nth args 0) (EVAL (nth args 1) env)) | |
30 | (LET env (rest (rest args))))))) | |
31 | ||
32 | (def! EVAL (fn* [ast env] (do | |
33 | ;;(do (prn "EVAL" ast "/" (keys @env)) ) | |
34 | (if (not (list? ast)) | |
35 | (eval-ast ast env) | |
36 | ||
37 | ;; apply list | |
38 | (let* [a0 (first ast)] | |
39 | (cond | |
40 | (= 'def! a0) | |
41 | (env-set env (nth ast 1) (EVAL (nth ast 2) env)) | |
42 | ||
43 | (= 'let* a0) | |
44 | (let* [let-env (new-env env)] | |
45 | (do | |
46 | (LET let-env (nth ast 1)) | |
47 | (EVAL (nth ast 2) let-env))) | |
48 | ||
49 | (= 'do a0) | |
50 | (let* [el (eval-ast (rest ast) env)] | |
51 | (nth el (- (count el) 1))) | |
52 | ||
53 | (= 'if a0) | |
54 | (let* [cond (EVAL (nth ast 1) env)] | |
55 | (if (or (= cond nil) (= cond false)) | |
56 | (if (> (count ast) 3) | |
57 | (EVAL (nth ast 3) env) | |
58 | nil) | |
59 | (EVAL (nth ast 2) env))) | |
60 | ||
61 | (= 'fn* a0) | |
62 | (fn* [& args] | |
63 | (EVAL (nth ast 2) (new-env env (nth ast 1) args))) | |
64 | ||
65 | "else" | |
66 | (let* [el (eval-ast ast env) | |
67 | f (first el) | |
68 | args (rest el)] | |
69 | (apply f args)))))))) | |
70 | ||
71 | ||
72 | ||
73 | (def! PRINT (fn* [exp] (pr-str exp))) | |
74 | ||
75 | ;; repl | |
76 | (def! repl-env (new-env)) | |
77 | (def! rep (fn* [strng] | |
78 | (PRINT (EVAL (READ strng), repl-env)))) | |
79 | ||
80 | (def! _ref (fn* [k v] (env-set repl-env k v))) | |
81 | ||
82 | ;; Import types related functions | |
83 | (map (fn* [data] (_ref (nth data 0) (nth data 1))) types_ns) | |
84 | ||
85 | ;; Defined using the language itself | |
86 | (_ref 'read-string read-string) | |
87 | (_ref 'eval (fn* [ast] (EVAL ast repl-env))) | |
88 | (_ref 'slurp slurp) | |
89 | (_ref 'slurp-do slurp-do) | |
90 | ||
91 | (rep "(def! not (fn* [a] (if a false true)))") | |
92 | (rep "(def! load-file (fn* [f] (eval (read-string (slurp-do f)))))") | |
93 | ||
94 | (def! -main (fn* [] | |
95 | (let* [line (readline "mal-user> ")] | |
96 | (if line | |
97 | (do | |
98 | (if (not (= "" line)) | |
99 | (try* | |
100 | (let* [res (rep line)] | |
101 | (println res)) | |
102 | (catch* exc | |
103 | (println "Uncaught exception:" exc)))) | |
104 | (-main)))))) | |
105 | (-main) |