Skip to content

Commit 7b49edb

Browse files
committed
Add pattern matching on map objects
1 parent e19bb81 commit 7b49edb

File tree

7 files changed

+255
-69
lines changed

7 files changed

+255
-69
lines changed

lib/tailored.js

Lines changed: 30 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "tailored",
3-
"version": "2.5.0",
3+
"version": "2.6.0",
44
"description": "Pattern matching library",
55
"main": "lib/tailored.js",
66
"jsnext:main": "src/index.js",
@@ -16,15 +16,15 @@
1616
"author": "Bryan Joseph <[email protected]>",
1717
"license": "MIT",
1818
"devDependencies": {
19-
"babel-core": "^6.24.0",
20-
"babel-preset-env": "^1.3.2",
21-
"babel-register": "^6.24.0",
22-
"chai": "^3.5.0",
23-
"mocha": "^3.2.0",
24-
"rollup": "^0.41.0",
19+
"babel-core": "^6.25.0",
20+
"babel-preset-env": "^1.6.0",
21+
"babel-register": "^6.24.1",
22+
"chai": "^4.1.0",
23+
"mocha": "^3.4.2",
24+
"rollup": "^0.45.2",
2525
"rollup-plugin-babel": "^2.7.1"
2626
},
2727
"dependencies": {
28-
"erlang-types": "^1.0.0"
28+
"erlang-types": "^1.0.1"
2929
}
3030
}

src/tailored/checks.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
Type,
99
StartsWith,
1010
Bound,
11-
BitStringMatch,
11+
BitStringMatch
1212
} from './types';
1313

1414
function is_number(value) {
@@ -79,6 +79,10 @@ function is_function(value) {
7979
return Object.prototype.toString.call(value) == '[object Function]';
8080
}
8181

82+
function is_map(value) {
83+
return value instanceof Map;
84+
}
85+
8286
export {
8387
is_number,
8488
is_string,
@@ -97,4 +101,5 @@ export {
97101
is_object,
98102
is_array,
99103
is_bitstring,
104+
is_map
100105
};

src/tailored/match.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
Type,
88
StartsWith,
99
Bound,
10-
BitStringMatch,
10+
BitStringMatch
1111
} from './types';
1212

1313
const patternMap = new Map();
@@ -21,6 +21,7 @@ patternMap.set(Type.prototype, Resolvers.resolveType);
2121
patternMap.set(BitStringMatch.prototype, Resolvers.resolveBitString);
2222
patternMap.set(Number.prototype, Resolvers.resolveNumber);
2323
patternMap.set(Symbol.prototype, Resolvers.resolveSymbol);
24+
patternMap.set(Map.prototype, Resolvers.resolveMap);
2425
patternMap.set(Array.prototype, Resolvers.resolveArray);
2526
patternMap.set(String.prototype, Resolvers.resolveString);
2627
patternMap.set(Boolean.prototype, Resolvers.resolveBoolean);

src/tailored/resolvers.js

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,30 @@ function resolveArray(pattern) {
137137
};
138138
}
139139

140+
function resolveMap(pattern) {
141+
let matches = new Map();
142+
143+
const keys = pattern.keys();
144+
145+
for (let key of keys) {
146+
matches.set(key, buildMatch(pattern.get(key)));
147+
}
148+
149+
return function(value, args) {
150+
if (!Checks.is_map(value) || pattern.size > value.size) {
151+
return false;
152+
}
153+
154+
for (let key of keys) {
155+
if (!value.has(key) || !matches.get(key)(value.get(key), args)) {
156+
return false;
157+
}
158+
}
159+
160+
return true;
161+
};
162+
}
163+
140164
function resolveObject(pattern) {
141165
let matches = {};
142166

@@ -342,5 +366,6 @@ export {
342366
resolveBoolean,
343367
resolveFunction,
344368
resolveNull,
345-
resolveBitString
369+
resolveBitString,
370+
resolveMap
346371
};

test/defmatch.spec.js

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,24 @@ describe('defmatch', () => {
330330
};
331331

332332
let fn = Tailored.defmatch(
333-
Tailored.clause([Tailored.bound(bound_value)], val => true)
333+
Tailored.clause([Tailored.capture(bound_value)], val => true)
334+
);
335+
336+
expect(fn(value)).to.equal(true);
337+
});
338+
339+
it('must match on maps with symbol keys', () => {
340+
const bound_value = new Map([
341+
[Symbol.for('__struct__'), Symbol.for('Elixir.Blueprint.AssertError')]
342+
]);
343+
344+
const value = new Map([
345+
[Symbol.for('__struct__'), Symbol.for('Elixir.Blueprint.AssertError')],
346+
[Symbol.for('msg'), 'something']
347+
]);
348+
349+
let fn = Tailored.defmatch(
350+
Tailored.clause([Tailored.capture(bound_value)], val => true)
334351
);
335352

336353
expect(fn(value)).to.equal(true);

0 commit comments

Comments
 (0)