Homework: Program Code Generator

This homework is necessary preparation for the lab. Make sure you type your code and you bring the file to the lab so that you will not have to waste time entering your code during the lab.

The contract for generateCodeForStatement is informal and vague. The details of the code to generate for each kind of statement are provided in the Code Generation slides (39-47, in particular). The code generated by your implementation must match the code-generation patterns described in the slides.

  1. First, assume you are given an implementation for the following static method. (In lab you will be given an implementation.)

    /**
     * Converts {@code Condition} into corresponding conditional jump
     * instruction byte code.
     *
     * @param c
     *            the {@code Condition} to be converted
     * @return the conditional jump instruction byte code corresponding to {@code c}
     * @ensures <pre>
     * conditionalJump =
     *  [conditional jump instruction byte code corresponding to c]
     * </pre>
     */
    private static Instruction conditionalJump(Condition c) {...}
    

    Using recursion and the conditionalJump method above, complete the body of the generateCodeForStatement static method below. Use the code for the case IF as a guide for the other cases.

    /**
     * Generates the sequence of virtual machine instructions ("byte codes")
     * corresponding to {@code s} and appends it at the end of {@code cp}.
     *
     * @param s
     *            the {@code Statement} for which to generate code
     * @param context
     *            the {@code Context} in which to find user defined instructions
     * @param cp
     *            the {@code Sequence} containing the generated code
     * @updates cp
     * @ensures <pre>
     * if [all instructions called in s are either primitive or
     *     defined in context]  and
     *    [context does not include any calling cycles, i.e., recursion] then
     *  cp = #cp * [sequence of virtual machine "byte codes" corresponding to s]
     * else
     *  [reports an appropriate error message to the console and terminates client]
     * </pre>
     */
    private static void generateCodeForStatement(Statement s,
            Map<String, Statement> context, Sequence<Integer> cp) {
    
        final int dummy = 0;
    
        switch (s.kind()) {
            case BLOCK: {
    
                // TODO - fill in case
    
                break;
            }
            case IF: {
                Statement b = s.newInstance();
                Condition c = s.disassembleIf(b);
                cp.add(cp.length(), conditionalJump(c).byteCode());
                int jump = cp.length();
                cp.add(cp.length(), dummy);
                generateCodeForStatement(b, context, cp);
                cp.replaceEntry(jump, cp.length());
                s.assembleIf(c, b);
                break;
            }
            case IF_ELSE: {
    
                // TODO - fill in case
    
                break;
            }
            case WHILE: {
    
                // TODO - fill in case
    
                break;
            }
    
            // case CALL will go here
    
            default: {
                // nothing to do here: this will never happen...
                break;
            }
        }
    }
    

Additional Questions

  1. Complete the case CALL in generateCodeForStatement.

  2. Complete the body of the generatedCode instance method for the Program component. To generate code for a given Program (this) you need to generate code for the body of the program and append a HALT instruction at the end of that. this must be restored.

    /**
     * Generates and returns the sequence of virtual machine instructions
     * ("byte codes") corresponding to {@code this}.
     *
     * @return the compiled program
     * @ensures <pre>
     * if [all instructions called in this are either primitive or
     *     defined in this.context]  and
     *    [this does not include any calling cycles, i.e., recursion] then
     *  generatedCode =
     *   [the sequence of virtual machine "byte codes" corresponding to this]
     * else
     *  [reports an appropriate error message to the console and terminates client]
     * </pre>
     */
    public Sequence<Integer> generatedCode();