racket/collects/syntax/scribblings/struct.scrbl
Matthew Flatt 20a1440dcf fix build-struct-generation' to work with racket/base'
and also still works with `mzscheme'
2011-09-03 07:49:22 -06:00

164 lines
7.2 KiB
Racket

#lang scribble/doc
@(require "common.rkt" (for-label syntax/struct))
@title[#:tag "struct"]{Expanding @racket[define-struct]-like Forms}
@defmodule[syntax/struct]
@defproc[(parse-define-struct [stx syntax?] [orig-stx syntax?])
(values identifier?
(or/c identifier? false/c)
(listof identifier?)
syntax?)]{
Parses @racket[stx] as a @racket[define-struct] form, but uses
@racket[orig-stx] to report syntax errors (under the assumption that
@racket[orig-stx] is the same as @racket[stx], or that they at least share
sub-forms). The result is four values: an identifier for the struct
type name, a identifier or #f for the super-name, a list of
identifiers for fields, and a syntax object for the inspector
expression.}
@defproc[(build-struct-names [name-id identifier?]
[field-ids (listof identifier?)]
[#:constructor-name ctr-name (or/c identifier? #f) #f]
[omit-sel? boolean?]
[omit-set? boolean?]
[src-stx (or/c syntax? false/c) #f])
(listof identifier?)]{
Generates the names bound by @racket[define-struct] given an
identifier for the struct type name and a list of identifiers for the
field names. The result is a list of identifiers:
@itemize[
@item{@racketidfont{struct:}@racket[name-id]}
@item{@racket[ctr-name], or @racketidfont{make-}@racket[name-id] if @racket[ctr-name] is @racket[#f]}
@item{@racket[name-id]@racketidfont{?}}
@item{@racket[name-id]@racketidfont{-}@racket[_field], for each
@racket[_field] in @racket[field-ids].}
@item{@racketidfont{set-}@racket[name-id]@racketidfont{-}@racket[_field]@racketidfont{!}
(getter and setter names alternate).}
@item{....}]
If @racket[omit-sel?] is true, then the selector names are omitted from the
result list. If @racket[omit-set?] is true, then the setter names are omitted
from the result list.
The default @racket[src-stx] is @racket[#f]; it is used to provide a
source location to the generated identifiers.}
@defproc[(build-struct-generation [name-id identifier?]
[field-ids (listof identifier?)]
[#:constructor-name ctr-name (or/c identifier? #f) #f]
[omit-sel? boolean?]
[omit-set? boolean?]
[super-type any/c #f]
[prop-value-list list? '(list)]
[immutable-k-list list? '(list)])
(listof identifier?)]{
Takes the same arguments as @racket[build-struct-names] and generates
an S-expression for code using @racket[make-struct-type] to generate
the structure type and return values for the identifiers created by
@racket[build-struct-names]. The optional @racket[super-type],
@racket[prop-value-list], and @racket[immutable-k-list] parameters take
S-expressions that are used as the corresponding argument expressions to
@racket[make-struct-type].}
@defproc[(build-struct-generation* [all-name-ids (listof identifier?)]
[name-id identifier?]
[field-ids (listof identifier?)]
[#:constructor-name ctr-name (or/c identifier? #f) #f]
[omit-sel? boolean?]
[omit-set? boolean?]
[super-type any/c #f]
[prop-value-list list? '(list)]
[immutable-k-list list? '(list)])
(listof identifier?)]{
Like @racket[build-struct-generation], but given the names produced by
@racket[build-struct-names], instead of re-generating them.}
@defproc[(build-struct-expand-info [name-id identifier?]
[field-ids (listof identifier?)]
[#:omit-constructor? no-ctr? any/c #f]
[#:constructor-name ctr-name (or/c identifier? #f) #f]
[#:omit-struct-type? no-type? any/c #f]
[omit-sel? boolean?]
[omit-set? boolean?]
[base-name (or/c identifier? boolean?)]
[base-getters (listof (or/c identifier? false/c))]
[base-setters (listof (or/c identifier? false/c))])
any]{
Takes mostly the same arguments as @racket[build-struct-names], plus a parent
identifier/@racket[#t]/@racket[#f] and a list of accessor and mutator
identifiers (possibly ending in @racket[#f]) for a parent type, and
generates an S-expression for expansion-time code to be used in the
binding for the structure name.
If @racket[no-ctr?] is true, then the constructor name is omitted from
the expansion-time information. Similarly, if @racket[no-type?] is
true, then the structure-type name is omitted.
A @racket[#t] for the @racket[base-name] means no super-type,
@racket[#f] means that the super-type (if any) is unknown, and an
identifier indicates the super-type identifier.}
@defproc[(struct-declaration-info? [v any/c]) boolean?]{
Returns @racket[#t] if @racket[x] has the shape of expansion-time
information for structure type declarations, @racket[#f] otherwise.
See @secref[#:doc refman]{structinfo}.}
@defproc[(generate-struct-declaration [orig-stx syntax?]
[name-id identifier?]
[super-id-or-false (or/c identifier? false/c)]
[field-id-list (listof identifier?)]
[current-context any/c]
[make-make-struct-type procedure?]
[omit-sel? boolean? #f]
[omit-set? boolean? #f])
syntax?]{
This procedure implements the core of a @racket[define-struct]
expansion.
The @racket[generate-struct-declaration] procedure is called by a
macro expander to generate the expansion, where the @racket[name-id],
@racket[super-id-or-false], and @racket[field-id-list] arguments
provide the main parameters. The @racket[current-context] argument is
normally the result of @racket[syntax-local-context]. The
@racket[orig-stx] argument is used for syntax errors. The optional
@racket[omit-sel?] and @racket[omit-set?] arguments default to
@racket[#f]; a @racket[#t] value suppresses definitions of field
selectors or mutators, respectively.
The @racket[make-struct-type] procedure is called to generate the
expression to actually create the struct type. Its arguments are
@racket[orig-stx], @racket[name-id-stx], @racket[defined-name-stxes],
and @racket[super-info]. The first two are as provided originally to
@racket[generate-struct-declaration], the third is the set of names
generated by @racket[build-struct-names], and the last is super-struct
info obtained by resolving @racket[super-id-or-false] when it is not
@racket[#f], @racket[#f] otherwise.
The result should be an expression whose values are the same as the
result of @racket[make-struct-type]. Thus, the following is a basic
@racket[make-make-struct-type]:
@RACKETBLOCK[
(lambda (orig-stx name-stx defined-name-stxes super-info)
#`(make-struct-type '#,name-stx
#,(and super-info (list-ref super-info 0))
#,(/ (- (length defined-name-stxes) 3) 2)
0 #f))]
but an actual @racket[make-make-struct-type] will likely do more.}