[R6RS] SYNTAX-CASE
dyb at cs.indiana.edu
dyb
Mon Apr 11 15:52:54 EDT 2005
> > This means we can still discuss changes to the proposal, but gives
> > Kent enough license to write down the bulk of it. Right?
>
> That's my understanding. Kent, will you write up a formal proposal
> that we can put up for vote (I prefer you do it so that we have a
> clear wording of what you have in mind.)
I propose that we accept syntax-case as proposed below and direct me to
produce a more precisely worded description, with input from Matthew
and anyone else who cares to contribute, but that we leave open the
possibility that we would reconsider the pattern language if a replacement
is proposed. What this does is insure that we have something in the
r6rs by default if efforts to produce something better falter.
Kent
--------
Syntax objects:
Syntax objects are opaque datatypes. Syntax objects may be created
by the expander or by the programmer via the syntax form or
datum->syntax-object (see below). Syntax objects represent program
fragments and sufficient information to place identifiers contained
within those fragments in their proper lexical context.
Syntax objects may be coerced to data via syntax-object->datum
(see below).
Terminology note: a syntax-object representing an identifier is
referred to as an identifier.
note: we may want to add syntax->list, especially for use in fenders
that want to map predicates, like identifier?, over lists of syntax
objects.
Transformers:
define-syntax, let-syntax, or letrec-syntax right-hand-sides are
transformers. A transformer is an expression that evaluates (at
expansion time) to a procedure of one argument. The expander
applies a transformer to a syntax object representing the input
form.
note: we may want the transformer to take two arguments: a syntax object
and a compile-time environment, provide a mechanism for extracting
bindings from the environment, and specify abstractly what the bindings
look like. We would presumably also want to extend define-syntax and
company right-hand sides to allow extended bindings to be placed into
the compile-time environment.
define-syntax:
No change in syntax, but allow define-syntax to appear wherever other
definitions can appear
indirect-export:
(indirect-export keyword identifier ...) is a declaration to the
module system that the transformer associated with keyword may
insert references to one or more of identifier .... If keyword is
directly or indirectly exported by a module, then identifier ...
are indirectly exported. Identifiers that are indirectly exported
and not separately directly exported can be referenced or assigned
only by the code produced by an exported transformer.
note: this can go away if we don't agree on module system. if we do
agree on a module system, it may be better to describe this form
with the module system.
syntax-rules
syntax-rules evaluates to a procedure of one argument.
syntax-rules is as in r5rs with the following extensions:
- Patterns are generalized slightly to allow a fixed number of
subpatterns to appear after an ellipsis, e.g., (x ... y z).
- Underscores are anonymous pattern variables that match anything
but are not bound to anything.
note: should also allow underscore in place of macro keyword in
'car' of syntax-rules pattern
- An optional fender may appear between the pattern and
template of any clause. the clause is chosen only if the
pattern matches the input and (if present) the fender
evaluates to a non-false value. within the fender, the
pattern variables appearing within the pattern are bound
to the corresponding pieces of the input.
syntax-rules may be defined as a macro in terms of syntax-case.
syntax-case
syntax-case has the following syntax:
(syntax-case expr (literal ...) clause ...)
where clause takes one of the two forms below.
(pattern output-expr)
(pattern fender output-expr)
(literal ...) and fenders are as in syntax-rules.
syntax-case evaluates expr, which must evaluate to a syntax object,
then attempts to find a matching clause by trying each pattern
and, for patterns that match, fender in turn.
The pattern variables of the matching clause are bound to the
corresponding pieces of the input within output-expr.
Patterns are similar to syntax-rules patterns except that the
pattern need not be list structured and, if list structured,
the first subform is not treated specially.
The following transformers for or are equivalent:
(syntax-rules ()
((_) #f)
((_ e) e)
((_ e1 e2 ...) (let ((t e1)) (if t t (or e2 ...)))))
(lambda (x)
(syntax-case x ()
((_) #'#f)
((_ e) #'e)
((_ e1 e2 ...) #'(let ((t e1)) (if t t (or e2 ...))))))
syntax
A syntax form, written as (syntax datum) or #'datum, evaluates to a
syntax object representing datum, with embedded pattern variables
lexically visible where the syntax form appears replaced by their
values. Ellipses are used as in syntax-rules templates. Information
necessary to place each identifier (except pattern variables replaced
as described above) in the lexical context of the syntax form is
incorporated into the syntax object.
syntax-object?
is bound to a procedure that takes a single argument. If the argument
is a syntax-object, it returns #t, otherwise it returns #f.
syntax-object->datum
is bound to a procedure that takes a single argument, which must be
a syntax-object. It returns a datum representing the syntax object.
All lexical-context information associated with embedded identifiers
is lost.
datum->syntax-object
is bound to a procedure of two arguments. The first is a template
identifier and the second is an arbitrary value. datum->syntax-object
converts the value into a syntax object with all of the information
necessary to make the object appear to the expander as if it appeared
in the source or macro output where and when the template identifier
first appeared.
generate-temporaries
is bound to a procedure of one argument. The argument must be a
proper list, the contents of which is of no consequence.
generate-temporaries returns a list of unique identifiers as long
as the input list.
identifier?
is bound to a procedure of one argument. It returns true if the
argument is an identifier (syntax object representing an identifier),
otherwise false.
bound-identifier=?
is bound to a procedure of two arguments, which must both be
identifiers. It returns true if a binding for either in the output
of a macro would capture references to the other.
free-identifier=?
is bound to a procedure of two arguments, which must both be
identifiers. It returns true if the two identifiers would refer
to the same binding if inserted into the output of a macro as
free identifiers.
note: we may also need literal-identifier=? if we add modules
identifier-syntax
identifier-syntax is an additional way to define transformers for
simulated variables. It takes one of the following two forms:
(identifier-syntax template)
(identifier-syntax
[id template]
[(set! id expr) template])
note: we probably want a lower-level version of this as supported
by both Chez Scheme and MzScheme.
with-syntax
with-syntax is a local binding construct (like let) for pattern
variables. It takes the following form:
(with-syntax ((pattern expr) ...) expr)
e.g.,
(with-syntax ((a 1) ((b ...) '(2 3 4))) #'(a b ...)) => (1 2 3 4)
it is may be defined as a macro in terms of syntax-case.
Note:
We may also want to consider adding fluid-let-syntax
More information about the R6RS
mailing list