triePruneBranch; preparation for echo-cancellation of SCNs
This commit is contained in:
parent
d29fb17ad6
commit
e9b431c50f
|
@ -423,35 +423,38 @@ function subtract(o1, o2, subtractSuccessesOpt) {
|
||||||
r2.forEach(function (val, key) { examineKey(key) });
|
r2.forEach(function (val, key) { examineKey(key) });
|
||||||
}
|
}
|
||||||
|
|
||||||
// Here, the target is complete. If it has only two keys,
|
return collapseWildcardSequences(target);
|
||||||
// one wild and one is_keyClose, and wild's continuation
|
|
||||||
// is a $WildcardSequence and the other continuation is
|
|
||||||
// identical to the sequence's continuation, then replace
|
|
||||||
// the whole thing with a nested $WildcardSequence.
|
|
||||||
// (We know w === rlookup(target, __) from before.)
|
|
||||||
//
|
|
||||||
// TODO: I suspect actually this applies even if there are
|
|
||||||
// more than two keys, so long as all their continuations
|
|
||||||
// are identical and there's at least one is_keyClose
|
|
||||||
// alongside a wild.
|
|
||||||
if (target.size === 2) {
|
|
||||||
var finalW = rlookup(target, __);
|
|
||||||
if (finalW instanceof $WildcardSequence) {
|
|
||||||
target.forEach(function (k, key) {
|
|
||||||
if ((key !== __) && is_keyClose(key)) {
|
|
||||||
if (Immutable.is(k, finalW.trie)) {
|
|
||||||
target = finalW;
|
|
||||||
return false; // terminate the iteration early
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return target;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function collapseWildcardSequences(target) {
|
||||||
|
// Here, the target is complete. If it has only two keys,
|
||||||
|
// one wild and one is_keyClose, and wild's continuation
|
||||||
|
// is a $WildcardSequence and the other continuation is
|
||||||
|
// identical to the sequence's continuation, then replace
|
||||||
|
// the whole thing with a nested $WildcardSequence.
|
||||||
|
// (We know w === rlookup(target, __) from before.)
|
||||||
|
//
|
||||||
|
// TODO: I suspect actually this applies even if there are
|
||||||
|
// more than two keys, so long as all their continuations
|
||||||
|
// are identical and there's at least one is_keyClose
|
||||||
|
// alongside a wild.
|
||||||
|
if (target.size === 2) {
|
||||||
|
var finalW = rlookup(target, __);
|
||||||
|
if (finalW instanceof $WildcardSequence) {
|
||||||
|
target.forEach(function (k, key) {
|
||||||
|
if ((key !== __) && is_keyClose(key)) {
|
||||||
|
if (Immutable.is(k, finalW.trie)) {
|
||||||
|
target = finalW;
|
||||||
|
return false; // terminate the iteration early
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
// Returns null on failed match, otherwise the appropriate success
|
// Returns null on failed match, otherwise the appropriate success
|
||||||
// value contained in the trie r.
|
// value contained in the trie r.
|
||||||
function matchValue(r, v) {
|
function matchValue(r, v) {
|
||||||
|
@ -616,6 +619,20 @@ function appendTrie(m, mTailFn) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function triePruneBranch(m, keys) {
|
||||||
|
if (keys.isEmpty()) return emptyTrie;
|
||||||
|
|
||||||
|
if (is_emptyTrie(m)) return emptyTrie;
|
||||||
|
if (m instanceof $WildcardSequence) {
|
||||||
|
return collapseWildcardSequences(triePruneBranch(expandWildseq(m.trie), keys));
|
||||||
|
}
|
||||||
|
if (m instanceof $Success) return m;
|
||||||
|
|
||||||
|
var key = keys.first();
|
||||||
|
var rest = keys.shift();
|
||||||
|
return rupdate(m, key, triePruneBranch(rlookupWild(m, key), rest));
|
||||||
|
}
|
||||||
|
|
||||||
function trieStep(m, key) {
|
function trieStep(m, key) {
|
||||||
if (is_emptyTrie(m)) return emptyTrie;
|
if (is_emptyTrie(m)) return emptyTrie;
|
||||||
if (m instanceof $WildcardSequence) return (is_keyClose(key) ? m.trie : m);
|
if (m instanceof $WildcardSequence) return (is_keyClose(key) ? m.trie : m);
|
||||||
|
@ -1006,6 +1023,7 @@ module.exports.subtract = subtract;
|
||||||
module.exports.matchValue = matchValue;
|
module.exports.matchValue = matchValue;
|
||||||
module.exports.matchTrie = matchTrie;
|
module.exports.matchTrie = matchTrie;
|
||||||
module.exports.appendTrie = appendTrie;
|
module.exports.appendTrie = appendTrie;
|
||||||
|
module.exports.triePruneBranch = triePruneBranch;
|
||||||
module.exports.trieStep = trieStep;
|
module.exports.trieStep = trieStep;
|
||||||
module.exports.relabel = relabel;
|
module.exports.relabel = relabel;
|
||||||
module.exports.compileProjection = compileProjection;
|
module.exports.compileProjection = compileProjection;
|
||||||
|
|
|
@ -439,3 +439,53 @@ describe('intersect', function () {
|
||||||
checkPrettyTrie(r.intersect(r.subtract(x, y), y), ['::: nothing']);
|
checkPrettyTrie(r.intersect(r.subtract(x, y), y), ['::: nothing']);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('triePruneBranch', function () {
|
||||||
|
it('should not affect empty trie', function () {
|
||||||
|
checkPrettyTrie(r.triePruneBranch(r.emptyTrie, Immutable.List([])), ['::: nothing']);
|
||||||
|
checkPrettyTrie(r.triePruneBranch(r.emptyTrie, Immutable.List([r.SOA])), ['::: nothing']);
|
||||||
|
checkPrettyTrie(r.triePruneBranch(r.emptyTrie, Immutable.List(["x"])), ['::: nothing']);
|
||||||
|
checkPrettyTrie(r.triePruneBranch(r.emptyTrie, Immutable.List([r.SOA, "x"])), ['::: nothing']);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should leave a hole in a full trie', function () {
|
||||||
|
var full = r.compilePattern(true, r.__);
|
||||||
|
checkPrettyTrie(r.triePruneBranch(full, Immutable.List([])), ['::: nothing']);
|
||||||
|
checkPrettyTrie(r.triePruneBranch(full, Immutable.List([r.SOA])),
|
||||||
|
[' ★ >{true}',
|
||||||
|
' <::: nothing']);
|
||||||
|
checkPrettyTrie(r.triePruneBranch(full, Immutable.List(["x"])),
|
||||||
|
[' ★ >{true}',
|
||||||
|
' "x"::: nothing']);
|
||||||
|
checkPrettyTrie(r.triePruneBranch(full, Immutable.List([r.SOA, "x"])),
|
||||||
|
[' ★ >{true}',
|
||||||
|
' < ★...> >{true}',
|
||||||
|
' > >{true}',
|
||||||
|
' "x"::: nothing']);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should prune in a finite tree and leave the rest alone', function () {
|
||||||
|
var A = r.compilePattern(true, ["y"])
|
||||||
|
var B = r.union(r.compilePattern(true, ["x"]), A);
|
||||||
|
var C = r.union(r.compilePattern(true, "z"), B);
|
||||||
|
checkPrettyTrie(r.triePruneBranch(A, Immutable.List([])), ['::: nothing']);
|
||||||
|
checkPrettyTrie(r.triePruneBranch(B, Immutable.List([])), ['::: nothing']);
|
||||||
|
checkPrettyTrie(r.triePruneBranch(C, Immutable.List([])), ['::: nothing']);
|
||||||
|
checkPrettyTrie(r.triePruneBranch(A, Immutable.List(["z"])), [' < "y" > >{true}']);
|
||||||
|
checkPrettyTrie(r.triePruneBranch(B, Immutable.List(["z"])), [' < "x" > >{true}',
|
||||||
|
' "y" > >{true}']);
|
||||||
|
checkPrettyTrie(r.triePruneBranch(C, Immutable.List(["z"])), [' < "x" > >{true}',
|
||||||
|
' "y" > >{true}']);
|
||||||
|
checkPrettyTrie(r.triePruneBranch(A, Immutable.List([r.SOA])), ['::: nothing']);
|
||||||
|
checkPrettyTrie(r.triePruneBranch(B, Immutable.List([r.SOA])), ['::: nothing']);
|
||||||
|
checkPrettyTrie(r.triePruneBranch(C, Immutable.List([r.SOA])), [' "z" >{true}']);
|
||||||
|
checkPrettyTrie(r.triePruneBranch(A, Immutable.List([r.SOA, "x"])), [' < "y" > >{true}']);
|
||||||
|
checkPrettyTrie(r.triePruneBranch(B, Immutable.List([r.SOA, "x"])), [' < "y" > >{true}']);
|
||||||
|
checkPrettyTrie(r.triePruneBranch(C, Immutable.List([r.SOA, "x"])), [' < "y" > >{true}',
|
||||||
|
' "z" >{true}']);
|
||||||
|
checkPrettyTrie(r.triePruneBranch(A, Immutable.List([r.SOA, "y"])), ['::: nothing']);
|
||||||
|
checkPrettyTrie(r.triePruneBranch(B, Immutable.List([r.SOA, "y"])), [' < "x" > >{true}']);
|
||||||
|
checkPrettyTrie(r.triePruneBranch(C, Immutable.List([r.SOA, "y"])), [' < "x" > >{true}',
|
||||||
|
' "z" >{true}']);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
Loading…
Reference in New Issue