Support for embedding matchers in patterns

This commit is contained in:
Tony Garnock-Jones 2014-05-28 17:22:08 -04:00
parent 461f96d5d4
commit 5c68f2243a
2 changed files with 67 additions and 5 deletions

View File

@ -11,6 +11,14 @@ function Routing(exports) {
throw new Error(message); throw new Error(message);
} }
function $Embedded(matcher) {
this.matcher = matcher;
}
function embeddedMatcher(matcher) {
return new $Embedded(matcher);
}
// The pattern argument defaults to wildcard, __. // The pattern argument defaults to wildcard, __.
function $Capture(pattern) { function $Capture(pattern) {
this.pattern = (typeof pattern === 'undefined' ? __ : pattern); this.pattern = (typeof pattern === 'undefined' ? __ : pattern);
@ -130,7 +138,11 @@ function Routing(exports) {
return rseq(SOA, acc); return rseq(SOA, acc);
} }
return rseq(JSON.stringify(p), acc); if (p instanceof $Embedded) {
return appendMatcher(p.matcher, function (v) { return acc; });
} else {
return rseq(JSON.stringify(p), acc);
}
} }
} }
@ -712,6 +724,27 @@ function Routing(exports) {
} }
} }
function appendMatcher(m, mTailFn) {
return walk(m);
function walk(m) {
if (is_emptyMatcher(m)) return emptyMatcher;
if (m instanceof $WildcardSequence) return rwildseq(walk(m.matcher));
if (m instanceof $Success) die("Ill-formed matcher");
var target = new $Dict();
for (var key in m.entries) {
var k = m.get(key);
if (is_keyClose(key) && (k instanceof $Success)) {
target = union(target, mTailFn(k.value));
} else {
rupdateInplace(target, key, walk(k));
}
}
return target.emptyGuard();
}
}
function relabel(m, f) { function relabel(m, f) {
return walk(m); return walk(m);
@ -751,10 +784,14 @@ function Routing(exports) {
return; return;
} }
if (p === __) { if (p instanceof $Embedded) {
acc.push(p); die("Cannot embed matcher in projection");
} else { } else {
acc.push(JSON.stringify(p)); if (p === __) {
acc.push(p);
} else {
acc.push(JSON.stringify(p));
}
} }
} }
} }
@ -773,7 +810,11 @@ function Routing(exports) {
return result; return result;
} }
return p; if (p instanceof $Embedded) {
return p.matcher;
} else {
return p;
}
} }
} }
@ -1446,12 +1487,14 @@ function Routing(exports) {
exports._$ = _$; exports._$ = _$;
exports.is_emptyMatcher = is_emptyMatcher; exports.is_emptyMatcher = is_emptyMatcher;
exports.emptyMatcher = emptyMatcher; exports.emptyMatcher = emptyMatcher;
exports.embeddedMatcher = embeddedMatcher;
exports.compilePattern = compilePattern; exports.compilePattern = compilePattern;
exports.union = unionN; exports.union = unionN;
exports.intersect = intersect; exports.intersect = intersect;
exports.erasePath = erasePath; exports.erasePath = erasePath;
exports.matchValue = matchValue; exports.matchValue = matchValue;
exports.matchMatcher = matchMatcher; exports.matchMatcher = matchMatcher;
exports.appendMatcher = appendMatcher;
exports.relabel = relabel; exports.relabel = relabel;
exports.compileProjection = compileProjection; exports.compileProjection = compileProjection;
exports.projectionToPattern = projectionToPattern; exports.projectionToPattern = projectionToPattern;

19
tr.js
View File

@ -232,3 +232,22 @@ dump(r.matcherKeys(r.project(r.project(r.union(r.compilePattern(r.arrayToSet(['A
dump(r.matcherEquals(R1a, A) === true); dump(r.matcherEquals(R1a, A) === true);
dump(r.matcherEquals(R1b, B) === true); dump(r.matcherEquals(R1b, B) === true);
})(); })();
(function () {
console.log("Embedding matchers in patterns");
var M1a =
r.compilePattern(r.arrayToSet(['A']),
[1, r.embeddedMatcher(r.compilePattern(r.arrayToSet(['B']), [2, 3])), 4]);
var M1b =
r.compilePattern(r.arrayToSet(['A']), [1, [2, 3], 4]);
var M2a =
r.compilePattern(r.arrayToSet(['A']),
[r.embeddedMatcher(r.compilePattern(r.arrayToSet(['B']), [1, 2])),
r.embeddedMatcher(r.compilePattern(r.arrayToSet(['C']), [3, 4]))]);
var M2b =
r.compilePattern(r.arrayToSet(['A']), [[1, 2], [3, 4]]);
dumpM(M1a);
dumpM(M2a);
dump(r.matcherEquals(M1a, M1b) === true);
dump(r.matcherEquals(M2a, M2b) === true);
})();