﻿id	summary	reporter	owner	description	type	status	priority	milestone	component	version	resolution	keywords	cc	difficulty
439	Quasiquote simplification and improved syntax checks	sjamaan	felix winkelmann	"While studying the expander, I stumbled upon a problem in the quasiquote code. It does not check for proper usage of unquote/unquote-splicing.

Right now, it silently ignores extra arguments to unquote and unquote-splicing:

{{{
(let ((a 1)) (quasiquote (unquote a b))) => 1
}}}

Also, there's an R5RS incompatibility:

{{{
(define x (list 1 2))
(quasiquote (quasiquote (unquote-splicing (unquote x))))
=> (quasiquote (unquote-splicing (unquote x)))
}}}

However, this should return {{{(quasiquote (unquote-splicing (1 2)))}}} because

  The nesting level increases by one inside each successive quasiquotation, and decreases by one inside each unquotation
-- R5RS 4.2.6, second paragraph

The first quasiquote opens, the second increases nesting to one, the unquote-splicing decreases it to zero and the unquote is at level 0 so should result in the x getting unquoted.

The attached patch fixes these problems.

I've also taken the opportunity to simplify the code a bit, reducing the total ""quasiquote""-code by 8 lines and making it more readable/understandable.  Because R5RS says the behavior of unquote and unquote-splicing is undefined for cases where they occur in positions other than the car of a 2-element list, I decided it's not worth the extra checking whether the cdr of a nested quasiquote call is actually a list or not. It complicated the code and make it a little inconsistent.

The patch also adds tests and fixes the broken {{{(f ..)}}} test syntax; it originally always succeeded, because it threw an error when no errors were thrown, causing the exception handler to always be invoked! Luckily, none of the existing tests are failing after this fix."	change request	closed	minor		expander	4.6.x	fixed	expander, quasiquote, syntax		
