Exercise: Logical And

As an exercise now support a logical And. This can be done in the same fashion the logical Or was supported:

  • The grammar update is provided and based on the C grammar.

  • Define an enum constant EK_LOGICAL_AND for the corresponding expression kind in expr.h

  • Support constant folding by adapting constFoldBinary() in expr.c.

  • Adapt functions loadExpr() and condJmpExpr() in expr.c

  • Adapt function printExprNode() in expr.c

For code generation the most relevant part will be condJmpExpr()`. And again, considering flow charts for the two cases where either a "true label" or "false label" is provided describes pretty much how to implement the relevant cases.

Grammar Update

The precedence of the logical And is higher than the precedence of the logical Or. In the production rules of the grammar it shows up between the production rule for the logical Or expressions and equality expressions:

\[\begin{array}{rcl}\text{logical-or-expr} & = & \text{logical-and-expr}\; \{\; \texttt{"||"}\; \text{logical-and-expr} \} \\\text{logical-and-expr} & = & \text{equality-expr}\; \{\; \texttt{"&&"}\; \text{equality-expr} \} \\\text{equality-expr} & = & \text{relational-expr}\; \{\; (\; \texttt{"=="}\; |\; \texttt{"!="}\; )\; \text{relational-expr} \} \\\text{relational-expr} & = & \text{additive-expr}\; \{\; (\; \texttt{">"}\; |\; \texttt{"<"}\; |\; \texttt{">="}\; |\; \texttt{"<="}\; )\; \text{additive-expr} \} \\\text{additive-expr} & = & \text{multiplicative-expr}\; \{\; (\; \texttt{"+"}\; |\; \texttt{"-"}\; )\; \text{multiplicative-expr} \} \\\text{multiplicative-expr} & = & \text{unary-expr}\; \{\; (\; \texttt{"*"}\; |\; \texttt{"/"}\; |\; \texttt{"%"} )\; \text{unary-expr} \} \\\end{array}\]

As before the same precedence level as in C can be used:

Precedence

Operators

Meaning

13

* (multiply)

/ (divide)

% (modulo)

Multiplicative

12

+ (add)

- (subtract)

Additive

10

< (less)

> (greater)

<= (less equal)

>= (greater equal)

Relation

9

==

!=

Equality

Inequality

5

&&

Logical And

4

||

Logical Or

Code Generation

Again we have to distinguish two cases. First the case that the jump should take place if the condition is true:

Flow chart for the logical And conjunction:

Flow chart with child nodes of the logical And conjunction:

And the case that the jump should take place if the condition is false:

Flow chart for the logical And conjunction:

Flow chart with child nodes of the logical And conjunction:

Tests

Here some simple test:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
$< 1 && 2;
$< 1 && 0;
$< 0 && 1;

$> a;
$> b;

x = a && (a = a + 1);
$< x;
$< a;

x = a && a + b > 0 && a + b < 10;
$< x;

x = a == 42 || a + b > 0 && a + b < 10;
$< x;

And here a test run:

theon$ make logical_and
../xtest_abc logical_and.s < logical_and.abc
../../../ulm-generator/1_ulm_build/stack/ulmas logical_and.s getuint64.s printuint64.s
(echo "#! ../../../ulm-generator/1_ulm_build/stack/ulm"; cat a.out) > logical_and
rm -f a.out
chmod +x logical_and
theon$ echo "3 4" | ./logical_and
1
0
0
1
4
1
1
theon$ echo "0 4" | ./logical_and
1
0
0
0
0
0
1
theon$ echo "7 4" | ./logical_and
1
0
0
1
8
0
0
theon$ echo "42 4" | ./logical_and
1
0
0
1
43
0
0
theon$ 

Here some test for short-circuit evaluation for the logical And:

1
2
3
4
5
$> a;

x = a && (a = a + 1);
$< x;
$< a;

Only when a is non-zero it gets incremented:

theon$ make logical_and_sce
../xtest_abc logical_and_sce.s < logical_and_sce.abc
../../../ulm-generator/1_ulm_build/stack/ulmas logical_and_sce.s getuint64.s printuint64.s
(echo "#! ../../../ulm-generator/1_ulm_build/stack/ulm"; cat a.out) > logical_and_sce
rm -f a.out
chmod +x logical_and_sce
rm logical_and_sce.s
theon$ echo "1" | ./logical_and_sce
1
2
theon$ echo "0" | ./logical_and_sce
0
0
theon$ 

Here the generated logical-and-sce.pdf for the expression trees in the program.