From e0b476cc0afaaa1ddf97dbb518b0860d5f01a370 Mon Sep 17 00:00:00 2001 From: Tony Garnock-Jones Date: Thu, 24 Jul 2014 20:18:51 -0700 Subject: [PATCH] matchPattern, projectObjects --- src/route.js | 47 ++++++++++++++++++++++++++++++++++++++++++++++- test/tr.js | 40 +++++++++++++++++++++------------------- 2 files changed, 67 insertions(+), 20 deletions(-) diff --git a/src/route.js b/src/route.js index 28cf361..79a1cd4 100644 --- a/src/route.js +++ b/src/route.js @@ -145,6 +145,45 @@ 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 (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 shallowCopyArray(s) { return s.slice(); } @@ -1044,13 +1083,17 @@ function matcherKeysToObjects(matcherKeysResult, compiledProjection) { var e = matcherKeysResult[i]; var d = {}; for (var j = 0; j < e.length; j++) { - d[compiledProjection.names[j] || j] = e[j]; + d[compiledProjection.names[j] || ('$' + j)] = e[j]; } result.push(d); } return result; } +function projectObjects(m, compiledProjection) { + return matcherKeysToObjects(matcherKeys(project(m, compiledProjection)), compiledProjection); +} + function prettyMatcher(m, initialIndent) { var acc = []; walk(initialIndent || 0, m); @@ -1514,6 +1557,7 @@ module.exports.is_emptyMatcher = is_emptyMatcher; module.exports.emptyMatcher = emptyMatcher; module.exports.embeddedMatcher = embeddedMatcher; module.exports.compilePattern = compilePattern; +module.exports.matchPattern = matchPattern; module.exports.union = unionN; module.exports.intersect = intersect; module.exports.erasePath = erasePath; @@ -1526,6 +1570,7 @@ module.exports.projectionToPattern = projectionToPattern; module.exports.project = project; module.exports.matcherKeys = matcherKeys; module.exports.matcherKeysToObjects = matcherKeysToObjects; +module.exports.projectObjects = projectObjects; module.exports.matcherEquals = matcherEquals; module.exports.prettyMatcher = prettyMatcher; module.exports.serializeMatcher = serializeMatcher; diff --git a/test/tr.js b/test/tr.js index 2818732..a3756c6 100644 --- a/test/tr.js +++ b/test/tr.js @@ -205,8 +205,8 @@ dumpM(r.union(r.compilePattern(r.arrayToSet('A'), [2]), var M2 = r.project(M, proj); dump(r.matcherKeys(M2)); dump(r.matcherKeys(r.project(M2, r.compileProjection(r._$, r._$)))); - dump(r.matcherKeysToObjects(r.matcherKeys(r.project(M2, r.compileProjection(r._$, r._$))), - proj)); + dump(r.matcherKeysToObjects(r.matcherKeys(M2), proj)); + dump(r.projectObjects(M, proj)); })(); (function () { @@ -214,23 +214,9 @@ dumpM(r.union(r.compilePattern(r.arrayToSet('A'), [2]), var M = r.union(r.compilePattern(r.arrayToSet(['A']), [1, 2]), r.compilePattern(r.arrayToSet(['C']), [1, 3]), r.compilePattern(r.arrayToSet(['B']), [3, 4])); - var proj = r.compileProjection([r._$("fst"), r._$("snd")]); - var M2 = r.project(M, proj); - dump(r.matcherKeys(M2)); - dump(r.matcherKeysToObjects(r.matcherKeys(r.project(M2, r.compileProjection(r._$, r._$))), - proj)); -})(); - -(function () { - console.log("matcherKeys using multiple-values in projections, with partial names"); - var M = r.union(r.compilePattern(r.arrayToSet(['A']), [1, 2]), - r.compilePattern(r.arrayToSet(['C']), [1, 3]), - r.compilePattern(r.arrayToSet(['B']), [3, 4])); - var proj = r.compileProjection([r._$, r._$("snd")]); - var M2 = r.project(M, proj); - dump(r.matcherKeys(M2)); - dump(r.matcherKeysToObjects(r.matcherKeys(r.project(M2, r.compileProjection(r._$, r._$))), - proj)); + dump(r.projectObjects(M, r.compileProjection([r._$("fst"), r._$("snd")]))); + dump(r.projectObjects(M, r.compileProjection([r._$, r._$("snd")]))); + dump(r.projectObjects(M, r.compileProjection([r._$("fst"), r._$]))); })(); (function () { @@ -289,3 +275,19 @@ dumpM(r.union(r.compilePattern(r.arrayToSet('A'), [2]), dump(r.matcherEquals(M1a, M1b) === true); dump(r.matcherEquals(M2a, M2b) === true); })(); + +(function () { + console.log("Calls to matchPattern"); + dump(r.matchPattern([1, 2, 3], [r.__, 2, r._$])); + dump(r.matchPattern([1, 2, 3], [r.__, 2, r._$("three")])); + dump(r.matchPattern([1, 2, 3], [r._$, 2, r._$("three")])); + dump(r.matchPattern([1, 2, 3], [r._$("one"), 2, r._$])); + dump(r.matchPattern([1, 2, 3], [r._$("one"), 2, r._$("three")])); + dump(r.matchPattern([1, 2, 3], [r.__, 999, r._$("three")]) === null); + dump(r.matchPattern([1, 2, 3], [r.__, 2, r._$("three"), 4]) === null); + + dump(r.matchPattern([1, [2, 999], 3], [r._$("one"), r._$(null, [2, r.__]), r._$("three")])); + dump(r.matchPattern([1, [2, 999], 3], [r._$("one"), r._$("two", [2, r.__]), r._$("three")])); + dump(r.matchPattern([1, [2, 999], 3], [r._$("one"), r._$(null, [2, r._$]), r._$("three")])); + dump(r.matchPattern([1, [2, 999], 3], [r._$("one"), r._$("two", [2, r._$]), r._$("three")])); +})();