Merge pull request #379 from bjh21/bjh21-unterminated-string-fixes
[jackhill/mal.git] / elisp / step2_eval.el
CommitLineData
c2b12e5b
VS
1(require 'mal/types)
2(require 'mal/reader)
3(require 'mal/printer)
c83a3eeb
VS
4
5(defvar repl-env (make-hash-table :test 'eq))
6(puthash '+ (lambda (a b) (mal-number (+ (mal-value a) (mal-value b)))) repl-env)
7(puthash '- (lambda (a b) (mal-number (- (mal-value a) (mal-value b)))) repl-env)
8(puthash '* (lambda (a b) (mal-number (* (mal-value a) (mal-value b)))) repl-env)
9(puthash '/ (lambda (a b) (mal-number (/ (mal-value a) (mal-value b)))) repl-env)
10
11(defun READ (input)
12 (read-str input))
13
14(defun EVAL (ast env)
ecb8de2d 15 (if (and (mal-list-p ast) (mal-value ast))
c83a3eeb
VS
16 (let* ((ast* (mal-value (eval-ast ast env)))
17 (fn (car ast*))
18 (args (cdr ast*)))
19 (apply fn args))
20 (eval-ast ast env)))
21
22(defun eval-ast (ast env)
23 (let ((type (mal-type ast))
24 (value (mal-value ast)))
25 (cond
26 ((eq type 'symbol)
27 (let ((definition (gethash value env)))
28 (or definition (error "Definition not found"))))
29 ((eq type 'list)
30 (mal-list (mapcar (lambda (item) (EVAL item env)) value)))
31 ((eq type 'vector)
32 (mal-vector (vconcat (mapcar (lambda (item) (EVAL item env)) value))))
33 ((eq type 'map)
34 (let ((map (copy-hash-table value)))
35 (maphash (lambda (key value)
36 (puthash key (EVAL value env) map))
37 map)
38 (mal-map map)))
39 (t
40 ;; return as is
41 ast))))
42
43(defun PRINT (input)
44 (pr-str input t))
45
46(defun rep (input)
47 (PRINT (EVAL (READ input) repl-env)))
48
49(defun readln (prompt)
50 ;; C-d throws an error
51 (ignore-errors (read-from-minibuffer prompt)))
52
53(defun println (format-string &rest args)
54 (if (not args)
55 (princ format-string)
56 (princ (apply 'format format-string args)))
57 (terpri))
58
59(defun main ()
60 (let (eof)
61 (while (not eof)
62 (let ((input (readln "user> ")))
63 (if input
64 (condition-case err
65 (println (rep input))
66 (end-of-token-stream
67 ;; empty input, carry on
68 )
69 (unterminated-sequence
70 (let* ((type (cadr err))
71 (end
72 (cond
73 ((eq type 'string) ?\")
74 ((eq type 'list) ?\))
75 ((eq type 'vector) ?\])
76 ((eq type 'map) ?}))))
77 (princ (format "Expected '%c', got EOF\n" end))))
78 (error ; catch-all
79 (println (error-message-string err))
80 (backtrace)))
81 (setq eof t)
82 ;; print final newline
83 (terpri))))))
84
85(main)