[R6RS] library proposal(s)
dyb at cs.indiana.edu
dyb at cs.indiana.edu
Tue Jun 13 11:43:17 EDT 2006
I've included below some proposals for updating the library syntax to
accommodate the features we've discussed. The SRFI 83 syntax is
given first, followed by three proposal variants, followed by some
orthogonal options.
Kent
--------
Review---SRFI 83 syntax:
(library <lib-path> <language> <body>)
<body> --> <impexp-form>* <comdef-form>*
<impexp-form> --> (import <import-spec>*)
| (export <export-spec>*)
<comdef-form> --> <command or definition>
| (indirect-export <indirect-spec>*)
| (begin <comdef-form>*)
| <derived-comdef>
<import-spec> --> <import-set>
| (for <import-set> <import-phase>*)
<import-phase> --> run
| expand
<export-spec> --> <export-set>
<indirect-spec> --> (<identifier> <identifier>*)
<import-set> --> <lib-path>
| (only <X-set> <identifier>*)
| (except <X-set> <identifier>*)
| (add-prefix <X-set> <identifier>)
| (rename <X-set> (<identifier> <identifier>)*)
<export-set> --> <identifier>
| (rename (<identifier> <identifier>)*)
Proposed syntax, Variant I:
(library <lib-path>
(import <import-spec>*)
(export <import-spec>*)
<library body>)
<library body> --> <command or definition>*
<command or definition> --> <command>
| <definition>
| (begin <command or definition>*)
| <derived command or definition>
<definition> --> <variable definition>
| <syntax definition>
| (indirect-export <indirect-spec>*)
<variable definition> --> (define <variable> <expression>)
| (define (<variable> <def formals>) <body>)
<syntax definition> --> (define-syntax <keyword> <transformer spec>)
<lambda expression> --> (lambda <formals> <body>)
<body> --> <command or definition>* <expression>
[ all else remains as in the SRFI 83 ]
Scoping: all imports and definitions occupy a single scope within
the library <body>.
Rationale: This variant eliminates <language>, thereby allowing
us to use the subsetting and renaming features of <import-spec>
for all imported libraries.
It also allows indirect-export in any definition context, so that
macros that expand into macro definitions can also produce any
necessary indirect-export forms. indirect-export forms would be
ignored except within a library <body>.
It also allows lambda bodies to contain interleaved commands and
definitions. I didn't allow this in the syntax srfi because I thought
that the library srfi required all of the definitions to appear before
all of the commands/expressions.
Example:
(library sane-if
(import (rename "scheme://r6rs" (r6rs:if if)))
(export if)
(define-syntax if
(syntax-rules ()
[(_ e1 e2 e3) (r6rs:if e1 e2 e3)])))
Proposed syntax, Variant II:
(library <lib-path> <language>
(import <import-spec>*)
(export <import-spec>*)
<body>)
<language> -> <import-spec>
[ all else remains as in Variant I ]
Scoping: the language and all imports and definitions occupy a single
scope within the library <body>.
Rationale: This variant keeps <language>, allowing an implementation
or future report more lattitude in changing the library syntax. (With
language r7rs, for example, the syntax of a library body might
differ.) As with Variant I, it still allows the use of the subsetting
and renaming features of <import-spec> for all imported libraries,
including the language library.
Example:
(library sane-if (rename "scheme://r6rs" (r6rs:if if))
(import)
(export if)
(define-syntax if
(syntax-rules ()
[(_ e1 e2 e3) (r6rs:if e1 e2 e3)])))
Proposed syntax, Variant III:
(library <lib-path> <language>
(import <import-spec>*)
(export <import-spec>*)
<body>)
<language> -> <lib-path>
[ all else remains as in Variant I ]
Scoping: the language occupies a single outer contour, and the imports
and definitions occupy a single outer contour.
Rationale: As with Variant II, this variant keeps <language>, allowing
an implementation or future report more lattitude in changing the
library syntax. While the language imports cannot be subject to
subsetting or renaming, the language bindings can be shadowed by
the imported bindings and definitions in the library body. This
allows an implementation or future report even more lattitude in
changing the library syntax, since it doesn't tie down the
<import-spec> syntax.
Example:
(library sane-if "scheme://r6rs"
(import (rename (only "scheme://r6rs" if) (r6rs:if if)))
(export if)
(define-syntax if
(syntax-rules ()
[(_ e1 e2 e3) (r6rs:if e1 e2 e3)])))
Orthogonal options:
* Instead of allowing definitions and commands to be interleaved in
a lambda body, we might want to go the other way and require
definitions to appear before commands in both library and lambda
bodies.
* Instead of tying down the import syntax and requiring imports to
appear only at the head of a library form, we might want to allow
import forms to be derived and/or appear anywhere a definition can
appear. (Allowing them to appear anywhere a definition appears
implies allowing them to be derived, but the converse is not
true.)
* Instead of tying down the export syntax, we might want to allow
export forms to be derived and/or appear anywhere amongst the
definitions in a language body. (Allowing them to appear anywhere a
definition appears implies allowing them to be derived, but the
converse is not true.)
* With variants II and III we may want for the language to be
imported "for expand" as well as "for run". (I'm not sure whether
this is true in SRFI 83.) With Variant I we may want for
all imports to be imported "for expand" as well as "for run"
unless the import-spec says otherwise. But see the next option
below.
* Instead of requiring the user to specify "for expand" or
"for run", the expander could automatically invoke (or cause to be
invoked) an imported module at the appropriate meta level if an
attempt is made to reference an identifier at that level.
* Another way to avoid "for expand" and "for run" is to allow local
imports. A local import within a transformer expression is
implicitly "for expand". This only works if the language and/or
all imports are implicitly imported "for expand" as well as "for
syntax".
More information about the R6RS
mailing list