www

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | Submodules | README | LICENSE

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))