DISABLE FDs (REMOVE ME).
[jackhill/mal.git] / picolisp / step9_try.l
CommitLineData
cc494944
VS
1(de load-relative (Path)
2 (load (pack (car (file)) Path)) )
3
4(load-relative "readline.l")
5(load-relative "types.l")
6(load-relative "reader.l")
7(load-relative "printer.l")
8(load-relative "env.l")
9(load-relative "func.l")
10(load-relative "core.l")
11
12(de READ (String)
13 (read-str String) )
14
15(def '*ReplEnv (MAL-env NIL))
16(for Bind *Ns (set> *ReplEnv (car Bind) (cdr Bind)))
17
18(de is-pair (Ast)
19 (and (memq (MAL-type Ast) '(list vector)) (MAL-value Ast) T) )
20
21(de quasiquote (Ast)
22 (if (not (is-pair Ast))
23 (MAL-list (list (MAL-symbol 'quote) Ast))
24 (let A (MAL-value Ast)
25 (cond
26 ((= (MAL-value (car A)) 'unquote)
27 (cadr A) )
28 ((and (is-pair (car A))
29 (= (MAL-value (car (MAL-value (car A)))) 'splice-unquote) )
30 (MAL-list (list (MAL-symbol 'concat)
31 (cadr (MAL-value (car A)))
32 (quasiquote (MAL-list (cdr A))) ) ) )
33 (T
34 (MAL-list (list (MAL-symbol 'cons)
35 (quasiquote (car A))
36 (quasiquote (MAL-list (cdr A))) ) ) ) ) ) ) )
37
38(de is-macro-call (Ast Env)
39 (when (= (MAL-type Ast) 'list)
40 (let A0 (car (MAL-value Ast))
41 (when (= (MAL-type A0) 'symbol)
42 (let Value (find> Env (MAL-value A0))
43 (and (isa '+Func Value) (get Value 'is-macro) T) ) ) ) ) )
44
45(de macroexpand (Ast Env)
46 (while (is-macro-call Ast Env)
47 (let (Ast* (MAL-value Ast)
48 Macro (get (find> Env (MAL-value (car Ast*))) 'fn)
49 Args (cdr Ast*) )
50 (setq Ast (apply (MAL-value Macro) Args)) ) )
51 Ast )
52
53(de EVAL (Ast Env)
54 (catch 'done
55 (while t
56 (when (not (= (MAL-type Ast) 'list))
57 (throw 'done (eval-ast Ast Env)) )
58 (setq Ast (macroexpand Ast Env))
59 (when (or (not (= (MAL-type Ast) 'list)) (not (MAL-value Ast)))
60 (throw 'done (eval-ast Ast Env)) )
61 (let (Ast* (MAL-value Ast)
62 A0* (MAL-value (car Ast*))
63 A1 (cadr Ast*)
64 A1* (MAL-value A1)
65 A2 (caddr Ast*)
66 A3 (cadddr Ast*) )
67 (cond
68 ((= A0* 'def!)
69 (throw 'done (set> Env A1* (EVAL A2 Env))) )
70 ((= A0* 'quote)
71 (throw 'done A1) )
72 ((= A0* 'quasiquote)
73 (setq Ast (quasiquote A1)) ) # TCO
74 ((= A0* 'defmacro!)
75 (let Form (EVAL A2 Env)
76 (put Form 'is-macro T)
77 (throw 'done (set> Env A1* Form)) ) )
78 ((= A0* 'macroexpand)
79 (throw 'done (macroexpand A1 Env)) )
80 ((= A0* 'try*)
81 (let Result (catch 'err (throw 'done (EVAL A1 Env)))
82 (if (isa '+MALError Result)
83 (let A (MAL-value A2)
84 (if (and (= (MAL-type A2) 'list)
85 (= (MAL-value (car A)) 'catch*) )
86 (let (Bind (MAL-value (cadr A))
87 Exc (MAL-value Result)
88 Form (caddr A)
89 Env* (MAL-env Env (list Bind) (list Exc)) )
90 (throw 'done (EVAL Form Env*)) )
91 (throw 'err Result) ) )
92 (throw 'done Result) ) ) )
93 ((= A0* 'let*)
94 (let Env* (MAL-env Env)
95 (for (Bindings A1* Bindings)
96 (let (Key (MAL-value (pop 'Bindings))
97 Value (EVAL (pop 'Bindings) Env*) )
98 (set> Env* Key Value) ) )
99 (setq Env Env* Ast A2) ) ) # TCO
100 ((= A0* 'do)
101 (mapc '((Form) (EVAL Form Env)) (head -1 (cdr Ast*)))
102 (setq Ast (last Ast*)) ) # TCO
103 ((= A0* 'if)
104 (if (not (memq (MAL-type (EVAL A1 Env)) '(nil false)))
105 (setq Ast A2) # TCO
106 (if A3
107 (setq Ast A3) # TCO
108 (throw 'done *MAL-nil) ) ) )
109 ((= A0* 'fn*)
110 (let (Binds (mapcar MAL-value A1*)
111 Body A2
112 Fn (MAL-fn
113 (curry (Env Binds Body) @
114 (let Env* (MAL-env Env Binds (rest))
115 (EVAL Body Env*) ) ) ) )
116 (throw 'done (MAL-func Env Body Binds Fn)) ) )
117 (T
118 (let (Ast* (MAL-value (eval-ast Ast Env))
119 Fn (car Ast*)
120 Args (cdr Ast*) )
121 (if (isa '+MALFn Fn)
122 (throw 'done (apply (MAL-value Fn) Args))
123 (let Env* (MAL-env (get Fn 'env) (get Fn 'params) Args)
124 (setq Ast (get Fn 'ast) Env Env*) ) ) ) ) ) ) ) ) )
125
126(de eval-ast (Ast Env)
127 (let Value (MAL-value Ast)
128 (case (MAL-type Ast)
129 (symbol (get> Env Value))
130 (list (MAL-list (mapcar '((Form) (EVAL Form Env)) Value)))
131 (vector (MAL-vector (mapcar '((Form) (EVAL Form Env)) Value)))
132 (map (MAL-map (mapcar '((Form) (EVAL Form Env)) Value)))
133 (T Ast) ) ) )
134
135(set> *ReplEnv 'eval (MAL-fn (curry (*ReplEnv) (Form) (EVAL Form *ReplEnv))))
fbe5bd7a 136(set> *ReplEnv '*ARGV* (MAL-list (mapcar MAL-string (cdr (argv)))))
cc494944
VS
137
138(de PRINT (Ast)
139 (pr-str Ast T) )
140
141(de rep (String)
142 (PRINT (EVAL (READ String) *ReplEnv)) )
143
144(rep "(def! not (fn* (a) (if a false true)))")
e6d41de4 145(rep "(def! load-file (fn* (f) (eval (read-string (str \"(do \" (slurp f) \"\nnil)\")))))")
cc494944 146(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)))))))")
cc494944
VS
147
148(load-history ".mal_history")
149
150(if (argv)
fbe5bd7a 151 (rep (pack "(load-file \"" (car (argv)) "\")"))
cc494944
VS
152 (use Input
153 (until (=0 (setq Input (readline "user> ")))
154 (let Output (catch 'err (rep Input))
155 (if (isa '+MALError Output)
156 (let Message (MAL-value Output)
157 (unless (= (MAL-value Message) "end of token stream")
158 (prinl "[error] " (pr-str Message)) ) )
159 (prinl Output) ) ) ) ) )
160
161(prinl)
162(bye)