1 ;; -*- lexical-binding: t; -*-
3 (defun load-relative (file)
4 (let* ((current-file (or load-file-name buffer-file-name
))
5 (current-file-directory (file-name-directory current-file
)))
6 (load (expand-file-name file current-file-directory
) nil t
)))
8 (load-relative "types.el")
9 (load-relative "env.el")
10 (load-relative "func.el")
11 (load-relative "reader.el")
12 (load-relative "printer.el")
13 (load-relative "core.el")
15 (defvar repl-env
(mal-env))
17 (dolist (binding core-ns
)
18 (let ((symbol (car binding
))
20 (mal-env-set repl-env symbol fn
)))
28 (if (and (mal-list-p ast
) (mal-value ast
))
29 (let* ((a (mal-value ast
))
37 (let ((identifier (mal-value a1
))
38 (value (EVAL a2 env
)))
39 (throw 'return
(mal-env-set env identifier value
))))
41 (let* ((env* (mal-env env
))
42 (bindings (mal-value a1
))
44 (when (vectorp bindings
)
45 (setq bindings
(append bindings nil
)))
47 (let ((key (mal-value (pop bindings
)))
48 (value (EVAL (pop bindings
) env
*)))
49 (mal-env-set env
* key value
)))
53 (let* ((a0...
(cdr a
))
54 (butlast (butlast a0...
))
55 (last (car (last a0...
))))
57 (eval-ast (mal-list butlast
) env
))
58 (setq ast last
))) ; TCO
60 (let* ((condition (EVAL a1 env
))
61 (condition-type (mal-type condition
))
64 (if (and (not (eq condition-type
'false
))
65 (not (eq condition-type
'nil
)))
69 (throw 'return mal-nil
)))))
71 (let* ((binds (mapcar 'mal-value
(mal-value a1
)))
75 (let ((env* (mal-env env binds args
)))
77 (throw 'return
(mal-func body binds env fn
))))
80 (let* ((ast* (mal-value (eval-ast ast env
)))
84 (let ((env* (mal-env (mal-func-env fn
)
88 ast
(mal-func-ast fn
))) ; TCO
90 (let ((fn* (mal-value fn
)))
91 (throw 'return
(apply fn
* args
))))))))
92 (throw 'return
(eval-ast ast env
))))))
94 (defun eval-ast (ast env
)
95 (let ((type (mal-type ast
))
96 (value (mal-value ast
)))
99 (let ((definition (mal-env-get env value
)))
100 (or definition
(error "Definition not found"))))
102 (mal-list (mapcar (lambda (item) (EVAL item env
)) value
)))
104 (mal-vector (vconcat (mapcar (lambda (item) (EVAL item env
)) value
))))
106 (let ((map (copy-hash-table value
)))
107 (maphash (lambda (key value
)
108 (puthash key
(EVAL value env
) map
))
115 (mal-env-set repl-env
'eval
(mal-fn (let ((env repl-env
)) (lambda (form) (EVAL form env
)))))
116 (mal-env-set repl-env
'*ARGV
* (mal-list (mapcar 'mal-string
(cdr argv
))))
122 (PRINT (EVAL (READ input
) repl-env
)))
124 (rep "(def! not (fn* (a) (if a false true)))")
125 (rep "(def! load-file (fn* (f) (eval (read-string (str \"(do \" (slurp f) \")\")))))")
127 (defun readln (prompt)
128 ;; C-d throws an error
129 (ignore-errors (read-from-minibuffer prompt
)))
131 (defun println (format-string &rest args
)
133 (princ format-string
)
134 (princ (apply 'format format-string args
)))
137 (defmacro with-error-handling
(&rest body
)
141 ;; empty input, carry on
143 (unterminated-sequence
144 (let* ((type (cadr err
))
147 ((eq type
'string
) ?
\")
148 ((eq type
'list
) ?\
))
149 ((eq type
'vector
) ?\
])
150 ((eq type
'map
) ?
}))))
151 (princ (format "Expected '%c', got EOF\n" end
))))
153 (println (error-message-string err
)))))
158 (rep (format "(load-file \"%s\")" (car argv
))))
161 (let ((input (readln "user> ")))
164 (println (rep input
)))
166 ;; print final newline