[R6RS] phases and modules (was syntax-case semantics)

Matthew Flatt mflatt at cs.utah.edu
Mon Mar 20 09:07:28 EST 2006

Summary of recommendations for the module SRFI, as triggered by the
SRFI-72 discussion:

 1. (Strongly recommended) When `let-syntax' is used in a compile-time
    expression, the RHS is a meta-compile-time expression, in a
    different phase from compile time.

 2. (Weakly recommended) Generalize module import to allow import from
    an arbitrary compile-time phase.

    (Strongly recommended) Keep the constraint that when a single
    identifier is imported into multiple phases, it must be
    consistently imported from the same source.


At Sun, 19 Mar 2006 22:07:47 -0500, William D Clinger wrote:
> Although SRFI 72's syntax objects are less abstract than
> Chez Scheme's or MzScheme's, I think the syntactic tower
> is more abstract, and offers some worthwhile advantages
> for users, writers, *and* implementors.  

SRFI-72 is more general than MzScheme in one direction, because it
allows imports into any phase for "earlier" compile times.

Curiously, SRFI-72 omits import in the direction of "later" evaluation
times; I note that for-template imports have proven especially useful
in MzScheme, but I don't advocate them for R6RS.

SRFI-72 (or the reference implementation) includes the module SRFI,
mostly. The SRFI-72 implementation is more general by providing
`begin-for-syntax', which can be nested, so that expressions in an
arbitrary phase can be written within a module.

The SRFI-72 implementation does not implement the order of expansion
specified by the module SRFI, though. For example,

	(library "m" "scheme://r6r
          (define x (y))
          (define-syntax y
            (syntax-rules ()
              [(_) 5])))

leads to an "unbound variable y" error, because the definition of x is
fully expanded before the macro `y' is available. This is relevant to
the issue of `begin-for-syntax', because the module SRFI's order may be
needed in practice, and the module SRFI's order doesn't generalize well
to `begin-for-syntax', much less nested `begin-for-syntax'es.

> This may have
> something to do with the phasing problems that Matthew 
> mentioned, so I'm anxious to get on with our discussion
> of those issues.

The module SRFI currently allows imports only in two phases. As a
compromise position between Chez and MzScheme/SRFI-72, if a single
identifier is imported into both phases, the identifier must be
imported into both phases from the same source.

In the SRFI, we forgot to specify what happens when `let-syntax' is
used in a compile-time expression. I suggest that the RHS is a
meta-compile-time expression, in a different phase from compile time.
This is consistent with SRFI-72 and MzScheme. Obviously, the RHS of a
`let-syntax' in a meta-compile-time expression is meta-meta-compile-time,
and so on.

If we have multiple compile times, then we might generalize imports to
arbitrary compile-time phases (but still require that if an identifier
is imported into multiple phases, it's consistently imported from the
same source).

Importing into only two phases still seems like a reasonable design
point, but I think the only argument in its favor is that it's been
implemented in MzScheme. Unless there's support from others for the
two-phase limit, and if we agree on meta-compile-time as above, then I
suggest that we allow imports into arbitrary compile-time phases.

[If we combine the idea of meta-compile-time with the two-phase import
compromise, there's no way to import into a module such that the
bindings apply to the RHS of a `let-syntax'. In practice, this means
that macros used by a compile-time expression are always imported
for-syntax from some other module.]

Given the complexity of specifying expansion order with an general
`begin-for-syntax', I recommend that we not include `begin-for-syntax'
in the R6RS module system.


P.S.: substitute "library" for "module" above as needed.

More information about the R6RS mailing list