Compiladores

Delta: An Incremental Compiler
Step 11: And Logical Operator

Description

Add support for the AND (&&) logical operator. This is an infix binary operator. It evaluates the second operand if and only if the first operand evaluates to true (any non-zero value). If the first operand evaluates to false (zero), the operator short-circuits and does not evaluate the second operand, as the overall result would already be false (zero). If both operands evaluate to true (any non-zero value) the overall result is true (one).

The AND operator has less precedence than all other operators and it associates from left to right.

Example

The Delta program:

10 && 20 && 30

should produce the following WAT code:

(module
  (func
    (export "_start")
    (result i32)
    i32.const 10
    if (result i32)
    i32.const 20
    if (result i32)
    i32.const 30
    i32.eqz
    i32.eqz
    else
    i32.const 0
    end
    else
    i32.const 0
    end
  )
)

The above WAT function’s return value should be:

1

Unit Tests

# File: tests/test_11_and.py

from unittest import TestCase
from delta import Compiler, SyntaxMistake
from wasmtime._trap import Trap


class TestAnd(TestCase):

    def setUp(self):
        self.c = Compiler('program')

    def test_syntax_mistake(self):
        with self.assertRaises(SyntaxMistake):
            self.c.realize('1 &&')

    def test_and1(self):
        self.assertEqual(1,
                         self.c.realize('true && true'))

    def test_and2(self):
        self.assertEqual(0,
                         self.c.realize('true && false'))

    def test_and3(self):
        self.assertEqual(0,
                         self.c.realize('false && true'))

    def test_and4(self):
        self.assertEqual(0,
                         self.c.realize('false && false'))

    def test_and5(self):
        self.assertEqual(1,
                         self.c.realize('1 && 2 && 3 && 4 && 5'))

    def test_and6(self):
        self.assertEqual(0,
                         self.c.realize('1 && 2 && 0 && 4 && 5'))

    def test_and7(self):
        self.assertEqual(0,
                         self.c.realize('!1 && !2 && !3'))

    def test_and8(self):
        self.assertEqual(1,
                         self.c.realize('!!1 && !!2 && !!3'))

    def test_and9(self):
        self.assertEqual(0,
                         self.c.realize('3 * 4 && 8 - 4 * 2'))

    def test_and10(self):
        self.assertEqual(1,
                         self.c.realize('3 * 4 && !(8 - 4 * 2)'))

    def test_and11(self):
        self.assertEqual(0,
                         self.c.realize('''
                         var t, u;
                         t = false;
                         u = true;
                         u && t && u/t
                         '''))

    def test_and_runtime_error(self):
        with self.assertRaises(Trap):
            self.c.realize('''
            var t, u;
            t = false;
            u = true;
            u && !t && u/t
            ''')