1220 lines
48 KiB
Text
1220 lines
48 KiB
Text
|
% Copyright 2005-2017 Cisco Systems, Inc.
|
||
|
%
|
||
|
% Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
% you may not use this file except in compliance with the License.
|
||
|
% You may obtain a copy of the License at
|
||
|
%
|
||
|
% http://www.apache.org/licenses/LICENSE-2.0
|
||
|
%
|
||
|
% Unless required by applicable law or agreed to in writing, software
|
||
|
% distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
% See the License for the specific language governing permissions and
|
||
|
% limitations under the License.
|
||
|
\chapter{Libraries and Top-level Programs\label{CHPTLIBRARIES}}
|
||
|
|
||
|
\index{libraries}%
|
||
|
\index{top-level-programs}%
|
||
|
The Revised$^6$ Report describes two units of portable code:
|
||
|
libraries and top-level programs.
|
||
|
A library is a named collection of bindings with a declared set of
|
||
|
explicitly exported bindings, a declared set of imported libraries, and a
|
||
|
body that initializes its bindings.
|
||
|
A top-level program is a stand-alone program with a declared set of
|
||
|
imported libraries and a body that is run when the top-level program is
|
||
|
run.
|
||
|
The bindings in a library are created and its initialization code run only
|
||
|
if the library is used, directly or indirectly, by a top-level program.
|
||
|
|
||
|
\index{\scheme{import}}%
|
||
|
The \scheme{import} declarations appearing within libraries and top-level
|
||
|
programs serve two purposes: first, they cause the imported libraries to
|
||
|
be loaded, and second, they cause the bindings of the imported libraries
|
||
|
to become visible in the importing library or top-level program.
|
||
|
Libraries are typically stored in the file system, with one library per
|
||
|
file, and the library name typically identifies the file-system path to
|
||
|
the library, possibly relative to a default or programmer-specified set of
|
||
|
library locations.
|
||
|
The exact mechanism by which top-level programs are run and libraries are
|
||
|
loaded is implementation-dependent.
|
||
|
|
||
|
This chapter describes the mechanisms by which libraries and programs are
|
||
|
loaded in {\ChezScheme} along with various features for controlling and
|
||
|
tracking this process.
|
||
|
It also describes the set of built-in libraries and syntactic forms for
|
||
|
defining new libraries and top-level programs outside of a library or
|
||
|
top-level program file.
|
||
|
|
||
|
% \section{Locating Libraries\label{SECTLOCATINGLIBRARIES}}
|
||
|
%
|
||
|
% In {\ChezScheme}, a library to be loaded implicitly by \scheme{import}
|
||
|
% must reside in a file whose name reflects the name of the library.
|
||
|
% For example, if the library's name is \scheme{(tools sorting)}, the
|
||
|
% base name of the file must be \scheme{sorting} with a valid extension, and
|
||
|
% the file must be in a directory named \scheme{tools} which itself resides
|
||
|
% in one of the directories searched by \scheme{import}.
|
||
|
% The set of directories searched by \scheme{import} is determined by
|
||
|
% the
|
||
|
% \index{\scheme{library-directories}}\scheme{library-directories}
|
||
|
% parameter, and the set of
|
||
|
% extensions is determined by the
|
||
|
% \index{\scheme{library-extensions}}\scheme{library-extensions}
|
||
|
% parameter.
|
||
|
% So, if \scheme{(library-directories)} contains the pathnames
|
||
|
% \scheme{"/usr/lib/scheme/libraries"} and \scheme{"."}, and
|
||
|
% \scheme{(library-extensions)} contains the extensions \scheme{.ss}
|
||
|
% and \scheme{.sls}, the path of the \scheme{(tools sorting)}
|
||
|
% library must be one of the following.
|
||
|
%
|
||
|
% \schemedisplay
|
||
|
% /usr/lib/scheme/libraries/tools/sorting.ss
|
||
|
% /usr/lib/scheme/libraries/tools/sorting.sls
|
||
|
% ./tools/sorting.ss
|
||
|
% ./tools/sorting.sls
|
||
|
% \endschemedisplay
|
||
|
%
|
||
|
% A file containing a library or set of libraries can be explicitly loaded
|
||
|
% via \scheme{load}, in which case the file may have any name and may reside
|
||
|
% anywhere in the file system.
|
||
|
%
|
||
|
% \index{\scheme{compile-library}}%
|
||
|
% \index{\scheme{compile-imported-libraries}}%
|
||
|
% A file containing a library may be compiled with \scheme{compile-file}
|
||
|
% or \scheme{compile-library}.
|
||
|
% The only difference between the two is that the latter treats the source
|
||
|
% file as if it were prefixed by an implicit \scheme{#!r6rs}.
|
||
|
% Any libraries upon which the library depends must be compiled first.
|
||
|
% This can be done manually or by setting the parameter
|
||
|
% \scheme{compile-imported-libraries} to \scheme{#t} before compiling
|
||
|
% the importing library.
|
||
|
% If one of the libraries imported by the library is subsequently
|
||
|
% recompiled (say because it was modified), the importing library must also
|
||
|
% be recompiled.
|
||
|
|
||
|
|
||
|
\section{Built-in Libraries\label{SECTBUILTINLIBRARIES}}
|
||
|
|
||
|
In addition to the RNRS libraries mandated by the Revised$^6$ Report:
|
||
|
|
||
|
\schemedisplay
|
||
|
(rnrs base (6))
|
||
|
(rnrs arithmetic bitwise (6))
|
||
|
(rnrs arithmetic fixnums (6))
|
||
|
(rnrs arithmetic flonums (6))
|
||
|
(rnrs bytevectors (6))
|
||
|
(rnrs conditions (6))
|
||
|
(rnrs control (6))
|
||
|
(rnrs enums (6))
|
||
|
(rnrs eval (6))
|
||
|
(rnrs exceptions (6))
|
||
|
(rnrs files (6))
|
||
|
(rnrs hashtables (6))
|
||
|
(rnrs io ports (6))
|
||
|
(rnrs io simple (6))
|
||
|
(rnrs lists (6))
|
||
|
(rnrs mutable-pairs (6))
|
||
|
(rnrs mutable-strings (6))
|
||
|
(rnrs programs (6))
|
||
|
(rnrs r5rs (6))
|
||
|
(rnrs records procedural (6))
|
||
|
(rnrs records syntactic (6))
|
||
|
(rnrs records inspection (6))
|
||
|
(rnrs sorting (6))
|
||
|
(rnrs syntax-case (6))
|
||
|
(rnrs unicode (6))
|
||
|
\endschemedisplay
|
||
|
|
||
|
\index{\scheme{(chezscheme)} library}%
|
||
|
\index{\scheme{(chezscheme csv7)} library}%
|
||
|
\index{\scheme{(scheme)} library}%
|
||
|
\index{\scheme{(scheme csv7)} library}%
|
||
|
{\ChezScheme} also provides two additional libraries: \scheme{(chezscheme)}
|
||
|
and \scheme{(chezscheme csv7)}.
|
||
|
The former can also be referenced as \scheme{(scheme)} and the latter can
|
||
|
also be referenced as \scheme{(scheme csv7)}.
|
||
|
|
||
|
The \scheme{(chezscheme)} library exports bindings for every identifier whose
|
||
|
binding is described in this document, including those for keywords like
|
||
|
\scheme{lambda}, auxiliary keywords like \scheme{else}, module names
|
||
|
like \scheme{scheme}, and procedure names like \scheme{cons}.
|
||
|
In most cases where an identifier exported from the
|
||
|
\scheme{(chezscheme)} library corresponds to an identifier exported from
|
||
|
one of the RNRS libraries, the bindings are identical.
|
||
|
In some cases, however, the \scheme{(chezscheme)} bindings extend the
|
||
|
\scheme{rnrs} bindings in some way.
|
||
|
For example, the \scheme{(chezscheme)} \scheme{syntax-rules} form allows
|
||
|
its clauses to have fenders (Section~\ref{SECTSYNTAXRULES}), while the
|
||
|
\scheme{(rnrs)} \scheme{syntax-rules} form does not.
|
||
|
Similarly, the \scheme{(chezscheme)} \scheme{current-input-port} procedure
|
||
|
accepts an optional \var{port} argument that, when specified, sets the
|
||
|
current input port to \var{port} (Section~\ref{SECTIOINPUT}), while the
|
||
|
\scheme{(rnrs)} \scheme{current-input-port} procedure does not.
|
||
|
When the \scheme{(chezscheme)} library extends an RNRS binding in some
|
||
|
way, the \scheme{(chezscheme)} library also exports the RNRS version,
|
||
|
with the name prefixed by \scheme{r6rs:}, e.g., \scheme{r6rs:syntax-rules}
|
||
|
or \scheme{r6rs:current-input-port}.
|
||
|
|
||
|
The \scheme{(chezscheme csv7)} Version~7 backward compatibility library
|
||
|
contains bindings for a set of syntactic forms and procedures whose syntax
|
||
|
or semantics directly conflicts with the RNRS bindings for the same
|
||
|
identifiers.
|
||
|
The following identifiers are exported from \scheme{(chezscheme csv7)}.
|
||
|
|
||
|
\schemedisplay
|
||
|
record-field-accessible?
|
||
|
record-field-accessor
|
||
|
record-field-mutable?
|
||
|
record-field-mutator
|
||
|
record-type-descriptor
|
||
|
record-type-field-decls
|
||
|
record-type-field-names
|
||
|
record-type-name
|
||
|
record-type-symbol
|
||
|
\endschemedisplay
|
||
|
|
||
|
The bindings of this library should be used only for old code; new
|
||
|
code should use the RNRS variants.
|
||
|
Each of these is also available in the \scheme{(chezscheme)} library with
|
||
|
the prefix \scheme{csv7:}, e.g., \scheme{csv7:record-type-name}.
|
||
|
|
||
|
The interaction environment in which code outside of a library or
|
||
|
RNRS top-level program is scoped contains all of the bindings of the
|
||
|
\scheme{(chezscheme)} library, as described in
|
||
|
Section~\ref{SECTUSEINTERACTIONENVIRONMENT}.
|
||
|
|
||
|
|
||
|
\section{Running Top-level Programs\label{SECTRUNNINGTOPLEVELPROGRAMS}}
|
||
|
|
||
|
\index{\scheme{scheme-script}}%
|
||
|
\index{\scheme{--program} command-line option}%
|
||
|
\index{\scheme{load-program}}%
|
||
|
A top-level program must reside in its own file, which may have any
|
||
|
name and may reside anywhere in the file system.
|
||
|
A top-level program residing in a file is run by one of three mechanisms:
|
||
|
the \scheme{scheme-script} command, the \scheme{--program} command-line
|
||
|
argument, or the \scheme{load-program} procedure.
|
||
|
|
||
|
The \scheme{scheme-script} command is used as follows:
|
||
|
|
||
|
\schemedisplay
|
||
|
scheme-script \var{program-filename} \var{arg} \dots
|
||
|
\endschemedisplay
|
||
|
|
||
|
It may also be run implicitly on Unix-based systems by placing the line
|
||
|
|
||
|
\schemedisplay
|
||
|
#! /usr/bin/env scheme-script
|
||
|
\endschemedisplay
|
||
|
|
||
|
at the front of the file containing the top-level program, making the
|
||
|
top-level program file executable, and executing the file.
|
||
|
This line may be replaced with
|
||
|
|
||
|
\schemedisplay
|
||
|
#! /usr/bin/scheme-script
|
||
|
\endschemedisplay
|
||
|
|
||
|
with \scheme{/usr/bin} replaced by the absolute path to the directory
|
||
|
containing \scheme{scheme-script} if it is not in \scheme{/usr/bin}.
|
||
|
The first form is recommended in the nonnormative appendices to the
|
||
|
Revised$^6$ Report~\cite{r6rsapps}, and works wherever
|
||
|
\scheme{scheme-script} appears in the path.
|
||
|
|
||
|
The \scheme{--program} command is used similarly with the \scheme{scheme}
|
||
|
or \scheme{petite} executables, either by running:
|
||
|
|
||
|
\schemedisplay
|
||
|
scheme --program \var{program-filename} \var{arg} \dots
|
||
|
petite --program \var{program-filename} \var{arg} \dots
|
||
|
\endschemedisplay
|
||
|
|
||
|
or by including
|
||
|
|
||
|
\schemedisplay
|
||
|
#! /usr/bin/scheme --script
|
||
|
\endschemedisplay
|
||
|
|
||
|
or
|
||
|
|
||
|
\schemedisplay
|
||
|
#! /usr/bin/petite --script
|
||
|
\endschemedisplay
|
||
|
|
||
|
at the front of the top-level program file, making the file executable,
|
||
|
and executing the file.
|
||
|
Again, \scheme{/usr/bin} should be replaced with the absolute path to
|
||
|
the actual directory in which \scheme{scheme} and/or \scheme{petite}
|
||
|
resides, if not \scheme{/usr/bin}.
|
||
|
|
||
|
The \scheme{load-program} procedure, described in
|
||
|
Section~\ref{SECTMISCCOMPILEEVAL}, is used like \scheme{load}:
|
||
|
|
||
|
\schemedisplay
|
||
|
(load-program \var{string})
|
||
|
\endschemedisplay
|
||
|
|
||
|
where \var{string} names the file in which the top-level program resides.
|
||
|
|
||
|
Regardless of the mechanism used, if the opening line is in one of the
|
||
|
forms described above, or more generally, consists of
|
||
|
\scheme{#!} followed by a space or a forward slash, the opening line
|
||
|
is not considered part of the program and is ignored once the Scheme
|
||
|
system starts up and begins to run the program.
|
||
|
Thus, the line may be present even in a file loaded by \scheme{load-program}.
|
||
|
In fact, \scheme{load-program} is ultimately used by the other two
|
||
|
mechanisms described above, via the value of the \scheme{scheme-program}
|
||
|
parameter described in Section~\ref{SECTMISCWAITERS}, and it is
|
||
|
\scheme{load-program} that scans past the \scheme{#!} line, if present,
|
||
|
before evaluating the program.
|
||
|
|
||
|
A top-level program may be compiled with the
|
||
|
\index{\scheme{compile-program}}\scheme{compile-program}
|
||
|
procedure described in Section~\ref{SECTMISCCOMPILEEVAL}.
|
||
|
\scheme{compile-program} copies the \scheme{#!} line from the source
|
||
|
file to the object file, followed by a compiled version of the source
|
||
|
code.
|
||
|
Any libraries upon which the top-level program depends, other than
|
||
|
built-in libraries, must be compiled first via \scheme{compile-file}
|
||
|
or \scheme{compile-library}.
|
||
|
This can be done manually or by setting the parameter
|
||
|
\scheme{compile-imported-libraries} to \scheme{#t} before compiling
|
||
|
the program.
|
||
|
The program must be recompiled if any of the libraries upon which
|
||
|
it depends are recompiled.
|
||
|
A compiled top-level program can be run just like a source top-level
|
||
|
program via each of the mechanisms described above.
|
||
|
|
||
|
\index{\scheme{load-library}}%
|
||
|
In {\ChezScheme}, a library may also be defined in the REPL or placed in a
|
||
|
file to be loaded via \scheme{load} or \scheme{load-library}.
|
||
|
The syntax for a library is the same whether the library is placed in
|
||
|
its own file and implicitly loaded via \scheme{import}, entered into
|
||
|
the REPL, or placed in a file along with other top-level expressions to
|
||
|
be evaluated by \scheme{load}.
|
||
|
A top-level program may also be defined in the REPL or placed in a file
|
||
|
to be loaded via \scheme{load}, but in this case, the syntax is slightly
|
||
|
different.
|
||
|
In the language of the Revised$^6$ Report, a top-level program is merely
|
||
|
an unwrapped sequence of subforms consisting of an \scheme{import} form
|
||
|
and a body, delimited only by the boundaries of the file in which it
|
||
|
resides.
|
||
|
In order for a top-level program to be entered in the REPL or placed in
|
||
|
a file to be evaluated by \scheme{load}, {\ChezScheme} allows top-level
|
||
|
programs to be enclosed in a
|
||
|
\index{\scheme{top-level-program}}\scheme{top-level-program} form.
|
||
|
|
||
|
\section{Library and Top-level Program Forms\label{SECTLIBRARYFORMS}}
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\noskipentryheader
|
||
|
\formdef{library}{\categorysyntax}{(library \var{name} \var{exports} \var{imports} \var{library-body})}
|
||
|
\returns unspecified
|
||
|
\listlibraries
|
||
|
\endnoskipentryheader
|
||
|
|
||
|
The \scheme{library} form defines a new library with the specified
|
||
|
name, exports, imports, and body.
|
||
|
Details on the syntax and semantics of the library form are given in
|
||
|
Section~\ref{TSPL:SECTLIBPROGRAMS} of {\TSPLFOUR} and in the Revised$^6$
|
||
|
Report.
|
||
|
|
||
|
Only one version of a library can be loaded at any given time, and an
|
||
|
exception is raised if a library is implicitly loaded via \scheme{import}
|
||
|
when another version of the library has already been loaded.
|
||
|
{\ChezScheme} permits a different version of the library, or a new
|
||
|
instance of the same version, to be entered explicitly into the REPL
|
||
|
or loaded explicitly from a file, to facilitate interactive testing
|
||
|
and debugging.
|
||
|
The programmer should take care to make sure that any code that uses
|
||
|
the library is also reentered or reloaded, to make sure that code
|
||
|
accesses the bindings of the new instance of the library.
|
||
|
|
||
|
\schemedisplay
|
||
|
(library (test (1)) (export x) (import (rnrs)) (define x 3))
|
||
|
(import (test))
|
||
|
(define f (lambda () x))
|
||
|
(f) ;=> 3
|
||
|
|
||
|
(library (test (1)) (export x) (import (rnrs)) (define x 4))
|
||
|
(import (test))
|
||
|
(f) ;=> 3 ; oops---forgot to redefine f
|
||
|
(define f (lambda () x))
|
||
|
(f) ;=> 4
|
||
|
|
||
|
(library (test (2)) (export x) (import (rnrs)) (define x 5))
|
||
|
(import (test))
|
||
|
(define f (lambda () x))
|
||
|
(f) ;=> 5
|
||
|
\endschemedisplay
|
||
|
|
||
|
As with module imports (Section~\ref{SECTSYNTAXMODULES}), a library
|
||
|
\scheme{import} may appear anywhere a definition may appear, including at
|
||
|
top level in the REPL, in a file to be loaded by \scheme{load}, or within
|
||
|
a \scheme{lambda}, \scheme{let}, \scheme{letrec}, \scheme{letrec*},
|
||
|
etc., body.
|
||
|
The same \scheme{import} form may be used to import from both libraries
|
||
|
and modules.
|
||
|
|
||
|
\schemedisplay
|
||
|
(library (foo) (export a) (import (rnrs)) (define a 'a-from-foo))
|
||
|
(module bar (b) (define b 'b-from-bar))
|
||
|
(let () (import (foo) bar) (list a b)) ;=> (a-from-foo b-from-bar)
|
||
|
\endschemedisplay
|
||
|
|
||
|
The \scheme{import} keyword is not visible within a library body
|
||
|
unless the library imports it from the \scheme{(chezscheme)} library.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{top-level-program}{\categorysyntax}{(top-level-program \var{imports} \var{body})}
|
||
|
\returns unspecified
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\index{top-level-programs}%
|
||
|
A \scheme{top-level-program} form may be entered into the REPL or placed
|
||
|
in a file to be loaded via \scheme{load}, where it behaves as if its
|
||
|
subforms were placed in a file and loaded via \scheme{load-program}.
|
||
|
Details on the syntax and semantics of a top-level program are given in
|
||
|
Section~\ref{TSPL:SECTLIBPROGRAMS} of {\TSPLFOUR} and in the Revised$^6$
|
||
|
Report.
|
||
|
|
||
|
The following transcript illustrates a \scheme{top-level-program} being
|
||
|
tested in the REPL.
|
||
|
|
||
|
\schemedisplay
|
||
|
> (top-level-program (import (rnrs))
|
||
|
(display "hello!\n"))
|
||
|
hello!
|
||
|
\endschemedisplay
|
||
|
|
||
|
\section{Standalone import and export forms\label{SECTLIBRARYIMPORTEXPORTFORMS}}
|
||
|
|
||
|
Although not required by the Revised$^6$ Report,
|
||
|
{\ChezScheme} supports the use of standalone import and
|
||
|
export forms.
|
||
|
The import forms can appear anywhere other definitions
|
||
|
can appear, including within a \scheme{library} body,
|
||
|
\scheme{module} (Section~\ref{SECTSYNTAXMODULES}) body,
|
||
|
\scheme{lambda} or other local body, and at top level.
|
||
|
The export forms can appear within the definitions of a
|
||
|
\scheme{library} or \scheme{module} body to specify additional
|
||
|
exports for the library or module.
|
||
|
|
||
|
Within a library or top-level program, the keywords for
|
||
|
these forms must be imported from the \scheme{(chezscheme)}
|
||
|
library to be available for use, since they are not
|
||
|
defined in any of the Revised$^6$ Report libraries.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{import}{\categorysyntax}{(import \var{import-spec} \dots)}
|
||
|
\formdef{import-only}{\categorysyntax}{(import-only \var{import-spec} \dots)}
|
||
|
\returns unspecified
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
An \scheme{import} or \scheme{import-only} form is a definition and can
|
||
|
appear anywhere other definitions can appear, including
|
||
|
at the top level of a program, nested within the bodies of
|
||
|
\scheme{lambda} expressions, and nested within modules
|
||
|
and libraries.
|
||
|
|
||
|
Each \var{import-spec} must take one of the following forms.
|
||
|
|
||
|
\schemedisplay
|
||
|
\var{import-set}
|
||
|
(for \var{import-set} \var{import-level} \dots)
|
||
|
\endschemedisplay
|
||
|
|
||
|
\noindent
|
||
|
The \scheme{for} wrapper and \var{import-level} are described in
|
||
|
Chapter~\ref{TSPL:CHPTLIBRARIES} of {\TSPLFOUR}.
|
||
|
They are ignored by {\ChezScheme}, which determines
|
||
|
automatically the levels at which identifiers must
|
||
|
be imported, as permitted by the Revised$^6$ Report.
|
||
|
This frees the programmer from the obligation
|
||
|
to do so and results in more generality as well as more
|
||
|
precision in the set of libraries actually imported
|
||
|
at compile and run time~\cite{Ghuloum:libraries,Ghuloum:phd}.
|
||
|
|
||
|
An \var{import-set} must take one of the following forms:
|
||
|
|
||
|
\schemedisplay
|
||
|
\var{library-spec}
|
||
|
\var{module-name}
|
||
|
(only \var{import-set} \var{identifier} \dots)
|
||
|
(except \var{import-set} \var{identifier} \dots)
|
||
|
(prefix \var{import-set} \var{prefix})
|
||
|
(add-prefix \var{import-set} \var{prefix})
|
||
|
(drop-prefix \var{import-set} \var{prefix})
|
||
|
(rename \var{import-set} (\var{import-name} \var{internal-name}) \dots)
|
||
|
(alias \var{import-set} (\var{import-name} \var{internal-name}) \dots)
|
||
|
\endschemedisplay
|
||
|
|
||
|
Several of these are specified by the Revised$^6$ Report; the remainder
|
||
|
are {\ChezScheme} extensions, including \var{module-name} and the
|
||
|
\scheme{add-prefix}, \scheme{drop-prefix}, and \scheme{alias} forms.
|
||
|
|
||
|
An \scheme{import} or \scheme{import-only} form makes the specified bindings
|
||
|
visible in the scope in which they appear.
|
||
|
Except at top level, they differ in that \scheme{import} leaves all bindings
|
||
|
except for those shadowed by the imported names visible, whereas \scheme{import-only}
|
||
|
hides all existing bindings, i.e., makes only the imported names visible.
|
||
|
At top level, \scheme{import-only} behaves like \scheme{import}.
|
||
|
|
||
|
Each \var{import-set} identifies a set of names to make visible
|
||
|
as follows.
|
||
|
|
||
|
\begin{description}
|
||
|
\item[\scheme{\var{library-spec}}:]
|
||
|
all exports of the library identified by the Revised$^6$ Report \var{library-spec}
|
||
|
(Chapter~\ref{TSPL:CHPTLIBRARIES}).
|
||
|
|
||
|
\item[\scheme{\var{module-name}}:]
|
||
|
all exports of module named by the identifier \var{module-name}
|
||
|
|
||
|
\item[\scheme{(only \var{import-set} \var{identifier} \dots)}:]
|
||
|
of those specified by \var{import-set}, just \scheme{\var{identifier} \dots}
|
||
|
|
||
|
\item[\scheme{(except \var{import-set} \var{identifier} \dots)}:]
|
||
|
all specified by \var{import-set} except \scheme{\var{identifier} \dots}
|
||
|
|
||
|
\item[\scheme{(prefix \var{import-set} \var{prefix})}:]
|
||
|
all specified by \var{import-set}, each prefixed by \var{prefix}
|
||
|
|
||
|
\item[\scheme{(add-prefix \var{import-set} \var{prefix})}:]
|
||
|
all specified by \var{import-set}, each prefixed by \var{prefix}
|
||
|
(just like \scheme{prefix})
|
||
|
|
||
|
\item[\scheme{(drop-prefix \var{import-set} \var{prefix})}:]
|
||
|
all specified by \var{import-set}, with prefix \var{prefix} removed
|
||
|
|
||
|
\item[\scheme{(rename \var{import-set} (\var{import-name} \var{internal-name}) \dots)}:]
|
||
|
all specified by \var{import-set}, with each identifier \var{import-name}
|
||
|
renamed to the corresponding identifier \var{internal-name}
|
||
|
|
||
|
\item[\scheme{(alias \var{import-set} (\var{import-name} \var{internal-name}) \dots)}:]
|
||
|
all specified by \var{import-set}, with each \var{internal-name} as an alias
|
||
|
for \var{import-name}
|
||
|
\end{description}
|
||
|
|
||
|
The \scheme{alias} form differs from the \scheme{rename} form in that both
|
||
|
\var{import-name} and \var{internal-name} are in the resulting set,
|
||
|
rather than just \var{internal-name}.
|
||
|
|
||
|
It is a syntax violation if the
|
||
|
given selection or transformation cannot be made because of a missing
|
||
|
export or prefix.
|
||
|
|
||
|
An identifier made visible via an import of a module or library is scoped as if its
|
||
|
definition appears where the import occurs.
|
||
|
The following example illustrates these scoping rules, using a local
|
||
|
module \scheme{m}.
|
||
|
|
||
|
\schemedisplay
|
||
|
(library (A) (export x) (import (rnrs)) (define x 0))
|
||
|
(let ([x 1])
|
||
|
(module m (x setter)
|
||
|
(define-syntax x (identifier-syntax z))
|
||
|
(define setter (lambda (x) (set! z x)))
|
||
|
(define z 2))
|
||
|
(let ([y x] [z 3])
|
||
|
(import m (prefix (A) a:))
|
||
|
(setter 4)
|
||
|
(list x a:x y z))) ;=> (4 0 1 3)
|
||
|
\endschemedisplay
|
||
|
|
||
|
\noindent
|
||
|
The inner \scheme{let} expression binds \scheme{y} to the value of
|
||
|
the \scheme{x} bound by the outer \scheme{let}.
|
||
|
The import of \scheme{m} makes the definitions of \scheme{x}
|
||
|
and \scheme{setter} visible within the inner \scheme{let}.
|
||
|
The import of \scheme{(A)} makes the variable \scheme{x} exported
|
||
|
from \scheme{(A)} visible as \scheme{a:x} within the body of the
|
||
|
inner \scheme{let}.
|
||
|
Thus, in the expression \scheme{(list x a:x y z)}, \scheme{x} refers to the
|
||
|
identifier macro exported from \scheme{m} while \scheme{a:x} refers to the
|
||
|
variable \scheme{x} exported from \scheme{(A)} and \scheme{y} and \scheme{z}
|
||
|
refer to the bindings established by the inner \scheme{let}.
|
||
|
The identifier macro \scheme{x} expands into a reference to
|
||
|
the variable \scheme{z} defined within the module.
|
||
|
|
||
|
With local import forms, it is rarely necessary to use the extended
|
||
|
import specifiers.
|
||
|
For example, an abstraction that encapsulates the import and reference
|
||
|
can easily be defined and used as follows.
|
||
|
|
||
|
\schemedisplay
|
||
|
(define-syntax from
|
||
|
(syntax-rules ()
|
||
|
[(_ m id) (let () (import-only m) id)]))
|
||
|
|
||
|
(library (A) (export x) (import (rnrs)) (define x 1))
|
||
|
(let ([x 10])
|
||
|
(module M (x) (define x 2))
|
||
|
(cons (from (A) x) (from M x))) ;=> (1 . 2)
|
||
|
\endschemedisplay
|
||
|
|
||
|
\noindent
|
||
|
The definition of \scheme{from} could use \scheme{import} rather than
|
||
|
\scheme{import-only}, but by using \scheme{import-only} we get feedback
|
||
|
if an attempt is made to import an identifier from a library or
|
||
|
module that does not export the identifier.
|
||
|
With \scheme{import} instead of \scheme{import-only}, the current binding,
|
||
|
if any, would be visible if the library or module does not export the
|
||
|
specified name.
|
||
|
|
||
|
\schemedisplay
|
||
|
(define-syntax lax-from
|
||
|
(syntax-rules ()
|
||
|
[(_ m id) (let () (import m) id)]))
|
||
|
|
||
|
(library (A) (export x) (import (rnrs)) (define x 1))
|
||
|
|
||
|
(let ([x 10])
|
||
|
(module M (x) (define x 2))
|
||
|
(+ (from (A) x) (from M y))) ;=> \var{exception: unbound identifier y}
|
||
|
|
||
|
(let ([x 10] [y 20])
|
||
|
(module M (x) (define x 2))
|
||
|
(+ (lax-from (A) x) (lax-from M y))) ;=> 21
|
||
|
\endschemedisplay
|
||
|
|
||
|
Import visibility interacts with hygienic macro expansion in such a
|
||
|
way that, as one might expect,
|
||
|
an identifier \var{x} imported from a module \var{M} is treated in
|
||
|
the importing context as if the corresponding export identifier had
|
||
|
been present in the import form along with \var{M}.
|
||
|
|
||
|
The \scheme{from} abstraction above works because both \var{M} and \var{id}
|
||
|
appear in the input to the abstraction, so the imported \var{id} captures
|
||
|
the reference to \var{id}.
|
||
|
|
||
|
The following variant of \var{from} also works, because both names are
|
||
|
introduced into the output by the transformer.
|
||
|
|
||
|
\schemedisplay
|
||
|
(module M (x) (define x 'x-of-M))
|
||
|
(define-syntax x-from-M
|
||
|
(syntax-rules ()
|
||
|
[(_) (let () (import M) x)]))
|
||
|
|
||
|
(let ([x 'local-x]) (x-from-M)) ;=> x-of-M
|
||
|
\endschemedisplay
|
||
|
|
||
|
On the other hand, imports of introduced module names do not capture
|
||
|
free references.
|
||
|
|
||
|
\schemedisplay
|
||
|
(let ([x 'local-x])
|
||
|
(define-syntax alpha
|
||
|
(syntax-rules ()
|
||
|
[(_ var) (let () (import M) (list x var))]))
|
||
|
|
||
|
(alpha x)) ;=> (x-of-M local-x)
|
||
|
\endschemedisplay
|
||
|
|
||
|
Similarly, imports from free module names do not capture references
|
||
|
to introduced variables.
|
||
|
|
||
|
\schemedisplay
|
||
|
(let ([x 'local-x])
|
||
|
(define-syntax beta
|
||
|
(syntax-rules ()
|
||
|
[(_ m var) (let () (import m) (list x var))]))
|
||
|
|
||
|
(beta M x)) ;=> (local-x x-of-M)
|
||
|
\endschemedisplay
|
||
|
|
||
|
This semantics extends to prefixed, renamed, and aliased bindings
|
||
|
created by the extended \scheme{import} specifiers \scheme{prefix},
|
||
|
\scheme{rename}, and \scheme{alias}.
|
||
|
|
||
|
The \scheme{from} abstraction
|
||
|
works for variables but not for exported keywords, record names,
|
||
|
or module names, since the output is an expression and may thus appear only where
|
||
|
expressions may appear.
|
||
|
A generalization of this technique is used in the following definition
|
||
|
of \scheme{import*}, which supports renaming of imported bindings and
|
||
|
selective import of specific bindings---without the use of the built-in
|
||
|
\scheme{import} subforms for selecting and renaming identifiers
|
||
|
|
||
|
\schemedisplay
|
||
|
(define-syntax import*
|
||
|
(syntax-rules ()
|
||
|
[(_ m) (begin)]
|
||
|
[(_ m (new old))
|
||
|
(module (new)
|
||
|
(module (tmp)
|
||
|
(import m)
|
||
|
(alias tmp old))
|
||
|
(alias new tmp))]
|
||
|
[(_ m id) (module (id) (import m))]
|
||
|
[(_ m spec0 spec1 ...)
|
||
|
(begin (import* m spec0) (import* m spec1 ...))]))
|
||
|
\endschemedisplay
|
||
|
|
||
|
\noindent
|
||
|
To selectively import an identifier from module or library \scheme{m}, the
|
||
|
\scheme{import*} form expands into an anonymous module that first
|
||
|
imports all exports of \scheme{m} then re-exports only the selected
|
||
|
identifier.
|
||
|
To rename on import the macro expands into an anonymous module that
|
||
|
instead exports an alias (Section~\ref{SECTSYNTAXALIAS}) bound to the new name.
|
||
|
|
||
|
If the output placed the definition of \scheme{new} in the same
|
||
|
scope as the import of \scheme{m}, a naming conflict would arise
|
||
|
whenever \scheme{new} is also present in the interface
|
||
|
of \scheme{m}.
|
||
|
To prevent this, the output instead places the import within a nested
|
||
|
anonymous module and links \scheme{old} and \scheme{new}
|
||
|
by means of an alias for the introduced identifier \scheme{tmp}.
|
||
|
|
||
|
The macro expands recursively to handle multiple import specifications.
|
||
|
Each of the following examples imports \scheme{cons} as \scheme{+} and \scheme{+} as
|
||
|
\scheme{cons}, which is probably not a very good idea.
|
||
|
|
||
|
\schemedisplay
|
||
|
(let ()
|
||
|
(import* scheme (+ cons) (cons +))
|
||
|
(+ (cons 1 2) (cons 3 4))) ;=> (3 . 7)
|
||
|
|
||
|
(let ()
|
||
|
(import* (rnrs) (+ cons) (cons +))
|
||
|
(+ (cons 1 2) (cons 3 4))) ;=> (3 . 7)
|
||
|
\endschemedisplay
|
||
|
|
||
|
% for testing
|
||
|
% (module m (x y z)
|
||
|
% (define x 'x)
|
||
|
% (define y 'y)
|
||
|
% (define z 'z))
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{export}{\categorysyntax}{(export \var{export-spec} \dots)}
|
||
|
\returns unspecified
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
An \scheme{export} form is a definition and can appear with other
|
||
|
definitions at the front of a \scheme{library} or \scheme{module}.
|
||
|
It is a syntax error for an \scheme{export} form to appear in other
|
||
|
contexts, including at top level or among the definitions of a
|
||
|
top-level program or \scheme{lambda} body.
|
||
|
|
||
|
Each \var{export-spec} must take one of the following forms.
|
||
|
|
||
|
\schemedisplay
|
||
|
\var{identifier}
|
||
|
(rename (\var{internal-name} \var{export-name}) \dots)
|
||
|
(import \var{import-spec} \dots)
|
||
|
\endschemedisplay
|
||
|
|
||
|
\noindent
|
||
|
where each \var{internal-name} and \var{export-name} is an identifier.
|
||
|
The first two are syntactically identical to \scheme{library}
|
||
|
\var{export-spec}s, while the third is syntactically
|
||
|
identical to a {\ChezScheme} \scheme{import} form, which is an extension of the
|
||
|
R6RS library \scheme{import} subform.
|
||
|
The first form names a single export, \var{identifier}, whose export
|
||
|
name is the same as its internal name.
|
||
|
The second names a set of exports, each of whose export name is
|
||
|
given explicitly and may differ from its internal name.
|
||
|
|
||
|
For the third, the identifiers identified by the \scheme{import} form
|
||
|
become exports, with aliasing, renaming, prefixing, etc., as specified by the
|
||
|
\var{import-spec}s.
|
||
|
The module or library whose bindings are exported by an \scheme{import}
|
||
|
form appearing within an \scheme{export} form can
|
||
|
be defined within or outside the exporting module or library and need
|
||
|
not be imported elsewhere within the exporting module or library.
|
||
|
|
||
|
The following library exports a two-armed-only variant of \scheme{if}
|
||
|
along with all remaining bindings of the \scheme{(rnrs)} library.
|
||
|
|
||
|
\schemedisplay
|
||
|
(library (rnrs-no-one-armed-if) (export) (import (except (chezscheme) if))
|
||
|
(export if (import (except (rnrs) if)))
|
||
|
(define-syntax if
|
||
|
(let ()
|
||
|
(import (only (rnrs) if))
|
||
|
(syntax-rules ()
|
||
|
[(_ tst thn els) (if tst thn els)]))))
|
||
|
|
||
|
(import (rnrs-no-one-armed-if))
|
||
|
(if #t 3 4) ;=> 3
|
||
|
(if #t 3) ;=> \var{exception: invalid syntax}
|
||
|
\endschemedisplay
|
||
|
|
||
|
Another way to define the same library would be to define the
|
||
|
two-armed-only \scheme{if} with a different internal name and use
|
||
|
\scheme{rename} to export it under the name \scheme{if}:
|
||
|
|
||
|
\schemedisplay
|
||
|
(library (rnrs-no-one-armed-if) (export) (import (chezscheme))
|
||
|
(export (rename (two-armed-if if)) (import (except (rnrs) if)))
|
||
|
(define-syntax two-armed-if
|
||
|
(syntax-rules ()
|
||
|
[(_ tst thn els) (if tst thn els)])))
|
||
|
|
||
|
(import (rnrs-no-one-armed-if))
|
||
|
(if #t 3 4) ;=> 3
|
||
|
(if #t 3) ;=> \var{exception: invalid syntax}
|
||
|
\endschemedisplay
|
||
|
|
||
|
The placement of the \scheme{export} form in the library body is
|
||
|
irrelevant, e.g., the \scheme{export} form can appear after the
|
||
|
definition in the examples above.
|
||
|
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{indirect-export}{\categorysyntax}{(indirect-export \var{id} \var{indirect-id} \dots)}
|
||
|
\returns unspecified
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
This form is a definition and can appear wherever any other definition
|
||
|
can appear.
|
||
|
|
||
|
An \scheme{indirect-export} form declares that the named
|
||
|
\var{indirect-id}s are indirectly exported to top level if \var{id}
|
||
|
is exported to top level.
|
||
|
|
||
|
In general, if an identifier is not directly exported by a library or
|
||
|
module, it can be referenced outside of the library or module only in
|
||
|
the expansion of a macro defined within and exported from the library
|
||
|
or module.
|
||
|
Even this cannot occur for libraries or modules defined at top level
|
||
|
(or nested within other libraries or modules), unless either (1)
|
||
|
the library or module has been set up to implicitly export all
|
||
|
identifiers as indirect exports, or (2) each indirectly exported
|
||
|
identifier is explicitly declared as an indirect export of some
|
||
|
other identifier that is exported, either directly or indirectly, from
|
||
|
the library or module, via an \scheme{indirect-export} or the built-in
|
||
|
indirect export feature of a \scheme{module} export subform.
|
||
|
By default, (1) is true for a library and false for a module, but the
|
||
|
default can be overridden via the \scheme{implicit-exports}
|
||
|
form, which is described below.
|
||
|
|
||
|
This form is meaningful only within a top-level library, top-level module,
|
||
|
or module enclosed within a library or top-level module, although it
|
||
|
has no effect if the library or module already implicitly exports all
|
||
|
bindings.
|
||
|
It is allowed anywhere else definitions can appear, however, so macros
|
||
|
that expand into indirect export forms can be used in any definition
|
||
|
context.
|
||
|
|
||
|
Indirect exports are listed so the compiler can determine the
|
||
|
exact set of bindings (direct and indirect) that must be inserted
|
||
|
into the top-level environment, and conversely, the set of bindings
|
||
|
that may be treated more efficiently as local bindings (and
|
||
|
perhaps discarded, if they are not used).
|
||
|
|
||
|
In the example below, \scheme{indirect-export} is used to indirectly
|
||
|
export \scheme{count} to top level when \scheme{current-count} is
|
||
|
exported to top level.
|
||
|
|
||
|
\schemedisplay
|
||
|
(module M (bump-count current-count)
|
||
|
(define-syntax current-count (identifier-syntax count))
|
||
|
(indirect-export current-count count)
|
||
|
(define count 0)
|
||
|
(define bump-count
|
||
|
(lambda ()
|
||
|
(set! count (+ count 1)))))
|
||
|
|
||
|
(import M)
|
||
|
(bump-count)
|
||
|
current-count ;=> 1
|
||
|
count ;=> \var{exception: unbound identifier count}
|
||
|
\endschemedisplay
|
||
|
|
||
|
An \scheme{indirect-export} form is not required to make \scheme{count}
|
||
|
visible for \scheme{bump-count}, since it is a procedure whose code
|
||
|
is contained within the module rather than a macro that might expand
|
||
|
into a reference to \scheme{count} somewhere outside the module.
|
||
|
|
||
|
It is often useful to use \scheme{indirect-export} in the output
|
||
|
of a macro that expands into another macro named \var{a} if
|
||
|
\var{a} expands into references to identifiers that might not
|
||
|
be directly exported, as illustrated by the alternative definition
|
||
|
of module \scheme{M} above.
|
||
|
|
||
|
\schemedisplay
|
||
|
(define-syntax define-counter
|
||
|
(syntax-rules ()
|
||
|
[(_ getter bumper init incr)
|
||
|
(begin
|
||
|
(define count init)
|
||
|
(define-syntax getter (identifier-syntax count))
|
||
|
(indirect-export getter count)
|
||
|
(define bumper
|
||
|
(lambda ()
|
||
|
(set! count (incr count)))))]))
|
||
|
|
||
|
(module M (bump-count current-count)
|
||
|
(define-counter current-count bump-count 0 add1))
|
||
|
\endschemedisplay
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{implicit-exports}{\categorysyntax}{(implicit-exports #t)}
|
||
|
\formdef{implicit-exports}{\categorysyntax}{(implicit-exports #f)}
|
||
|
\returns unspecified
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
An \scheme{implicit-exports} form is a definition and can appear with other
|
||
|
definitions at the front of a \scheme{library} or \scheme{module}.
|
||
|
It is a syntax error for an \scheme{implicit-exports} form to appear in other
|
||
|
contexts, including at top level or among the definitions of a
|
||
|
top-level program or \scheme{lambda} body.
|
||
|
|
||
|
The \scheme{implicit-exports} form determines whether identifiers
|
||
|
not directly exported from a module or library are automatically
|
||
|
indirectly exported to the top level if any meta-binding (keyword, meta
|
||
|
definition, or property definition) is directly exported to top level
|
||
|
from the library or module.
|
||
|
The default for libraries is \scheme{#t}, to match the behavior required
|
||
|
by the Revised$^6$ Report, while the default for modules is \scheme{#f}.
|
||
|
The \scheme{implicit-exports} form is meaningful only within a library,
|
||
|
top-level module, or module enclosed within a library or top-level module.
|
||
|
It is allowed in a module enclosed within a \scheme{lambda}, \scheme{let},
|
||
|
or similar body, but ignored there because none of that module's bindings
|
||
|
can be exported to top level.
|
||
|
|
||
|
The advantage of \scheme{(implicit-exports #t)} is that indirect exports
|
||
|
need not be listed explicitly, which is convenient.
|
||
|
A disadvantage is that it often results in more bindings than necessary
|
||
|
being elevated to top level where they cannot be discarded as useless
|
||
|
by the optimizer.
|
||
|
For modules, another disadvantage is such bindings
|
||
|
cannot be proven immutable, which inhibits important optimizations such
|
||
|
as procedure inlining.
|
||
|
This can result in significantly lower run-time performance.
|
||
|
|
||
|
\section{Explicitly invoking libraries\label{SECTLIBRARYINVOCATION}}
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\noskipentryheader
|
||
|
\formdef{invoke-library}{\categoryprocedure}{(invoke-library \var{libref})}
|
||
|
\returns unspecified
|
||
|
\listlibraries
|
||
|
\endnoskipentryheader
|
||
|
|
||
|
\var{libref} must be an s-expression in the form of a library reference.
|
||
|
The syntax for library references is given in
|
||
|
Chapter~\ref{TSPL:CHPTLIBRARIES} of {\TSPLFOUR} and in the Revised$^6$
|
||
|
Report.
|
||
|
|
||
|
A library is implicitly invoked when or before some expression
|
||
|
outside the library (e.g., in another library or in a top-level
|
||
|
program) evaluates a reference to one of the library's exported
|
||
|
variables.
|
||
|
When the library is invoked, its body expressions (the right-hand-sides
|
||
|
of the library's variable definitions and its initialization
|
||
|
expressions) are evaluated.
|
||
|
Once invoked, the library is not invoked again within the same process,
|
||
|
unless it is first explicitly redefined or reloaded.
|
||
|
|
||
|
\scheme{invoke-library} explicitly invokes the library specified
|
||
|
by \var{libref} if it has not already been invoked or has since
|
||
|
been redefined or reloaded.
|
||
|
If the library has not yet been loaded, \scheme{invoke-library}
|
||
|
first loads the library via the process described in
|
||
|
Section~\ref{SECTUSELIBRARIES}.
|
||
|
|
||
|
\scheme{invoke-library} is typically only useful for libraries whose
|
||
|
body expressions have side effects.
|
||
|
It is useful to control when the side effects occur and to force
|
||
|
invocation of a library that has no exported variables.
|
||
|
Invoking a library does not force the compile-time code (macro
|
||
|
transformer expressions and meta definitions) to be loaded or
|
||
|
evaluated, nor does it cause the library's bindings to become
|
||
|
visible.
|
||
|
|
||
|
It is good practice to avoid externally visible side effects in
|
||
|
library bodies so the library can be used equally well at compile
|
||
|
time and run time.
|
||
|
When feasible, consider moving the side effects of a library body
|
||
|
to an initialization routine and adding a top-level program that
|
||
|
imports the library and calls the initialization routine.
|
||
|
With this structure, calls to \scheme{invoke-library} on the
|
||
|
library can be replaced by calls to
|
||
|
\index{\scheme{load-program}}\scheme{load-program} on the
|
||
|
top-level program.
|
||
|
|
||
|
\section{Library Parameters\label{SECTLIBRARYPARAMETERS}}
|
||
|
|
||
|
\index{\scheme{import}}%
|
||
|
The parameters described below control where \scheme{import} looks
|
||
|
when attempting to load a library, whether it compiles the libraries
|
||
|
it loads, and whether it displays tracking messages as it performs its
|
||
|
search.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{library-directories}{\categorythreadparameter}{library-directories}
|
||
|
\formdef{library-extensions}{\categorythreadparameter}{library-extensions}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
The parameter \scheme{library-directories} determines where the files
|
||
|
containing library source and object code are located in the file system,
|
||
|
and the parameter \scheme{library-extensions} determines the filename
|
||
|
extensions for the files holding the code, as described in
|
||
|
section~\ref{SECTUSELIBRARIES}.
|
||
|
The values of both parameters are lists of pairs of strings.
|
||
|
The first string in each \scheme{library-directories} pair identifies a
|
||
|
source-file root directory, and the second identifies the corresponding
|
||
|
object-file root directory.
|
||
|
Similarly, the first string in each \scheme{library-extensions} pair
|
||
|
identifies a source-file extension, and the second identifies the
|
||
|
corresponding object-file extension.
|
||
|
The full path of a library source or object file consists of the source or
|
||
|
object root followed by the components of the library name prefixed by
|
||
|
slashes, with the library extension added on the end.
|
||
|
For example, for root \scheme{/usr/lib/scheme}, library name
|
||
|
\scheme{(app lib1)}, and extension \scheme{.sls}, the full path is
|
||
|
\scheme{/usr/lib/scheme/app/lib1.sls}.
|
||
|
If the library name portion forms an absolute pathname, e.g.,
|
||
|
\scheme{~/.myappinit}, the \scheme{library-directories} parameter is
|
||
|
ignored and no prefix is added.
|
||
|
|
||
|
The initial values of these parameters are shown below.
|
||
|
|
||
|
\schemedisplay
|
||
|
(library-directories) ;=> (("." . "."))
|
||
|
|
||
|
(library-extensions) ;=> ((".chezscheme.sls" . ".chezscheme.so")
|
||
|
;== (".ss" . ".so")
|
||
|
;== (".sls" . ".so")
|
||
|
;== (".scm" . ".so")
|
||
|
;== (".sch" . ".so"))
|
||
|
\endschemedisplay
|
||
|
|
||
|
As a convenience, when either of these parameters is set, any element of
|
||
|
the list can be specified as a single source string, in which case the
|
||
|
object string is determined automatically.
|
||
|
For \scheme{library-directories}, the object string is the same as
|
||
|
the source string, effectively naming the
|
||
|
same directory as a source- and object-code root.
|
||
|
For \scheme{library-extensions}, the object string is the result of
|
||
|
removing the last (or only) extension from the string and appending
|
||
|
\scheme{".so"}.
|
||
|
The \scheme{library-directories} and \scheme{library-extensions}
|
||
|
parameters also accept as input strings in the format described
|
||
|
in Section~\ref{SECTUSESCRIPTING}
|
||
|
for the
|
||
|
\index{\scheme{--libdirs} command-line option}\scheme{--libdirs} and
|
||
|
\index{\scheme{--libexts} command-line option}\scheme{--libexts} command-line
|
||
|
options.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{compile-imported-libraries}{\categorythreadparameter}{compile-imported-libraries}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
When the value of this parameter is \scheme{#t}, \scheme{import}
|
||
|
automatically calls the value of the \scheme{compile-library-handler} parameter (which defaults
|
||
|
to a procedure that simply calls \scheme{compile-library}) on any imported library if
|
||
|
the object file is missing, older than the corresponding source file,
|
||
|
older than any source files included (via \index{\scheme{include}}\scheme{include}) when the
|
||
|
object file was created, or itself requires a library that has or must
|
||
|
be recompiled, as described in Section~\ref{SECTUSELIBRARIES}.
|
||
|
The default initial value of this parameter is \scheme{#f}.
|
||
|
It can be set to \scheme{#t} via the command-line option
|
||
|
\index{\scheme{--compile-imported-libraries} command-line option}\scheme{--compile-imported-libraries}.
|
||
|
|
||
|
When \scheme{import} compiles a library via this mechanism, it does not
|
||
|
also load the compiled library, because this would cause portions of
|
||
|
library to be reevaluated.
|
||
|
Because of this, run-time expressions in the file outside of a
|
||
|
\scheme{library} form will not be evaluated.
|
||
|
If such expressions are present and should be evaluated, the library
|
||
|
should be loaded explicitly.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{import-notify}{\categorythreadparameter}{import-notify}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
When the new parameter \scheme{import-notify} is set to a true value,
|
||
|
\scheme{import} displays messages to the console-output port as it
|
||
|
searches for the file containing each library it needs to load.
|
||
|
The default value of this parameter is \scheme{#f}.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{library-search-handler}{\categorythreadparameter}{library-search-handler}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
The value of parameter must be a procedure that follows the protocol described
|
||
|
below for \scheme{default-library-search-handler}, which is the default value
|
||
|
of this parameter.
|
||
|
|
||
|
The value of this parameter is invoked to locate the source or object code for
|
||
|
a library during \scheme{import}, \scheme{compile-whole-program}, or
|
||
|
\scheme{compile-whole-library}.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{default-library-search-handler}{\categoryprocedure}{(default-library-search-handler \var{who} \var{library} \var{directories} \var{extensions})}
|
||
|
\returns see below
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
This procedure is the default value of the \scheme{library-search-handler},
|
||
|
which is
|
||
|
called to locate the source or object code for a library
|
||
|
during \scheme{import},
|
||
|
\scheme{compile-whole-program}, or \scheme{compile-whole-library}.
|
||
|
\var{who} is a symbol that provides context in \scheme{import-notify} messages.
|
||
|
\var{library} is the name of the desired library.
|
||
|
\var{directories} is a list of source and object directory pairs in
|
||
|
the form returned by \scheme{library-directories}.
|
||
|
\var{extensions} is a list of source and object extension pairs in the form
|
||
|
returned by \scheme{library-extensions}.
|
||
|
|
||
|
This procedure searches the specified directories until it finds a library source or
|
||
|
object file with one of the specified extensions.
|
||
|
If it finds the source file first, it constructs the corresponding
|
||
|
object file path and checks whether the file exists.
|
||
|
If it finds the object file first, the procedure looks for a corresponding
|
||
|
source file with one of the given source extensions in a source directory paired
|
||
|
with that object directory.
|
||
|
The procedure returns three values:
|
||
|
the file-system path of the library source file or \scheme{#f} if not found,
|
||
|
the file-system path of the corresponding object file, which may be \scheme{#f},
|
||
|
and a boolean that is true if the object file exists.
|
||
|
|
||
|
\section{Library Inspection\label{SECTLIBRARYINSPECTION}}
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\noskipentryheader
|
||
|
\formdef{library-list}{\categoryprocedure}{(library-list)}
|
||
|
\returns a list of the libraries currently defined
|
||
|
\listlibraries
|
||
|
\endnoskipentryheader
|
||
|
|
||
|
The set of libraries initially defined includes those listed in
|
||
|
Section~\ref{SECTBUILTINLIBRARIES} above.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{library-version}{\categoryprocedure}{(library-version \var{libref})}
|
||
|
\returns the version of the specified library
|
||
|
\formdef{library-exports}{\categoryprocedure}{(library-exports \var{libref})}
|
||
|
\returns a list of the exports of the specified library
|
||
|
\formdef{library-requirements}{\categoryprocedure}{(library-requirements \var{libref})}
|
||
|
\returns a list of libraries required by the specified library
|
||
|
\formdef{library-requirements}{\categoryprocedure}{(library-requirements \var{libref} \var{options})}
|
||
|
\returns a list of libraries required by the specified library, filtered by \var{options}
|
||
|
\formdef{library-object-filename}{\categoryprocedure}{(library-object-filename \var{libref})}
|
||
|
\returns the name of the object file holding the specified library, if any
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
Information can be obtained only for built-in libraries or libraries
|
||
|
previously loaded into the system.
|
||
|
\var{libref} must be an s-expression in the form of a library reference.
|
||
|
The syntax for library references is given in
|
||
|
Chapter~\ref{TSPL:CHPTLIBRARIES} of {\TSPLFOUR} and in the Revised$^6$
|
||
|
Report.
|
||
|
|
||
|
The \scheme{library-version} return value is a list of numbers
|
||
|
(possibly empty) representing the library's version.
|
||
|
|
||
|
The list of exports returned by \scheme{library-exports} is a list of
|
||
|
symbols, each identifying one of the library's exports.
|
||
|
The order in which the elements appear is unspecified.
|
||
|
|
||
|
When the optional \var{options} argument is supplied, it must be
|
||
|
an enumeration set over the symbols constituting
|
||
|
valid library-requirements options, as described in the
|
||
|
\scheme{library-requirements-options} entry below.
|
||
|
It defaults to a set containing all of the options.
|
||
|
Each element of the list of libraries returned by
|
||
|
\scheme{library-requirements} is an s-expression form of a library
|
||
|
reference.
|
||
|
The library reference includes the actual version of the library that is
|
||
|
present in the system (if nonempty), even if a version was not specified
|
||
|
when it was imported.
|
||
|
The order in which the libraries appear in the list returned by
|
||
|
\scheme{library-requirements} is unspecified.
|
||
|
|
||
|
\scheme{library-object-filename} returns a string naming the object
|
||
|
file if the specified library was loaded from or compiled to an object
|
||
|
file.
|
||
|
Otherwise, it returns \scheme{#f}.
|
||
|
|
||
|
|
||
|
\schemedisplay
|
||
|
(with-output-to-file "A.ss"
|
||
|
(lambda ()
|
||
|
(pretty-print
|
||
|
'(library (A (1 2)) (export x z)
|
||
|
(import (rnrs))
|
||
|
(define x 'ex)
|
||
|
(define y 23)
|
||
|
(define-syntax z
|
||
|
(syntax-rules ()
|
||
|
[(_ e) (+ y e)])))))
|
||
|
'replace)
|
||
|
(with-output-to-file "B.ss"
|
||
|
(lambda ()
|
||
|
(pretty-print
|
||
|
'(library (B) (export x w)
|
||
|
(import (rnrs) (A))
|
||
|
(define w (cons (z 12) x)))))
|
||
|
'replace)
|
||
|
(compile-imported-libraries #t)
|
||
|
(import (B))
|
||
|
(library-exports '(A)) ;=> (x z) ; or (z x)
|
||
|
(library-exports '(A (1 2))) ;=> (x z) ; or (z x)
|
||
|
(library-exports '(B)) ;=> (x w) ; or (w x)
|
||
|
(library-version '(A)) ;=> (1 2)
|
||
|
(library-version '(B)) ;=> ()
|
||
|
(library-requirements '(A)) ;=> ((rnrs (6)))
|
||
|
(library-requirements '(B)) ;=> ((rnrs (6)) (A (1 2)))
|
||
|
(library-object-filename '(A)) ;=> "A.so"
|
||
|
(library-object-filename '(B)) ;=> "B.so"
|
||
|
\endschemedisplay
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{library-requirements-options}{\categorysyntax}{(library-requirements-options \var{symbol} \dots)}
|
||
|
\returns a library-requirements-options enumeration set
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
Library-requirements-options enumeration sets are passed to
|
||
|
\scheme{library-requirements} to determine the library requirements
|
||
|
to be listed. The available options are described below.
|
||
|
|
||
|
\begin{description}
|
||
|
\item[\scheme{import}:]
|
||
|
Include the libraries that must be imported when the specified library
|
||
|
is imported.
|
||
|
|
||
|
\item[\scheme{visit@visit}:]
|
||
|
Includes the libraries that must be visited when the specified library
|
||
|
is visited.
|
||
|
|
||
|
\item[\scheme{invoke@visit}:]
|
||
|
Include the libraries that must be invoked when the specified library
|
||
|
is visited.
|
||
|
|
||
|
\item[\scheme{invoke}:]
|
||
|
Includes the libraries that must be invoked when the specified library
|
||
|
is invoked.
|
||
|
\end{description}
|
||
|
|