Integrate the reader in lispstrack.lisp
[jscl.git] / backquote.lisp
1 ;;; A little backquote implementation without optimizations of any
2 ;;; kind for lispstrack.
3
4 (defun backquote-expand-1 (form)
5   (cond
6     ((symbolp form)
7      (list 'quote form))
8     ((atom form)
9      form)
10     ((eq (car form) 'unquote)
11      (car form))
12     ((eq (car form) 'backquote)
13      (backquote-expand-1 (backquote-expand-1 (cadr form))))
14     (t
15      (cons 'append
16            (mapcar (lambda (s)
17                      (cond
18                        ((and (listp s) (eq (car s) 'unquote))
19                         (list 'list (cadr s)))
20                        ((and (listp s) (eq (car s) 'unquote-splicing))
21                         (cadr s))
22                        (t
23                         (list 'list (backquote-expand-1 s)))))
24                    form)))))
25
26 (defun backquote-expand (form)
27   (if (and (listp form) (eq (car form) 'backquote))
28       (backquote-expand-1 (cadr form))
29       form))
30
31 (defmacro backquote (form)
32   (backquote-expand-1 form))
33
34 ;;; Tests. Compare backquote agains the backquote of the host Lisp.
35 (macrolet ((test (form1 form2)
36              `(assert (equal ,form1 ,form2))))
37   (test (backquote (1 2 3 4))
38         `(1 2 3 4))
39   (test (backquote (1 2 (+ 3 4)))
40         `(1 2 (+ 3 4)))
41   (test (backquote (1 2 (unquote (+ 3 4))))
42         `(1 2 ,(+ 3 4)))
43   (test (backquote (1 2 (unquote-splicing '(3 4))))
44         `(1 2 ,@'(3 4)))
45   (test (backquote (backquote x))
46         ``x)
47   (let ((x 10))
48     (test `',x
49           (backquote (quote (unquote x)))))
50   (let ((x 10))
51     (test (eval ``(,,x))
52           (eval (backquote (backquote ((unquote (unquote x)))))))))