(Xfig Source and PDF version of diagram available.)
This section shows how the Perl program from Figure 3.3 (the ``add and print'' example) is compiled to Kawa's IR. Figure 5.1 shows a diagram representing how the ``add and print'' example is compiled to Kawa's IR.
The top-level Perl package is compiled to a ModuleExp. Contained by that ModuleExp are two Declaration objects for the two scalar variables used in the program.
The ModuleExp contains one subexpression, a BeginExp. A BeginExp is used to organize a set of subexpressions, and evaluate them for their side effects.
One such subexpression is the ApplyExp. This expression is a generalized way to evaluate a function. The functions can be existing LambdaExps, or, as in this case, a reference to some known procedure. In this case, we refer to a PrimProcedure object, which simply refers to a known function that is written in Java. However, an ApplyExp can just as easily refer to unnamed functions compiled by Kawa, or named functions written in Perl or Scheme. This flexibility is a great advantage over other methods for compiling non-Java languages to the JVM.
Another particularly flexible mechanism is variable binding. The SetExp is used to set a variable to a particular value. Each SetExp refers to some variable. However, the binding of that variable need not be specified directly. The variable is looked up by Kawa in the current context. Thus, worrying about how the variable is bound is left up to the IR. The compiler from perl's IR to Kawa's IR need not specifically worry about that issue.
The complement to the SetExp is the RefExp. A RefExp refers back to a variable so its value can be used as an r-value. It should be noted that while in this example, we are dealing only with simple scalars, these expressions can be used to solve the issues with Perl's tie. Kawa has a binding mechanism, whereby variable declarations can have particular constraints associated with their use. SetExps and RefExps are evaluated or compiled with references to these constraint objects. At runtime, the constraint objects are resolved. In this manner, JVM code can automatically be generated to handle complex variable access mechanisms, such as exist with Perl's tie.
Through this example, Kawa's flexibility is clear. The direct compilation method discussed in Chapter 4 failed because it attempted to compile from perl's IR to a very low level JVM interface--the Jasmin assembler. The perl IR can be massaged much more easily into Kawa's IR, because Kawa provides higher level semantic concepts and an infrastructure for compilation.
Copyright © 2000, 2001 Bradley M. Kuhn.
Verbatim copying and distribution of this entire thesis is permitted in any medium, provided this notice is preserved.