13.4 Module Names and Loading
13.4.1 Resolving Module Names
The name of a declared module is represented by a resolved
module path, which encapsulates either a symbol or a complete
filesystem path (see Paths). A symbol normally refers
to a predefined module or module declared through reflective
evaluation (e.g., eval). A filesystem path normally refers to
a module declaration that was loaded on demand via require or
A module path is a datum that matches the grammar for
module-path for require. A module path is relative
to another module.
A resolved module path is interned. That is, if two
resolved module path values encapsulate paths that are
equal?, then the resolved module path values are
corresponds to a datum that matches
the grammar for module-path
A parameter that determines the current module name
, which manages the conversion from other kinds of module
references to a symbol or resolved module path
. For example,
when the expander encounters (require module-path)
is not an identifier, then the expander passes
to the module name resolver to obtain a symbol
or resolved module path. When such a require
appears within a
module, the 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 resolved module path
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
When given four arguments, the first is a module path, either
equivalent to a quoted module-path for require or
a file system path. The second is name for the source module, if
any, to which the path is relative; if the second argument is
#f, the module path is relative to (or (current-load-relative-directory) (current-directory)). The third
argument is a syntax object that can be used for error
reporting, if it is not #f. If the last argument is
#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 #f is not provided as the third
argument to the module name resolver, then the name is put into
the table and the corresponding file is loaded with a variant of
load/use-compiled that passes the expected module name to the
While loading a file, the default module name resolver sets the
current-module-declare-name parameter to the resolved module
name. Also, the default module name resolver records in a
private 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 exn:fail exception is raised
with a message about a dependency cycle.
Module loading is suppressed (i.e., #f is supplied as a third
argument to the module name resolver) when resolving module paths in
syntax objects (see Syntax Objects). When a
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
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.
A parameter that determines a module name that is used when evaluating
declaration (when the parameter value is not
). In that case, the id
from the module
declaration is ignored, and the parameter’s value is used as the name
of the declared module.
13.4.2 Compiled Modules and References
While expanding a 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
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
module-compiled-imports) or from syntax objects in macro
expansion (see Syntax Object Content), the module reference is reported in
the form of a module path index. A module path index
is a semi-interned (multiple references to the same relative module
tend to use the same module path index value, but not always)
opaque value that encodes a module path (see module-path?)
and either a resolved module path or another module path
index to which it is relative.
A module path index that uses both #f for its path and
base module path index represents “self” – i.e., the module
declaration that was the source of the module path index – and
such a module path index can be used as the root for a chain of
module path indexes at compile time. 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” 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 module
path index that contains the required module path and the
“self” module path index.
A module path index has state. When it is resolved to
a resolved module path, then the resolved module path is
stored with the module path index. In particular, when a module
is loaded, its root 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. The transient nature of resolved
names allows the module code to be loaded with a different resolved
name than the name when it was compiled.
Returns a resolved module path
for the resolved module name,
computing the resolved name (and storing it in mpi
) if it has
not been computed before.
Resolving a module path index uses the current module
name resolver (see current-module-name-resolver). Depending
on the kind of module paths encapsulated by mpi, the computed
resolved name can depend on the value of
Returns two values: a module path, and a base module path index
to which the module path is relative.
A #f second result means that the path is relative to an
unspecified directory (i.e., its resolution depends on the value of
A #f for the first result implies a #f for the
second result, and means that mpi represents “self” (see
Takes a module declaration in compiled form and returns a symbol for
the module’s declared name.
Takes a module declaration in compiled form and returns an association
list mapping phase level
shifts (where #f
to a shift into the label phase level
) to module references for
the module’s explicit imports.
Returns two association lists mapping phase level values (where
#f corresponds to the label phase level) to exports at
the corresponding phase. The first association list is for exported
variables, and the second is for exported syntax. Beware however, that
value bindings re-exported though a rename transformer are in
the syntax list instead of the value list.
Each associated list, which is represented by list? in the
result contracts above, more precisely matches the contract
For each element of the list, the leading symbol is the name of the
The second part – the list of module path index values,
etc. – describes the origin of the exported identifier. If the origin
list is null, then the exported identifier is defined in the
module. If the exported identifier is re-exported, instead, then the
origin list provides information on the import that was re-exported.
The origin list has more than one element if the binding was imported
multiple times from (possibly) different sources.
For each origin, a module path index by itself means that the
binding was imported with a phase level shift of 0
(i.e., a plain require without for-meta,
for-syntax, etc.), and imported identifier has the same name
as the re-exported name. An origin represented with a list indicates
explicitly the import, the import phase level shift (where
#f corresponds to a for-label import), the import
name of the re-exported binding, and the phase level of the
Returns information intended to reflect the “language” of the
module’s implementation as originally attached to the syntax of the
module’s declaration though the 'module-language
. See also module
If no information is available for the module, the result is
#f. Otherwise, the result is (vector mp name val)
such that ((dynamic-require mp name) val) should return
function that takes a single argument. The function’s argument is a
key for reflected information, and the result is a value associated
with that key. Acceptable keys and the interpretation of results is
up to external tools, such as DrScheme. If no information is
available for a given key, the result should be #f.
See also module->language-info.
13.4.3 Dynamic Module Access
If provided is #f, then the result is #<void>,
and the module is not visited (see Module Phases and Visits) or
even made available (for on-demand visits) in phases
above the base phase.
When provided is a symbol, the value of the module’s export
with the given name is returned, and still the module is not
visited or made available in higher phases. If the
module exports provide as syntax, then a use of the binding
is expanded and evaluated in a fresh namespace to which the module is
attached, which means that the module is visited in the fresh
namespace. If the module has no such exported variable or syntax, then
fail-thunk is called; the default fail-thunk raises
exn:fail:contract. If the variable named by provided
is exported protected (see Code Inspectors), then the
exn:fail:contract exception is raised.
If provided is 0, then the module is
instantiated but not visited, the same as when
provided is #f. With 0, however, the module
is made available in higher phases.
If provided is #<void>, then the module is
visited but not instantiated (see Module Phases and Visits),
and the result is #<void>.
Returns information intended to reflect the “language” of the
implementation of mod
, which must be declared (but not
d or visit
ed) in the current
namespace. The information is the same as would have been returned by
applied to the module’s
implementation as compiled code.