Next: expander lexenv rib sealing, Previous: expander lexenv rib type, Up: expander lexenv rib [Index]
rib
objectsA non–sealed rib
object is extensible: new syntactic bindings can be
added to it. This happens every time the expander processes internal
definitions in a top–level body or internal body; examples are: the
top–level body of a program; the top–level body of a library; the
internal-body
syntax; the internal body of lambda
; the
internal body of let
and its variants.
Adding an identifier–to–label mapping to an extensible rib
is
achieved by prepending items to the field’s lists.
For example, an empty extensible rib
has fields:
name* = () mark** = () label* = ()
adding a syntactic binding to it with source name ‘ciao’, marks ‘(src)’ and label ‘lab.ciao’ means mutating the fields to:
name* = (ciao) mark** = ((src)) label* = (lab.ciao)
we can think of this operation as “pushing the syntactic binding’s tuple”:
{ ciao, (src), lab.ciao }
on the rib
. Adding another binding with source name ‘hello’,
marks ‘(src)’ and label ‘lab.hello’ means to push the tuple.
{ hello, (src), lab.hello }
that is to mutate the fields to:
name* = (hello ciao) mark** = ((src) (src)) label* = (lab.hello lab.ciao)
As further example, let’s consider the syntactic form:
(internal-body (define a 1) (define b 2) (list a b))
when starting to expand the internal body: a new rib
is created and
added to the metadata of the syntax object representing the body itself;
when each internal definition is encountered, a new entry for the
identifier is added (via side effect) to the rib
:
name* = (b a) mark** = ((src) (src)) label* = (lab.b lab.a)
The order in which the syntactic binding’s tuples appear in the rib
does not matter: two tuples are different when both the source name’s
symbol and the marks are different and it is an error to add twice a
tuple to the same rib
.
While it is an error to add twice a syntactic binding’s tuple to the
same rib
, when expanding syntactic forms at the top–level of an
interaction environment: it is possible to redefine a previously defined
syntactic binding and to shadow a previously imported syntactic binding.
Interaction environment objects (see iklib environment) hold a
rib
object representing their top–level lexical contour; such rib
holds tuples representing both the syntactic bindings imported from
libraries and the syntactic bindings defined when expanding expressions
at the top–level.
Let’s say we are expanding syntactic forms read from the REPL (which uses an interaction environment); if we type:
vicare> (define a 1) vicare> (define a 2)
after the first define
is expanded the tuples in the rib
representing the top–level lexical contour are:
name* = (a) mark** = ((src)) label* = (lab.a.1)
and after the second define
is expanded the tuples are:
name* = (a) mark** = ((src)) label* = (lab.a.2)
we see that the old label gensym has been replaced with a new label gensym: this causes the syntactic binding to be redefined.
Next: expander lexenv rib sealing, Previous: expander lexenv rib type, Up: expander lexenv rib [Index]