MCS-287 Lab 4: Interpretation (Spring 2006)

Due: May 15, 2006


In this lab, you will start with Tucker and Noonan's interpreter for Jay and build on it in at least three of the six ways described in the six sections that follow after the one devoted to the provided interpreter. (I hope to see you achieve more than three of the improvements.) Those sections are not listed in any particular order; you can tackle them as you please.

The provided interpreter

I am providing you with a file,, which is essentially the same as Tucker and Noonan have on their web site from Appendix B and Chapter 4. I updated it for Java Generics, made the overriding union operation on states act as a function rather than a mutator, and added a main so that it can be used as follows (once you compile it):

java Semantics someInputFile.jay

Assuming the input file can successfully be parsed and passes type checking, a command like that should give you one line of output displaying the final state. That is, the output shows the values of the variables once the program has completed. (Of course, the program could fail to terminate, in which case this output will not be produced.)

My hope is that this will compile correctly and just work when dropped in the directory with your files from the prior lab. However, depending on what you did in the prior labs, there is some possibility that you may need to tinker a bit. Don't worry (quite yet) if you included break, continue, and float in your prior lab; it is OK if initially the interpreter only works on programs that don't make use of these features. On the other hand, if you changed the type checker to use a check method instead of V, then you will need to correspondingly modify the main method in

Adding break and continue

You can add break and continue statements to, provided that you have added them to the scanner, parser, and type checker as described in the prior lab.

The M (meaning) procedure for these new types of statements should throw special exceptions, which are caught in the M procedure for loops. These exceptions will need to carry along the current state.

Adding float

You can add the float type to to, provided that you have added it to the scanner, parser, and type checker as described in the prior lab. The interaction of this type with int should correspond to the type checking rules described in the prior lab.

Using the Visitor pattern or AspectJ

As in the prior lab, the interpreter can be redesigned to make use of the Visitor pattern or AspectJ, rather than doing type dispatch with instanceof and casts.

Providing short-circuit evaluation

Change the && and || operators to use short-circuit evaluation. That is, arrange that expressions such as false && 3 == 3/0 don't cause divide-by-zero exceptions.

Signaling "can't happen" errors

Several procedures in the interpreter contain sequences of if statements that should exhaustively cover all possible cases. (For example, any Statement should be a Skip, an Assignment, a Conditional, a Loop, or a Block.) These procedures are designed so that if a bug causes this expectation to fail, the procedure will return null. That is a bad design, because it means the symptom of an failed assumption will be a NullPointerException elsewhere, rather than an error message directly pinpointing the trouble.

Modify all these procedures so that rather than returning null, they throw an Error that contains a message explaining what went wrong.

Interpreting loops by looping

The M method that interprets Loop statements does so by re-invoking itself however many times prove necessary. Rewrite this method so that it uses a Java while loop instead.

What you should turn in

Please turn in a printout of your final version of as well as any new files that you added. You need not turn in the prior files, even if you modified them.

Course web site:
Instructor: Max Hailperin <>