===================== Exercise: Logical And [TOC] ===================== 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: ---- LATEX --------------------------------------------------------------------- \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) |Multiplicative | | | | | | | `/` (divide) | | | | | | | | `%` (modulo) | | +---------------+---------------------------------------+---------------+ | 12 | `+` (add) | Additive | | | | | | | `-` (subtract) | | +---------------+---------------------------------------+---------------+ | 10 | `<` (less) | Relation | | | | | | | `>` (greater) | | | | | | | | `<=` (less equal) | | | | | | | | `>=` (greater equal) | | +---------------+---------------------------------------+---------------+ | 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: ---- TIKZ -------------------------------------------------------------------- \begin{tikzpicture} \input{flowchart.tex} \SetMargin{1}{4}{0}{5.1} \renewcommand\BoxWidth { 5 } \PutStatement{0}{code before} \PutJump{1}{$C_1 \land C_2$} \PutStatement{2}{load 0 into \%dest} \PutJump{3}{} \PutStatement{4}{load 1 into \%dest} \PutStatement{5}{code after} \AddPath{0}{1} \AddPath{1}{2} \AddCondJumpPath{1}{4} \AddPath{2}{3} \AddPath{4}{5} \AddJumpPathLeft{3}{5} \end{tikzpicture} ------------------------------------------------------------------------------ + Flow chart with child nodes of the logical And conjunction: ---- TIKZ -------------------------------------------------------------------- \begin{tikzpicture} \input{flowchart.tex} \SetMargin{1}{1}{0}{5.1} \renewcommand\BoxWidth { 5 } \PutStatement{0}{code before} \PutJump{1}{$C_1$} \PutJump{2}{$C_2$} \PutStatement{3}{load 0 into \%dest} \PutJump{4}{} \PutStatement{5}{load 1 into \%dest} \PutStatement{6}{code after} \AddPath{0}{1} \AddPath{1}{2} \AddPath{2}{3} \AddCondJumpPathLeftAlt{1}{3} \AddCondJumpPath{2}{5} \AddPath{3}{4} \AddPath{5}{6} \AddJumpPathLeft{4}{6} \end{tikzpicture} ------------------------------------------------------------------------------ And the case that the jump should take place if the condition is false: + Flow chart for the logical And conjunction: ---- TIKZ -------------------------------------------------------------------- \begin{tikzpicture} \input{flowchart.tex} \SetMargin{1}{4}{0}{5.1} \renewcommand\BoxWidth { 5 } \PutStatement{0}{code before} \PutJump{1}{$C_1 \land C_2$} \PutStatement{2}{load 1 into \%dest} \PutJump{3}{} \PutStatement{4}{load 0 into \%dest} \PutStatement{5}{code after} \AddPath{0}{1} \AddPath{1}{2} \AddCondJumpPathAlt{1}{4} \AddPath{2}{3} \AddPath{4}{5} \AddJumpPathLeft{3}{5} \end{tikzpicture} ------------------------------------------------------------------------------ + Flow chart with child nodes of the logical And conjunction: ---- TIKZ -------------------------------------------------------------------- \begin{tikzpicture} \input{flowchart.tex} \SetMargin{1}{1}{0}{5.1} \renewcommand\BoxWidth { 5 } \PutStatement{0}{code before} \PutJump{1}{$C_1$} \PutJump{2}{$C_2$} \PutStatement{3}{load 1 into \%dest} \PutJump{4}{} \PutStatement{5}{load 0 into \%dest} \PutStatement{6}{code after} \AddPath{0}{1} \AddPath{1}{2} \AddPath{2}{3} \AddCondJumpPathAlt{1}{5} \AddCondJumpPathAlt{2}{5} \AddPath{3}{4} \AddPath{5}{6} \AddJumpPathLeft{4}{6} \end{tikzpicture} ------------------------------------------------------------------------------ Tests ===== Here some simple test: ---- CODE (file=session26/git/abc_step5/examples/logical_and.abc) -------------- $< 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: ---- SHELL (path=session26/git/abc_step5/examples/) ---------------------------- make logical_and echo "3 4" | ./logical_and echo "0 4" | ./logical_and echo "7 4" | ./logical_and echo "42 4" | ./logical_and -------------------------------------------------------------------------------- Here some test for __short-circuit evaluation__ for the logical And: ---- CODE (file=session26/git/abc_step5/examples/logical_and_sce.abc) ---------- $> a; x = a && (a = a + 1); $< x; $< a; -------------------------------------------------------------------------------- Only when ``a`` is non-zero it gets incremented: ---- SHELL (path=session26/git/abc_step5/examples/) ---------------------------- make logical_and_sce echo "1" | ./logical_and_sce echo "0" | ./logical_and_sce -------------------------------------------------------------------------------- ---- SHELL (path=session26/git/abc_step5, hide) -------------------------------- ./xtest_abc foo.s logical-and-sce.tex < examples/logical_and_sce.abc lualatex logical-and-sce.tex cp logical-and-sce.pdf /home/www/htdocs/numerik/hpc/ss22/hpc0/session26/ -------------------------------------------------------------------------------- Here the generated __logical-and-sce.pdf__ for the expression trees in the program. :links: short-circuit evaluation -> https://en.wikipedia.org/wiki/Short-circuit_evaluation logical-and-sce.pdf -> https://www.mathematik.uni-ulm.de/numerik/hpc/ss22/hpc0/session26/logical-and-sce.pdf