units chapter in reference
svn: r6976
This commit is contained in:
parent
ba1670a88d
commit
08c04d2579
|
@ -303,6 +303,7 @@
|
|||
[(_ [spec ...] desc ...) #'(defform*/subs [spec ...] () desc ...)]))
|
||||
(define-syntax (defform stx)
|
||||
(syntax-case stx ()
|
||||
[(_ #:literals (lit ...) spec desc ...) #'(defform*/subs #:literals (lit ...) [spec] () desc ...)]
|
||||
[(_ spec desc ...) #'(defform*/subs [spec] () desc ...)]))
|
||||
(define-syntax (defform/subs stx)
|
||||
(syntax-case stx ()
|
||||
|
|
|
@ -71,6 +71,8 @@
|
|||
|
||||
@title[#:tag "mzlib:class" #:style 'toc]{Classes and Objects}
|
||||
|
||||
@local-table-of-contents[]
|
||||
|
||||
A @deftech{class} specifies
|
||||
|
||||
@itemize{
|
||||
|
@ -143,8 +145,6 @@ Classes, objects, and interfaces are all values. However, a class or
|
|||
interface is not an object (i.e., there are no ``meta-classes'' or
|
||||
``meta-interfaces'').
|
||||
|
||||
@local-table-of-contents[]
|
||||
|
||||
@; ------------------------------------------------------------------------
|
||||
|
||||
@section[#:tag "mz:createinterface"]{Creating Interfaces}
|
||||
|
|
|
@ -20,6 +20,7 @@ language.
|
|||
@include-section["data.scrbl"]
|
||||
@include-section["struct.scrbl"]
|
||||
@include-section["class.scrbl"]
|
||||
@include-section["units.scrbl"]
|
||||
@include-section["control.scrbl"]
|
||||
@include-section["concurrency.scrbl"]
|
||||
@include-section["macros.scrbl"]
|
||||
|
|
628
collects/scribblings/reference/units.scrbl
Normal file
628
collects/scribblings/reference/units.scrbl
Normal file
|
@ -0,0 +1,628 @@
|
|||
#reader(lib "docreader.ss" "scribble")
|
||||
@require[(all-except "mz.ss" link)]
|
||||
@require[(lib "unit.ss")]
|
||||
@require-for-syntax[mzscheme]
|
||||
|
||||
@begin[
|
||||
(define-syntax defkeywords
|
||||
(syntax-rules (*)
|
||||
[(_ [* (form ...) as see])
|
||||
(defform* [form ...]
|
||||
"Allowed only in a " (scheme as) "; see " (scheme see) ".")]
|
||||
[(_ [* (form ...) see-eg])
|
||||
(defform* [form ...]
|
||||
"Allowed only in certain forms; see, for example, " (scheme see-eg) ".")]
|
||||
[(_ [form as see])
|
||||
(defkeywords [* (form) as see])]
|
||||
[(_ [form see-eg])
|
||||
(defkeywords [* (form) see-eg])]
|
||||
[(_ f ...)
|
||||
(begin (defkeywords f) ...)]))
|
||||
]
|
||||
|
||||
@title[#:tag "mzlib:unit" #:style 'toc]{Units}
|
||||
|
||||
@local-table-of-contents[]
|
||||
|
||||
@deftech{Units} are used to organize a program into separately
|
||||
compilable and reusable components. A unit resembles a procedure in
|
||||
that both are first-class values that are used for abstraction. While
|
||||
procedures abstract over values in expressions, units abstract over
|
||||
names in collections of definitions. Just as a procedure is invoked to
|
||||
evaluate its expressions given actual arguments for its formal
|
||||
parameters, a unit is invoked to evaluate its definitions given actual
|
||||
references for its imported variables. Unlike a procedure, however, a
|
||||
unit's imported variables can be partially linked with the exported
|
||||
variables of another unit {\em prior to invocation}. Linking merges
|
||||
multiple units together into a single compound unit. The compound unit
|
||||
itself imports variables that will be propagated to unresolved
|
||||
imported variables in the linked units, and re-exports some variables
|
||||
from the linked units for further linking.
|
||||
|
||||
@; ------------------------------------------------------------------------
|
||||
|
||||
@section[#:tag "mz:creatingunits"]{Creating Units}
|
||||
|
||||
@defform/subs[
|
||||
#:literals (import export prefix rename only except tag init-depend tag)
|
||||
(unit
|
||||
(import tagged-sig-spec ...)
|
||||
(export tagged-sig-spec ...)
|
||||
init-depends-decl
|
||||
unit-body-expr-or-defn
|
||||
...)
|
||||
|
||||
([tagged-sig-spec
|
||||
sig-spec
|
||||
(tag id sig-spec)]
|
||||
|
||||
[sig-spec
|
||||
sig-id
|
||||
(prefix id sig-spec)
|
||||
(rename sig-spec (id id) ...)
|
||||
(only sig-spec id ...)
|
||||
(except sig-spec id ...)]
|
||||
|
||||
[init-depends-decl
|
||||
code:blank
|
||||
(init-depend tagged-sig-id ...)]
|
||||
|
||||
[tagged-sig-id
|
||||
sig-id
|
||||
(tag id sig-id)])]{
|
||||
|
||||
Produces a unit that encapsulates its
|
||||
@scheme[unit-body-expr-or-defn]s. Expressions in the @scheme[unit]
|
||||
body can refer to identifiers bound by the @scheme[sig-spec]s of the
|
||||
@scheme[import] clause, and the body must include one definition for
|
||||
each identifier of a @scheme[sig-spec] in the @scheme[export] clause.
|
||||
An identifier that is exported cannot be @scheme[set!]ed in either the
|
||||
defining unit or in importing units, although the implicit assignment
|
||||
to initialize the variable may be visible as a mutation.
|
||||
|
||||
Each import or export @scheme[sig-spec] ultimately refers to a
|
||||
@scheme[sig-id], which is an identifier that is bound to a signature
|
||||
by @scheme[define-signature].
|
||||
|
||||
In a specific import or export position, the set of identifiers bound
|
||||
or required by a particular @scheme[sig-id] can be adjusted in a few
|
||||
ways:
|
||||
|
||||
@itemize{
|
||||
|
||||
@item{@scheme[(prefix id sig-spec)] as an import binds the same as
|
||||
@scheme[sig-spec], except that each binding is prefixed with @scheme[id].
|
||||
As an export, this form causes definitions using the @scheme[id]
|
||||
prefix to satisfy the exports required by @scheme[sig-spec].}
|
||||
|
||||
@item{@scheme[(rename sig-spec (id id) ...)] as
|
||||
an import binds the same as @scheme[sig-spec], except that the first @scheme[id]
|
||||
is used for the binding instead of the second @scheme[id] (where
|
||||
@scheme[sig-spec] by itself must imply a binding for the second @scheme[id]).
|
||||
As an export, this form causes a definition for the first @scheme[id]
|
||||
to satisfy the export named by the second @scheme[id] in @scheme[sig-spec].}
|
||||
|
||||
@item{@scheme[(only sig-spec id ...)] as
|
||||
an import binds the same as @scheme[sig-spec], but restricted to just the
|
||||
listed @scheme[id]s (where
|
||||
@scheme[sig-spec] by itself must imply a binding for each @scheme[id]).
|
||||
This form is not allowed for an export.}
|
||||
|
||||
@item{@scheme[(except sig-spec id ...)] as
|
||||
an import binds the same as @scheme[sig-spec], but excluding all listed
|
||||
@scheme[id]s (where
|
||||
@scheme[sig-spec] by itself must imply a binding for each @scheme[id]).
|
||||
This form is not allowed for an export.}
|
||||
|
||||
}
|
||||
|
||||
As suggested by the grammar, these adjustments to a signature can be
|
||||
nested arbitrarily.
|
||||
|
||||
A unit's declared imports are matched with actual supplied imports by
|
||||
signature. That is, the order in which imports are suppplied to a unit
|
||||
when linking is irrelevant; all that matters is the signature
|
||||
implemented by each supplied import. One actual import must be
|
||||
provided for each declared import. Similarly, when a unit implements
|
||||
multiple signatures, the order of the export signatures does not
|
||||
matter.
|
||||
|
||||
To support multiple imports or exports for the same signature, an
|
||||
import or export can be tagged using the form @scheme[(tag
|
||||
id sig-spec)]. When an import declaration of a unit is
|
||||
tagged, then one actual import must be given the same tag (with the
|
||||
same signature) when the unit is linked. Similarly, when an export
|
||||
declaration is tagged for a unit, then references to that particular
|
||||
export must explicitly use the tag.
|
||||
|
||||
A unit is prohibited syntactically from importing two signatures that
|
||||
are not distinct, unless they have different tags; two signatures are
|
||||
@defterm{distinct} only if when they share no ancestor through
|
||||
@scheme[extends]. The same syntactic constraint applies to exported
|
||||
signatures. In addition, a unit is prohibited syntactically from
|
||||
importing the same identifier twice (after renaming and other
|
||||
transformations on a @scheme[sig-spec]), exporting the same identifier
|
||||
twice (again, after renaming), or exporting an identifier that is
|
||||
imported.
|
||||
|
||||
When units are linked, the bodies of the linked units are
|
||||
executed in an order that is specified at the linking site. An
|
||||
optional @scheme[(init-depend tagged-sig-id ...)]
|
||||
declaration constrains the allowed orders of linking by specifying
|
||||
that the current unit must be initialized after the unit that supplies
|
||||
the corresponding import. Each @scheme[tagged-sig-id] in an
|
||||
@scheme[init-depend] declaration must have a corresponding import in the
|
||||
@scheme[import] clause.}
|
||||
|
||||
@defform/subs[
|
||||
#:literals (define-syntaxes define-values open extends)
|
||||
(define-signature id extension-decl
|
||||
(sig-elem ...))
|
||||
|
||||
([extension-decl
|
||||
code:blank
|
||||
(code:line extends sig-id)]
|
||||
|
||||
[sig-elem
|
||||
id
|
||||
(define-syntaxes (id ...) expr)
|
||||
(define-values (value-id ...) expr)
|
||||
(open sig-spec)
|
||||
(sig-form-id . datum)])]{
|
||||
|
||||
Binds an identifier to a signature that specifies a group
|
||||
of bindings for import or export:
|
||||
|
||||
@itemize{
|
||||
|
||||
@item{Each @scheme[id] in a signature declaration means that a unit
|
||||
implementing the signature must supply a variable definition for the
|
||||
@scheme[id]. That is, @scheme[id] is available for use in units
|
||||
importing the signature, and @scheme[id] must be defined by units
|
||||
exporting the signature.}
|
||||
|
||||
@item{Each @scheme[define-syntaxes] form in a signature declaration
|
||||
introduces a macro to that is available for use in any unit that
|
||||
imports the signature. Free variables in the definition's
|
||||
@scheme[expr] refer to other identifiers in the signature first, or
|
||||
the context of the @scheme[define-signature] form if the signature
|
||||
does not include the identifier.}
|
||||
|
||||
@item{Each @scheme[define-values] form in a signature declaration
|
||||
introduces code that effectively prefixes every unit that imports the
|
||||
signature. Free variables in the definition's @scheme[expr] are
|
||||
treated the same as for @scheme[define-syntaxes].}
|
||||
|
||||
@item{Each @scheme[(open sig-spec)] adds to the signature everything
|
||||
specified by @scheme[sig-spec].}
|
||||
|
||||
@item{Each @scheme[(sig-form-id . datum)] extends the signature in a
|
||||
way that is defined by @scheme[sig-form-id], which must be bound by
|
||||
@scheme[define-signature-form]. One such binding is for
|
||||
@scheme[struct].}
|
||||
|
||||
}
|
||||
|
||||
When a @scheme[define-signature] form includes a @scheme[extends]
|
||||
clause, then the define signature automatically includes everything in
|
||||
the extended signature. Furthermore, any implementation of the new
|
||||
signature can be used as an implementation of the extended signature.}
|
||||
|
||||
@defkeywords[[(open sig-spec) _sig-elem define-signature]
|
||||
[(only sig-spec id ...) _sig-spec unit]
|
||||
[(except sig-spec id ...) _sig-spec unit]
|
||||
[(rename sig-spec (id id) ...) _sig-spec unit]
|
||||
[(prefix id sig-spec) _sig-spec unit]
|
||||
[(import tagged-sig-spec ...) unit]
|
||||
[(export tagged-sig-spec ...) unit]
|
||||
[(link linkage-decl ...) compound-unit]
|
||||
[* [(tag id sig-spec)
|
||||
(tag id sig-id)] unit]
|
||||
[(init-depend tagged-sig-id ...) init-depend-decl unit]]
|
||||
|
||||
@defidform[extends]{
|
||||
|
||||
This form is allowed only within @scheme[define-signature].}
|
||||
|
||||
@; ------------------------------------------------------------------------
|
||||
|
||||
@section[#:tag "mz:invokingunits"]{Invoking Units}
|
||||
|
||||
@defform*[#:literals (import)
|
||||
[(invoke-unit unit-expr)
|
||||
(invoke-unit unit-expr (import tagged-sig-spec ...))]]{
|
||||
|
||||
Invokes the unit produced by @scheme[unit-expr]. For each of the
|
||||
unit's imports, the @scheme[invoke-unit] expression must contain a
|
||||
@scheme[tagged-sig-spec] in the @scheme[import] clause; see
|
||||
@scheme[unit] for the grammar of @scheme[tagged-sig-spec]. If the unit
|
||||
has no imports, the @scheme[import] clause can be omitted.
|
||||
|
||||
When no @scheme[tagged-sig-spec]s are provided, @scheme[unit-expr]
|
||||
must produce a unit that expect no imports. To invoke the unit, all
|
||||
bindings are first initialized to the @|undefined-const| value. Next,
|
||||
the unit's body definitions and expressions are evaluated in order; in
|
||||
the case of a definition, evaluation sets the value of the
|
||||
corresponding variable(s). Finally, the result of the last expression
|
||||
in the unit is the result of the @scheme[invoke-unit] expression.
|
||||
|
||||
Each supplied @scheme[tagged-sig-spec] takes bindings from the
|
||||
surrounding context and turns them into imports for the invoked unit.
|
||||
The unit need not declare an imports for evey provided
|
||||
@scheme[tagged-sig-spec], but one @scheme[tagged-sig-spec] must be
|
||||
provided for each declared import of the unit. For each variable
|
||||
identifier in each provided @scheme[tagged-sig-spec], the value of the
|
||||
identifier's binding in the surrounding context is used for the
|
||||
corresponding import in the invoked unit.}
|
||||
|
||||
@defform[
|
||||
#:literals (import export)
|
||||
(define-values/invoke-unit unit-expr
|
||||
(import tagged-sig-spec ...)
|
||||
(export tagged-sig-spec ...))]{
|
||||
|
||||
Like @scheme[invoke-unit], but the values of the unit's exports are
|
||||
copied to new bindings.
|
||||
|
||||
The unit produced by @scheme[unit-expr] is linked and invoked as for
|
||||
@scheme[invoke-unit]. In addition, the @scheme[export] clause is
|
||||
treated as a kind of import into the local definition context. That
|
||||
is, for every binding that would be available in a unit that used the
|
||||
@scheme[export] clauses's @scheme[tagged-sig-spec] as an import, a
|
||||
definition is generated for the context of the
|
||||
@scheme[define-values/invoke-unit] form.}
|
||||
|
||||
@; ------------------------------------------------------------------------
|
||||
|
||||
@section[#:tag "mz:compoundunits"]{Linking Units and Creating Compound Units}
|
||||
|
||||
@defform/subs[
|
||||
#:literals (: import export link tag)
|
||||
(compound-unit
|
||||
(import link-binding ...)
|
||||
(export tagged-link-id ...)
|
||||
(link linkage-decl ...))
|
||||
|
||||
([link-binding
|
||||
(link-id : tagged-sig-id)]
|
||||
|
||||
[tagged-link-id
|
||||
(tag id link-id)
|
||||
link-id]
|
||||
|
||||
[linkage-decl
|
||||
((link-binding ...) unit-expr tagged-link-id)])]{
|
||||
|
||||
Links several units into one new compound unit without immediately
|
||||
invoking any of the linked units. The @scheme[unit-expr]s in the
|
||||
@scheme[link] clause determine the units to be linked in creating the
|
||||
compound unit. The @scheme[unit-expr]s are evaluated when the
|
||||
@scheme[compound-unit] form is evaluated.
|
||||
|
||||
The @scheme[import] clause determines the imports of the compound
|
||||
unit. Outside the compound unit, these imports behave as for a plain
|
||||
unit; inside the compound unit, they are propagated to some of the
|
||||
linked units. The @scheme[export] clause determines the exports of the
|
||||
compound unit. Again, outside the compound unit, these exports are
|
||||
trested the same as for a plain unit; inside the compound unit, they
|
||||
are drawn from the exports of the linked units. Finally, the left-hand
|
||||
and right-hand parts of each declaration in the @scheme[link] clause
|
||||
specify how the compound unit's imports and exports are propagated to
|
||||
the linked units.
|
||||
|
||||
Individual elements of an imported or exported signature are not
|
||||
available within the compound unit. Instead, imports and exports are
|
||||
connected at the level of whole signatures. Each specific import or
|
||||
export (i.e., an instance of some signature, possibly tagged) is given
|
||||
a @scheme[link-id] name. Specifically, a @scheme[link-id] is bound by
|
||||
the @scheme[import] clause or the left-hand part of an declaration in
|
||||
the @scheme[link] clause. A bound @scheme[link-id] is referenced in
|
||||
the right-hand part of a declaration in the @scheme[link] clause or by
|
||||
the @scheme[export] clause.
|
||||
|
||||
The left-hand side of a @scheme[link] declaration gives names to each
|
||||
expected export of the unit produced by the corresponding
|
||||
@scheme[unit-expr]. The actual unit may export additional signatures,
|
||||
and it may export an extension of a specific signature instead of just
|
||||
the specified one. If the unit does not export one of the specified
|
||||
signatures (with the specified tag, if any), the
|
||||
@exnraise[exn:fail:contract] when the @scheme[compound-unit] form is
|
||||
evaluated.
|
||||
|
||||
The right-hand side of a @scheme[link] declaration specifies the
|
||||
imports to be supplied to the unit produced by the corresponding
|
||||
@scheme[unit-expr]. The actual unit may import fewer signatures, and
|
||||
it may import a signature that is extended by the specified one. If
|
||||
the unit imports a signature (with a particular tag) that is not
|
||||
included in the supplied imports, the @exnraise[exn:fail:contract]
|
||||
when the @scheme[compound-unit] form is evaluated. Each
|
||||
@scheme[link-id] supplied as an import must be bound either in the
|
||||
@scheme[import] clause or in some declaration within the @scheme[link]
|
||||
clause.
|
||||
|
||||
The order of declarations in the @scheme[link] clause determines the
|
||||
order of invocation of the linked units. When the compound unit is
|
||||
invoked, the unit produced by the first @scheme[unit-expr] is invoked
|
||||
first, then the second, and so on. If the order specified in the
|
||||
@scheme[link] clause is inconsistent with @scheme[init-depend]
|
||||
declarations of the actual units, then the
|
||||
@exnraise[exn:fail:contract] when the @scheme[compound-unit] form is
|
||||
evaluated.}
|
||||
|
||||
@; ------------------------------------------------------------------------
|
||||
|
||||
@section[#:tag "mz:linkinference"]{Inferred Linking}
|
||||
|
||||
@defform[
|
||||
#:literals (import export)
|
||||
(define-unit unit-id
|
||||
(import tagged-sig-spec ...)
|
||||
(export tagged-sig-spec ...)
|
||||
init-depends-decl
|
||||
unit-body-expr-or-defn
|
||||
...)
|
||||
]{
|
||||
|
||||
Binds @scheme[unit-id] to both a unit and static information about the
|
||||
unit.
|
||||
|
||||
Evaluating a reference to an @scheme[unit-id] bound by
|
||||
@scheme[define-unit] produces a unit, just like evaluating an
|
||||
@scheme[id] bound by @scheme[(define id (unit ...))]. In addition,
|
||||
however, @scheme[unit-id] can be used in @scheme[compound-unit/infer].
|
||||
See @scheme[unit] for information on @scheme[tagged-sig-spec],
|
||||
@scheme[init-depends-decl], and @scheme[unit-body-expr-or-defn].}
|
||||
|
||||
@defform/subs[
|
||||
#:literals (import export :)
|
||||
(compound-unit/infer
|
||||
(import tagged-infer-link-import ...)
|
||||
(export tagged-infer-link-export ...)
|
||||
(link infer-linkage-decl ...))
|
||||
|
||||
([tagged-infer-link-import
|
||||
tagged-sig-id
|
||||
(link-id : tagged-sig-id)]
|
||||
|
||||
[tagged-infer-link-export
|
||||
(tag id infer-link-export)
|
||||
infer-link-export]
|
||||
|
||||
[infer-link-export
|
||||
link-id
|
||||
sig-id]
|
||||
|
||||
[infer-linkage-decl
|
||||
((link-binding ...) unit-id tagged-link-id)
|
||||
unit-id])]{
|
||||
|
||||
Like @scheme[compound-unit]. Syntactically, the difference between
|
||||
@scheme[compound-unit] and @scheme[compound-unit/infer] is that the
|
||||
@scheme[unit-expr] for a linked unit is replaced with a
|
||||
@scheme[unit-id], where a @scheme[unit-id] is bound by
|
||||
@scheme[define-unit] (or one of the other unit-binding forms that we
|
||||
introduce later in this section). Furthermore, an import can name just
|
||||
a @scheme[sig-id] without locally binding a @scheme[link-id], and an
|
||||
export can be based on a @scheme[sig-id] instead of a
|
||||
@scheme[link-id], and a declaration in the @scheme[link] clause can be
|
||||
simply a @scheme[unit-id] with no specified exports or imports.
|
||||
|
||||
The @scheme[compound-unit/infer] form expands to
|
||||
@scheme[compound-unit] by adding @scheme[sig-ids] as needed to
|
||||
the @scheme[import] clause, by replacing @scheme[sig-id]s in the
|
||||
@scheme[export] clause by @scheme[link-id]s, and by completing
|
||||
the declarations of the @scheme[link] clause. This completion is based
|
||||
on static information associated with each
|
||||
@scheme[unit-id]. Links and exports can be inferred when all
|
||||
signatures exported by the linked units are distinct from each other
|
||||
and from all imported signatures, and when all imported signatures are
|
||||
distinct. Two signatures are @defterm{distinct} only if when they
|
||||
share no ancestor through @scheme[extends].
|
||||
|
||||
The long form of a @scheme[link] declaration can be used to resolve
|
||||
ambiguity by giving names to some of a unit's exports and supplying
|
||||
specific bindings for some of a unit's imports. The long form need not
|
||||
name all of a unit's exports or supply all of a unit's imports if the
|
||||
remaining parts can be inferred.
|
||||
|
||||
Like @scheme[compound-unit], the @scheme[compound-unit/infer] form
|
||||
produces a (compound) unit without statically binding information
|
||||
about the result unit's imports and exports. That is,
|
||||
@scheme[compound-unit/infer] consumes static information, but it does
|
||||
not generate it. Two additional forms,
|
||||
@scheme[define-compound-unit] and
|
||||
@scheme[define-compound-unit/infer], generate static information
|
||||
(where the former does not consume static information).}
|
||||
|
||||
@defform[
|
||||
#:literals (import export link)
|
||||
(define-compound-unit id
|
||||
(import link-binding ...)
|
||||
(export tagged-link-id ...)
|
||||
(link linkage-decl ...))
|
||||
]{
|
||||
|
||||
Like @scheme[compound-unit], but binds static information about the
|
||||
compound unit like @scheme[define-unit].}
|
||||
|
||||
|
||||
@defform[
|
||||
#:literals (import export link)
|
||||
(define-compound-unit/infer id
|
||||
(import link-binding ...)
|
||||
(export tagged-infer-link-export ...)
|
||||
(link infer-linkage-decl ...))
|
||||
]{
|
||||
|
||||
Like @scheme[compound-unit/infer], but binds static information about
|
||||
the compound unit like @scheme[define-unit].}
|
||||
|
||||
@defform[
|
||||
#:literals (import export)
|
||||
(define-unit-binding unit-id
|
||||
unit-expr
|
||||
(import tagged-sig-spec ...+)
|
||||
(export tagged-sig-spec ...+)
|
||||
init-depends-decl)
|
||||
]{
|
||||
|
||||
Like @scheme[define-unit], but the unit implementation is determined
|
||||
from an existing unit produced by @scheme[unit-expr]. The imports and
|
||||
exports of the unit produced by @scheme[unit-expr] must be consistent
|
||||
with the declared imports and exports, otherwise the
|
||||
@exnraise[exn:fail:contract] when the @scheme[define-unit-binding]
|
||||
form is evaluated.}
|
||||
|
||||
@defform[(invoke-unit/infer unit-id)]{
|
||||
|
||||
Like @scheme[invoke-unit], but uses static information associated with
|
||||
@scheme[unit-id] to infer which imports must be assembled from the
|
||||
current context.}
|
||||
|
||||
@defform[(define-values/invoke-unit/infer unit-id)]{
|
||||
|
||||
Like @scheme[define-values/invoke-unit], but uses static information
|
||||
associated with @scheme[unit-id] to infer which imports must be
|
||||
assembled from the current context and what exports should be bound
|
||||
by the definition.}
|
||||
|
||||
@; ------------------------------------------------------------------------
|
||||
|
||||
@section{Generating A Unit from Context}
|
||||
|
||||
@defform[
|
||||
(unit-from-context tagged-sig-spec)
|
||||
]{
|
||||
|
||||
Creates a unit that implements an interface using bindings in the
|
||||
enclosing environment. The generated unit is essentially the same as
|
||||
|
||||
@schemeblock[
|
||||
(unit
|
||||
(import)
|
||||
(export tagged-sig-spec)
|
||||
(define id expr) ...)
|
||||
]
|
||||
|
||||
for each @scheme[id] that must be defined to satisfy the exports, and
|
||||
each corresponding @scheme[expr] produces the value of @scheme[id] in
|
||||
the environment of the @scheme[unit-from-context] expression. (The unit
|
||||
cannot be written as above, however, since each @scheme[id] definition
|
||||
within the unit shadows the binding outside the @scheme[unit] form.)
|
||||
|
||||
See @scheme[unit] for the grammar of @scheme[tagged-sig-spec].}
|
||||
|
||||
@defform[
|
||||
(define-unit-from-context id tagged-sig-spec)
|
||||
]{
|
||||
|
||||
Like @scheme[unit-from-context], in that a unit is constructed from
|
||||
the enclosing environment, and like @scheme[define-unit], in that
|
||||
@scheme[id] is bound to static information to be used later with inference.}
|
||||
|
||||
@; ------------------------------------------------------------------------
|
||||
|
||||
@section{Structural Matching}
|
||||
|
||||
@defform[
|
||||
#:literals (import export)
|
||||
(unit/new-import-export
|
||||
(import tagged-sig-spec ...)
|
||||
(export tagged-sig-spec ...)
|
||||
init-depends-decl
|
||||
((tagged-sig-spec ...) unit-expr tagged-sig-spec))
|
||||
]{
|
||||
|
||||
Similar to @scheme[unit], except the body of the unit is determined by
|
||||
an existing unit produced by @scheme[unit-expr]. The result is a unit
|
||||
that whose implementation is @scheme[unit-expr], but whose imports,
|
||||
exports, and initialization dependencies are as in the
|
||||
@scheme[unit/new-import-export] form (instead of as in the unit
|
||||
produced by @scheme[unit-expr]).
|
||||
|
||||
The final clause of the @scheme[unit/new-import-export] form
|
||||
determines the connection between the old and new imports and exports.
|
||||
The connection is similar to the way that @scheme[compound-unit]
|
||||
propagates imports and exports; the difference is that the connection
|
||||
between @scheme[import] and the right-hand side of the link clause is
|
||||
based on the names of elements in signatures, rather than the names of
|
||||
the signatures. That is, a @scheme[tagged-sig-spec] on the right-hand
|
||||
side of the link clause need not apppear as a @scheme[tagged-sig-spec]
|
||||
in the @scheme[import] clause, but each of the bindings implied by the
|
||||
linking @scheme[tagged-sig-spec] must be implied by some
|
||||
@scheme[tagged-sig-spec] in the @scheme[import] clause. Similarly,
|
||||
each of the bindings implied by an @scheme[export]
|
||||
@scheme[tagged-sig-spec] must be implied by some left-hand-side
|
||||
@scheme[tagged-sig-spec] in the linking clause.}
|
||||
|
||||
@defform[
|
||||
(define-unit/new-import-export unit-id
|
||||
(import tagged-sig-spec ...)
|
||||
(export tagged-sig-spec ...)
|
||||
init-depends-decl
|
||||
((tagged-sig-spec ...) unit-expr tagged-sig-spec))
|
||||
]{
|
||||
|
||||
Like @scheme[unit/new-import-export], but binds static information to
|
||||
@scheme[unit-id] like @scheme[define-unit].}
|
||||
|
||||
@; ------------------------------------------------------------------------
|
||||
|
||||
@section[#:tag "mz:define-sig-form"]{Extending the Syntax of Signatures}
|
||||
|
||||
@defform*[
|
||||
[(define-signature-form sig-form-id expr)
|
||||
(define-signature-form (sig-form-id id) body ...+)]
|
||||
]
|
||||
|
||||
Binds @scheme[sig-form-id] for use within a @scheme[define-signature]
|
||||
form.
|
||||
|
||||
In the first form, the result of @scheme[expr] must be a transformer
|
||||
procedure. In the second form, @scheme[sig-form-id] is bound to a
|
||||
transformer procedure whose argument is @scheme[id] and whose body is
|
||||
the @scheme[body]s. The result of the transformer must be a list of
|
||||
syntax objects, which are substituted for a use of
|
||||
@scheme[sig-form-id] in a @scheme[define-signature] expansion. (The
|
||||
result is a list so that the transformer can produce multiple
|
||||
declarations; @scheme[define-signature] has no splicing @scheme[begin]
|
||||
form.)}
|
||||
|
||||
@defform/subs[
|
||||
#:literals (-type -selectors -setters -constructor)
|
||||
(struct id (field-id ...) omit-decl ...)
|
||||
|
||||
([omit-decl
|
||||
-type
|
||||
-selectors
|
||||
-setters
|
||||
-constructor])]{
|
||||
|
||||
For use with @scheme[define-signature]. The expansion of a
|
||||
@scheme[struct] signature form includes all of the identifiers that
|
||||
would be bound by @scheme[(define-struct id (field-id ...))], except
|
||||
that a @scheme[omit-decl] can cause some of the bindings to be
|
||||
omitted. Specifically @scheme[-type] causes
|
||||
@schemeidfont{struct:}@scheme[id] to be omitted, @scheme[-selectors]
|
||||
causes all @scheme[id]@schemeidfont{-}@scheme[_field-id]s to be
|
||||
omitted, @scheme[-setters] causes all
|
||||
@schemeidfont{set-}@scheme[id]@schemeidfont{-}@scheme[field-id]@schemeidfont{!}s
|
||||
to be omitted, and @scheme[-construct] causes
|
||||
@schemeidfont{make-}@scheme[id] to be omitted. These omissions are
|
||||
reflected in the static information bound to @scheme[id] (which is
|
||||
used by, for example, pattern matchers).}
|
||||
|
||||
@; ------------------------------------------------------------------------
|
||||
|
||||
@section{Unit Utilities}
|
||||
|
||||
@defproc[(unit? [v any/c]) boolean?]{
|
||||
|
||||
Returns @scheme[#t] if @scheme[v] is a unit, @scheme[#f] otherwise.}
|
||||
|
||||
|
||||
@defform[(provide-signature-elements sig-spec ...)]{
|
||||
|
||||
Expands to a @scheme[provide] of all identifiers implied by the
|
||||
@scheme[sig-spec]s. See @scheme[unit] for the grammar of
|
||||
@scheme[sig-spec].}
|
Loading…
Reference in New Issue
Block a user