Next: scheme library examples, Previous: scheme library form, Up: scheme library [Index]
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
p_a and p_b and imported for levels q_a,
q_b, and q_c are valid at levels p_a + q_a,
p_a + q_b, p_a + q_c, p_b + q_a, p_b + q_b,
and p_b + q_c. 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, 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.
Next: scheme library examples, Previous: scheme library form, Up: scheme library [Index]