diff --git a/collects/r5rs/main.ss b/collects/r5rs/main.ss index a17f5120d2..a39d84d29d 100644 --- a/collects/r5rs/main.ss +++ b/collects/r5rs/main.ss @@ -199,7 +199,7 @@ [unquote (zero? depth) (raise-syntax-error - #f + 'unquote "invalid context within quasiquote" stx form)] @@ -212,7 +212,7 @@ [unquote-splicing (zero? depth) (raise-syntax-error - #f + 'unquote-splicing "invalid context within quasiquote" stx form)] @@ -220,6 +220,12 @@ #`(mcons 'quasiquote #,(loop #'e (add1 depth)))] [(a . b) #`(mcons #,(loop #'a depth) #,(loop #'b depth))] + [#(unquote a ...) + (raise-syntax-error + 'unquote + "invalid context within quasiquote" + stx + form)] [#(a ...) #`(mlist->vector #,(loop (syntax->list #'(a ...)) depth))] [other #'(r5rs:quote other)])) diff --git a/collects/r6rs/scribblings/r6rs.scrbl b/collects/r6rs/scribblings/r6rs.scrbl index 9a6436bfeb..acad9ae87e 100644 --- a/collects/r6rs/scribblings/r6rs.scrbl +++ b/collects/r6rs/scribblings/r6rs.scrbl @@ -512,8 +512,8 @@ several known ways: (pair? #f "r6rs-Z-H-14.html" "node_idx_608") (positive? #f "r6rs-Z-H-14.html" "node_idx_476") (procedure? #f "r6rs-Z-H-14.html" "node_idx_342") - (quasiquote #f "r6rs-Z-H-14.html" "node_idx_768") - (quote #f "r6rs-Z-H-14.html" "node_idx_362") + (quasiquote #t "r6rs-Z-H-14.html" "node_idx_768") + (quote #t "r6rs-Z-H-14.html" "node_idx_362") (rational-valued? #f "r6rs-Z-H-14.html" "node_idx_452") (rational? #f "r6rs-Z-H-14.html" "node_idx_446") (rationalize #f "r6rs-Z-H-14.html" "node_idx_536") @@ -546,8 +546,8 @@ several known ways: (symbol? #f "r6rs-Z-H-14.html" "node_idx_646") (tan #f "r6rs-Z-H-14.html" "node_idx_550") (truncate #f "r6rs-Z-H-14.html" "node_idx_532") - (unquote #f "r6rs-Z-H-14.html" "node_idx_770") - (unquote-splicing #f "r6rs-Z-H-14.html" "node_idx_772") + (unquote #t "r6rs-Z-H-14.html" "node_idx_770") + (unquote-splicing #t "r6rs-Z-H-14.html" "node_idx_772") (values #f "r6rs-Z-H-14.html" "node_idx_760") (vector #f "r6rs-Z-H-14.html" "node_idx_728") (vector->list #f "r6rs-Z-H-14.html" "node_idx_736") diff --git a/collects/scheme/private/qq-and-or.ss b/collects/scheme/private/qq-and-or.ss index ee0d490d92..61df94fe76 100644 --- a/collects/scheme/private/qq-and-or.ss +++ b/collects/scheme/private/qq-and-or.ss @@ -298,6 +298,19 @@ #f) (let-values (((l) (vector->list (syntax-e x)))) + ;; special case: disallow #(unquote ) + (if (stx-pair? l) + (let-values ([(first) (stx-car l)]) + (if (identifier? first) + (if (free-identifier=? first unquote-stx) + (raise-syntax-error + 'unquote + "invalid context within quasiquote" + in-form + first) + (void)) + (void))) + (void)) (let-values (((l2) (qq l level))) (if (eq? l l2) diff --git a/collects/scribblings/reference/syntax.scrbl b/collects/scribblings/reference/syntax.scrbl index a1edd5003d..a7bd70bc88 100644 --- a/collects/scribblings/reference/syntax.scrbl +++ b/collects/scribblings/reference/syntax.scrbl @@ -14,6 +14,8 @@ scheme/splicing)) @(define cvt (schemefont "CVT")) +@(define unquote-id (scheme unquote)) +@(define unquote-splicing-id (scheme unquote-splicing)) @title[#:tag "syntax" #:style 'toc]{Syntactic Forms} @@ -1862,33 +1864,33 @@ expression). @defform[(quasiquote datum)]{ The same as @scheme[(quote datum)] if @scheme[datum] does not include -@scheme[(unquote _expr)] or @scheme[(unquote-splicing _expr)]. An -@scheme[(unquote _expr)] expression escapes from the quote, however, +@scheme[(#,unquote-id _expr)] or @scheme[(#,unquote-splicing-id _expr)]. An +@scheme[(#,unquote-id _expr)] form escapes from the quote, however, and the result of the @scheme[_expr] takes the place of the -@scheme[(unquote _expr)] form in the @scheme[quasiquote] result. An -@scheme[(unquote-splicing _expr)] similarly escapes, but the +@scheme[(#,unquote-id _expr)] form in the @scheme[quasiquote] result. An +@scheme[(#,unquote-splicing-id _expr)] similarly escapes, but the @scheme[_expr] must produce a list, and its elements are spliced as -multiple values place of the @scheme[(unquote-splicing _expr)], which +multiple values place of the @scheme[(#,unquote-splicing-id _expr)], which must appear as the @scheme[car] or a quoted pair, as an element of a quoted vector, or as an element of a quoted @tech{prefab} structure; in the case of a pair, if the @scheme[cdr] of the relevant quoted pair is empty, then @scheme[_expr] need not produce a list, and its result is used directly in place of the quoted pair (in the same way that @scheme[append] accepts a non-list final argument). In a quoted -@tech{hash table}, an @scheme[(unquote _expr)] or -@scheme[(unquote-splicing _expr)] expression escapes only in the +@tech{hash table}, an @scheme[(#,unquote-id _expr)] or +@scheme[(#,unquote-splicing-id _expr)] expression escapes only in the second element of an entry pair (i.e., the value), while entry keys are always implicitly quoted. If @scheme[unquote] or @scheme[unquote-splicing] appears within @scheme[quasiquote] in any -other way than as @scheme[(unquote _expr)] or -@scheme[(unquote-splicing _expr)], a syntax error is reported. +other way than as @scheme[(#,unquote-id _expr)] or +@scheme[(#,unquote-splicing-id _expr)], a syntax error is reported. @mz-examples[ (eval:alts (#,(scheme quasiquote) (0 1 2)) `(0 1 2)) -(eval:alts (#,(scheme quasiquote) (0 (#,(scheme unquote) (+ 1 2)) 4)) `(0 ,(+ 1 2) 4)) -(eval:alts (#,(scheme quasiquote) (0 (#,(scheme unquote-splicing) (list 1 2)) 4)) `(0 ,@(list 1 2) 4)) -(eval:alts (#,(scheme quasiquote) (0 (#,(scheme unquote-splicing) 1) 4)) `(0 ,@1 4)) -(eval:alts (#,(scheme quasiquote) (0 (#,(scheme unquote-splicing) 1))) `(0 ,@1)) +(eval:alts (#,(scheme quasiquote) (0 (#,unquote-id (+ 1 2)) 4)) `(0 ,(+ 1 2) 4)) +(eval:alts (#,(scheme quasiquote) (0 (#,unquote-splicing-id (list 1 2)) 4)) `(0 ,@(list 1 2) 4)) +(eval:alts (#,(scheme quasiquote) (0 (#,unquote-splicing-id 1) 4)) `(0 ,@1 4)) +(eval:alts (#,(scheme quasiquote) (0 (#,unquote-splicing-id 1))) `(0 ,@1)) ] A @scheme[quasiquote], @scheme[unquote], or @scheme[unquote-splicing]