This step is simple to express:
implement a type-checker for MiniJava according to the type system
definition you have developed as your
fourth
homework assignment. The distinct activities that
constitute this task are:
- Definition of a suitable representation for types. A particular
method that needs to be
supported is an equality-test on types. The existing abstract syntax
classes that implement
types may be used, but they will need to be complemented in order to
support equality.
- Definition of a flexible structure for representing environments.
A linked list approach is
recommended, but there are many variations to this theme. Moreover, the
difference
between looking up a variable identifier and class identifier needs to
be captured in some
appropriate manner.
- Definition of abstract methods in classes like Exp and Statement
that correspond to the
respective typing judgment, as well as implementation of these methods
in every concrete
class of the abstract syntax hierarchy.
- Addition of some form of source file position information to the
abstract syntax tree, so that
type errors can be adequately reported. One way of doing that is to
modify the lexer so that the
semantic information returned for a keyword or separator symbol is its file position, and then to
attach that information to selected parts of the syntax tree as it is
constructed by the parser.
Now we've come to the point when it's time to generate executable code
for validated MiniJava
programs. This is the final mandatory step of the programming project,
but it can be implemented
with varying levels of ambition:
- The basic option is to implement a code generator that
corresponds to the E1 and S1
schemes you have constructed as part of homework assignment 5. This implies using
the stack for all intermediate values, and a very naive technique for
implementing
the conditionals in if- and while-statements.
- As a more refined, but still very basic attempt, the context
sensitive compilation schemes
branchTrue and branchFalse from lecture 10 (pp 47-53) can be added to the
previous
implementation to improve the handling of if and while conditionals.
- Add a simple register allocator for temporaries, by implementing
the stack simulation
described in the slides for lecture 10.
Apart from that, this option is like no. 2 above.
Please note that the enumerated alternatives is a menu of choices, you
are not supposed to complete
more than one of these tasks.
The Pentium-based server
tau10.sm.luth.se
is available for testing the output from your
compiler. The server is running Linux with your personal directories
mounted, and you can log on
using your ordinary username and password.
A note regarding code generation: The Linux calling convention for the
IA32 treats register ebx
as callee saves, and the others as the caller's responsibility. That
means that your method prologue/
epilogue must push/pop ebx if it is used at all within the function.
Other registers must be saved
during method calls only if their values are used after the call. For
more information regarding
assembly language programming for IA32 under Linux, see this
online
book, in particular
appendices B, C and F.