Put matchPattern back: actor.js will need it.
This commit is contained in:
parent
dc35e7c1bd
commit
fbbad85b04
|
@ -16,6 +16,19 @@ function makeStructureConstructor(label, argumentNames) {
|
|||
};
|
||||
}
|
||||
|
||||
function isStructure(s) {
|
||||
return !!(s.$SyndicateMeta$);
|
||||
}
|
||||
|
||||
function structureToArray(s) {
|
||||
var result = [s.$SyndicateMeta$.label];
|
||||
var args = s.$SyndicateMeta$.arguments;
|
||||
for (var i = 0; i < args.length; i++) {
|
||||
result.push(s[args[i]]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function $Special(name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
@ -143,6 +156,48 @@ function compilePattern(v, p) {
|
|||
}
|
||||
}
|
||||
|
||||
function matchPattern(v, p) {
|
||||
var captureCount = 0;
|
||||
var result = {};
|
||||
try {
|
||||
walk(v, p);
|
||||
} catch (e) {
|
||||
if (e.matchPatternFailed) return null;
|
||||
throw e;
|
||||
}
|
||||
result.length = captureCount;
|
||||
return result;
|
||||
|
||||
function walk(v, p) {
|
||||
if (p === v) return;
|
||||
|
||||
if (p === __) return;
|
||||
|
||||
if (isStructure(p)) { p = structureToArray(p); }
|
||||
if (isStructure(v)) { v = structureToArray(v); }
|
||||
|
||||
if (Array.isArray(p) && Array.isArray(v) && p.length === v.length) {
|
||||
for (var i = 0; i < p.length; i++) {
|
||||
walk(v[i], p[i]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (isCapture(p)) {
|
||||
var thisCapture = captureCount++;
|
||||
walk(v, capturePattern(p));
|
||||
result[captureName(p) || ('$' + thisCapture)] = v;
|
||||
return;
|
||||
}
|
||||
|
||||
if (p instanceof $Embedded) {
|
||||
die("$Embedded patterns not supported in matchPattern()");
|
||||
}
|
||||
|
||||
throw {matchPatternFailed: true};
|
||||
}
|
||||
}
|
||||
|
||||
function rupdate(r, key, k) {
|
||||
var oldWild = r.get(__, emptyTrie);
|
||||
if (Immutable.is(k, oldWild)) {
|
||||
|
@ -1033,6 +1088,7 @@ module.exports.is_emptyTrie = is_emptyTrie;
|
|||
module.exports.emptyTrie = emptyTrie;
|
||||
module.exports.embeddedTrie = embeddedTrie;
|
||||
module.exports.compilePattern = compilePattern;
|
||||
module.exports.matchPattern = matchPattern;
|
||||
module.exports._union = union;
|
||||
module.exports.union = unionN;
|
||||
module.exports.intersect = intersect;
|
||||
|
|
|
@ -351,6 +351,55 @@ describe("embedding tries in patterns", function () {
|
|||
});
|
||||
});
|
||||
|
||||
describe("calls to matchPattern", function () {
|
||||
it("should yield appropriately-named/-numbered fields", function () {
|
||||
expect(r.matchPattern([1, 2, 3], [r.__, 2, r._$])).to.eql({'$0': 3, 'length': 1});
|
||||
expect(r.matchPattern([1, 2, 3], [r.__, 2, r._$("three")])).to.eql({'three': 3, 'length': 1});
|
||||
expect(r.matchPattern([1, 2, 3], [r._$, 2, r._$("three")]))
|
||||
.to.eql({'$0': 1, 'three': 3, 'length': 2});
|
||||
expect(r.matchPattern([1, 2, 3], [r._$("one"), 2, r._$]))
|
||||
.to.eql({'one': 1, '$1': 3, 'length': 2});
|
||||
expect(r.matchPattern([1, 2, 3], [r._$("one"), 2, r._$("three")]))
|
||||
.to.eql({'one': 1, 'three': 3, 'length': 2});
|
||||
});
|
||||
|
||||
it("should fail on value mismatch", function () {
|
||||
expect(r.matchPattern([1, 2, 3], [r.__, 999, r._$("three")])).to.be(null);
|
||||
});
|
||||
|
||||
it("should fail on array length mismatch", function () {
|
||||
expect(r.matchPattern([1, 2, 3], [r.__, 2, r._$("three"), 4])).to.be(null);
|
||||
});
|
||||
|
||||
it("matches substructure", function () {
|
||||
expect(r.matchPattern([1, [2, 999], 3], [r._$("one"), r._$(null, [2, r.__]), r._$("three")]))
|
||||
.to.eql({ one: 1, '$1': [ 2, 999 ], three: 3, length: 3 });
|
||||
expect(r.matchPattern([1, [2, 999], 3], [r._$("one"), r._$("two", [2, r.__]), r._$("three")]))
|
||||
.to.eql({ one: 1, two: [ 2, 999 ], three: 3, length: 3 });
|
||||
expect(r.matchPattern([1, [999, 2], 3], [r._$("one"), r._$(null, [2, r.__]), r._$("three")]))
|
||||
.to.be(null);
|
||||
expect(r.matchPattern([1, [999, 2], 3], [r._$("one"), r._$("two", [2, r.__]), r._$("three")]))
|
||||
.to.be(null);
|
||||
});
|
||||
|
||||
it("matches nested captures", function () {
|
||||
expect(r.matchPattern([1, [2, 999], 3], [r._$("one"), r._$(null, [2, r._$]), r._$("three")]))
|
||||
.to.eql({ one: 1, '$2': 999, '$1': [ 2, 999 ], three: 3, length: 4 });
|
||||
expect(r.matchPattern([1, [2, 999], 3], [r._$("one"), r._$("two", [2, r._$]), r._$("three")]))
|
||||
.to.eql({ one: 1, '$2': 999, two: [ 2, 999 ], three: 3, length: 4 });
|
||||
});
|
||||
|
||||
it("matches structures", function () {
|
||||
var ctor = r.makeStructureConstructor('foo', ['bar', 'zot']);
|
||||
expect(r.matchPattern(ctor(123, 234), ctor(r._$("bar"), r._$("zot"))))
|
||||
.to.eql({ bar: 123, zot: 234, length: 2 });
|
||||
expect(r.matchPattern(["foo", 123, 234], ctor(r._$("bar"), r._$("zot"))))
|
||||
.to.eql({ bar: 123, zot: 234, length: 2 });
|
||||
expect(r.matchPattern(ctor(123, 234), ["foo", r._$("bar"), r._$("zot")]))
|
||||
.to.eql({ bar: 123, zot: 234, length: 2 });
|
||||
});
|
||||
});
|
||||
|
||||
describe("Projection with no captures", function () {
|
||||
it("should yield the empty sequence when there's a match", function () {
|
||||
var emptySequence = [' >{["A"]}'];
|
||||
|
|
Loading…
Reference in New Issue