4.4 Syntax Property Bundles
| (require resyntax/grimoire/syntax-property-bundle) | |
| package: resyntax | |
A syntax property bundle is an immutable tree of syntax properties that has been detached from any particular syntax object tree. Each property in a bundle is addressed by the combination of a syntax path, identifying the subform the property belongs to, and a symbol property key. A bundle contains at most one value for each path and key combination. Property bundles are a plain data representation of metadata that can be attached to and extracted from arbitrary syntax objects and their subforms.
Ordinarily, syntax properties live directly on syntax objects. Representing them separately as plain
data lets Resyntax manipulate the properties themselves: bundles can be filtered, merged, inspected,
and rearranged without ever touching a syntax object. Resyntax’s expansion analyzers work this
way —
Although syntax objects themselves permit arbitrary property keys, property keys in a bundle are more limited. A syntax property bundle key must be an interned symbol. This is for two reasons, one specific and one general:
Interned symbol keys are the only syntax property keys that can be iterated by syntax-property-symbol-keys, so such keys are the only kind that bundles can faithfully transfer between syntax objects. Since the entire purpose of property bundles is to transfer properties between syntax objects, allowing uninterned symbol keys would have no purpose.
More generally, syntax objects are not plain serializable data. Syntax objects are not safe to transfer from one Racket process to another. This is relied upon by various layers of the Racket macro system and similar low-level systems for encapsulation purposes. Some syntax properties are only used during macro expansion with opaque keys to provide private communication channels between macros that implement some library abstraction. Exposing such keys directly would allow intermediate macros in client code using that library to violate its abstractions. These sorts of opaque keys are often gensyms or similar unserializable unique values, and the Racket macro system takes care to make sure no API exists that provides uncontrolled access to them.
4.4.1 Constructing Syntax Property Bundles
procedure
v : any/c
struct
(struct syntax-property-entry (path key value) #:transparent) path : syntax-path? key : interned-symbol? value : any/c
procedure
(syntax-property-bundle entry ...) → syntax-property-bundle?
entry : syntax-property-entry?
procedure
(sequence->syntax-property-bundle entries)
→ syntax-property-bundle? entries : (sequence/c syntax-property-entry?)
value
:
(reducer/c (entry/c syntax-path? (hash/c interned-symbol? any/c #:immutable #true)) syntax-property-bundle?)
4.4.2 Querying Syntax Property Bundles
procedure
(syntax-property-bundle-get-property bundle path key [ failure-result]) → any/c bundle : syntax-property-bundle? path : syntax-path? key : interned-symbol?
failure-result : failure-result/c = (λ () (raise (make-exn:fail:contract ....)))
procedure
(syntax-property-bundle-get-immediate-properties bundle path) → immutable-hash? bundle : syntax-property-bundle? path : syntax-path?
procedure
(syntax-property-bundle-get-all-properties bundle path) → syntax-property-bundle? bundle : syntax-property-bundle? path : syntax-path?
procedure
(syntax-property-bundle-entries bundle)
→ (sequence/c syntax-property-entry?) bundle : syntax-property-bundle?
procedure
(syntax-property-bundle-as-map bundle) → immutable-sorted-map?
bundle : syntax-property-bundle?
4.4.3 Moving Properties Between Bundles and Syntax Objects
procedure
(syntax-immediate-properties stx [ #:base-path base-path]) → syntax-property-bundle? stx : syntax? base-path : syntax-path? = root-syntax-path
procedure
(syntax-all-properties stx [ #:base-path base-path]) → syntax-property-bundle? stx : syntax? base-path : syntax-path? = root-syntax-path
procedure
(syntax-add-all-properties stx bundle) → syntax?
stx : syntax? bundle : syntax-property-bundle?