1 (load-file "../mal/env.mal")
2 (load-file "../mal/core.mal")
5 (def! READ (fn* [strng]
10 (def! is-pair (fn* [x]
15 (def! QUASIQUOTE (fn* [ast]
20 (= 'unquote (first ast))
23 (if (is-pair (first ast))
24 (if (= 'splice-unquote (first (first ast)))
26 (list 'concat (nth (first ast) 1) (QUASIQUOTE (rest ast)))
29 (list 'cons (QUASIQUOTE (first ast)) (QUASIQUOTE (rest ast))))))
31 (def! is-macro-call (fn* [ast env]
33 (let* [a0 (first ast)]
36 (let* [m (meta (env-get env a0))]
41 (def! MACROEXPAND (fn* [ast env]
42 (if (is-macro-call ast env)
43 (let* [mac (env-get env (first ast))]
44 (MACROEXPAND (apply mac (rest ast)) env))
47 (def! eval-ast (fn* [ast env] (do
48 ;;(do (prn "eval-ast" ast "/" (keys env)) )
50 (symbol? ast) (env-get env ast)
52 (list? ast) (map (fn* [exp] (EVAL exp env)) ast)
54 (vector? ast) (apply vector (map (fn* [exp] (EVAL exp env)) ast))
56 (map? ast) (apply hash-map
58 (map (fn* [k] [k (EVAL (get ast k) env)])
63 (def! LET (fn* [env args]
64 (if (> (count args) 0)
66 (env-set env (nth args 0) (EVAL (nth args 1) env))
67 (LET env (rest (rest args)))))))
69 (def! EVAL (fn* [ast env] (do
70 ;;(do (prn "EVAL" ast "/" (keys @env)) )
75 (let* [ast (MACROEXPAND ast env)]
79 (let* [a0 (first ast)]
82 (env-set env (nth ast 1) (EVAL (nth ast 2) env))
85 (let* [let-env (new-env env)]
87 (LET let-env (nth ast 1))
88 (EVAL (nth ast 2) let-env)))
94 (let* [a1 (nth ast 1)]
95 (EVAL (QUASIQUOTE a1) env))
102 mac (with-meta f (assoc m "ismacro" true))]
103 (env-set env a1 mac))
106 (let* [a1 (nth ast 1)]
107 (MACROEXPAND a1 env))
110 (if (= 'catch* (nth (nth ast 2) 0))
112 (EVAL (nth ast 1) env)
114 (EVAL (nth (nth ast 2) 2)
118 (EVAL (nth ast 1) env))
121 (let* [el (eval-ast (rest ast) env)]
122 (nth el (- (count el) 1)))
125 (let* [cond (EVAL (nth ast 1) env)]
126 (if (or (= cond nil) (= cond false))
127 (if (> (count ast) 3)
128 (EVAL (nth ast 3) env)
130 (EVAL (nth ast 2) env)))
134 (EVAL (nth ast 2) (new-env env (nth ast 1) args)))
137 (let* [el (eval-ast ast env)
140 (apply f args))))))))))
144 (def! PRINT (fn* [exp] (pr-str exp)))
147 (def! repl-env (new-env))
148 (def! rep (fn* [strng]
149 (PRINT (EVAL (READ strng) repl-env))))
151 ;; core.mal: defined directly using mal
152 (map (fn* [data] (env-set repl-env (nth data 0) (nth data 1))) core_ns)
153 (env-set repl-env 'eval (fn* [ast] (EVAL ast repl-env)))
154 (env-set repl-env '*ARGV* (rest *ARGV*))
156 ;; core.mal: defined using the new language itself
157 (rep (str "(def! *host-language* \"" *host-language* "-mal\")"))
158 (rep "(def! not (fn* [a] (if a false true)))")
159 (rep "(def! load-file (fn* (f) (eval (read-string (str \"(do \" (slurp f) \")\")))))")
160 (rep "(defmacro! cond (fn* (& xs) (if (> (count xs) 0) (list 'if (first xs) (if (> (count xs) 1) (nth xs 1) (throw \"odd number of forms to cond\")) (cons 'cond (rest (rest xs)))))))")
161 (rep "(defmacro! or (fn* (& xs) (if (empty? xs) nil (if (= 1 (count xs)) (first xs) `(let* (or_FIXME ~(first xs)) (if or_FIXME or_FIXME (or ~@(rest xs))))))))")
164 (def! repl-loop (fn* []
165 (let* [line (readline "mal-user> ")]
168 (if (not (= "" line))
172 (println "Uncaught exception:" exc))))
175 (def! -main (fn* [& args]
176 (if (> (count args) 0)
177 (rep (str "(load-file \"" (first args) "\")"))
179 (rep "(println (str \"Mal [\" *host-language* \"]\"))")