~ chicken-core (chicken-5) 3d8167f6b9e0f27141a3efd0045bf0240ed8fb67
commit 3d8167f6b9e0f27141a3efd0045bf0240ed8fb67 Author: Peter Bex <peter.bex@xs4all.nl> AuthorDate: Mon Jan 24 19:26:58 2011 +0100 Commit: Peter Bex <peter.bex@xs4all.nl> CommitDate: Mon Jan 24 19:28:00 2011 +0100 Apply CR#439. Voting time is over. Nobody cares about it anyway diff --git a/expand.scm b/expand.scm index 88c71ad5..5d4f3931 100644 --- a/expand.scm +++ b/expand.scm @@ -1384,31 +1384,23 @@ (let ((head (car x)) (tail (cdr x))) (cond ((c %unquote head) - (if (pair? tail) - (let ((hx (car tail))) - (if (eq? n 0) - hx - (list '##sys#list `(##core#quote ,%unquote) - (walk hx (fx- n 1)) ) ) ) - `(##core#quote ,%unquote) ) ) + (cond ((eq? n 0) + (##sys#check-syntax 'unquote x '(_ _)) + (car tail)) + (else (list '##sys#cons `(##core#quote ,%unquote) + (walk tail (fx- n 1)) ) ))) ((c %quasiquote head) - (if (pair? tail) - `(##sys#list (##core#quote ,%quasiquote) - ,(walk (car tail) (fx+ n 1)) ) - (list '##sys#cons (list '##core#quote %quasiquote) - (walk tail n)) ) ) - ((pair? head) - (let ((hx (car head)) - (tx (cdr head))) - (if (and (c hx %unquote-splicing) (pair? tx)) - (let ((htx (car tx))) - (if (eq? n 0) - `(##sys#append ,htx - ,(walk tail n) ) - `(##sys#cons (##sys#list (##core#quote ,%unquote-splicing) - ,(walk htx (fx- n 1)) ) - ,(walk tail n) ) ) ) - `(##sys#cons ,(walk head n) ,(walk tail n)) ) ) ) + (list '##sys#cons `(##core#quote ,%quasiquote) + (walk tail (fx+ n 1)) ) ) + ((and (pair? head) (c %unquote-splicing (car head))) + (cond ((eq? n 0) + (##sys#check-syntax 'unquote-splicing head '(_ _)) + `(##sys#append ,(cadr head) ,(walk tail n))) + (else + `(##sys#cons + (##sys#cons (##core#quote ,%unquote-splicing) + ,(walk (cdr head) (fx- n 1)) ) + ,(walk tail n))))) (else `(##sys#cons ,(walk head n) ,(walk tail n)) ) ) ) ) ) ) (define (simplify x) diff --git a/tests/syntax-tests.scm b/tests/syntax-tests.scm index 60ebf7ae..9200aafb 100644 --- a/tests/syntax-tests.scm +++ b/tests/syntax-tests.scm @@ -715,6 +715,88 @@ a)) (f (eval '((cute + <...> 1) 1))) +;;; (quasi-)quotation + +(f (eval '(let ((a 1)) (unquote a)))) +(t 'unquote (quasiquote unquote)) +(f (eval '(quasiquote (a unquote . 1)))) ; "Bad syntax". Also ok: '(a unquote . 1) +(t 'a (quasiquote a)) +(f (eval '(quasiquote a b))) +(f (eval '(quote a b))) +(f (eval '(quasiquote))) +(f (eval '(quote))) +(f (eval '(quasiquote . a))) +(f (eval '(quote . a))) +(t '(foo . 1) (let ((bar 1)) + (quasiquote (foo . (unquote bar))))) +(f (eval '(let ((a 1) + (b 2)) + (quasiquote (unquote a b))))) ; > 1 arg + +(t '(quasiquote (unquote a)) (quasiquote (quasiquote (unquote a)))) +(t '(quasiquote x y) (quasiquote (quasiquote x y))) + +(t '(unquote-splicing a) (quasiquote (unquote-splicing a))) +(t '(1 2) (let ((a (list 2))) (quasiquote (1 (unquote-splicing a))))) +(f (eval '(let ((a 1)) ; a is not a list + (quasiquote (1 (unquote-splicing a)))))) +(f (eval '(let ((a (list 1)) + (b (list 2))) + (quasiquote (1 (unquote-splicing a b)))))) ; > 1 arg + +;; level counting +(define x (list 1 2)) + +;; Testing R5RS-compliance: +(t '(quasiquote (unquote (1 2))) + (quasiquote (quasiquote (unquote (unquote x))))) +(t '(quasiquote (unquote-splicing (1 2))) + (quasiquote (quasiquote (unquote-splicing (unquote x))))) +(t '(quasiquote (unquote 1 2)) + (quasiquote (quasiquote (unquote (unquote-splicing x))))) +(t 'x + (quasiquote (unquote (quasiquote x)))) +(t '(quasiquote (unquote-splicing (quasiquote (unquote x)))) + (quasiquote (quasiquote (unquote-splicing (quasiquote (unquote x)))))) +(t '(quasiquote (unquote (quasiquote (unquote-splicing x)))) + (quasiquote (quasiquote (unquote (quasiquote (unquote-splicing x)))))) +(t '(quasiquote (unquote (quasiquote (unquote (1 2))))) + (quasiquote (quasiquote (unquote (quasiquote (unquote (unquote x))))))) + +;; The following are explicitly left undefined by R5RS. For consistency +;; we define any unquote-(splicing) or quasiquote that occurs in the CAR of +;; a pair to decrease, respectively increase the level count by one. + +(t '(quasiquote . #(1 (unquote x) 3)) ; cdr is not a pair + (quasiquote (quasiquote . #(1 (unquote x) 3)))) +(t '(quasiquote #(1 (unquote x) 3)) ; cdr is a list of one + (quasiquote (quasiquote #(1 (unquote x) 3)))) +(t '(quasiquote a #(1 (unquote x) 3) b) ; cdr is longer + (quasiquote (quasiquote a #(1 (unquote x) 3) b))) + +(t '(quasiquote (unquote . #(1 (1 2) 3))) ; cdr is not a pair + (quasiquote (quasiquote (unquote . #(1 (unquote x) 3))))) +(t '(quasiquote (unquote #(1 (1 2) 3))) ; cdr is a list of one + (quasiquote (quasiquote (unquote #(1 (unquote x) 3))))) +(t '(quasiquote (unquote a #(1 (1 2) 3) b)) ; cdr is longer + (quasiquote (quasiquote (unquote a #(1 (unquote x) 3) b)))) + +(t '(quasiquote (unquote-splicing . #(1 (1 2) 3))) ; cdr is not a pair + (quasiquote (quasiquote (unquote-splicing . #(1 (unquote x) 3))))) +(t '(quasiquote (unquote-splicing #(1 (1 2) 3))) ; cdr is a list of one + (quasiquote (quasiquote (unquote-splicing #(1 (unquote x) 3))))) +(t '(quasiquote (unquote-splicing a #(1 (1 2) 3) b)) ; cdr is longer + (quasiquote (quasiquote (unquote-splicing a #(1 (unquote x) 3) b)))) + +(t 'quasiquote (quasiquote quasiquote)) +(t 'unquote (quasiquote unquote)) +(t 'unquote-splicing (quasiquote unquote-splicing)) +(t '(x quasiquote) (quasiquote (x quasiquote))) +; (quasiquote (x unquote)) is identical to (quasiquote (x . (unquote))).... +;; It's either this (error) or make all calls to unquote with more or less +;; than one argument resolve to a literal unquote. +(f (eval '(quasiquote (x unquote)))) +(t '(x unquote-splicing) (quasiquote (x unquote-splicing))) ;; Let's internal defines properly compared to core define procedure when renamed (f (eval '(let-syntax ((foo (syntax-rules () ((_ x) (begin (define x 1)))))) (let () (foo a))Trap