add syntax-binding-set
functions
The `syntax-binding-set` functions enable explicit construction of lexical information for a syntax objects.
This commit is contained in:
parent
9658c723db
commit
9704cc4731
|
@ -12,7 +12,7 @@
|
|||
|
||||
(define collection 'multi)
|
||||
|
||||
(define version "7.0.0.11")
|
||||
(define version "7.0.0.12")
|
||||
|
||||
(define deps `("racket-lib"
|
||||
["racket" #:version ,version]))
|
||||
|
|
|
@ -279,6 +279,41 @@ then the @exnraise[exn:fail:contract].
|
|||
The @racket[ignored] argument is allowed for backward compatibility
|
||||
and has no effect on the returned syntax object.}
|
||||
|
||||
@deftogether[(
|
||||
@defproc[(syntax-binding-set? [v any/c]) boolean?]
|
||||
@defproc[(syntax-binding-set) syntax-binding-set?]
|
||||
@defproc[(syntax-binding-set->syntax [binding-set syntax-binding-set?] [datum any/c]) syntax-binding-set?]
|
||||
@defproc[(syntax-binding-set-extend [binding-set syntax-binding-set?]
|
||||
[symbol symbol?]
|
||||
[phase (or/c exact-integer? #f)]
|
||||
[mpi module-path-index?]
|
||||
[#:source-symbol source-symbol symbol? symbol]
|
||||
[#:source-phase source-phase (or/c exact-integer? #f) phase]
|
||||
[#:nominal-module nominal-mpi module-path-index? mpi]
|
||||
[#:nominal-phase nominal-phase (or/c exact-integer? #f) source-phase]
|
||||
[#:nominal-symbol nominal-symbol symbol? source-symbol]
|
||||
[#:nominal-require-phase nominal-require-phase (or/c exact-integer? #f) 0]
|
||||
[#:inspector inspector (or/c inspector? #f) #f])
|
||||
syntax-binding-set?]
|
||||
)]{
|
||||
|
||||
A @deftech{syntax binding set} supports explicit construction of
|
||||
binding information for a syntax object. Start by creating an empty
|
||||
binding set with @racket[syntax-binding-set], add bindings with
|
||||
@racket[binding-set-extend], and create a syntax object that hash the
|
||||
bindings as its @tech{lexical information} using
|
||||
@racket[syntax-binding-set->syntax].
|
||||
|
||||
The first three arguments to @racket[syntax-binding-set-extend]
|
||||
establish a binding of @racket[symbol] at @racket[phase] to an
|
||||
identifier that is defined in the module referenced by @racket[mpi].
|
||||
Supply @racket[source-symbol] to make the binding of @racket[symbol]
|
||||
refer to a different provided variable from @racket[mpi], and so on;
|
||||
the optional arguments correspond to the results of
|
||||
@racket[identifier-binding].
|
||||
|
||||
@history[#:added "7.0.0.12"]}
|
||||
|
||||
|
||||
@defproc[(datum-intern-literal [v any/c]) any/c]{
|
||||
|
||||
|
|
|
@ -1922,6 +1922,61 @@
|
|||
(error-test #'(a-rule-pattern) no-match?)
|
||||
(error-test #'(a-rule-pattern 1) no-match?))
|
||||
|
||||
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Explicit binding sets
|
||||
|
||||
(let ([bs (syntax-binding-set-extend
|
||||
(syntax-binding-set-extend
|
||||
(syntax-binding-set-extend
|
||||
(syntax-binding-set)
|
||||
'car 0 (module-path-index-join ''#%runtime #f))
|
||||
'cdr 1 (module-path-index-join ''#%runtime #f)
|
||||
#:source-phase 0
|
||||
#:nominal-require-phase 1)
|
||||
'items 0 (module-path-index-join ''#%runtime #f)
|
||||
#:source-symbol 'list)])
|
||||
(test #t free-identifier=?
|
||||
(syntax-binding-set->syntax bs 'car)
|
||||
#'car)
|
||||
(test #f free-identifier=?
|
||||
(syntax-binding-set->syntax bs 'cdr)
|
||||
#'cdr)
|
||||
(test #t free-identifier=?
|
||||
(syntax-binding-set->syntax bs 'cdr)
|
||||
#'cdr
|
||||
1)
|
||||
(test #f free-identifier=?
|
||||
(syntax-binding-set->syntax bs 'list)
|
||||
#'list)
|
||||
(test #t free-identifier=?
|
||||
(syntax-binding-set->syntax bs 'items)
|
||||
#'list))
|
||||
|
||||
(module synthesizes-self-reference racket/base
|
||||
(require (for-syntax racket/base))
|
||||
(provide results)
|
||||
|
||||
(define x 5)
|
||||
|
||||
(define-syntax (f stx)
|
||||
(define the-x
|
||||
(syntax-binding-set->syntax
|
||||
(syntax-binding-set-extend
|
||||
(syntax-binding-set)
|
||||
'x 0 (variable-reference->module-path-index
|
||||
(#%variable-reference)))
|
||||
'x))
|
||||
|
||||
#`(list #,the-x
|
||||
x
|
||||
(eval (quote-syntax #,the-x))
|
||||
(eval (quote-syntax x))))
|
||||
|
||||
(define results (f)))
|
||||
|
||||
(dynamic-require ''synthesizes-self-reference 0)
|
||||
(test '(5 5 5 5) dynamic-require ''synthesizes-self-reference 'results)
|
||||
|
||||
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Extra taint tests
|
||||
|
||||
|
|
|
@ -12,7 +12,8 @@
|
|||
"cert.rkt"
|
||||
"submodule.rkt"
|
||||
"generic-interfaces.rkt"
|
||||
"kw-syntax-local.rkt" ; shadows local-expand and variants
|
||||
"kw-syntax-local.rkt" ; shadows `local-expand` and variants
|
||||
"kw-syntax-binding.rkt" ; shadows `syntax-binding-set-extend`
|
||||
(for-syntax "stxcase-scheme.rkt"))
|
||||
|
||||
(#%provide (all-from-except "pre-base.rkt"
|
||||
|
@ -40,6 +41,7 @@
|
|||
(all-from "submodule.rkt")
|
||||
(all-from "generic-interfaces.rkt")
|
||||
(all-from "kw-syntax-local.rkt")
|
||||
(all-from "kw-syntax-binding.rkt")
|
||||
(for-syntax syntax-rules syntax-id-rules ... _)
|
||||
(rename -open-input-file open-input-file)
|
||||
(rename -open-output-file open-output-file)
|
||||
|
|
18
racket/collects/racket/private/kw-syntax-binding.rkt
Normal file
18
racket/collects/racket/private/kw-syntax-binding.rkt
Normal file
|
@ -0,0 +1,18 @@
|
|||
(module kw-syntax-local "pre-base.rkt"
|
||||
(require (prefix-in k: '#%kernel))
|
||||
|
||||
(provide syntax-binding-set-extend)
|
||||
|
||||
(define (syntax-binding-set-extend bs as-sym as-phase mpi
|
||||
#:source-symbol [sym as-sym]
|
||||
#:source-phase [phase as-phase]
|
||||
#:nominal-module [nominal-mpi mpi]
|
||||
#:nominal-phase [nominal-phase phase]
|
||||
#:nominal-symbol [nominal-sym sym]
|
||||
#:nominal-require-phase [nominal-require-phase 0]
|
||||
#:inspector [insp #f])
|
||||
(k:syntax-binding-set-extend bs as-sym as-phase mpi
|
||||
sym phase
|
||||
nominal-mpi nominal-phase nominal-sym
|
||||
nominal-require-phase
|
||||
insp)))
|
|
@ -79,7 +79,12 @@
|
|||
syntax-disarm
|
||||
syntax-rearm
|
||||
syntax-taint
|
||||
|
||||
|
||||
syntax-binding-set
|
||||
syntax-binding-set?
|
||||
syntax-binding-set-extend
|
||||
syntax-binding-set->syntax
|
||||
|
||||
raise-syntax-error
|
||||
struct:exn:fail:syntax
|
||||
exn:fail:syntax
|
||||
|
|
|
@ -1407,3 +1407,17 @@
|
|||
'kar)
|
||||
(check-value (cadr (identifier-binding s-also-in-alt))
|
||||
'car) ; because using combined scopes is ambiguous
|
||||
|
||||
;; ----------------------------------------
|
||||
;; Explicitly constructed binding sets
|
||||
|
||||
(eval-expression
|
||||
#:check '(#t #f)
|
||||
'(let-values ([(bs) (syntax-binding-set-extend
|
||||
(syntax-binding-set)
|
||||
'car 0 (module-path-index-join ''#%runtime #f))])
|
||||
(list
|
||||
(free-identifier=? (syntax-binding-set->syntax bs 'car)
|
||||
(quote-syntax car))
|
||||
(free-identifier=? (syntax-binding-set->syntax bs 'cdr)
|
||||
(quote-syntax cdr)))))
|
||||
|
|
|
@ -109,8 +109,9 @@
|
|||
|
||||
compile-keep-source-locations! ; to enable if the back end wants them
|
||||
|
||||
;; This functions are provided for basic testing
|
||||
;; The remaining functions are provided for basic testing
|
||||
;; (such as "demo.rkt")
|
||||
|
||||
syntax? syntax-e
|
||||
identifier?
|
||||
syntax-property
|
||||
|
@ -118,7 +119,7 @@
|
|||
module-compiled-exports
|
||||
module-compiled-indirect-exports
|
||||
read-accept-compiled
|
||||
|
||||
|
||||
syntax-shift-phase-level
|
||||
bound-identifier=?)
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#lang racket/base
|
||||
(require "../common/phase.rkt"
|
||||
"../common/module-path.rkt"
|
||||
(rename-in "syntax.rkt"
|
||||
[syntax->datum raw:syntax->datum]
|
||||
[datum->syntax raw:datum->syntax])
|
||||
|
@ -17,6 +18,10 @@
|
|||
[identifier-binding-symbol raw:identifier-binding-symbol])
|
||||
(rename-in "track.rkt"
|
||||
[syntax-track-origin raw:syntax-track-origin])
|
||||
(rename-in "binding-set.rkt"
|
||||
[syntax-binding-set raw:syntax-binding-set]
|
||||
[syntax-binding-set-extend raw:syntax-binding-set-extend]
|
||||
[syntax-binding-set->syntax raw:syntax-binding-set->syntax])
|
||||
"../expand/syntax-local.rkt"
|
||||
"srcloc.rkt"
|
||||
"../common/contract.rkt"
|
||||
|
@ -38,6 +43,10 @@
|
|||
syntax->datum
|
||||
maybe-syntax->datum
|
||||
datum->syntax
|
||||
syntax-binding-set?
|
||||
syntax-binding-set
|
||||
syntax-binding-set-extend
|
||||
syntax-binding-set->syntax
|
||||
syntax->list
|
||||
identifier?
|
||||
bound-identifier=?
|
||||
|
@ -91,6 +100,38 @@
|
|||
(raise-argument-error who "(or #f syntax?)" stx-p))
|
||||
(raw:datum->syntax stx-c s (to-srcloc-stx stx-l) stx-p))
|
||||
|
||||
(define/who (syntax-binding-set)
|
||||
(raw:syntax-binding-set null))
|
||||
|
||||
(define/who (syntax-binding-set-extend bs as-sym as-phase mpi
|
||||
[sym as-sym]
|
||||
[phase as-phase]
|
||||
[nominal-mpi mpi]
|
||||
[nominal-phase phase]
|
||||
[nominal-sym sym]
|
||||
[nominal-require-phase 0]
|
||||
[insp #f])
|
||||
(check who syntax-binding-set? bs)
|
||||
(check who symbol? as-sym)
|
||||
(check who phase? #:contract phase?-string as-phase)
|
||||
(check who module-path-index? mpi)
|
||||
(check who symbol? sym)
|
||||
(check who phase? #:contract phase?-string phase)
|
||||
(check who module-path-index? nominal-mpi)
|
||||
(check who phase? #:contract phase?-string nominal-phase)
|
||||
(check who symbol? nominal-sym)
|
||||
(check who phase? #:contract phase?-string nominal-require-phase)
|
||||
(check who inspector? #:or-false insp)
|
||||
(raw:syntax-binding-set-extend bs as-sym as-phase mpi
|
||||
sym phase
|
||||
nominal-mpi nominal-phase nominal-sym
|
||||
nominal-require-phase
|
||||
insp))
|
||||
|
||||
(define/who (syntax-binding-set->syntax bs datum)
|
||||
(check who syntax-binding-set? bs)
|
||||
(raw:syntax-binding-set->syntax bs datum))
|
||||
|
||||
(define/who (syntax->list s)
|
||||
(check who syntax? s)
|
||||
(raw:syntax->list s))
|
||||
|
|
38
racket/src/expander/syntax/binding-set.rkt
Normal file
38
racket/src/expander/syntax/binding-set.rkt
Normal file
|
@ -0,0 +1,38 @@
|
|||
#lang racket/base
|
||||
(require "syntax.rkt"
|
||||
"scope.rkt"
|
||||
"module-binding.rkt")
|
||||
|
||||
(provide syntax-binding-set
|
||||
syntax-binding-set?
|
||||
syntax-binding-set-extend
|
||||
syntax-binding-set->syntax)
|
||||
|
||||
(struct syntax-binding-set (binds))
|
||||
(struct bind (sym phase binding))
|
||||
|
||||
(define (syntax-binding-set-extend bs as-sym as-phase mpi
|
||||
sym phase
|
||||
nominal-mpi nominal-phase nominal-sym
|
||||
nominal-require-phase
|
||||
inspector)
|
||||
(struct-copy syntax-binding-set bs
|
||||
[binds
|
||||
(cons (bind as-sym
|
||||
as-phase
|
||||
(make-module-binding mpi phase sym
|
||||
#:extra-inspector inspector
|
||||
#:nominal-module nominal-mpi
|
||||
#:nominal-phase nominal-phase
|
||||
#:nominal-sym nominal-sym
|
||||
#:nominal-require-phase nominal-require-phase))
|
||||
(syntax-binding-set-binds bs))]))
|
||||
|
||||
(define (syntax-binding-set->syntax bs datum)
|
||||
(define s (add-scope (datum->syntax #f datum)
|
||||
(new-multi-scope 'binding-set)))
|
||||
(for ([bind (in-list (syntax-binding-set-binds bs))])
|
||||
(add-binding-in-scopes! (syntax-scope-set s (bind-phase bind))
|
||||
(bind-sym bind)
|
||||
(bind-binding bind)))
|
||||
s)
|
|
@ -22,7 +22,6 @@
|
|||
;; ----------------------------------------
|
||||
|
||||
(define (make-module-binding module phase sym
|
||||
#:wrt [wrt-sym sym]
|
||||
#:nominal-module [nominal-module module]
|
||||
#:nominal-phase [nominal-phase phase]
|
||||
#:nominal-sym [nominal-sym sym]
|
||||
|
|
|
@ -13,12 +13,12 @@
|
|||
consistently.)
|
||||
*/
|
||||
|
||||
#define MZSCHEME_VERSION "7.0.0.11"
|
||||
#define MZSCHEME_VERSION "7.0.0.12"
|
||||
|
||||
#define MZSCHEME_VERSION_X 7
|
||||
#define MZSCHEME_VERSION_Y 0
|
||||
#define MZSCHEME_VERSION_Z 0
|
||||
#define MZSCHEME_VERSION_W 11
|
||||
#define MZSCHEME_VERSION_W 12
|
||||
|
||||
#define MZSCHEME_VERSION_MAJOR ((MZSCHEME_VERSION_X * 100) + MZSCHEME_VERSION_Y)
|
||||
#define MZSCHEME_VERSION_MINOR ((MZSCHEME_VERSION_Z * 1000) + MZSCHEME_VERSION_W)
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user