CMPU-331 Compilers (Spring 2019)

Overview

There is a lot to do in this phase.

  1. You must implement twelve semantic actions. These actions are responsible for processing simple expressions in Vascal code.
    (Actions 31, 31, 40, 41, 42, 43, 44, 45, 46, 48, 55 and 56.)
  2. You will also begin using the Quadruple class. This class stores the intermediate code as it is generated during parsing.
  3. New, helper functions will be created which the semantic actions will use during code processing and generation.
  4. You must also make updates to existing components.

Resources

Augmented Grammar

Semantic Actions Phase II

Quadruple and Quadruples Classes

The Quadruple class stores lines of intermediate code as it is generated. The Quadruples (or Quadruple Store) class stores and manages the quadruples. It also has a function to dump its current contents to screen.

Sample code is available here.

Sample Code

Sample .VAS files are available for you to test your code on, together with .TVI files for you to compare against.

Please use only Phase 2 code samples which have the _ns suffix: this indicates that there are no array variables in the code, which is not yet handled.

Sample code for Phase II.

IMPORTANT NOTE

The address numbers in your code may differ from the ones in this sample code. This depends on the precise order in which they are generated. Of primary importance are the numbers for the alloc command, and that the address numbers refer to the correct symbols.

Requirements

1. Quadruple and Quadruples Classes

Implement the Quadruple and Quadruples classes to store intermediate code.

2. Typecheck() Function

The Typecheck(x, y) function compares the types of two variables whose identifiers are specified in x and y. It outputs an integer result as shown in the table below.

x y out
int int 0
real real 1
real int 2
int real 3

The data types can be found by accessing the appropriate fields of the symbol table.

3. Create() Function

Create() is used to create a new variable. This is almost always (note 'almost') a temporary variable. More information can be found on the specification page.

To make sure each temporary variable is distinct, I suggest creating a member variable for the SemanticActions class, initialised to zero. Each time you create a temporary variable, you can get a unique ID by appending the value of this member variable to some string, then increment the variable.

GetTempVar() Function

I might suggest having a helper function whose only purpose is to create temporary variable names. This will reduce code duplication, and thus the opportunities for bugs.

4. Gen() Function

Gen() is used to create the intermediate code. It takes one, two, three or four parameters and instantiates a new quadruple to store them. It is also responsible for performing lookup of the location in memory (global or local) of any specified identifiers.

Please read the appropriate section of the specifications document, as it covers this function very fully.

5. Update Existing Actions

You should update actions 3 and 9 as indicated.

Action 3

If this action does not already handle local memory, you must update it so that it can.

Action 9

You must add code to generate a piece of 'stub code', which is responsible for calling entry point MAIN in our Vascal code. It should look something like this:

generate(“call”, “main”, “0”);
generate(“exit”);

6. Backpatch() Function

The Backpatch() function is an extremely important one. While moving forward through the Vascal code we must often generate a line of intermediate code at a specific point; however, we may not have all the information we need at that time. A good example of this is variable assignment: allocating memory is the first instruction in a function, but at that point we don't know for how many variables we must assign space.

To deal with this, we generate a line of code where we must but we use a placeholder symbol, such as _, to indicate that there is missing data. We do not simply leave the field empty. When it is possible to do so we can then replace the placeholder with the correct value. This is backpatching.

Create a Backpatch() function as described in the specifications document.

7. GlobalStore and LocalStore Variables

We need to keep track of where we create instructions to allocate memory. These are extremely important. The GlobalStore and LocalStore variables keep track of these. These will be used with the Backpatch() function.

The actual names are not prescribed: you may choose whatever name you like, as long you can remember it and I can understand it when grading. :-)

8. Semantic Action Routines

  1. Implement semantic actions 55 and 56.
  2. Implement actions 30, 40, 42 and 44.
  3. Implement actions 31, 41, 46 and 48.
  4. Implement actions 43 and 45.

Submission