Add support for the case
statement. It has the following syntax:
\( \; \; \; \; \texttt{case} \; \textit{expression}_0 \; \texttt{\{} \)
\( \; \; \; \; \; \; \; \; \texttt{when} \; \textit{expression}_1 \; \texttt{\{}\)
\( \; \; \; \; \; \; \; \; \; \; \; \; \textit{statements}_1 \)
\( \; \; \; \; \; \; \; \; \texttt{\}} \)
\( \; \; \; \; \; \; \; \; \texttt{when} \; \textit{expression}_2 \; \texttt{\{}\)
\( \; \; \; \; \; \; \; \; \; \; \; \; \textit{statements}_2 \)
\( \; \; \; \; \; \; \; \; \texttt{\}} \)
\( \; \; \; \; \; \; \; \; \vdots \)
\( \; \; \; \; \; \; \; \; \texttt{when} \; \textit{expression}_n \; \texttt{\{}\)
\( \; \; \; \; \; \; \; \; \; \; \; \; \textit{statements}_n \)
\( \; \; \; \; \; \; \; \; \texttt{\}} \)
\( \; \; \; \; \; \; \; \; \texttt{else} \; \texttt{\{}\)
\( \; \; \; \; \; \; \; \; \; \; \; \; \textit{statements}_{n+1} \)
\( \; \; \; \; \; \; \; \; \texttt{\}} \)
\( \; \; \; \; \texttt{\} } \)
The case
statement can have zero or more when
clauses. The else
clause is optional, but must go at the end if present.
The case
statement described above is equivalent to:
\( \; \; \; \; \texttt{if} \; \textit{expression}_0 \; \texttt{==} \; \textit{expression}_1 \texttt{\{} \; \)
\( \; \; \; \; \; \; \; \; \textit{statements}_1 \)
\( \; \; \; \; \texttt{\} } \)
\( \; \; \; \; \texttt{else if} \; \textit{expression}_0 \; \texttt{==} \; \textit{expression}_2 \; \texttt{\{} \; \)
\( \; \; \; \; \; \; \; \; \textit{statements}_2 \)
\( \; \; \; \; \texttt{\} } \)
\( \; \; \; \; \vdots \)
\( \; \; \; \; \texttt{else if} \; \textit{expression}_0 \; \texttt{==} \; \textit{expression}_n \; \texttt{\{} \; \)
\( \; \; \; \; \; \; \; \; \textit{statements}_n \)
\( \; \; \; \; \texttt{\} } \)
\( \; \; \; \; \texttt{else \{} \; \)
\( \; \; \; \; \; \; \; \; \textit{statements}_{n+1} \)
\( \; \; \; \; \texttt{\} } \)
Make sure to consider case
and when
as Delta reserved keywords from now on.
The Delta program:
var x, y; x = 3; y = 0; case x { when 1 { y = 10; } when 2 { y = 20; } when 3 { y = 30; } else { y = 40; } } y
should produce the following WAT code:
(module (func (export "_start") (result i32) (local $x i32) (local $y i32) i32.const 3 local.set $x i32.const 0 local.set $y local.get $x i32.const 1 i32.eq if i32.const 10 local.set $y else local.get $x i32.const 2 i32.eq if i32.const 20 local.set $y else local.get $x i32.const 3 i32.eq if i32.const 30 local.set $y else i32.const 40 local.set $y end end end local.get $y ) )
The above WAT function’s return value should be:
30
# File: tests/test_21_case.py from unittest import TestCase from delta import Compiler, SyntaxMistake from delta.semantics import SemanticMistake class TestCaseWhen(TestCase): def setUp(self): self.c = Compiler('program_start') def test_syntax_mistake(self): with self.assertRaises(SyntaxMistake): self.c.realize('case {}') def test_semantic_mistake(self): with self.assertRaises(SemanticMistake): self.c.realize('var case; 0') def test_case1(self): self.assertEqual(0, self.c.realize(''' var x; case 0 { } x ''')) def test_case2(self): self.assertEqual(0, self.c.realize(''' var x; case 0 { when 0 { } when 1 { } when 2 { } when 3 { } when 4 { } when 5 { } else { } } x ''')) def test_case3(self): self.assertEqual(1, self.c.realize(''' var x; case true { when true { x = 1; } when false { x = 2; } } x ''')) def test_case4(self): self.assertEqual(2, self.c.realize(''' var x; case false { when true { x = 1; } when false { x = 2; } } x ''')) def test_case5(self): self.assertEqual(40, self.c.realize(''' var x, y; x = 0; y = 0; case x { when 1 { y = 10; } when 2 { y = 20; } when 3 { y = 30; } else { y = 40; } } y ''')) def test_case6(self): self.assertEqual(0, self.c.realize(''' var x, y; x = 0; y = 0; case x { when 1 { y = 10; } when 2 { y = 20; } when 3 { y = 30; } } y ''')) def test_case7(self): self.assertEqual(30, self.c.realize(''' var x, y; x = 3; y = 0; case x { when 1 { y = 10; } when 2 { y = 20; } when 3 { y = 30; } else { y = 40; } } y ''')) def test_case8(self): self.assertEqual(333, self.c.realize(''' var x, y, z; x = 2; y = 4; z = 0; case x + y * z { when 3 - 2 { z = 100; } when 5 - 2 { z = 200; } when 1 + 1 { z = 300; case y - 1 { when x { y = y + 0; z = z + 10; } when x + 1 { y = y + 1; z = z + 10; } when x + 2 { y = y + 2; z = z + 20; } when x + 3 { y = y + 3; z = z + 30; } else { y = y + 4; z = z + 40; } } z = z + 18; } else { z = 400; } } y + z '''))