Section 6.6.3 of the dragon book (Compilers: Principles, Techniques, and Tools 2nd Edition) describes how to translate the flow-of-control statements like if
/if-else
/while
into intermediate code.
For example,
The translation of
if (B) S1
consists ofB.code
followed byS1.code
. WithinB.code
are jumps based on the value ofB
. IfB
is true, control flows to the first instruction ofS1.code
, and ifB
is false, control flows to the instruction immediately followingS1.code
.
The labels for the jumps in
B.code
andS.code
are managed using inherited attributes. With a boolean expressionB
, we associate two labels:B.true
, the label to which control flows ifB
is true, andB.false
, the label to which control flows ifB
is false. With a statementS
, we associate an inherited attributeS.next
denoting a label for the instruction immediately after the code forS
.
I understand the translation. It lets B
to generate the goto
jumps based on the value of B
. Since B
itself does not know where to jump. Therefore, we associate it with two inherited attributes B.true
and B.false
, which are provided by the node S
.
I am wondering is this translation unnecessarily complicated? Why do not let S
generate the branch
instruction based on the value of B
. Similary, is the inherited attribute S.next
necessary?
I find an answer in Section 7.4.1 of the book "Engineering a Compiler (2nd Edition)":
Traditionally, two representations have been proposed for boolean values: a numerical encoding and a positional encoding. The former assigns specific values to true and false and manipulates them using the target machine’s arithmetic and logical operations. The latter approach encodes the value of the expression as a position in the executable code. It uses comparisons and conditional branches to evaluate the expression; the different control-flow paths represent the result of evaluation. Each approach works well for some examples, but not for others.
The dragon book uses the positional encoding.