Refactor quasiquote.
authorJan Nieuwenhuizen <janneke@gnu.org>
Thu, 22 Dec 2016 11:11:55 +0000 (12:11 +0100)
committerJan Nieuwenhuizen <janneke@gnu.org>
Thu, 22 Dec 2016 11:11:55 +0000 (12:11 +0100)
* module/mes/quasiquote.mes (quasiquote): Refactor.
* tests/quasiquote.test: Add tests.

module/mes/quasiquote.mes
tests/quasiquote.test

index 05bf41b88a296118b87a3c3fae21c86660265cf8..334f057e5a233f23411ca6a5cbe4564ddf53ee9e 100644 (file)
 
 (define-macro (quasiquote x)
   (define (loop x)
-    (if (not (pair? x)) (cons 'quote (cons x '()))
-        (if (eq? (car x) 'quasiquote) (loop (loop (cadr x)))
-            (if (eq? (car x) 'unquote) (cadr x)
-                (if (and (pair? (car x)) (eq? (caar x) 'unquote-splicing))
-                    ((lambda (d)
-                       (list 'append (cadar x) d))
-                     (loop (cdr x)))
-                    ((lambda (a d)
-                       (if (pair? d)
-                           (if (eq? (car d) 'quote)
-                               (if (and (pair? a) (eq? (car a) 'quote))
-                                   (list 'quote (cons (cadr a) (cadr d)))
-                                   (if (null? (cadr d))
-                                       (list 'list a)
-                                       (list 'cons* a d)))
-                               (if (memq (car d) '(list cons*))
-                                   (cons (car d) (cons a (cdr d)))
+    (cond ((vector? x) (list 'list->vector (loop (vector->list x))))
+          ((not (pair? x)) (cons 'quote (cons x '())))
+          ;;((eq? (car x) 'quasiquote) (loop (loop (cadr x))))
+          ((eq? (car x) 'quasiquote) (loop (loop
+                                            (if (null? (cddr x)) (cadr x)
+                                                (cons 'list (cdr x))))))
+          ((eq? (car x) 'unquote) (if (null? (cddr x)) (cadr x)
+                                      (cons 'list (cdr x))))
+          ((and (pair? (car x)) (eq? (caar x) 'unquote-splicing))
+           ((lambda (d)
+              (if (null? (cddar x)) (list 'append (cadar x) d)
+                  (list 'quote (append (cdar x) d))))
+            (loop (cdr x))))
+          (else ((lambda (a d)
+                   (if (pair? d)
+                       (if (eq? (car d) 'quote)
+                           (if (and (pair? a) (eq? (car a) 'quote))
+                               (list 'quote (cons (cadr a) (cadr d)))
+                               (if (null? (cadr d))
+                                   (list 'list a)
                                    (list 'cons* a d)))
-                           (list 'cons* a d)))
-                     (loop (car x))
-                     (loop (cdr x))))))))
+                           (if (memq (car d) '(list cons*))
+                               (cons (car d) (cons a (cdr d)))
+                               (list 'cons* a d)))
+                       (list 'cons* a d)))
+                 (loop (car x))
+                 (loop (cdr x))))))
   (loop x))
index 4d307f68bbaeb87b10c1e31d4f2205732d49f8af..ac57511d5bbb9aad34b4383a19cf2b5b297ab1d8 100755 (executable)
@@ -46,4 +46,36 @@ exit $?
 (pass-if "unquote-splicing 3" (sequal? `(1 ,@(list 2 3) 4) '(1 2 3 4)))
 (pass-if "unquote-splicing 4" (sequal? (let ((s-r '(2 3))) `(1 ,@s-r 4)) '(1 2 3 4)))
 
+;; From R6RS spec
+(pass-if-equal "qq 0" '(list 3 4)
+  `(list ,(+ 1 2) 4))
+(pass-if-equal "qq 1" '(list a (quote a))
+  (let ((name 'a))
+    `(list ,name ',name)) )
+(pass-if-equal "qq 2" '(a 3 4 5 6 b)
+  `(a ,(+ 1 2) ,@(map abs '(4 -5 6)) b))
+(pass-if-equal "qq 3" '((foo 7) . cons)
+  `((foo ,(- 10 3)) ,@(cdr '(c)) . ,(car '(cons))))
+(pass-if-equal "qq 4" '#(10 5 #t #t #f #f #f 8)
+  `#(10 5 ,(even? 4) ,@(map even? '(2 3 5 7)) 8))
+;; (pass-if-equal "qq 5" '(foo foo foo)
+;;   (let ((name 'foo))
+;;     `((unquote name name name))))
+;; (pass-if-equal "qq 6" '(foo foo foo)
+;;   (let ((name '(foo)))
+;;     `((unquote-splicing name name name))))
+;; (pass-if-equal "qq 7" '`(foo (unquote (append x y) (even? 9)))
+;;   (let ((q '((append x y) (even? 9))))
+;;     ``(foo ,,@q)))
+;; (pass-if-equal "qq 8" '(foo (2 3 4 5) #f)
+;;   (let ((x '(2 3))
+;;         (y '(4 5)))
+;;     `(foo (unquote (append x y) (even? 9)))))
+;; (pass-if-equal "qq 9" '(a `(b ,(+ 1 2) ,(foo 4 d) e) f)
+;;   `(a `(b ,(+ 1 2) ,(foo ,(+ 1 3) d) e) f))
+;; (pass-if-equal "qq 10" '(a `(b ,x ,'y d) e)
+;;   (let ((name1 'x)
+;;         (name2 'y))
+;;     `(a `(b ,,name1 ,',name2 d) e)))
+
 (result 'report)