Compiler Design

Delta: An Incremental Compiler
Step 18: Or Logical Operator

Description

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

The OR operator has less precedence than the AND operator 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 1
    else
    i32.const 20
    if (result i32)
    i32.const 1
    else
    i32.const 30
    i32.eqz
    i32.eqz
    end
    end
  )
)

The above WAT function’s return value should be:

1

Unit Tests

# File: tests/test_18_or.py

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


class TestOr(TestCase):

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

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

    def test_or1(self):
        self.assertEqual(1,
                         self.c.realize('true || true'))

    def test_or2(self):
        self.assertEqual(1,
                         self.c.realize('true || false'))

    def test_or3(self):
        self.assertEqual(1,
                         self.c.realize('false || true'))

    def test_or4(self):
        self.assertEqual(0,
                         self.c.realize('false || false'))

    def test_or5(self):
        self.assertEqual(1,
                         self.c.realize('5 || 0 || 3 || 2'))

    def test_or6(self):
        self.assertEqual(0,
                         self.c.realize('0 || 0 || 0 || 0'))

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

    def test_or8(self):
        self.assertEqual(1,
                         self.c.realize('!!1 || !!2 || !!3'))

    def test_or9(self):
        self.assertEqual(1,
                         self.c.realize('3 * 4 || 8 - 4 * 2'))

    def test_or10(self):
        self.assertEqual(0,
                         self.c.realize('!(3 * 4) || 8 - 4 * 2'))

    def test_or11(self):
        self.assertEqual(1,
                         self.c.realize('''
                         var t, u;
                         t = false;
                         u = true;
                         !u || !t || u/t
                         '''))

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