racket/collects/scribblings/reference/module-reflect.scrbl
Matthew Flatt cbf1d0752c fix many cross-references
svn: r6971
2007-07-26 18:57:19 +00:00

302 lines
13 KiB
Racket

#reader(lib "docreader.ss" "scribble")
@require["mz.ss"]
@title{Module Names and Loading}
@;------------------------------------------------------------------------
@section[#:tag "mz:modnameresolver"]{Resolving Module Names}
The name of a declared module is either a symbol or a @deftech{resolved
module path}. A symbol normally refers to a predefined module or
module declared through reflective evaluation (e.g., @scheme[eval]). A
@tech{resolved module path} encapsulates a filesystem path (see
@secref["mz:pathutils"]) and normally refers to a module declaration
that was loaded on demand via @scheme[require] or other forms.
@defproc[(resolved-module-path? [v any/c]) boolean?]{
Returns @scheme[#f] if @scheme[v] is a @tech{resolved module path},
@scheme[#f] otherwise.}
@defproc[(make-resolved-module-path [path path-string?])
resolved-module-path?]{
Returns a @tech{resolved module path} that encapsulates @scheme[path]
as relative to @scheme[current-directory] and expanded (see
@scheme[expand-path]), simplified (see @scheme[simplify-path]), and
with all but the last path element case-normalized (see
@scheme[normal-case-path]).
A @tech{resolved module path} is interned. That is, if two
@tech{resolved module path} values encapsulate paths that are
@scheme{equal?}, then the @tech{resolved module path} values are
@scheme{eq?}.}
@defproc[(resolved-module-path->path [module-path resolved-module-path?])
path?]{
Returns the path encapsulated by a @tech{resolved module path}.}
@defproc[(module-path? [v any/c]) boolean?]{
Returns @scheme[#t] if @scheme[v] corresponds to a datum that matches
the grammar for @scheme[_module-path] for @scheme[require],
@scheme[#f] otherwise.}
@defparam[current-module-name-resolver proc
(case->
((or/c symbol? resolved-module-path?)
. -> .
any)
((or/c module-path? path?)
(or/c false/c symbol? resolved-module-path?)
boolean?
. -> .
(or/c symbol? resolved-module-path?)))]{
A parameter that determines the current @deftech{module name
resolver}, which manages the conversion from other kinds of module
references to a symbol or @tech{resolved module path}. For example,
when the expander encounters @scheme[(require _module-path)] where
@scheme[_module-path] is not an identifier, then the expander passes
@scheme['_module-path] to the module name resolver to obtain a symbol
or resolved module path. When such a @scheme[require] appears within a
module, the @deftech{module path resolver} is also given the name of
the enclosing module, so that a relative reference can be converted to
an absolute symbol or @tech{resolved module path}.
A @tech{module name resolver} takes one and three arguments:
%
@itemize{
@item{When given one argument, it is a name for a module declaration
that is already loaded. Such a call to the module name resolver is a
notification that the corresponding module does not need to be
loaded (for the current namespace, or any other namespace that
shares the same module registry). The module name resolver's result
is ignored.}
@item{When given three arguments, the first is a module path, either
equivalent to a quoted @scheme[module-path] for @scheme[require] or
a file system path. The second is name for the source module, if
any, to which the path is relative; f the second argument is
@scheme[#f], the module path is relative to @scheme[(or
(current-load-relative-directory) (current-directory))]. If the
argument is @scheme[#t], then the module declaration should be
loaded (if it is not already), otherwise the module path should be
simply resolved to a name. The result is the resolved name.}
}
For the second case, the standard module name resolver keeps a
per-registry table of loaded module name. If a resolved module path is
not in the table, and @scheme[#f] is not provided as the third
argument to the @tech{module name resolver}, then the name is put into
the table and the corresponding file is loaded with a variant of
@scheme[load/use-compiled] that passes the expected module name to the
@tech{compiled-load handler}.
While loading a file, the default @tech{module name resolver} sets the
@scheme[current-module-name-prefix] parameter, so that the name of any
module declared in the loaded file is given a prefix. The resolver
sets the prefix to the resolved module name, minus the de-suffixed
file name. Also, the default @tech{module name resolver} records in a
private @tech{continuation mark} the filename being loaded, and it
checks whether such a mark already exists; if such a continuation mark
does exist in the current continuation, then the @exnraise[exn:fail]
with a message about a dependency cycle.
Module loading is suppressed (i.e., @scheme[#f] is supplied as a third
argument to the module name resolver) when resolving module paths in
@tech{syntax objects} (see @secref["mz:stxobj-model"]). When a
@tech{syntax object} is manipulated, the current namespace might not
match the original namespace for the syntax object, and the module
should not necessarily be loaded in the current namespace.
The current module name resolver is called with a single argument by
@scheme[namespace-attach-module] to notify the resolver that a module
was attached to the current namespace (and should not be loaded in the
future for the namespace's registry). No other Scheme operation
invokes the module name resolver with a single argument, but other
tools (such as DrScheme) might call this resolver in this mode to
avoid redundant module loads.}
@defparam[current-module-name-prefix prefix (or/c path? false/c)]{
A parameter that determines a prefix used when evaluating a
@scheme[module] declaration when the prefix is not @scheme[#f]. In
that case, the quoted form of the @scheme[_id] from the
@scheme[module] declaration is converted to a path element (via
@scheme[symbol->string] and @scheme[string->path-element]), combined
with the prefix (via @scheme[build-path]), and then converted to a
@tech{resolved module path} (via @scheme[make-resolved-module-path])
which is used as the name of the declared module.}
@;------------------------------------------------------------------------
@section[#:tag "mz:modpathidx"]{Compiled Modules and References}
While expanding a @scheme[module] declaration, the expander resolves
module paths for imports to load module declarations as necessary and
to determine imported bindings, but the compiled form of a
@scheme[module] declaration preserves the original module path.
Consequently, a compiled module can be moved to another filesystem,
where the module name resolver can resolve inter-module references
among compiled code.
When a module reference is extracted from compiled form (see
@scheme[module-compiled-imports]) or from syntax objects in macro
expansion (see @secref["mz:stxops"]), the module reference is
typically reported in the form of a @deftech{module path index}. A
@tech{module path index} is a semi-interned (multiple references to
the same relative module tend to use the same @tech{module path index}
value, but not always) opaque value that encodes a module path (see
@scheme[module-path?]) and another @tech{module path index} to which
it is relative.
A @tech{module path index} that uses both @scheme[#f] for its path and
base @tech{module path index} represents ``self''---i.e., the module
declaration that was the source of the @tech{module path index}---and
such a @tech{module path index} is always used as the root for a chain
of @tech{module path index}. For example, when extracting information
about an identifier's binding within a module, if the identifier is
bound by a definition within the same module, the identifier's source
module is reported using the ``self'' @tech{module path index}. If the
identifier is instead defined in a module that is imported via a
module path (as opposed to a literal module name), then the
identifier's source module will be reported using a @tech{module path
index} that contains the @scheme[require]d module path and the
``self'' @tech{module path index}.
A @tech{module path index} has state. When it is @deftech{resolved} to
a symbolic module name, then the symbol or @tech{resolved module path}
is stored with the @tech{module path index}. In particular, when a
module is loaded, its root @tech{module path index} is resolved to
match the module's declaration-time name. This resolved path is
forgotten, however, in identifiers that the module contributes to the
compiled and marshaled form of other modules. This transient nature of
resolved names allows the module code to be loaded with a different
resolved name than the name when it was compiled.
Where a @tech{module path index} is expected, a symbol can usually
take its place, representing a literal module name. A symbol is used
instead of a @tech{module path index} when a module is imported using
its name directly with @scheme[require] instead of a module path (in
which case the symbol is also the resolved name of the module).
@defproc[(module-path-index? [v any/c]) boolean?]{
Returns @scheme[#t] if @scheme[v] is a @tech{module path index},
@scheme[#f] otherwise.}
@defproc[(module-path-index-resolve [mpi module-path-index?])
(or/c symbol? resolved-module-path?)]{
Returns a symbol or @tech{resolved module path} for the resolved
module name, computing the resolved name (and storing it in
@scheme[mpi]) if it has not been computed before.
Resolving a @tech{module path index} uses the current @tech{module
name resolver} (see @scheme[current-module-name-resolver]). Depending
on the kind of module paths encapsulated by @scheme[mpi], the computed
resolved name can depend on the value of
@scheme[current-load-relative-directory] or
@scheme[current-directory].}
@defproc[(module-path-index-split [mpi module-path-index?])
(values (or/c (and/c module-path? (not/c symbol?)) false/c)
(or/c module-path-index? false/c))]{
Returns two values: a module path, and a base @tech{module path
index}, symbol, or @scheme[#f] to which the module path is relative.
A @scheme[#f] second result means that the path is relative to an
unspecified directory (i.e., its resolution depends on the value of
@scheme[current-load-relative-directory] and/or
@scheme[current-directory]).
A @scheme[#f] for the first result implies a @scheme[#f] for the
second result, and means that @scheme[mpi] represents ``self'' (see
above).}
@defproc[(module-path-index-join [path (or/c (and/c module-path? (not/c symbol?))
false/c)]
[mpi (or/c module-path-index? false/c)])
module-path-index?]{
Combines @scheme[path] and @scheme[mpi] to create a new @tech{module
path index}. The @scheme[path] argument can @scheme[#f] only if
@scheme[mpi] i also @scheme[false].}
@defproc[(compiled-module-expression? [v any/c]) boolean?]{
Returns @scheme[#t] if @scheme[v] is a compiled @scheme[module]
declaration, @scheme[#f] otherwise. See also
@scheme[current-compile].}
@defproc[(module-compiled-name [compiled-module-code compiled-module-expression?])
symbol?]{
Takes a module declaration in compiled form and returns a symbol for
the module's declared name.}
@defproc[(module-compiled-imports [compiled-module-code compiled-module-expression?])
(values (listof (or/c module-path-index? symbol?))
(listof (or/c module-path-index? symbol?))
(listof (or/c module-path-index? symbol?)))]{
Takes a module declaration in compiled form and returns three values:
a list of module references for the module's explicit imports, a list
of module references for the module's explicit for-syntax imports, and
a list of module references for the module's explicit for-template
imports.}
@defproc[(module-compiled-exports [compiled-module-code compiled-module-expression?])
(values (listof symbol?)
(listof symbol?))]{
Takes a module declaration in compiled form and returns two values: a
list of symbols for the module's explicit variable exports, a list
symbols for the module's explicit syntax exports.}
@;------------------------------------------------------------------------
@section[#:tag "mz:dynreq"]{Dynamic Module Access}
@defproc[(dynamic-require [mod module-path?][provided (or/c symbol? false/c void?)])
any]{
Dynamically instantiates the module specified by @scheme[mod] for
@tech{phase} 0 in the current namespace's registry, if it is not yet
instantiated. If @scheme[mod] is not a symbol, the current
@tech{module name resolver} may load a module declaration to resolve
it (see @scheme[current-module-name-resolver]); the path is resolved
relative to @scheme[current-load-relative-directory] and/or
@scheme[current-directory].
If @scheme[provided] is @scheme[#f], then the result is
@|void-const|. Otherwise, when @scheme[provided] is a symbol, the
value of the module's export with the given name is returned. If the
module exports @scheme[provide] as syntax, then a use of the binding
is expanded and evaluated (in a fresh namespace to which the module is
attached). If the module has no such exported variable or syntax, or
if the variable is protected (see @secref["mz:modprotect"]), the
@exnraise[exn:fail:contract].
If @scheme[provided] is @|void-const|, then the module is
@tech{visit}ed (see @secref["mz:mod-parse"]), but not
@tech{instantiate}d. The result is @|void-const|.}
@defproc[(dynamic-require-for-syntax [mod module-path?]
[provided (or/c symbol? false/c)])
any]{
Like @scheme[dynamic-require], but in @tech{phase} 1.}