In November 2003, I was implementing a (toy) compiler and a Web content management system at the same time. I came up with an idea I think I should write down so I don’t forget it. (At the time, the idea was considered an overkill for the administrative UI of our content management system, so it was not implemented.)
As described in Modern Compiler Implementation in Java (2nd
ed.) by Andrew W. Appel, a given piece of AST can occur in
three major roles: as an expression, as a statement or as an
expression which evaluates to a jump conditional. The crux of the
matter is that the most efficient intermediate language
representation depends on the context in which the piece of AST
occurs. For example, it is more efficient to translate a comparison
expression in an if
condition directly to a jump than to
translate to an expression that concretely yields a boolean value and
a jump based on comparing that value to zero.
Let us consider the expression (expr1 < expr2).
If that expression occurred alone as a statement (which does not make
lot of sense but is allowed in many programming languages), one would
need to evaluate expr1 and expr2 for side
effects but the value of the comparison would be of no interest and
does not need to be computed. If, however, the expression occured as
the condition of an if
statement or a while
statement, one would still not generate intermediate language code
for computing the boolean value of the comparison but instead would
generate intermediate code that jumps on a less-than condition.
Finally, if the expression occured as the R-value of an assignment,
one would generate intermediate code that actually yields a boolean
value.
So the intermediate language subtree for given expression depends on the context of the expression. But what does this have to do with generating Web UIs?
Well, it turns out that the HTML markup needed for expressing a given logical part of a form depends on the context of that logical part. Let us consider a form input field and its label as a unit that replaces the less-than comparison of the previous example. A tree containing high-level nodes such as the encapsulation of a form field and its label takes the role of the AST and a generated DOM tree takes the role of the intermediate language tree.
If the field+label node occurred in a normal inline context, the
visitor doing translation to a DOM tree would merely call a method
returning a DOM DocumentFragment
with a label
element and an input
element. However, if the
field+label node occurred in a table context, the visitor would call
method returning a tr
element with two td
children and a label
element in the first td
and an input
element in the second td
.
Thus, different DOM representations would be generated for the same
high-level node depending on context, but the programmer putting
together the logical form would not worry about the distinction.