Next: , Previous: , Up: expander lexenv rib   [Index]


15.3.1.2 Extending rib objects

A 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.

Redefining or shadowing syntactic bindings

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: , Previous: , Up: expander lexenv rib   [Index]