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'); }); });