better literal detection

v6.3-exception
Matthew Butterick 6 years ago
parent 3a6f7c407a
commit 35c7fe7a7a

@ -135,6 +135,14 @@
"no matching case for calling pattern" "no matching case for calling pattern"
(syntax->datum stx))])) (syntax->datum stx))]))
(define-for-syntax (literalize-pat pat)
(cond
[(syntax->list pat) => (λ (subpats) (datum->syntax pat (map literalize-pat subpats)))]
[else (syntax-case pat ()
[pat (and (identifier? #'pat) (literal-identifier-datum? (syntax->datum #'pat)))
#'(~literal pat)]
[pat #'pat])]))
(define-syntax (define-macro-cases stx) (define-syntax (define-macro-cases stx)
(define (error-source stx) (or (syntax-property stx 'caller) 'define-macro-cases)) (define (error-source stx) (or (syntax-property stx 'caller) 'define-macro-cases))
(syntax-parse stx (syntax-parse stx
@ -145,16 +153,13 @@
[(_ id:id (pat:expr . result-exprs:expr) ... else-clause:else-clause) [(_ id:id (pat:expr . result-exprs:expr) ... else-clause:else-clause)
(unless (ellipses-follow-wildcards-or-subpatterns? #'(pat ...)) (unless (ellipses-follow-wildcards-or-subpatterns? #'(pat ...))
(raise-syntax-error (error-source #'id) "ellipsis in pattern can only appear after wildcard or subpattern" (syntax->datum stx))) (raise-syntax-error (error-source #'id) "ellipsis in pattern can only appear after wildcard or subpattern" (syntax->datum stx)))
(with-syntax ([(BOUND-LITS UNBOUND-LITS) (with-syntax ([(PAT ...) (map literalize-pat (syntax->list #'(pat ...)))])
(generate-bound-and-unbound-literals #'(pat ...) #:treat-as-bound #'id)])
#'(define-macro id #'(define-macro id
(λ (stx) (λ (stx)
(define result (define result
(syntax-parameterize ([caller-stx (make-rename-transformer #'stx)]) (syntax-parameterize ([caller-stx (make-rename-transformer #'stx)])
(syntax-parse (syntax-case stx () [any #'any]) (syntax-parse (syntax-case stx () [any #'any])
#:literals BOUND-LITS [PAT . result-exprs] ...
#:datum-literals UNBOUND-LITS
[pat . result-exprs] ...
else-clause))) else-clause)))
(if (syntax? result) (if (syntax? result)
result result

@ -1,8 +1,8 @@
#lang racket/base #lang racket/base
(require "syntax-flatten.rkt" racket/list racket/match) (require "syntax-flatten.rkt" racket/list racket/match)
(provide ellipses-follow-wildcards-or-subpatterns? generate-literals generate-bound-and-unbound-literals) (provide ellipses-follow-wildcards-or-subpatterns? generate-literals generate-bound-and-unbound-literals literal-identifier-datum?)
(define (literal-identifier? pat-datum) (define (literal-identifier-datum? pat-datum)
(and (symbol? pat-datum) (and (symbol? pat-datum)
(not (memq pat-datum '(... _))) ; isn't a reserved identifier (not (memq pat-datum '(... _))) ; isn't a reserved identifier
(let ([pat-str (symbol->string pat-datum)]) (let ([pat-str (symbol->string pat-datum)])
@ -11,14 +11,14 @@
(define (wildcard? pat-datum) (define (wildcard? pat-datum)
(and (symbol? pat-datum) (and (symbol? pat-datum)
(not (literal-identifier? pat-datum)) (not (literal-identifier-datum? pat-datum))
(not (memq pat-datum '(... _))))) (not (memq pat-datum '(... _)))))
;; generate literals for any symbols that are not ... or _ and not IN_CAPS ;; generate literals for any symbols that are not ... or _ and not IN_CAPS
(define (generate-literals pats) (define (generate-literals pats)
(for*/list ([pat-arg (in-list (syntax-flatten pats))] (for*/list ([pat-arg (in-list (syntax-flatten pats))]
[pat-datum (in-value (syntax->datum pat-arg))] [pat-datum (in-value (syntax->datum pat-arg))]
#:when (literal-identifier? pat-datum)) #:when (literal-identifier-datum? pat-datum))
pat-arg)) pat-arg))

Loading…
Cancel
Save