Answers to Self-Study Questions

Test Yourself #1

Question 1

public void codeGen(PrintWriter p) {
  String falseLab = newLabel();
  myExp.codeGen();
  p.println("ifeq " + flaseLab);    // pop 1 value; if 0 (false) goto FLab
  myTrueVarDeclOrStmtList.codeGen(p);
  p.println(flaseLab + ":");
}

Question 2

  1. LoopLabel:
  2. Evaluate the condition, leaving the value on the stack.
  3. Pop the top-of-stack value and see if it's zero; if zero, jump to DoneLab
  4. Code for the statements in the body of the loop.
  5. Goto LoopLabel
  6. DoneLabel:

Test Yourself #2

The OrNode's genJumpCode method has two String parameters, TrueLab and FalseLab. Here is the form of the code it generates:

    code to evaluate the left operand, jumping to TrueLab if true, else to L1
L1: code to evaluate the right operand, jumping to TrueLab if true, else to FalseLab
Here is a high-level version of the code that would be generated for the statement if (a || b>0) { ... }:
   // code generated by the IdNode for a
    push a's value
    pop; if zero goto L1
    goto TrueLab
  L1:               // label generated by the OrNode
   // code generated by the GreaterNode
    push b's value
    push 0
    pop 2 values; if > goto TrueLab
    goto FalseLab
   TrueLab:         // label generated by the IfStmtNode
    -- code for the stmts in the if, generated by the IfStmtNode --
   FalseLab:        // label generated by the IfStmtNode

Test Yourself #3

How does the code generated for an OrNode using the control-flow method compare to the code generated using the numeric method? Below are outlines of the code generated in each case. Remember that for the control-flow approach, TrueLab and FalseLab are parameters of the genJumpCode method, and L1 is created and generated by the code for the OrNode. For the numeric approach, both FalseLab and DoneLab are created and generated by the code for the OrNode.

   Numeric Code                           Control-Flow Code
   ------------                           -----------------
   -- code to evaluate left operand,      -- code to evaluate left operand,
   -- leaving the value on the stack      -- with jumps to TrueLab and L1

   pop; if zero goto FalseLab             L1:
   push 1
   goto DoneLab
FalseLab:

   -- code to evaluate right operand,     -- code to evaluate right operand,
   -- leaving the value on the stack      -- with jumps to TrueLab and FalseLab
DoneLab:
As was the case for the AndNode, the numeric code includes 3 instructions in addition to the ones generated to evaluated the two operands, while the control-flow approach generates no additional instructions (just the ones generated for the two operands). Only when an operand is a boolean variable is the control-flow code for the operand worse than the numeric approach.