diff options
Diffstat (limited to 'js/baba-yaga/tests/with-when-expressions.test.js')
-rw-r--r-- | js/baba-yaga/tests/with-when-expressions.test.js | 158 |
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'); + }); +}); |