Next: expander lexenv descriptors, Previous: expander lexenv rib, Up: expander lexenv [Index]
Under Vicare, we adopt the following definitions:
An object of type <stx>
.
A compound object holding: nulls, pairs, vectors, numbers, strings,
bytevectors, chars, booleans, keywords, would–block objects, unbound
objects, EOF objects, broken weak pointer objects, objects of type
<stx>
.
An unwrapped symbol object cannot be part of an unwrapped syntax object: an attempt to use an unwrapped syntax object holding an unwrapped symbol will, sooner or later, cause an exception to be raised.
Disjoint object type representing wrapped syntax objects: source code expressions associated to meta data representing their lexical contour.
Objects of type <stx>
have the following fields:
expr
A symbolic expression representing source code, possibly annotated;
these expressions are the ones produced by the Scheme source code
reader. They can be raw source code expressions or nested hierarchies
of annotation
objects returned by get-annotated-datum
(see iklib reader annotations).
mark*
Null or a proper list of eq?
–unique objects, including the
symbol ‘src’, used to distinguish between identifiers introduced by
the source code and identifiers introduced by applications of macro
transformers. Each of these marks can be either a generated mark or an
anti–mark.
Two marks must be eq?
–comparable, so, by default, we use empty
strings as marks and #f
as anti–mark: their generation is fast.
rib*
Null or a proper list of rib
objects or shift
symbols. Every
rib
represents a nested lexical contour; a shift
represents
the return from a macro transformer application.
While expanding source code: upon entering a syntactic form representing
a lexical contour, a new rib
is added to the syntax object
representing the syntactic form itself, to allow syntactic identifiers
in the form to be captured by the bindings introduced in that contour.
annotated-expr*
Null or a proper list of annotated expressions: #f
or input forms
of macro transformer calls. This field is used to trace the
transformations a form undergoes when it is processed as macro use. The
#f
items are inserted when this instance is processed as input
form of a macro call, but is later discarded.
The following bindings are exported by the library (vicare
expander)
.
Return #t
if stx is a wrapped or unwrapped syntax object;
otherwise return #f
.
Return #t
if stx is a wrapped syntax object; else return
#f
.
<stx>
: stx-expr stxReturn a symbolic expression, possibly annotated.
<stx>
: stx-mark* stxReturn null or a proper list of eq?
–unique objects acting as
lexical contour marks, including the symbol ‘src’.
<stx>
: stx-rib* stxReturn null or a proper list of rib
instances or shift
symbols.
<stx>
: stx-annotated-expr* stxReturn null or a proper list of annotated expressions: #f
or input
forms of macro transformer calls.
All the syntactic identifiers are <stx>
objects with a symbol in their
expr
field; other objects such as pairs and vectors may be
wrapped or unwrapped. A wrapped pair is an <stx>
whose expr
field is a pair:
(syntax (a . b))
an unwrapped pair is a pair whose car and cdr fields are themselves syntax objects (wrapped or unwrapped):
((syntax a) . (syntax b))
It makes sense to associate lexical contour informations to syntactic identifiers, while associating them to datums is useless from the point of view of expanding source code. For example, in the following code the identifiers ‘var’ belong to different lexical contours, and so have different meanings, while the datum ‘123’ is always the same in all the lexical contours:
(let ((var 123)) (let ((var 123)) var))
We can create a syntax object holding a raw expression as follows:
(import (vicare)) (define X 1) (begin-for-syntax (datum->syntax #'X 'ciao)) ⇒ #<syntactic-identifier expr=ciao mark*=(src)>
and we can create a syntax object holding an annotated expression as follows:
(import (vicare)) (define X 1) (begin-for-syntax (let* ((port (open-string-input-port "(list X)")) (datum (get-annotated-datum port)) (stx (datum->syntax #'X datum))) datum ⇒ #[annotation expression=#<omitted> stripped=(list X) textual-position=#[r6rs-record: &source-position port-id="*string-input-port*" byte=0 character=0 line=1 column=1]] stx) ⇒ #<syntax expr=(list X) mark*=(src) line=1 column=1 source=*string-input-port*>
we can unwrap a syntax object by using syntax-case
:
(import (vicare)) (define X 1) (begin-for-syntax (let* ((port (open-string-input-port "(list X)")) (datum (get-annotated-datum port)) (stx (datum->syntax #'X datum)) (stx (syntax-case stx () ((?head ?tail) (list #'?head #'?tail))))) stx) ⇒ (#<syntactic-identifier expr=list mark*=(src)> #<syntactic-identifier expr=X mark*=(src)>)
Next: expander lexenv descriptors, Previous: expander lexenv rib, Up: expander lexenv [Index]