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.
I am providing you with a file, Semantics.java
,
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 Semantics.java
.
You can add break
and continue
statements
to Semantics.java
, 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.
You can add the float
type to to
Semantics.java
, 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.
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.
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.
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.
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.
Please turn in a printout of your final version of
Semantics.java
as well as any new files that you added.
You need not turn in the prior files, even if you modified them.