Import and export levels
Expanding a library may require run-time information from another library. For example, if a macro transformer calls
a procedure from library A, then the library A must be instantiated before expanding any use of the macro in library B.
Library A may not be needed when library B is eventually run as part of a program, or it may be needed for run time of
library B, too. The library mechanism distinguishes these times by phases, which are explained in this section.
Every library can be characterized by expand-time information (minimally, its imported libraries, a list of the exported
keywords, a list of the exported variables, and code to evaluate the transformer expressions) and run-time information (minimally,
code to evaluate the variable definition right-hand-side expressions, and code to evaluate the body expressions). The expand-time
information must be available to expand references to any exported binding, and the run-time information must be available
to evaluate references to any exported variable binding.
A phase is a time at which the expressions within a library are evaluated. Within a library body, top-level expressions
and the right-hand sides of define forms are evaluated at run time, i.e., phase 0, and the right-hand sides of define-syntax
forms are evaluated at expand time, i.e., phase 1. When define-syntax, let-syntax, or letrec-syntax forms appear within code
evaluated at phase n, the right-hand sides are evaluated at phase n + 1.
These phases are relative to the phase in which the library itself is used. An instance of a library corresponds to an
evaluation of its variable definitions and expressions in a particular phase relative to another library—a process called
instantiation. For example, if a top-level expression in a library B refers to a variable export from another library A, then
it refers to the export from an instance of A at phase 0 (relative to the phase of B). But if a phase 1 expression within B
refers to the same binding from A, then it refers to the export from an instance of A at phase 1 (relative to the phase of B).
A visit of a library corresponds to the evaluation of its syntax definitions in a particular phase relative to another library—
a process called visiting. For example, if a top-level expression in a library B refers to a macro export from another library A,
then it refers to the export from a visit of A at phase 0 (relative to the phase of B), which corresponds to the evaluation of
the macro's transformer expression at phase 1.
A level is a lexical property of an identifier that determines in which phases it can be referenced. The level for each identifier
bound by a definition within a library is 0; that is, the identifier can be referenced only at phase 0 within the library. The
level for each imported binding is determined by the enclosing for form of the import in the importing library, in addition to
the levels of the identifier in the exporting library. Import and export levels are combined by pairwise addition of all level
combinations. For example, references to an imported identifier exported for levels pa and pb and imported for levels qa, qb,
and qc are valid at levels pa + qa, pa + qb, pa + qc, pb + qa, pb + qb, and pb + qc. An <import set> without an enclosing for is
equivalent to (for <import set> run), which is the same as (for <import set> (meta 0)).
The export level of an exported binding is 0 for all bindings that are defined within the exporting library. The export levels
of a reexported binding, i.e., an export imported from another library, are the same as the effective import levels of that binding
within the reexporting library.
For the libraries defined in the library report, the export level is 0 for nearly all bindings. The exceptions are syntax-rules,
identifier-syntax, ..., and _ from the (rnrs base (6)) library, which are exported with level 1, set! from the (rnrs base (6)) library,
which is exported with levels 0 and 1, and all bindings from the composite (rnrs (6)) library (see library chapter on “Composite library”),
which are exported with levels 0 and 1.
Macro expansion within a library can introduce a reference to an identifier that is not explicitly imported into the library.
In that case, the phase of the reference must match the identifier's level as shifted by the difference between the phase of
the source library (i.e., the library that supplied the identifier's lexical context) and the library that encloses the reference.
For example, suppose that expanding a library invokes a macro transformer, and the evaluation of the macro transformer refers to
an identifier that is exported from another library (so the phase-1 instance of the library is used); suppose further that the value
of the binding is a syntax object representing an identifier with only a level-n binding; then, the identifier must be used only
at phase n + 1 in the library being expanded. This combination of levels and phases is why negative levels on identifiers can be
useful, even though libraries exist only at non-negative phases.
If any of a library's definitions are referenced at phase 0 in the expanded form of a program, then an instance of the referenced
library is created for phase 0 before the program's definitions and expressions are evaluated. This rule applies transitively:
if the expanded form of one library references at phase 0 an identifier from another library, then before the referencing library
is instantiated at phase n, the referenced library must be instantiated at phase n. When an identifier is referenced at any phase n
greater than 0, in contrast, then the defining library is instantiated at phase n at some unspecified time before the reference is
evaluated. Similarly, when a macro keyword is referenced at phase n during the expansion of a library, then the defining library is
visited at phase n at some unspecified time before the reference is evaluated.
An implementation may distinguish instances/visits of a library for different phases or to use an instance/visit at any phase as
an instance/visit at any other phase. An implementation may further expand each library form with distinct visits of libraries in
any phase and/or instances of libraries in phases above 0. An implementation may create instances/visits of more libraries at more
phases than required to satisfy references. When an identifier appears as an expression in a phase that is inconsistent with the identifier's
level, then an implementation may raise an exception either at expand time or run time, or it may allow the reference. Thus, a library
whose meaning depends on whether the instances of a library are distinguished or shared across phases or library expansions may be
unportable.