diff --git a/default-recommendations/hash-shortcuts.rkt b/default-recommendations/hash-shortcuts.rkt index 6b5a7017..0f3a97c5 100644 --- a/default-recommendations/hash-shortcuts.rkt +++ b/default-recommendations/hash-shortcuts.rkt @@ -17,6 +17,7 @@ resyntax/default-recommendations/private/lambda-by-any-name resyntax/default-recommendations/private/literal-constant resyntax/default-recommendations/private/pure-expression + resyntax/default-recommendations/private/self-quoting-literal resyntax/default-recommendations/private/syntax-equivalence resyntax/default-recommendations/private/syntax-identifier-sets resyntax/private/syntax-neighbors @@ -143,10 +144,6 @@ #:original-splice (orig-definition orig-hash-set!))))) -(define-syntax-class self-quoting-literal - (pattern (~or _:boolean _:character _:number _:regexp _:byte-regexp _:string _:bytes))) - - ;; A datum within a quasiquoted expression that can be lifted directly into expression position, ;; either because it's self-quoting or because it's a symbol that can be wrapped in a quote. Quoted ;; datums like (quote x) are excluded because quasiquote treats them as plain data: the quasiquoted diff --git a/default-recommendations/list-shortcuts-test.rkt b/default-recommendations/list-shortcuts-test.rkt index 1582d7bf..54685f17 100644 --- a/default-recommendations/list-shortcuts-test.rkt +++ b/default-recommendations/list-shortcuts-test.rkt @@ -135,6 +135,27 @@ no-change-test: "quasiquotation with only constants not refactorable to list" - `(1 2 3) +no-change-test: "quasiquotation with quoted datums not refactorable to list" +------------------------------ +(define (f y) + `(1 ,y 'x)) +------------------------------ + + +no-change-test: "quasiquotation with symbols not refactorable to list" +------------------------------ +(define (f y) + `(1 ,y x)) +------------------------------ + + +no-change-test: "quasiquotation with nested lists not refactorable to list" +------------------------------ +(define (f y) + `(1 ,y (2 3))) +------------------------------ + + test: "unnecessary splicing quasiquotation refactorable to append" ------------------------------ (define (f xs ys zs) diff --git a/default-recommendations/list-shortcuts.rkt b/default-recommendations/list-shortcuts.rkt index b1c0aeee..374a6511 100644 --- a/default-recommendations/list-shortcuts.rkt +++ b/default-recommendations/list-shortcuts.rkt @@ -18,7 +18,7 @@ resyntax/base resyntax/default-recommendations/analyzers/ignored-result-values resyntax/default-recommendations/private/lambda-by-any-name - resyntax/default-recommendations/private/literal-constant + resyntax/default-recommendations/private/self-quoting-literal resyntax/default-recommendations/private/syntax-identifier-sets syntax/parse) @@ -106,15 +106,18 @@ (sort lst less-than #:key f1)) +;; Elements that aren't unquoted must be self-quoting to lift them out of the quasiquote unchanged. +;; Quoted datums like (quote x) are quasiquoted as plain data, so `(1 'x) is the list (1 (quote x)), +;; not the list (1 x) that a lifted 'x expression would produce. (define-syntax-class unquoted #:attributes (expr literal?) #:literals (unquote) - (pattern expr:literal-constant #:attr literal? #true) + (pattern expr:self-quoting-literal #:attr literal? #true) (pattern (unquote expr) #:attr literal? #false)) (define-refactoring-rule quasiquote-to-list - #:description "This quasiquotation is equialent to a simple `list` call." + #:description "This quasiquotation is equivalent to a simple `list` call." #:literals (quasiquote) (quasiquote (arg:unquoted ...)) #:when (for/or ([literal? (in-list (attribute arg.literal?))]) @@ -123,7 +126,7 @@ (define-refactoring-rule quasiquote-to-append - #:description "This quasiquotation is equialent to calling `append`." + #:description "This quasiquotation is equivalent to calling `append`." #:literals (quasiquote unquote-splicing) (quasiquote ((unquote-splicing arg) ...)) (append arg ...)) diff --git a/default-recommendations/private/self-quoting-literal.rkt b/default-recommendations/private/self-quoting-literal.rkt new file mode 100644 index 00000000..485f6be8 --- /dev/null +++ b/default-recommendations/private/self-quoting-literal.rkt @@ -0,0 +1,18 @@ +#lang racket/base + + +(provide self-quoting-literal) + + +(require syntax/parse) + + +;@---------------------------------------------------------------------------------------------------- + + +;; A datum that evaluates to itself, so it means the same thing in expression position as it does +;; within quoted or quasiquoted data. Symbols and quoted datums like (quote x) are notably not +;; self-quoting: a symbol in expression position is a variable reference, and within quasiquoted +;; data (quote x) is a two-element list rather than the value x. +(define-syntax-class self-quoting-literal + (pattern (~or _:boolean _:character _:number _:regexp _:byte-regexp _:string _:bytes)))