Online Book Reader

Home Category

Beautiful Code [288]

By Root 5183 0
are omitted for brevity, along with the meta environment, which plays no role here since we are not expanding any transformer expressions.

The let expression is recognized as a core form because let is present in the initial wrap and environment. The transformer for let recursively expands the righthand-side expression #t in the input environment, yielding #t. It also recursively expands the body with an extended wrap that maps x to a fresh label l1:

<(or #f t) [t x () l1]>

Substitutions are shown with enclosing brackets, the name and list of marks separated by the symbol x, and the label following a right arrow.

The environment is also extended to map the label to a binding of type lexical with the fresh name t.1:

l1 lexical(t.1)

The or form is recognized as a macro call, so the transformer for or is invoked, producing a new expression to be evaluated in the same environment. The input of the or transformer is marked with a fresh mark m2, and the same mark is added to the output, yielding:

<( (( #f))

( ))

m2>

The differences between the syntax objects representing the introduced identifier t and the identifier t extracted from the input are crucial in determining how each is renamed when the expander reaches it, which will be described shortly.

The #f appearing on the righthand side of the let is technically a syntax object with the same wraps as the occurrence of t extracted from the input, but the wrap is unimportant for constants, so we treat it, for the sake of simplicity, as if it were not wrapped.

We have another core let expression. In the process of recognizing and parsing the let expression, the mark m2 is pushed onto the subforms:

( (( #f))

<( )

m2>)

The transformer for let recursively expands the righthand-side expression #f, yielding #f, then recursively expands the body with an extended wrap mapping the introduced t with mark m2 to a fresh label l2:

<( )

[t x (m2) l2]

m2>

The environment is also extended to map the label to a binding of type lexical with the fresh name t.2:

l2 lexical(t.2), l1 lexical(t.1)

The resulting expression is recognized as an if core form. In the process of recognizing and parsing it, the expander pushes the outer substitution and marks onto the component parts. The mark m2 that already appears in the wrap for the last occurrence of t cancels the mark m2 on the outer wrap, leaving that occurrence of t unmarked:

(

)

The transformer for if recursively processes its subforms in the input environment. The first:

is recognized as an identifier reference because the expression is a symbol (t). The substitution appearing in the wrap applies in this case, since the name (t) and marks (m2) are the same. So the expander looks for l2 in the environment and finds that it maps to the lexical variable t.2. The second subform is the same and so also maps to t.2. The third, however, is different:

)

This identifier lacks the m2 mark, so the first substitution does not apply, even though the name is the same. The second does apply because it has the same name and the same set of marks (none beyond the top mark from the suppressed initial wrap). The expander thus looks for l1 in the environment and finds that it maps to t.1.

On the way out, the if expression is reconstructed as:

(if t.2 t.2 t.1)

The inner let expression is reconstructed as:

(let ([t.2 #f]) (if t.2 t.2 t.1))

And the outer let expression is reconstructed as:

(let ([t.1 #t]) (let ([t.2 #f]) (if t.2 t.2 t.1)))

which is exactly what we want, although the particular choice of fresh names is not important as long as they are distinct.

Syntactic Abstraction: The syntax-case Expander > Conclusion

25.4. Conclusion

The simplified expander described here illustrates the basic

Return Main Page Previous Page Next Page

®Online Book Reader