#lang scribble/doc @(require "mz.ss") @title{Module Names and Loading} @;------------------------------------------------------------------------ @section[#:tag "modnameresolver"]{Resolving Module Names} The name of a declared module is represented by a @deftech{resolved module path}, which encapsulates either a symbol or a complete filesystem path (see @secref["pathutils"]). A symbol normally refers to a predefined module or module declared through reflective evaluation (e.g., @racket[eval]). A filesystem path normally refers to a module declaration that was loaded on demand via @racket[require] or other forms. A @deftech{module path} is a datum that matches the grammar for @racket[_module-path] for @racket[require]. A module path is relative to another module. @defproc[(resolved-module-path? [v any/c]) boolean?]{ Returns @racket[#f] if @racket[v] is a @tech{resolved module path}, @racket[#f] otherwise.} @defproc[(make-resolved-module-path [path (or/c symbol? (and/c path? complete-path?))]) resolved-module-path?]{ Returns a @tech{resolved module path} that encapsulates @racket[path]. If @racket[path] is not a symbol, it normally should be @tech{cleanse}d (see @racket[cleanse-path]) and simplified (see @racket[simplify-path]). A @tech{resolved module path} is interned. That is, if two @tech{resolved module path} values encapsulate paths that are @racket[equal?], then the @tech{resolved module path} values are @racket[eq?].} @defproc[(resolved-module-path-name [module-path resolved-module-path?]) (or/c path? symbol?)]{ Returns the path or symbol encapsulated by a @tech{resolved module path}.} @defproc[(module-path? [v any/c]) boolean?]{ Returns @racket[#t] if @racket[v] corresponds to a datum that matches the grammar for @racket[_module-path] for @racket[require], @racket[#f] otherwise.} @defparam[current-module-name-resolver proc (case-> (resolved-module-path? . -> . any) ((or/c module-path? path?) (or/c #f resolved-module-path?) (or/c #f syntax?) boolean? . -> . 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 @tech{resolved module path}. For example, when the expander encounters @racket[(require _module-path)] where @racket[_module-path] is not an identifier, then the expander passes @racket['_module-path] to the module name resolver to obtain a symbol or resolved module path. When such a @racket[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 four 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 four arguments, the first is a module path, either equivalent to a quoted @racket[module-path] for @racket[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 @racket[#f], the module path is relative to @racket[(or (current-load-relative-directory) (current-directory))]. The third argument is a @tech{syntax object} that can be used for error reporting, if it is not @racket[#f]. If the last argument is @racket[#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 @racket[#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 @racket[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 @racket[current-module-declare-name] parameter to the resolved module name (while the @tech{compiled-load handler} sets @racket[current-module-declare-source]). Also, the default @tech{module name resolver} records in a private @tech{continuation mark} the module 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., @racket[#f] is supplied as a third argument to the module name resolver) when resolving module paths in @tech{syntax objects} (see @secref["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 @racket[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 Racket operation invokes the module name resolver with a single argument, but other tools (such as DrRacket) might call this resolver in this mode to avoid redundant module loads.} @defparam[current-module-declare-name name (or/c resolved-module-path? #f)]{ A parameter that determines a module name that is used when evaluating a @racket[module] declaration (when the parameter value is not @racket[#f]). In that case, the @racket[_id] from the @racket[module] declaration is ignored, and the parameter's value is used as the name of the declared module.} @defparam[current-module-declare-source src (or/c symbol? (and/c path? complete-path?) #f)]{ A parameter that determines source information to be associated with a module when evaluating a @racket[module] declaration. Source information is used in error messages and reflected by @racket[variable-reference->module-source]. When the parameter value is @racket[#f], the module's name (as determined by @racket[current-module-declare-name]) is used as the source name instead of the parameter value.} @;------------------------------------------------------------------------ @section[#:tag "modpathidx"]{Compiled Modules and References} While expanding a @racket[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 @racket[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 @racket[module-compiled-imports]) or from syntax objects in macro expansion (see @secref["stxops"]), the module reference is 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 @racket[module-path?]) and either a @tech{resolved module path} or another @tech{module path index} to which it is relative. A @tech{module path index} that uses both @racket[#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} can be used as the root for a chain of @tech{module path index}es 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'' @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 @racket[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 @tech{resolved module path}, then the @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. 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. @defproc[(module-path-index? [v any/c]) boolean?]{ Returns @racket[#t] if @racket[v] is a @tech{module path index}, @racket[#f] otherwise.} @defproc[(module-path-index-resolve [mpi module-path-index?]) resolved-module-path?]{ Returns a @tech{resolved module path} for the resolved module name, computing the resolved name (and storing it in @racket[mpi]) if it has not been computed before. Resolving a @tech{module path index} uses the current @tech{module name resolver} (see @racket[current-module-name-resolver]). Depending on the kind of module paths encapsulated by @racket[mpi], the computed resolved name can depend on the value of @racket[current-load-relative-directory] or @racket[current-directory].} @defproc[(module-path-index-split [mpi module-path-index?]) (values (or/c module-path? #f) (or/c module-path-index? resolved-module-path? #f))]{ Returns two values: a module path, and a base @tech{module path index} or @racket[#f] to which the module path is relative. A @racket[#f] second result means that the path is relative to an unspecified directory (i.e., its resolution depends on the value of @racket[current-load-relative-directory] and/or @racket[current-directory]). A @racket[#f] for the first result implies a @racket[#f] for the second result, and means that @racket[mpi] represents ``self'' (see above).} @defproc[(module-path-index-join [path (or/c module-path? #f)] [mpi (or/c module-path-index? resolved-module-path? #f)]) module-path-index?]{ Combines @racket[path] and @racket[mpi] to create a new @tech{module path index}. The @racket[path] argument can @racket[#f] only if @racket[mpi] is also @racket[#f].} @defproc[(compiled-module-expression? [v any/c]) boolean?]{ Returns @racket[#t] if @racket[v] is a compiled @racket[module] declaration, @racket[#f] otherwise. See also @racket[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?]) (listof (cons/c (or/c exact-integer? #f) (listof module-path-index?)))]{ Takes a module declaration in compiled form and returns an association list mapping @tech{phase level} shifts (where @racket[#f] corresponds to a shift into the @tech{label phase level}) to module references for the module's explicit imports.} @defproc[(module-compiled-exports [compiled-module-code compiled-module-expression?]) (values (listof (cons/c (or/c exact-integer? #f) list?)) (listof (cons/c (or/c exact-integer? #f) list?)))] Returns two association lists mapping @tech{phase level} values (where @racket[#f] corresponds to the @tech{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 @tech{rename transformer} are in the syntax list instead of the value list. Each associated list, which is represented by @racket[list?] in the result contracts above, more precisely matches the contract @racketblock[ (listof (list/c symbol? (listof (or/c module-path-index? (list/c module-path-index? (or/c exact-integer? #f) symbol? (or/c exact-integer? #f)))))) ] For each element of the list, the leading symbol is the name of the export. The second part---the list of @tech{module path index} values, etc.---describes the origin of the exported identifier. If the origin list is @racket[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 @tech{module path index} by itself means that the binding was imported with a @tech{phase level} shift of @racket[0] (i.e., a plain @racket[require] without @racket[for-meta], @racket[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 @tech{phase level} shift (where @racket[#f] corresponds to a @racket[for-label] import), the import name of the re-exported binding, and the @tech{phase level} of the import.} @defproc[(module-compiled-language-info [compiled-module-code compiled-module-expression?]) (or/c #f (vector/c module-path? symbol? any/c))]{ @guidealso["module-runtime-config"] 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 @indexed-racket['module-language] @tech{syntax property}. See also @racket[module]. If no information is available for the module, the result is @racket[#f]. Otherwise, the result is @racket[(vector _mp _name _val)] such that @racket[((dynamic-require _mp _name) _val)] should return function that takes two arguments. The function's arguments are a key for reflected information and a default value. Acceptable keys and the interpretation of results is up to external tools, such as DrRacket. If no information is available for a given key, the result should be the given default value. See also @racket[module->language-info] and @racketmodname[racket/language-info].} @;------------------------------------------------------------------------ @section[#:tag "dynreq"]{Dynamic Module Access} @defproc[(dynamic-require [mod module-path?] [provided (or/c symbol? #f 0 void?)] [fail-thunk (-> any) (lambda () ....)]) any]{ Dynamically @tech{instantiates} the module specified by @racket[mod] in the current namespace's registry at the namespace's @tech{base phase}, if it is not yet @tech{instantiate}d. The current @tech{module name resolver} may load a module declaration to resolve @racket[mod] (see @racket[current-module-name-resolver]); the path is resolved relative to @racket[current-load-relative-directory] and/or @racket[current-directory]. If @racket[provided] is @racket[#f], then the result is @|void-const|, and the module is not @tech{visit}ed (see @secref["mod-parse"]) or even made @tech{available} (for on-demand @tech{visits}) in phases above the @tech{base phase}. When @racket[provided] is a symbol, the value of the module's export with the given name is returned, and still the module is not @tech{visit}ed or made @tech{available} in higher phases. If the module exports @racket[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 @tech{visit}ed in the fresh namespace. If the module has no such exported variable or syntax, then @racket[fail-thunk] is called; the default @racket[fail-thunk] raises @racket[exn:fail:contract]. If the variable named by @racket[provided] is exported protected (see @secref["modprotect"]), then the @exnraise[exn:fail:contract]. If @racket[provided] is @racket[0], then the module is @tech{instantiate}d but not @tech{visit}ed, the same as when @racket[provided] is @racket[#f]. With @racket[0], however, the module is made @tech{available} in higher phases. If @racket[provided] is @|void-const|, then the module is @tech{visit}ed but not @tech{instantiate}d (see @secref["mod-parse"]), and the result is @|void-const|.} @defproc[(dynamic-require-for-syntax [mod module-path?] [provided (or/c symbol? #f)] [fail-thunk (-> any) (lambda () ....)]) any]{ Like @racket[dynamic-require], but in a @tech{phase} that is @math{1} more than the namespace's @tech{base phase}.} @defproc[(module->language-info [mod (or/c module-path? path? resolved-module-path?)] [load? any/c #f]) (or/c #f (vector/c module-path? symbol? any/c))]{ Returns information intended to reflect the ``language'' of the implementation of @racket[mod]. If @racket[load?] is @racket[#f], the module named by @racket[mod] must be declared (but not necessarily @tech{instantiate}d or @tech{visit}ed) in the current namespace; otherwise, @racket[mod] may be loaded (as for @racket[dynamic-require] and other functions). The information returned by @racket[module->language-info] is the same as would have been returned by @racket[module-compiled-language-info] applied to the module's implementation as compiled code.} @defproc[(module->imports [mod (or/c module-path? path? resolved-module-path?)]) (listof (cons/c (or/c exact-integer? #f) (listof module-path-index?)))]{ Like @racket[module-compiled-imports], but produces the imports of @racket[mod], which must be declared (but not necessarily @tech{instantiate}d or @tech{visit}ed) in the current namespace.} @defproc[(module->exports [mod (or/c module-path? path? resolved-module-path?)]) (values (listof (cons/c (or/c exact-integer? #f) list?)) (listof (cons/c (or/c exact-integer? #f) list?)))]{ Like @racket[module-compiled-exports], but produces the exports of @racket[mod], which must be declared (but not necessarily @tech{instantiate}d or @tech{visit}ed) in the current namespace.}