HANDBOOK / CASE STUDY / The Compiler /

# Translating Statements

Here is the specification for translating statements:

    179  'action' Statement(Stmt: STMT)
    180     'rule' Statement(assign(V, E, Pos)) :
    181        Designator(V -> TV)
    182        Expression(E -> TE)
    183        Assign(TV, TE, Pos)
    184     'rule' Statement(read(V, Pos)) :
    185        Designator(V -> T)
    186        CheckSimple(T, Pos)
    187        TypeCode(T -> N)
    188        REA(N)
    189        STI
    190     'rule' Statement(write(E, Pos)) :
    191        Expression(E -> T)
    192        CheckSimple(T, Pos)
    193        TypeCode(T -> N)
    194        WRI(N)
    195     'rule' Statement(call(Ident, Actuals, Pos)) :
    196        Apply(Ident, Pos -> Obj)
    197        CheckProcedure(Obj, Pos -> Formals, Level, Start)
    198        GetCurrentNesting(-> CurLev)
    199        MST(CurLev-Level)
    200        ParamList(Formals, Actuals  -> Size)
    201        JSR(Size, Start)
    202     'rule' Statement(if(E, S1, S2, Pos)) :
    203        Expression(E -> T)
    204        CheckBool(T, Pos)
    205        NewLabel(-> L1)
    206        NewLabel(-> L2)
    207        FJP(L1)
    208        Statement(S1)
    209        JMP(L2)
    210        LAB(L1)
    211        Statement(S2)
    212        LAB(L2)
    213     'rule' Statement(while(E, S, Pos)) :
    214        NewLabel(-> L1)
    215        NewLabel(-> L2)
    216        JMP(L2)
    217        LAB(L1)
    218        Statement(S)
    219        LAB(L2)
    220        Expression(E -> T)
    221        CheckBool(T, Pos)
    222        INV
    223        FJP(L1)
    224     'rule' Statement(seq(S1, S2)) :
    225        Statement(S1)
    226        Statement(S2)

    227  'action' Assign(LhsType: TYPE, RhsType: TYPE, Pos: POS)
    228     'rule' Assign(integer, integer, Pos) : STI
    229     'rule' Assign(real, integer, Pos) : FLT STI
    230     'rule' Assign(real, real, Pos) : STI
    231     'rule' Assign(boolean, boolean, Pos) : STI
    232     'rule' Assign(T1, T2, Pos) :
    233        Error("Invalid types in assignment", Pos)

    234  'action' ParamList(Formals: DECLLIST, Actuals: EXPRLIST
    235           -> Size: INT)
    236     'rule' ParamList(decllist(dcl(Id,D,_), Fs), exprlist(E,Es,Pos)
    237            -> S+1) :
    238        Param(D, E, Pos)
    239        ParamList(Fs, Es -> S)
    240     'rule' ParamList(nil, nil -> 0)
    241     'rule' ParamList(decllist(D, Fs), nil(Pos) -> 0) :
    242        Error("Too few actual parameters", Pos)
    243     'rule' ParamList(nil, exprlist(E, Es, Pos) -> 0) :
    244        Error("Too many actual parameters", Pos)

    245  'action' Param(Formal: DEF, Actual: EXPR, Pos: POS)
    246     'rule' Param(valueparam(FType), Actual, Pos) :
    247        Expression(Actual -> AType)
    248        CheckEquiv(FType, AType, Pos)
    249     'rule' Param(varparam(FType), Actual, Pos) :
    250        CheckDesignator(Actual, Pos -> D)
    251        Designator(D -> AType)
    252        CheckEquiv(FType, AType, Pos)

`Statement`

The predicate `Statement(Stmt)` analyzes and translates statements. For each alternative of the abstract syntax, there is a separate rule.

As an example, consider the treatment of if-statements that are represented by

       if(E, S1, S2, Pos)

The code for this construct is

       code for expression E
       FJP(L1)
       code for statement S1
       JMP(L2)
       LAB(L1)
       code for statement S2
       LAB(L2)

where `L1` and `L2` are two unique labels. First, the expression is evaluated. If this yields false, the `FJP` instruction jumps to `L2`. Otherwise, the statement `S1` is executed. After that, we jump over the code for `S2`. The code for `S2` is preceded by a label `S2`, which is the target of `FJP`.

New labels are created by `NewLabel`. The predicate `Expression` not only generates codes for its argument `E`, but also computes the type `T` of `E`. In an if-statement this type must be `bool`. This is checked by `CheckBool`.

Hence, the rule for `if` is

    'rule' Statement(if(E, S1, S2, Pos)) :
       Expression(E -> T)
       CheckBool(T, Pos)
       NewLabel(-> L1)
       NewLabel(-> L2)
       FJP(L1)
       Statement(S1)
       JMP(L2)
       LAB(L1)
       Statement(S2)
       LAB(L2)

An assignment

       assign(V, E, Pos)

is compiled into code for the designator `V` and code for the expression `E`.

After evaluation of these code sequences, the stack top comprises the address given by `V` and the value of `E`. An instruction `STI` is used to store the value at the given address and to remove the two items from the stack. The types `TV` and `TE` of `V` and `E` must be equal and scalar. In addition, `TV` may be real and `TE` may be int. Then the `STI` must be preceeded by an `FLT` instruction. This check and the generation of `FLT` and `STI` are expressed by the predicate `Assign`.

The code for a procedure call is

       MST(CurLev-Level)
       code for parameters
       JSR(Size, Start)

where `CurLev` is the current nesting level and the procedure has been declared at level `Level` and with start label `Start`. The code for parameters is generated by `ParamList`.

`Assign`

`Assign(LhsType, RhsType, Pos)` checks whether a value of type `RhsType` can be assigned to a designator of type `LhsType`. If so, it emits the corresponding instruction(s).

`ParamList`

The code for parameter passing is constructed by the predicate `ParamList(Formals, Actuals -> Size)` which processes the lists of formal and actual parameters in parallel.

`Param`

A pair of formal and actual parameters is handled by `Param(Formal, Actual, Pos)`.