diff --git a/js/src/route.js b/js/src/route.js index c5ba6ad..cdbb76e 100644 --- a/js/src/route.js +++ b/js/src/route.js @@ -415,9 +415,19 @@ function subtract(o1, o2, subtractSuccessesOpt) { if (!k2) { return; } - updatedK = walkWild(key, k2, w1, walkFlipped); + // There is an entry in r2 but not r1 for our key. + updatedK = + is_emptyTrie(w1) ? emptyTrie : + is_keyOpen(key) ? walk(rwildseq(w1), k2) : + is_keyClose(key) ? ((w1 instanceof $WildcardSequence) ? walk(w1.trie, k2) : emptyTrie) : + walk(w1, k2); } else if (!k2) { - updatedK = walkWild(key, k1, w2, walk); + // There is an entry in r1 but not r2 for our key. + updatedK = + is_emptyTrie(w2) ? k1 : + is_keyOpen(key) ? walk(k1, rwildseq(w2)) : + is_keyClose(key) ? ((w2 instanceof $WildcardSequence) ? walk(k1, w2.trie) : k1) : + walk(k1, w2); } else { updatedK = walk(k1, k2); } @@ -476,16 +486,6 @@ function subtract(o1, o2, subtractSuccessesOpt) { return target; } - - function walkWild(key, k, w, walker) { - if (is_emptyTrie(w)) return k; - if (is_keyOpen(key)) return walker(k, rwildseq(w)); - if (is_keyClose(key)) { - if (w instanceof $WildcardSequence) return walker(k, w.trie); - return k; - } - return walker(k, w); - } } // Returns null on failed match, otherwise the appropriate success diff --git a/js/test/test-patch.js b/js/test/test-patch.js index d6c5f07..d028658 100644 --- a/js/test/test-patch.js +++ b/js/test/test-patch.js @@ -92,6 +92,22 @@ describe('patch sequencing', function () { ' 2::: nothing'], [' < $Observe < 1 2 > > >{true}']); }); + + it('works for longer chains of asserts and retracts', function () { + var rawPatch = + Patch.assert(1) + .andThen(Patch.retract(2)) + .andThen(Patch.retract(3)) + .andThen(Patch.assert(4)) + .andThen(Patch.retract(99)); + checkPrettyPatch(rawPatch, + [' 1 >{true}', + ' 4 >{true}'], + [' 2 >{true}', + ' 3 >{true}', + ' 99 >{true}']); + + }); }); describe('patch lifting', function () { diff --git a/js/test/test-route.js b/js/test/test-route.js index 5450ffe..14e41af 100644 --- a/js/test/test-route.js +++ b/js/test/test-route.js @@ -180,6 +180,18 @@ describe("subtraction", function () { " 3 ★...> >{true}", " >::: nothing"]); }); + + it("should be idempotent if the subtrahend doesn't overlap the minuend", function () { + checkPrettyTrie(r.compilePattern(true, 1), + [' 1 >{true}']); + checkPrettyTrie(r.subtract(r.compilePattern(true, 1), + r.compilePattern(true, 2)), + [' 1 >{true}']); + checkPrettyTrie(r.subtract(r.compilePattern(true, 1), + r.compilePattern(true, 2), + function (v1, v2) { return null; }), + [' 1 >{true}']); + }); }); describe("subtract after union", function () {