racket/pkgs/racket-doc/scribblings/reference/namespaces.scrbl
Matthew Flatt 2661d46929 toward deterministic bytecode generation
Progress toward making the bytecode compiler deterministic, so that a
fresh `make base` always produces exactly the same bytecode from the
same sources. Most changes involve avoiding hash-table order
dependencies and adjusting scope identity. The namespace used to load
a reader extension is also better defined. Plus many other little
changes.

The identity of a scope that is unmarshaled from a bytecode file now
incorporates the hash of the file, and the relative order of scopes is
preserved in a bytecode file. This combination allows compilation to
start with modules that loaded and compiled in different orders
(including delayed loading of bytecode fragments within one file).

Formerly, a reader extension triggered by `#lang` or `#reader` was
loaded in whatever namespace happens to be current. That's
unpredictable and can pollute a module build at the level of bytecode.
To help make builds deterministic, reader extensions are now loaded in
a root namespace of the current namespace.

Deterministic compilation in general relies on deterministic macros.
The two most common ways for a macro to be non-deterministic are by
using `gensym` (use `generate-temporaries`, instead) and by using an
unsorted hash-table traversal (don't do that).

At this point, bytecode generation is unlikely to be completely
deterministic, since I uncovered non-determinism mostly by iterating
attempts over the base collections. For now, the intent is not to
provide guarantees outside of the compilation of the base collections
--- but "more deterministic" is likely to be useful in the short run,
and we can improve further in the long run.
2015-08-07 15:48:39 -06:00

470 lines
18 KiB
Racket

#lang scribble/doc
@(require "mz.rkt")
@title[#:tag "Namespaces"]{Namespaces}
See @secref["namespace-model"] for basic information on the
@tech{namespace} model.
A new @tech{namespace} is created with procedures like
@racket[make-empty-namespace], and @racket[make-base-namespace], which
return a first-class namespace value. A namespace is used by setting
the @racket[current-namespace] parameter value, or by providing the
namespace to procedures such as @racket[eval] and
@racket[eval-syntax].
@defproc[(namespace? [v any/c]) boolean?]{
Returns @racket[#t] if @racket[v] is a namespace value, @racket[#f]
otherwise.}
@defproc[(make-empty-namespace) namespace?]{
Creates a new @tech{namespace} that is empty, and whose @tech{module
registry} contains no mappings. The namespace's @tech{base phase} is
the same as the @tech{base phase} of the @tech{current
namespace}. Attach modules from an existing namespace to the new one
with @racket[namespace-attach-module].
The new namespace is associated with a new @deftech{root namespace},
which has the same @tech{module registry} as the returned namespace
and has a @tech{base phase} of 0. The new @tech{root namespace} is
the same as the returned namespace if both have @tech{base phase} 0.}
@defproc[(make-base-empty-namespace) namespace?]{
Creates a new empty @tech{namespace} like @racket[make-empty-namespace],
but with @racketmodname[racket/base]
attached. The namespace's @tech{base phase} is the same as the
@tech{phase} in which the @racket[make-base-empty-namespace]
function was created.}
@defproc[(make-base-namespace) namespace?]{
Creates a new @tech{namespace} like @racket[make-empty-namespace], but
with @racketmodname[racket/base] attached and
@racket[require]d into the top-level environment. The namespace's
@tech{base phase} is the same as the @tech{phase} in which the
@racket[make-base-namespace] function was created.}
@defform[(define-namespace-anchor id)]{
Binds @racket[id] to a namespace anchor that can be used with
@racket[namespace-anchor->empty-namespace] and
@racket[namespace-anchor->namespace].
This form can be used only in a @tech{top-level context} or in a
@tech{module-context}.}
@defproc[(namespace-anchor? [v any/c]) boolean?]{
Returns @racket[#t] if @racket[v] is a namespace-anchor value,
@racket[#f] otherwise.}
@defproc[(namespace-anchor->empty-namespace [a namespace-anchor?]) namespace?]{
Returns an empty namespace that shares a @tech{module registry}
and @tech{root namespace} with
the source of the anchor, and whose @tech{base phase} is the
@tech{phase} in which the anchor was created.
If the anchor is from a @racket[define-namespace-anchor] form in a
module context, then the source is the namespace in which the
containing module is instantiated. If the anchor is from a
@racket[define-namespace-anchor] form in a top-level content, then the
source is the namespace in which the anchor definition was evaluated.}
@defproc[(namespace-anchor->namespace [a namespace-anchor?]) namespace?]{
Returns a namespace corresponding to the source of the anchor.
If the anchor is from a @racket[define-namespace-anchor] form in a
module context, then the result is a namespace for the module's body
in the anchor's phase. The result is the same as a namespace obtained
via @racket[module->namespace].
If the anchor is from a @racket[define-namespace-anchor] form in a
top-level content, then the result is the namespace in which the
anchor definition was evaluated.}
@defparam[current-namespace n namespace?]{
A @tech{parameter} that determines the @techlink{current namespace}.}
@defproc[(namespace-symbol->identifier [sym symbol?]) identifier?]{
Similar to @racket[datum->syntax] restricted to symbols. The
@tech{lexical information} of the resulting identifier corresponds to
the top-level environment of the current namespace; the identifier has
no source location or properties.}
@defproc[(namespace-base-phase [namespace namespace? (current-namespace)]) exact-integer?]{
Returns the @tech{base phase} of @racket[namespace].}
@defproc[(namespace-module-identifier [where (or/c namespace? exact-integer? #f)
(current-namespace)])
identifier?]{
Returns an identifier whose binding is @racket[module] in the
@tech{base phase} of @racket[where] if it is a namespace, or in the
@racket[where] @tech{phase level} otherwise.
The @tech{lexical information} of the identifier includes bindings (in
the same @tech{phase level}) for all syntactic forms that appear in
fully expanded code (see @secref["fully-expanded"]), but using the
name reported by the second element of @racket[identifier-binding] for
the binding; the @tech{lexical information} may also include other
bindings.}
@defproc[(namespace-variable-value [sym symbol?]
[use-mapping? any/c #t]
[failure-thunk (or/c (-> any) #f) #f]
[namespace namespace? (current-namespace)])
any]{
Returns a value for @racket[sym] in @racket[namespace], using
@racket[namespace]'s @tech{base phase}. The returned value depends on
@racket[use-mapping?]:
@itemize[
@item{If @racket[use-mapping?] is true (the default), and if
@racket[sym] maps to a top-level variable or an imported variable
(see @secref["namespace-model"]), then the result is the same as
evaluating @racket[sym] as an expression. If @racket[sym] maps to
syntax or imported syntax, then @racket[failure-thunk] is called or
the @exnraise[exn:fail:syntax]. If @racket[sym] is mapped to an
undefined variable or an uninitialized module variable, then
@racket[failure-thunk] is called or the
@exnraise[exn:fail:contract:variable].}
@item{If @racket[use-mapping?] is @racket[#f], the namespace's
syntax and import mappings are ignored. Instead, the value of the
top-level variable named @racket[sym] in namespace is returned. If
the variable is undefined, then @racket[failure-thunk] is called or
the @exnraise[exn:fail:contract:variable].}
]
If @racket[failure-thunk] is not @racket[#f],
@racket[namespace-variable-value] calls @racket[failure-thunk] to
produce the return value in place of raising an
@racket[exn:fail:contract:variable] or @racket[exn:fail:syntax]
exception.}
@defproc[(namespace-set-variable-value! [sym symbol?]
[v any/c]
[map? any/c #f]
[namespace namespace? (current-namespace)])
void?]{
Sets the value of @racket[sym] in the top-level environment of
@racket[namespace] in the @tech{base phase}, defining @racket[sym] if
it is not already defined.
If @racket[map?] is supplied as true, then the namespace's
@tech{identifier} mapping is also adjusted (see
@secref["namespace-model"]) in the @tech{phase level} corresponding to
the @tech{base phase}, so that @racket[sym] maps to the variable.}
@defproc[(namespace-undefine-variable! [sym symbol?]
[namespace namespace? (current-namespace)])
void?]{
Removes the @racket[sym] variable, if any, in the top-level
environment of @racket[namespace] in its @tech{base phase}. The
namespace's @tech{identifier} mapping (see @secref["namespace-model"])
is unaffected.}
@defproc[(namespace-mapped-symbols [namespace namespace? (current-namespace)])
(listof symbol?)]{
Returns a list of all symbols that are mapped to variables, syntax,
and imports in @racket[namespace] for the @tech{phase level}
corresponding to the @tech{namespace}'s @tech{base phase}.}
@defproc[(namespace-require [quoted-raw-require-spec any/c])
void?]{
Performs the import corresponding to @racket[quoted-raw-require-spec]
in the top-level environment of the current namespace, like a
top-level @racket[#%require]. The @racket[quoted-raw-require-spec]
argument must be a datum that corresponds to a quoted
@racket[_raw-require-spec] for @racket[#%require], which includes
module paths.
Module paths in @racket[quoted-raw-require-spec] are resolved with respect
to @racket[current-load-relative-directory] or
@racket[current-directory] (if the former is @racket[#f]), even if the
current namespace corresponds to a module body.}
@defproc[(namespace-require/copy [quoted-raw-require-spec any/c])
void?]{
Like @racket[namespace-require] for syntax exported from the module,
but exported variables at the namespace's @tech{base phase} are
treated differently: the export's current value is copied to a
top-level variable in the current namespace.}
@defproc[(namespace-require/constant [quoted-raw-require-spec any/c])
void?]{
Like @racket[namespace-require], but for each exported variable at the
@tech{namespace}'s @tech{base phase}, the export's value is copied to
a corresponding top-level variable that is made immutable. Despite
setting the top-level variable, the corresponding identifier is bound
as imported.}
@defproc[(namespace-require/expansion-time [quoted-raw-require-spec any/c])
void?]{
Like @racket[namespace-require], but only the transformer part of the
module is executed relative to the @tech{namespace}'s @tech{base
phase}; that is, the module is merely @tech{visit}ed, and not
@tech{instantiate}d (see @secref["mod-parse"]). If the required module
has not been instantiated before, the module's variables remain
undefined.}
@defproc[(namespace-attach-module [src-namespace namespace?]
[modname module-path?]
[dest-namespace namespace? (current-namespace)])
void?]{
Attaches the instantiated module named by @racket[modname] in
@racket[src-namespace] (at its @tech{base phase}) to the @tech{module
registry} of @racket[dest-namespace].
In addition to @racket[modname], every module that it imports
(directly or indirectly) is also recorded in the current namespace's
@tech{module registry}, and instances at the same @tech{phase}
are also attached to @racket[dest-namespace] (while
@tech{visits} at the module's phase and instances at higher or lower phases are
not attached, nor even made @tech{available} for on-demand
@tech{visits}). The inspector of the module invocation in
@racket[dest-namespace] is the same as inspector of the invocation in
@racket[src-namespace].
If @racket[modname] is not a symbol, the current module name resolver
is called to resolve the path, but no module is loaded; the resolved
form of @racket[modname] is used as the module name in
@racket[dest-namespace].
If @racket[modname] refers to a submodule or a module with submodules,
unless the module was loaded from bytecode (i.e., a @filepath{.zo}
file) independently from submodules within the same top-level module,
then declarations for all submodules within the module's top-level
module are also attached to @racket[dest-namespace].
If @racket[modname] does not refer to an @tech{instantiate}d module in
@racket[src-namespace], or if the name of any module to be attached
already has a different declaration or same-@tech{phase} instance in
@racket[dest-namespace], then the @exnraise[exn:fail:contract].
If @racket[src-namespace] and @racket[dest-namespace] do not have the
same @tech{base phase}, then the @exnraise[exn:fail:contract].}
@defproc[(namespace-attach-module-declaration [src-namespace namespace?]
[modname module-path?]
[dest-namespace namespace? (current-namespace)])
void?]{
Like @racket[namespace-attach-module], but the module
specified by @racket[modname] need only be declared (and not
necessarily @tech{instantiate}d) in @racket[src-namespace], and the
module is merely declared in @racket[dest-namespace].}
@defproc[(namespace-unprotect-module [inspector inspector?]
[modname module-path?]
[namespace namespace? (current-namespace)])
void?]{
Changes the inspector for the instance of the module referenced by
@racket[modname] in @racket[namespace]'s @tech{module registry} so
that it is controlled by the current code inspector. The given
@racket[inspector] must currently control the invocation of the module
in @racket[namespace]'s @tech{module registry}, otherwise the
@exnraise[exn:fail:contract]. See also @secref["modprotect"].}
@defproc[(namespace-module-registry [namespace namespace?])
any]{
Returns the @tech{module registry} of the given namespace. This value
is useful only for identification via @racket[eq?].}
@defproc[(module->namespace [mod (or/c module-path?
resolved-module-path?
module-path-index?)])
namespace?]{
Returns a namespace that corresponds to the body of an instantiated
module in the current namespace's @tech{module registry} and in the
current namespace's @tech{base phase}, making the module
@tech{available} for on-demand @tech{visits} at the namespace's
@tech{base phase}. The returned namespace has the same @tech{module
registry} as the current namespace. Modifying a binding in the
namespace changes the binding seen in modules that require the
namespace's module.
Module paths in a top-level @racket[require] expression are resolved
with respect to the namespace's module. New @racket[provide]
declarations are not allowed.
If the current code inspector does not control the invocation of the
module in the current namespace's @tech{module registry}, the
@exnraise[exn:fail:contract]; see also @secref["modprotect"].
Bindings in the namespace cannot be modified if the
@racket[compile-enforce-module-constants] parameter was true when the
module was declared, unless the module declaration itself included
assignments to the binding via @racket[set!].}
@defproc[(namespace-syntax-introduce [stx syntax?]) syntax?]{
Returns a syntax object like @racket[stx], except that the current
namespace's bindings are included in the @tech{syntax object}'s
@tech{lexical information} (see @secref["stxobj-model"]). The
additional context is overridden by any existing @tech{top-level
bindings} in the @tech{syntax object}'s @tech{lexical information}, or
by any existing or future @tech{module bindings} in the @tech{lexical
information}.}
@defproc[(module-provide-protected? [module-path-index (or/c symbol? module-path-index?)]
[sym symbol?])
boolean?]{
Returns @racket[#f] if the module declaration for
@racket[module-path-index] defines @racket[sym] and exports it
unprotected, @racket[#t] otherwise (which may mean that the symbol
corresponds to an unexported definition, a protected export, or an
identifier that is not defined at all within the module).
The @racket[module-path-index] argument can be a symbol; see
@secref["modpathidx"] for more information on module path
indices.
Typically, the arguments to @racket[module-provide-protected?]
correspond to the first two elements of a list produced by
@racket[identifier-binding].}
@defproc[(variable-reference? [v any/c]) boolean?]{
Return @racket[#t] if @racket[v] is a @tech{variable reference}
produced by @racket[#%variable-reference], @racket[#f] otherwise.}
@defproc[(variable-reference-constant? [varref variable-reference?]) boolean?]{
Returns @racket[#t] if the variable represented by @racket[varref]
will retain its current value (i.e., @racket[varref] refers to a
variable that cannot be further modified by @racket[set!] or
@racket[define]), @racket[#f] otherwise.}
@defproc[(variable-reference->empty-namespace [varref variable-reference?])
namespace?]{
Returns an empty namespace that shares module declarations and
instances with the namespace in which @racket[varref] is instantiated,
and with the same phase as @racket[varref].}
@defproc[(variable-reference->namespace [varref variable-reference?])
namespace?]{
If @racket[varref] refers to a @tech{module-level variable}, then the
result is a namespace for the module's body in the referenced
variable's @tech{phase}; the result is the same as a namespace
obtained via @racket[module->namespace].
If @racket[varref] refers to a @tech{top-level variable}, then the
result is the namespace in which the referenced variable is defined.}
@defproc[(variable-reference->resolved-module-path [varref variable-reference?])
(or/c resolved-module-path? #f)]{
If @racket[varref] refers to a @tech{module-level variable}, the
result is a @tech{resolved module path} naming the module.
If @racket[varref] refers to a @tech{top-level variable}, then the
result is @racket[#f].}
@defproc[(variable-reference->module-path-index [varref variable-reference?])
(or/c module-path-index? #f)]{
If @racket[varref] refers to a @tech{module-level variable}, the
result is a @tech{module path index} naming the module.
If @racket[varref] refers to a @tech{top-level variable}, then the
result is @racket[#f].}
@defproc[(variable-reference->module-source [varref variable-reference?])
(or/c symbol? (and/c path? complete-path?) #f)]{
If @racket[varref] refers to a @tech{module-level variable}, the
result is a path or symbol naming the module's source (which is
typically, but not always, the same as in the @tech{resolved module
path}). If the relevant module is a @tech{submodule}, the result
corresponds to the enclosing top-level module's source.
If @racket[varref] refers to a @tech{top-level variable}, then the
result is @racket[#f].}
@defproc[(variable-reference->phase [varref variable-reference?])
exact-nonnegative-integer?]{
Returns the @tech{phase} of the variable referenced by @racket[varref].}
@defproc[(variable-reference->module-base-phase [varref variable-reference?])
exact-integer?]{
Returns the @tech{phase} in which the module is instantiated for the
variable referenced by @racket[varref], or @racket[0] if the variable
for @racket[varref] is not within a module.
For a variable with a module, the result is less than the result of
@racket[(variable-reference->phase varref)] by @math{n} when the
variable is bound at @tech{phase level} @math{n} within the module.}
@defproc[(variable-reference->module-declaration-inspector [varref variable-reference?])
inspector?]{
Returns the declaration @tech{inspector} (see @secref["modprotect"])
for the module of @racket[varref], where @racket[varref] must refer to
an anonymous module variable as produced by
@racket[(#%variable-reference)].}