From 3c07250db4bb2984fa9756c6f4250a2caef80111 Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Thu, 22 Jun 2017 13:33:51 -0600 Subject: [PATCH] fix printer for `(unquote @d)` Avoid printing `(unquote @d)` or `(unsyntax @d)` as `,@d` or `#,@d`, which would mean `(unquote-splicing @d)` or `(unsyntax-splicing @d)` to the reader, by adding an extra space before the `@`. --- .../scribblings/reference/printer.scrbl | 9 ++++++++- pkgs/racket-test-core/tests/racket/print.rktl | 4 ++++ racket/collects/racket/pretty.rkt | 16 +++++++++++++++- racket/src/racket/src/print.c | 19 +++++++++++++++++++ 4 files changed, 46 insertions(+), 2 deletions(-) diff --git a/pkgs/racket-doc/scribblings/reference/printer.scrbl b/pkgs/racket-doc/scribblings/reference/printer.scrbl index c091e82219..0b7e47918a 100644 --- a/pkgs/racket-doc/scribblings/reference/printer.scrbl +++ b/pkgs/racket-doc/scribblings/reference/printer.scrbl @@ -199,7 +199,10 @@ or @litchar["#,@"], respectively. After the reader syntax, the second element of the list is printed. When the list is a tail of an enclosing list, the tail is printed after a @litchar{.} in the enclosing list (after which the reader abbreviations work), instead of -including the tail as two elements of the enclosing list. +including the tail as two elements of the enclosing list. If the +reader syntax @litchar{,} or @litchar{#,} is followed by a symbol +that prints with a leading @litchar["@"], then the printer adds an +extra space before the @litchar["@"]. The printed form of a pair is the same in both @racket[write] and @racket[display] modes, except as the printed form of the pair's @@ -251,6 +254,10 @@ always @tech{quotable}, a pair is @tech{quotable} when its @racket[car] and @racket[cdr] are @tech{quotable}, and a mutable list is never @tech{quotable}. +@history[#:changed "6.9.0.6" @elem{Added a space when printing @litchar{,} + or @litchar{#,} followed by a symbol + that prints with a leading @litchar["@"].}] + @section[#:tag "print-string"]{Printing Strings} All @tech{strings} @racket[display] as their literal character sequences. diff --git a/pkgs/racket-test-core/tests/racket/print.rktl b/pkgs/racket-test-core/tests/racket/print.rktl index 86b1866014..76e1fae7ea 100644 --- a/pkgs/racket-test-core/tests/racket/print.rktl +++ b/pkgs/racket-test-core/tests/racket/print.rktl @@ -193,6 +193,10 @@ (ptest "'`a" '`a) (ptest "'`,#,#`a" '`,#,#`a) (ptest "'`,#,#`,@#,@a" '`,#,#`,@#,@a) + (ptest "'`,#,#`,@, @a" '`,#,#`,@, @a) + (ptest "'`,#,#`,@#, @a" '`,#,#`,@#, @a) + (ptest "'`,#,#`,@,|@a,|" '`,#,#`,@,|@a,|) + (ptest "'`,#,#`,@#,|@a,|" '`,#,#`,@#,|@a,|) (ptest "(fxvector 1 10000 3)" (fxvector 1 10000 3)) (ptest "(flvector 1.1 10000.1 3.1 0.0)" (flvector 1.1 10000.1 3.1 0.0)) diff --git a/racket/collects/racket/pretty.rkt b/racket/collects/racket/pretty.rkt index 6b8bcc3756..e306abe3d7 100644 --- a/racket/collects/racket/pretty.rkt +++ b/racket/collects/racket/pretty.rkt @@ -763,7 +763,21 @@ (equal? open "(")) (begin (out (read-macro-prefix expr car)) - (wr (read-macro-body expr car cdr) depth qd)) + ;; Special case: "," or "#," followed by a symbol that might start "@" + (cond + [(and (or (eq? (car expr) 'unquote) + (eq? (car expr) 'unsyntax)) + (symbol? (cadr expr))) + (define s (if display? + (symbol->string (cadr expr)) + (format "~s" (cadr expr)))) + (when (and (positive? (string-length s)) + (eqv? #\@ (string-ref s 0))) + ;; Avoid ambiguity by adding a space + (out " ")) + (out s)] + [else + (wr (read-macro-body expr car cdr) depth qd)])) (wr-lst expr #t depth pair? car cdr open close qd))) (define (wr-lst l check? depth pair? car cdr open close qd) diff --git a/racket/src/racket/src/print.c b/racket/src/racket/src/print.c index a6b915f03f..23dc068a68 100644 --- a/racket/src/racket/src/print.c +++ b/racket/src/racket/src/print.c @@ -3908,6 +3908,25 @@ print_pair(Scheme_Object *pair, int notdisplay, int compact, && !first_unquoted && is_special_reader_form(pp, notdisplay, pair)) { print_special_reader_form(SCHEME_CAR(pair), pp, notdisplay); + /* Corner case: if we just printed "#," or ",", make sure we don't + next print a symbol that starts "@". For example, "," + followed by the symbol whose string is "@d" should not print + as ",@d". */ + if ((SAME_OBJ(SCHEME_CAR(pair), unquote_symbol) + || SAME_OBJ(SCHEME_CAR(pair), unsyntax_symbol)) + && (SCHEME_SYMBOLP(SCHEME_CADR(pair)) + && (SCHEME_SYM_VAL(SCHEME_CADR(pair))[0] == '@'))) { + /* Double-check that `@` will be the next character: */ + const char *sv; + sv = scheme_symbol_name_and_size(SCHEME_CADR(pair), NULL, + ((pp->can_read_pipe_quote + ? SCHEME_SNF_PIPE_QUOTE + : SCHEME_SNF_NO_PIPE_QUOTE))); + if (sv[0] == '@') { + /* Avoid ambiguity: */ + print_utf8_string(pp, " ", 0, 1); + } + } (void)print(SCHEME_CADR(pair), notdisplay, compact, ht, mt, pp); return; } else if ((notdisplay == 3) && !first_unquoted) {