syntax/parse: added literal-set->predicate
closes PR 11968
This commit is contained in:
parent
d22a16a3c7
commit
c8a691490a
|
@ -10,6 +10,7 @@
|
||||||
"runtime.rkt")
|
"runtime.rkt")
|
||||||
(provide define-conventions
|
(provide define-conventions
|
||||||
define-literal-set
|
define-literal-set
|
||||||
|
literal-set->predicate
|
||||||
kernel-literals)
|
kernel-literals)
|
||||||
|
|
||||||
(define-syntax (define-conventions stx)
|
(define-syntax (define-conventions stx)
|
||||||
|
@ -181,6 +182,24 @@ Use cases, explained:
|
||||||
(that's why the weird (if (z?) 0 1) term)
|
(that's why the weird (if (z?) 0 1) term)
|
||||||
|#
|
|#
|
||||||
|
|
||||||
|
;; FIXME: keep one copy of each identifier (?)
|
||||||
|
|
||||||
|
(define-syntax (literal-set->predicate stx)
|
||||||
|
(syntax-case stx ()
|
||||||
|
[(literal-set->predicate litset-id)
|
||||||
|
(let ([val (and (identifier? #'litset-id)
|
||||||
|
(syntax-local-value/record #'litset-id literalset?))])
|
||||||
|
(unless val (raise-syntax-error #f "expected literal set name" stx #'litset-id))
|
||||||
|
(let ([lits (literalset-literals val)])
|
||||||
|
(with-syntax ([((_sym lit phase-var) ...) lits])
|
||||||
|
#'(make-literal-set-predicate (list (list (quote-syntax lit) phase-var) ...)))))]))
|
||||||
|
|
||||||
|
(define (make-literal-set-predicate lits)
|
||||||
|
(lambda (x [phase (syntax-local-phase-level)])
|
||||||
|
(for/or ([lit (in-list lits)])
|
||||||
|
(let ([lit-id (car lit)]
|
||||||
|
[lit-phase (cadr lit)])
|
||||||
|
(free-identifier=?/phases x phase lit-id lit-phase)))))
|
||||||
|
|
||||||
;; Literal sets
|
;; Literal sets
|
||||||
|
|
||||||
|
|
|
@ -93,6 +93,24 @@ whose binding at phase 1 is the @scheme[x] from module
|
||||||
@schememodname['common].
|
@schememodname['common].
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@defform[(literal-set->predicate litset-id)]{
|
||||||
|
|
||||||
|
Given the name of a literal set, produces a predicate that recognizes
|
||||||
|
identifiers in the literal set. The predicate takes one required
|
||||||
|
argument, an identifier @racket[_id], and one optional argument, the
|
||||||
|
phase @racket[_phase] at which to examine the binding of @racket[_id];
|
||||||
|
the @racket[_phase] argument defaults to
|
||||||
|
@racket[(syntax-local-phase-level)].
|
||||||
|
|
||||||
|
@myexamples[
|
||||||
|
(define kernel? (literal-set->predicate kernel-literals))
|
||||||
|
(kernel? #'lambda)
|
||||||
|
(kernel? #'#%plain-lambda)
|
||||||
|
(kernel? #'define-values)
|
||||||
|
(kernel? #'define-values 4)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
@defform/subs[(define-conventions name-id convention-rule ...)
|
@defform/subs[(define-conventions name-id convention-rule ...)
|
||||||
([convention-rule (name-pattern syntax-class)]
|
([convention-rule (name-pattern syntax-class)]
|
||||||
[name-pattern exact-id
|
[name-pattern exact-id
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
syntax/parse/debug
|
syntax/parse/debug
|
||||||
rackunit
|
rackunit
|
||||||
"setup.rkt")
|
"setup.rkt")
|
||||||
(require (for-syntax syntax/parse))
|
|
||||||
|
|
||||||
(define-literal-set lits0 #:phase 0
|
(define-literal-set lits0 #:phase 0
|
||||||
(define lambda))
|
(define lambda))
|
||||||
|
@ -97,3 +96,14 @@
|
||||||
(go #'define 'define)
|
(go #'define 'define)
|
||||||
(go #'begin #f)
|
(go #'begin #f)
|
||||||
(void)))
|
(void)))
|
||||||
|
|
||||||
|
(require (for-label '#%kernel))
|
||||||
|
|
||||||
|
(test-case "litset->pred"
|
||||||
|
(let ([kernel? (literal-set->predicate kernel-literals)])
|
||||||
|
(check-equal? (kernel? #'#%plain-lambda) #t)
|
||||||
|
(check-equal? (kernel? #'define-values) #t)
|
||||||
|
(check-equal? (kernel? #'define-values #f) #t)
|
||||||
|
(check-equal? (kernel? #'define-values 4) #f)
|
||||||
|
(check-equal? (kernel? #'foo) #f)
|
||||||
|
(void)))
|
||||||
|
|
Loading…
Reference in New Issue
Block a user