meta-struct.scrbl (7448B)
1 #lang scribble/manual 2 @require[@for-label[phc-toolkit/stx 3 (only-meta-in 0 phc-toolkit/meta-struct) 4 (only-meta-in 1 phc-toolkit/untyped/meta-struct) 5 racket/base 6 racket/struct-info]] 7 8 @title{meta operations on structs} 9 @author{@author+email["Suzanne Soy" "racket@suzanne.soy"]} 10 11 @section{Typed macros and procedures} 12 13 @defmodule[phc-toolkit/meta-struct 14 #:use-sources 15 [(submod (lib "phc-toolkit/meta-struct.rkt") typed)]] 16 17 @defform[(struct-predicate s) 18 #:grammar [[s meta-struct?]]]{ 19 Expands to a predicate for the given @racket[struct], with the 20 type @racket[(-> any/c boolean? : s)].} 21 22 @defform[(struct-constructor s) 23 #:grammar [[s meta-struct?]]]{ 24 This macro expands to the constructor function for the given @racket[struct], 25 with the type @racket[(-> _arg … s)] where each @racket[_arg] corresponds to an 26 argument expected by the @racket[struct]'s constructor.} 27 28 @defform*[{(struct-accessor s i) 29 (struct-accessor s field)} 30 #:grammar [[s meta-struct?] 31 [i (expr/c exact-nonnegative-integer?)] 32 [field identifier?]]]{ 33 This macro expands to the @racket[i]-th accessor function for the given 34 @racket[struct], with the type @racket[(-> s _t)] where @racket[_t] is the 35 @racket[struct]'s @racket[_i]-th field's type. 36 37 If the second argument is an identifier, then this macro concatenates the 38 identifiers @racket[s] and @racket[field] with a @racket[-] in between, and 39 expands to the resulting @racket[_s-field]. The lexical context of 40 @racket[_s-field] is the same as the lexical context of @racket[s]. In some 41 rare cases this might not resolve to the accessor for @racket[field] on 42 @racket[s]. Passing an @racket[exact-nonnegative-integer?] as the second 43 argument should be more reliable.} 44 45 @defproc[#:kind "phase 1 procedure" 46 (struct-type-is-immutable? [st Struct-TypeTop]) 47 boolean?]{ 48 Returns @racket[#t] if the given struct type can be determined 49 to have only immutable fields. Returns @racket[#f] otherwise.} 50 51 @defproc[(struct-instance-is-immutable? [v struct?]) 52 boolean?]{ 53 Returns @racket[#t] if @racket[v] can be determined to be an instance of an 54 immutable struct. Returns @racket[#f] otherwise. Note that when given an 55 instance of an opaque struct @racket[struct-instance-is-immutable?] cannot 56 access the struct info, and therefore returns @racket[#f].} 57 58 @include-section{meta-struct-untyped.scrbl} 59 60 @section{Untyped for-syntax utilities} 61 62 @defmodule[phc-toolkit/untyped/meta-struct 63 #:use-sources 64 [(submod (lib "phc-toolkit/meta-struct.rkt") untyped)]] 65 66 @defproc[(meta-struct? [v any/c]) boolean?]{ 67 Returns @racket[#t] if @racket[v] can be used by the 68 functions provided by this module, and @racket[#f] 69 otherwise. More precisely, @racket[v] must be an 70 @racket[identifier] whose @racket[syntax-local-value] is a 71 @racket[struct-info?]. 72 73 @history[#:changed "1.0" "This function is provided at phase 1."]} 74 75 @defstruct[meta-struct-info ([type-descriptor (or/c identifier? #f)] 76 [constructor (or/c identifier? #f)] 77 [predicate (or/c identifier? #f)] 78 [accessors (list*of identifier? 79 (or/c (list/c #f) null?))] 80 [mutators (list*of (or/c identifier? #f) 81 (or/c (list/c #f) null?))] 82 [super-type (or/c identifier? #f)])]{ 83 Encapsulates the result of @racket[extract-struct-info] in 84 a structure with named fields, instead of an obscure 85 six-element list. The precise contents of each field is 86 described in 87 @secref["structinfo" #:doc '(lib "scribblings/reference/reference.scrbl")]. 88 89 @history[#:changed "1.0" "The identifiers are provided at phase 1."]} 90 91 @defproc[(get-meta-struct-info [s meta-struct?] 92 [#:srcloc srcloc (or/c #f syntax?) #f]) 93 meta-struct-info?]{ 94 Returns the @racket[meta-struct-info] for the given 95 identifier. The optional @racket[#:srcloc] keyword argument 96 gives the source location for error messages in case the 97 given identifier is not a @racket[meta-struct?]. 98 99 @history[#:changed "1.0" "This function is provided at phase 1."]} 100 101 @defproc[(meta-struct-subtype? [sub meta-struct?] [super meta-struct?]) 102 boolean?]{ 103 Returns @racket[#t] if the @racket[struct] associated to 104 the identifier @racket[sub] is a subtype of the 105 @racket[struct] associated to the identifier 106 @racket[super], and @racket[#f] otherwise or if the current 107 inspector is not strong enough to know. 108 109 @history[#:changed "1.0" "This function is provided at phase 1."]} 110 111 @defproc[#:kind "phase 1 procedure" 112 (struct-type-id-is-immutable? [id identifier?]) 113 boolean?]{ 114 Returns @racket[#t] if the struct with the given @racket[id] can be determined 115 to have only immutable fields. Returns @racket[#f] otherwise.} 116 117 @(require (for-syntax racket/base 118 racket/syntax 119 racket/struct 120 racket/vector)) 121 122 @(define-for-syntax (strip-loc e) 123 (cond [(syntax? e) (datum->syntax e (strip-loc (syntax-e e)) #f)] 124 [(pair? e) (cons (strip-loc (car e)) (strip-loc (cdr e)))] 125 [(vector? e) (vector-map strip-loc e)] 126 [(box? e) (box (strip-loc (unbox e)))] 127 [(prefab-struct-key e) 128 => (λ (k) (apply make-prefab-struct 129 k 130 (strip-loc (struct->list e))))] 131 [else e])) 132 133 @(define-syntax (shorthand stx) 134 (syntax-case stx () 135 [(_ base expresion-type) 136 (with-syntax ([loc (datum->syntax #'base #'base #f)] 137 [name (format-id #'base "meta-struct-~a" #'base)] 138 [accessor (format-id #'base "meta-struct-info-~a" #'base)] 139 [tmpl (format-id #'base "!struct-~a" #'base)]) 140 #`(deftogether 141 [(defproc (name [s meta-struct?] 142 [#:srcloc srcloc (or/c #f syntax?) #f]) 143 (expressionof 144 (→ s #,(strip-loc #'expresion-type)))) 145 (defform #:kind "template metafunction" 146 (tmpl #,(strip-loc #'s) #,(strip-loc #'maybe-srcloc)) 147 #:grammar ([s meta-struct?] 148 [maybe-srcloc (code:line) 149 #||# (code:line #:srcloc srcloc)]))] 150 @list{ 151 @;{} Shorthand for @racket[(accessor (get-meta-struct-info s))] 152 @;{} (with the optional @racket[#:srcloc] passed to 153 @;{} @racket[get-meta-struct-info]). The precise contents of the 154 @;{} returned value field is described in 155 @;{} @secref["structinfo" 156 #:doc '(lib "scribblings/reference/reference.scrbl")]. 157 @;{} 158 @;{} @history[#:changed "1.0" 159 "This function is provided at phase 1."]}))])) 160 161 @(shorthand type-descriptor (or/c identifier? #f)) 162 @(shorthand constructor (or/c identifier? #f)) 163 @(shorthand predicate (or/c identifier? #f)) 164 @(shorthand accessors (list*of identifier? 165 (or/c (list/c #f) null?))) 166 @(shorthand mutators (list*of (or/c identifier? #f) 167 (or/c (list/c #f) null?))) 168 @(shorthand super-type (or/c identifier? #f))