This site is a static rendering of the Trac instance that was used by R7RS-WG1 for its work on R7RS-small (PDF), which was ratified in 2013. For more information, see Home. For a version of this page that may be more recent, see ModulesShinn in WG2's repo for R7RS-large.

Modules­Shinn

DekuDekuplex
2010-06-03 04:46:07
2Corrected misspelling: "except" -> "exception".history
source

Title

WG1 Library Syntax

Authors

Alex Shinn

Abstract

A simple, static module syntax is provided which can easily be implemented on top of existing module systems. Modules have separate namespaces, and can import and export variables and macros with fine-grained control. The description of the module is done with a Scheme-like DSL, clearly separated from the code of the module for ease of static analysis. Users are free to either include the module code directly in the DSL or in separate files or both.

Issues

Rationale

The charter explicitly requires a module system:

To promote extensibility, the language developed by working group 1 must include support for macros and modules in a way that is appropriate for the language's size and goals. Semantics compatible with interactive read/eval/print loops should be provided.

Module systems serve the purpose of encapsulating code and managing namespaces. Although lambda lets us manage local identifiers, it does't allow us to encapsulate macros, and it wants for a friendlier interface for typical "module-like" uses.

Specification

A module definition takes the following form:

(library <module-name> <module-declarations>)

The keyword library is used for compatibility with R6RS - except for this one keyword, this proposal will refer to modules, reserving the option to change terminology at a later date.

The module name is a list of symbols or exact integers specifying the name of the module, for use when importing from other modules. R6RS does not allow non-symbol components, but as this is popular and convenient for numeric concepts such as (srfi 1) and (rfc 821) it is explicitly allowed.

The <module-declarations> can be any of:

Future standards may extend the syntax with additional forms.

export specifies a set of bindings to be exported. Each <export-spec> has one of the two forms:

where the former exports the identifier with the same name, and the latter can be used to rename the identifier on export.

import specifies one or more modules to import into the current module. An <import-set> has one of the following forms:

By default, all of the bindings in a module's export clause are imported with the same names (or the exported names if exported with a rename form). The additional <import-set> forms modify this as follows.

It is a syntax error if the same identifier is imported twice, from any combination of modules or multiple import forms.

body and include declarations provide a means to specify the Scheme code that makes up the body of the module. body takes the forms literally and splices them as a begin, whereas include takes one or more file names, reads all the top-level forms in the files, and splices the results. The forms from all body and include declarations are expanded in the order in which they occur in the module declaration.

The bodies of an imported module may be evaluated multiple times, but will be evaluated at least once before the body of any module which imports it is evaluated. It is a syntax error if any set of modules form a cyclic import dependency.

REPL Interaction

To load a module into an interactive REPL, a REPL should extend the standard environment with an import form that works as within a module declaration, but importing the bindings directly into the REPL environment.

Multiple imports of the same identifier in the same import form is still a syntax error, however identifiers may later be rebound by subsequent import forms.

Top-Level Programs

To be specified.

Implementation

Scheme48 provides a module system compatibile with this, with some minor syntactic differences, and using plain identifiers instead of lists for module names. Chibi-Scheme provides a similar module system based on the Scheme48 system, removing all keywords and regulating the module names, now lists, to a separate namespace.

Compatibility

R5RS

The R5RS has no module system, so implementations all provide their own incompatible module systems. To work together and with WG1 standard Scheme implementations, they should support the specified library syntax in addition to (or in place of) their current syntax.

R6RS

The syntax is largely a subset of the R6RS library form, with the exception that there is no implicit body. To support WG1 library forms, the core library (e.g. (rnrs 7)) should provide two macros, include and body. body can be defined simply as an alias for begin:

(define-syntax body (syntax-rules () ((body x ...) (begin x ...))))

include can't be defined with syntax-rules, but can in a low-level macro system. The R6RS library specification gives a sample definition of include.

WG2

WG2 will likely need to address phasing issues, and provide the equivalent of the R6RS for form.