1 ;; -*- lexical-binding: t; -*-
10 (defvar repl-env
(mal-env))
12 (dolist (binding core-ns
)
13 (let ((symbol (car binding
))
15 (mal-env-set repl-env symbol fn
)))
17 (defun mal-pair-p (mal-object)
18 (let ((type (mal-type mal-object
))
19 (value (mal-value mal-object
)))
20 (if (and (or (eq type
'list
) (eq type
'vector
))
21 (not (zerop (length value
))))
25 (defun quasiquote (ast)
26 (if (not (mal-pair-p ast
))
27 (mal-list (list (mal-symbol 'quote
) ast
))
28 (let* ((a (mal-listify ast
))
33 ((eq (mal-value a0
) 'unquote
)
36 (eq (mal-value (car (mal-value a0
)))
38 (mal-list (list (mal-symbol 'concat
)
40 (quasiquote (mal-list a0...
)))))
42 (mal-list (list (mal-symbol 'cons
)
44 (quasiquote (mal-list a0...
)))))))))
46 (defun macro-call-p (ast env
)
47 (when (mal-list-p ast
)
48 (let ((a0 (car (mal-value ast
))))
49 (when (mal-symbol-p a0
)
50 (let ((value (mal-env-find env
(mal-value a0
))))
51 (when (and (mal-func-p value
)
52 (mal-func-macro-p value
))
55 (defun MACROEXPAND (ast env
)
56 (while (macro-call-p ast env
)
57 (let* ((a (mal-value ast
))
58 (a0* (mal-value (car a
)))
60 (macro (mal-env-find env a0
*)))
61 (setq ast
(apply (mal-value (mal-func-fn macro
)) a0...
))))
70 (when (not (mal-list-p ast
))
71 (throw 'return
(eval-ast ast env
)))
73 (setq ast
(MACROEXPAND ast env
))
74 (when (or (not (mal-list-p ast
)) (not (mal-value ast
)))
75 (throw 'return
(eval-ast ast env
)))
77 (let* ((a (mal-value ast
))
85 (let* ((identifier (mal-value a1
))
86 (value (EVAL a2 env
)))
87 (throw 'return
(mal-env-set env identifier value
))))
89 (let* ((env* (mal-env env
))
90 (bindings (mal-value a1
))
92 (when (vectorp bindings
)
93 (setq bindings
(append bindings nil
)))
95 (let ((key (mal-value (pop bindings
)))
96 (value (EVAL (pop bindings
) env
*)))
97 (mal-env-set env
* key value
)))
102 ((eq a0
* 'quasiquote
)
103 (setq ast
(quasiquote a1
))) ; TCO
105 (let ((identifier (mal-value a1
))
106 (value (EVAL a2 env
)))
107 (setf (aref (aref value
1) 4) t
)
108 (throw 'return
(mal-env-set env identifier value
))))
109 ((eq a0
* 'macroexpand
)
110 (throw 'return
(MACROEXPAND a1 env
)))
113 (throw 'return
(EVAL a1 env
))
115 (if (and a2
(eq (mal-value (car (mal-value a2
))) 'catch
*))
116 (let* ((a2* (mal-value a2
))
117 (identifier (mal-value (cadr a2
*)))
119 (err* (if (eq (car err
) 'mal-custom
)
123 (mal-string (error-message-string err
))))
124 (env* (mal-env env
(list identifier
) (list err
*))))
125 (throw 'return
(EVAL form env
*)))
126 (signal (car err
) (cdr err
))))))
128 (let* ((a0...
(cdr a
))
129 (butlast (butlast a0...
))
130 (last (car (last a0...
))))
132 (eval-ast (mal-list butlast
) env
))
133 (setq ast last
))) ; TCO
135 (let* ((condition (EVAL a1 env
))
136 (condition-type (mal-type condition
))
139 (if (and (not (eq condition-type
'false
))
140 (not (eq condition-type
'nil
)))
141 (setq ast then
) ; TCO
143 (setq ast else
) ; TCO
144 (throw 'return
(mal-nil))))))
146 (let* ((binds (mapcar 'mal-value
(mal-value a1
)))
150 (let ((env* (mal-env env binds args
)))
151 (EVAL body env
*))))))
152 (throw 'return
(mal-func body binds env fn
))))
154 ;; not a special form
155 (let* ((ast* (mal-value (eval-ast ast env
)))
159 (let ((env* (mal-env (mal-func-env fn
)
163 ast
(mal-func-ast fn
))) ; TCO
165 (let ((fn* (mal-value fn
)))
166 (throw 'return
(apply fn
* args
)))))))))))
168 (defun eval-ast (ast env
)
169 (let ((type (mal-type ast
))
170 (value (mal-value ast
)))
173 (let ((definition (mal-env-get env value
)))
174 (or definition
(error "Definition not found"))))
176 (mal-list (mapcar (lambda (item) (EVAL item env
)) value
)))
178 (mal-vector (vconcat (mapcar (lambda (item) (EVAL item env
)) value
))))
180 (let ((map (copy-hash-table value
)))
181 (maphash (lambda (key value
)
182 (puthash key
(EVAL value env
) map
))
189 (mal-env-set repl-env
'eval
(mal-fn (let ((env repl-env
)) (lambda (form) (EVAL form env
)))))
190 (mal-env-set repl-env
'*ARGV
* (mal-list (mapcar 'mal-string
(cdr argv
))))
196 (PRINT (EVAL (READ input
) repl-env
)))
198 (rep "(def! not (fn* (a) (if a false true)))")
199 (rep "(def! load-file (fn* (f) (eval (read-string (str \"(do \" (slurp f) \"\nnil)\")))))")
200 (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)))))))")
202 (defun readln (prompt)
203 ;; C-d throws an error
204 (ignore-errors (read-from-minibuffer prompt
)))
206 (defun println (format-string &rest args
)
208 (princ format-string
)
209 (princ (apply 'format format-string args
)))
212 (defmacro with-error-handling
(&rest body
)
216 ;; empty input, carry on
218 (unterminated-sequence
219 (let* ((type (cadr err
))
222 ((eq type
'string
) ?
\")
223 ((eq type
'list
) ?\
))
224 ((eq type
'vector
) ?\
])
225 ((eq type
'map
) ?
}))))
226 (princ (format "Expected '%c', got EOF\n" end
))))
228 (println (error-message-string err
)))))
233 (rep (format "(load-file \"%s\")" (car argv
))))
236 (let ((input (readln "user> ")))
239 (println (rep input
)))
241 ;; print final newline