about summary refs log tree commit diff stats
path: root/js/baba-yaga/tests/with-when-expressions.test.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/baba-yaga/tests/with-when-expressions.test.js')
-rw-r--r--js/baba-yaga/tests/with-when-expressions.test.js158
1 files changed, 158 insertions, 0 deletions
diff --git a/js/baba-yaga/tests/with-when-expressions.test.js b/js/baba-yaga/tests/with-when-expressions.test.js
new file mode 100644
index 0000000..af14d10
--- /dev/null
+++ b/js/baba-yaga/tests/with-when-expressions.test.js
@@ -0,0 +1,158 @@
+import assert from 'assert';
+import { createLexer } from '../src/core/lexer.js';
+import { createParser } from '../src/core/parser.js';
+import { createInterpreter } from '../src/core/interpreter.js';
+
+function interpret(code) {
+  const lexer = createLexer(code);
+  const tokens = lexer.allTokens();
+  const parser = createParser(tokens);
+  const ast = parser.parse();
+  const interpreter = createInterpreter(ast);
+  interpreter.interpret();
+  return interpreter;
+}
+
+describe('with header: when expressions', () => {
+  it('evaluates simple single-line when expressions', () => {
+    const code = `
+      test : x ->
+        with (status : when x is 0 then "zero" _ then "other";) -> status;
+      result : test 0;
+    `;
+    const itp = interpret(code);
+    assert.strictEqual(itp.scope.get('result'), 'zero');
+  });
+
+  it('evaluates multi-line when expressions', () => {
+    const code = `
+      test : x ->
+        with (
+          status : when x is
+            0 then "zero"
+            _ then when (x < 10) is
+              true then "small"
+              _ then "large";
+        ) -> status;
+      result1 : test 0;
+      result2 : test 5;
+      result3 : test 15;
+    `;
+    const itp = interpret(code);
+    assert.strictEqual(itp.scope.get('result1'), 'zero');
+    assert.strictEqual(itp.scope.get('result2'), 'small');
+    assert.strictEqual(itp.scope.get('result3'), 'large');
+  });
+
+  it('evaluates complex when expressions with pattern guards', () => {
+    const code = `
+      test : x ->
+        with (
+          category : when x is
+            n if (n < 0) then "negative"
+            0 then "zero"
+            n if (n > 10) then "large"
+            _ then "small";
+        ) -> category;
+      result1 : test -5;
+      result2 : test 0;
+      result3 : test 5;
+      result4 : test 15;
+    `;
+    const itp = interpret(code);
+    assert.strictEqual(itp.scope.get('result1'), 'negative');
+    assert.strictEqual(itp.scope.get('result2'), 'zero');
+    assert.strictEqual(itp.scope.get('result3'), 'small');
+    assert.strictEqual(itp.scope.get('result4'), 'large');
+  });
+
+  it('evaluates mixed when expressions with other types', () => {
+    const code = `
+      test : x ->
+        with (
+          num : x + 1;
+          category : when x is
+            0 then "zero"
+            _ then when (x < 10) is
+              true then "small"
+              _ then "large";
+          isValid : x > 0;
+        ) -> { num: num, category: category, isValid: isValid };
+      result : test 5;
+    `;
+    const itp = interpret(code);
+    const result = itp.scope.get('result');
+    assert.strictEqual(result.num.value, 6);
+    assert.strictEqual(result.category, 'small');
+    assert.strictEqual(result.isValid, true);
+  });
+
+  it('evaluates deeply nested when expressions', () => {
+    const code = `
+      test : x ->
+        with (
+          status : when x is
+            0 then "zero"
+            _ then when (x < 10) is
+              true then "small"
+              _ then when (x < 100) is
+                true then "medium"
+                _ then when (x < 1000) is
+                  true then "large"
+                  _ then "huge";
+        ) -> status;
+      result1 : test 0;
+      result2 : test 5;
+      result3 : test 50;
+      result4 : test 500;
+      result5 : test 5000;
+    `;
+    const itp = interpret(code);
+    assert.strictEqual(itp.scope.get('result1'), 'zero');
+    assert.strictEqual(itp.scope.get('result2'), 'small');
+    assert.strictEqual(itp.scope.get('result3'), 'medium');
+    assert.strictEqual(itp.scope.get('result4'), 'large');
+    assert.strictEqual(itp.scope.get('result5'), 'huge');
+  });
+
+  it('works with arithmetic expressions in when conditions', () => {
+    const code = `
+      test : x ->
+        with (
+          status : when (x + 1) is
+            1 then "zero-based"
+            _ then when ((x * 2) > 10) is
+              true then "large"
+              _ then "small";
+        ) -> status;
+      result1 : test 0;
+      result2 : test 3;
+      result3 : test 6;
+    `;
+    const itp = interpret(code);
+    assert.strictEqual(itp.scope.get('result1'), 'zero-based');
+    assert.strictEqual(itp.scope.get('result2'), 'small');
+    assert.strictEqual(itp.scope.get('result3'), 'large');
+  });
+
+  it('works with function calls in when conditions', () => {
+    const code = `
+      test : list ->
+        with (
+          len : length list;
+          status : when len is
+            0 then "empty"
+            _ then when (len > 5) is
+              true then "long"
+              _ then "short";
+        ) -> status;
+      result1 : test [];
+      result2 : test [1, 2, 3];
+      result3 : test [1, 2, 3, 4, 5, 6];
+    `;
+    const itp = interpret(code);
+    assert.strictEqual(itp.scope.get('result1'), 'empty');
+    assert.strictEqual(itp.scope.get('result2'), 'short');
+    assert.strictEqual(itp.scope.get('result3'), 'long');
+  });
+});