All: *ARGV* and *host-language*. Misc syncing/fixes.
[jackhill/mal.git] / clojure / src / step2_eval.clj
1 (ns step2-eval
2 (:require [clojure.repl]
3 [readline]
4 [reader]
5 [printer]))
6
7 ;; read
8 (defn READ [& [strng]]
9 (let [line (if strng strng (read-line))]
10 (reader/read-string strng)))
11
12 ;; eval
13 (declare EVAL)
14 (defn eval-ast [ast env]
15 (cond
16 (symbol? ast) (or (get env ast)
17 (throw (Error. (str ast " not found"))))
18
19 (seq? ast) (doall (map #(EVAL % env) ast))
20
21 (vector? ast) (vec (doall (map #(EVAL % env) ast)))
22
23 (map? ast) (apply hash-map (doall (map #(EVAL % env)
24 (mapcat identity ast))))
25
26 :else ast))
27
28 (defn EVAL [ast env]
29 ;;(prn "EVAL" ast (keys @env)) (flush)
30 (if (not (seq? ast))
31 (eval-ast ast env)
32
33 ;; apply list
34 (let [el (eval-ast ast env)
35 f (first el)
36 args (rest el)]
37 (apply f args))))
38
39 ;; print
40 (defn PRINT [exp] (pr-str exp))
41
42 ;; repl
43 (def repl-env {'+ +
44 '- -
45 '* *
46 '/ /})
47 (defn rep
48 [strng]
49 (PRINT (EVAL (READ strng) repl-env)))
50
51 ;; repl loop
52 (defn repl-loop []
53 (let [line (readline/readline "user> ")]
54 (when line
55 (when-not (re-seq #"^\s*$|^\s*;.*$" line) ; blank/comment
56 (try
57 (println (rep line))
58 (catch Throwable e
59 (clojure.repl/pst e))))
60 (recur))))
61
62 (defn -main [& args]
63 (repl-loop))