diff --git a/src/waforth.wat b/src/waforth.wat index 04eb304..119601c 100644 --- a/src/waforth.wat +++ b/src/waforth.wat @@ -288,7 +288,9 @@ ;; 6.1.0140 (func $plus-loop + (call $ensureCompiling) + (call $compilePlusLoop)) (!def_word "+LOOP" "$plus-loop" !fImmediate) @@ -468,7 +470,8 @@ (i32.store8 (i32.const !moduleHeaderFunctionTypeBase) (get_local $params)) (set_global $cp (i32.const !moduleBodyBase)) (set_global $currentLocal (i32.add (i32.const -1) (get_local $params))) - (set_global $lastLocal (i32.add (i32.const -1) (get_local $params)))) + (set_global $lastLocal (i32.add (i32.const -1) (get_local $params))) + (set_global $branchNesting (i32.const -1))) (func $endColon (local $bodySize i32) @@ -1655,19 +1658,29 @@ EOF (i32.store8 (get_global $cp) (i32.const 0x04)) (set_global $cp (i32.add (get_global $cp) (i32.const 1))) (i32.store8 (get_global $cp) (i32.const 0x40)) - (set_global $cp (i32.add (get_global $cp) (i32.const 1)))) + (set_global $cp (i32.add (get_global $cp) (i32.const 1))) + + (set_global $branchNesting (i32.add (get_global $branchNesting) (i32.const 1)))) (func $compileElse (i32.store8 (get_global $cp) (i32.const 0x05)) (set_global $cp (i32.add (get_global $cp) (i32.const 1)))) - (func $compileThen (call $emitEnd)) + (func $compileThen + (set_global $branchNesting (i32.sub (get_global $branchNesting) (i32.const 1))) + (call $emitEnd)) (func $compileDo (set_global $currentLocal (i32.add (get_global $currentLocal) (i32.const 2))) (if (i32.gt_s (get_global $currentLocal) (get_global $lastLocal)) (then (set_global $lastLocal (get_global $currentLocal)))) + + ;; Save branch nesting + (i32.store (get_global $tors) (get_global $branchNesting)) + (set_global $tors (i32.add (get_global $tors) (i32.const 4))) + (set_global $branchNesting (i32.const 0)) + (call $compilePop) (call $emitSetLocal (i32.sub (get_global $currentLocal) (i32.const 1))) (call $compilePop) @@ -1685,6 +1698,8 @@ EOF ;; Assumes increment is on the operand stack (func $compileLoopEnd + (local $btors i32) + (call $emitGetLocal (i32.sub (get_global $currentLocal) (i32.const 1))) (call $emitAdd) (call $emitSetLocal (i32.sub (get_global $currentLocal) (i32.const 1))) @@ -1695,14 +1710,20 @@ EOF (call $emitBr (i32.const 0)) (call $emitEnd) (call $emitEnd) - (set_global $currentLocal (i32.sub (get_global $currentLocal) (i32.const 2)))) + (set_global $currentLocal (i32.sub (get_global $currentLocal) (i32.const 2))) + + ;; Restore branch nesting + (set_global $branchNesting (i32.load (tee_local $btors (i32.sub (get_global $tors) (i32.const 4))))) + (set_global $tors (get_local $btors))) + (func $compileLeave - (call $emitBr (i32.const 1))) + (call $emitBr (i32.add (get_global $branchNesting) (i32.const 1)))) (func $compileBegin (call $emitBlock) - (call $emitLoop)) + (call $emitLoop) + (set_global $branchNesting (i32.add (get_global $branchNesting) (i32.const 2)))) (func $compileWhile (call $compilePop) @@ -1712,7 +1733,8 @@ EOF (func $compileRepeat (call $emitBr (i32.const 0)) (call $emitEnd) - (call $emitEnd)) + (call $emitEnd) + (set_global $branchNesting (i32.sub (get_global $branchNesting) (i32.const 2)))) (func $compileUntil (call $compilePop) @@ -1720,7 +1742,8 @@ EOF (call $emitBrIf (i32.const 0)) (call $emitBr (i32.const 1)) (call $emitEnd) - (call $emitEnd)) + (call $emitEnd) + (set_global $branchNesting (i32.sub (get_global $branchNesting) (i32.const 2)))) (func $compileRecurse ;; call 0 @@ -2105,6 +2128,7 @@ EOF (global $currentLocal (mut i32) (i32.const 0)) (global $lastLocal (mut i32) (i32.const -1)) + (global $branchNesting (mut i32) (i32.const -1)) ;; Compilation pointer (global $cp (mut i32) (i32.const !moduleBodyBase))) diff --git a/tests/standard-testsuite/core.f.js b/tests/standard-testsuite/core.f.js index 88f8864..12952a2 100644 --- a/tests/standard-testsuite/core.f.js +++ b/tests/standard-testsuite/core.f.js @@ -713,7 +713,7 @@ T{ : GD4 DO 1 0 DO J LOOP -1 +LOOP ; -> }T T{ : GD5 123 SWAP 0 DO I 4 > IF DROP 234 LEAVE THEN LOOP ; -> }T T{ 1 GD5 -> 123 }T T{ 5 GD5 -> 123 }T -\\TODO T{ 6 GD5 -> 234 }T +T{ 6 GD5 -> 234 }T T{ : GD6 ( PAT: T{0 0},{0 0}{1 0}{1 1},{0 0}{1 0}{1 1}{2 0}{2 1}{2 2} ) 0 SWAP 0 DO diff --git a/tests/tests.js b/tests/tests.js index 0140917..f443c08 100644 --- a/tests/tests.js +++ b/tests/tests.js @@ -88,6 +88,7 @@ function loadTests(wasmModule, arrayToBase64) { expect(r).to.be.undefined; output = output.substr(0, output.length); } else { + expect(r).to.not.be.an("undefined", "Error running: " + s); expect(r).to.not.be.below(0); output = output.substr(0, output.length - 3); // Strip 'ok\n' from output } @@ -656,19 +657,17 @@ function loadTests(wasmModule, arrayToBase64) { }); describe("LEAVE", () => { - it.only("should leave", () => { + it("should leave", () => { run(`: FOO 4 0 DO 3 LEAVE 6 LOOP 4 ;`); run("FOO 5"); expect(stackValues()).to.eql([3, 4, 5]); }); - // it.only("should leave an if in a loop", () => { - // run(`: FOO 5 0 DO I I 3 = IF LEAVE THEN I LOOP 123 ;`); - // run("FOO 5"); - // expect(stack[0]).to.eql(3); - // expect(stack[1]).to.eql(4); - // expect(stack[2]).to.eql(5); - // }); + it("should leave an if in a loop", () => { + run(`: FOO 5 0 DO I I 3 = IF 124 LEAVE THEN I LOOP 123 ;`); + run("FOO 5"); + expect(stackValues()).to.eql([0, 0, 1, 1, 2, 2, 3, 124, 123, 5]); + }); }); describe("+LOOP", () => { @@ -690,6 +689,12 @@ function loadTests(wasmModule, arrayToBase64) { expect(stack[1]).to.eql(3); expect(stack[2]).to.eql(5); }); + + it.skip("should work with decrementing loops", () => { + run(": GD2 DO I -1 +LOOP ;"); + run("1 4 GD2"); + expect(stackValues()).to.eql([]); + }); }); describe("I", () => {