Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pattern Matching #22

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
366 changes: 354 additions & 12 deletions src/index.js

Large diffs are not rendered by default.

23 changes: 23 additions & 0 deletions src/stdlib.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,29 @@ export const lightscriptImports = {
"bitwiseZeroFillRightShift": "inline",
};

export const runtimeHelpers = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I liked this way of doing helpers a lot, so I tried to adopt it. When I applied it to my local build of lscdiag I got some very strange code output in the generated helpers. Took me a while to figure out why -- turns out that minifiers mangle these things and then fn.toString() brings in the minified code.

We could just say we don't care about that, but I think live compilers and minifiers are good things generally, whereas this, while neat, could just be replaced with a plain string passed to babel-template. I recommend the latter approach.

Copy link
Contributor Author

@rattrayalex rattrayalex Jun 9, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, yeah, that's why. I kind of don't mind – it's babel helping make sure that I'm writing cross-browser code. But yes, if you see the tests, the output isn't the exact same as what I wrote.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't sound quite right... the transform being run here is just the one specified in .babelrc for the plugin, which is just env: { node: 4 } -- that's definitely not cross browser code.

I think having cross-browser code is a good point, but might be better to paste the helper into babel-repl, set the env to Netscape Navigator 1.0, and paste the output into a plain string.

Alternatively, an extra build step could compile the helpers with a different env? But that seems like overtooling.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My current implementation of hasProps and hasLength doesn't change due to this factor, which I think is desirable, so I think I'll leave this as-is for now, hope that's ok

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I hadn't read that comment very carefully – I did check in the babel repl that with an ie<6 target the output doesn't change

hasProps: function hasProps(obj) {
if (obj == null) return false;
if (typeof obj !== "object" && typeof obj !== "function") return false;
let i = arguments.length;
while (--i > 0) {
if (!(arguments[i] in obj)) return false;
}
return true;
},
hasLength: function hasLength(arr, minLength, maxLength) {
minLength = minLength || 0;
maxLength = maxLength != null ? maxLength : Number.MAX_SAFE_INTEGER;
return (
arr != null &&
typeof arr !== "function" &&
arr.length === arr.length|0 &&
arr.length >= minLength &&
arr.length <= maxLength
);
},
};

export const everyLodashMethod = [
"add",
"after",
Expand Down
18 changes: 18 additions & 0 deletions test/fixtures/match/arr-pattern/actual.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
match x:
| with []:
"empty"
| with [ a, b ]:
a - b
| with [ a, b = 2 ]:
a + b - 2
| with [ a, ...b ]:
b.concat(a)
| with [
[
b
d = 'e'
]
[ g, , h ]
...j
]:
[b, d, g, ...j].join('')
92 changes: 92 additions & 0 deletions test/fixtures/match/arr-pattern/exec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
assert.equal(
"empty",
match []:
| with []:
"empty"
)
assert.equal(
"empty",
match []:
| with []:
"empty"
)
assert.equal(
undefined,
match []:
| with [a]:
a + 1
)
assert.equal(
undefined,
match [1]:
| with [a, b]:
a + b
)
assert.equal(
5,
match [1]:
| with [a, b = 4]:
a + b
)
assert.equal(
3,
match [1, 2]:
| with [a, b]:
a + b
)
assert.equal(
4,
match [1, 2, 3]:
| with [a,, b]:
a + b
)
assert.equal(
undefined,
match [1, 2]:
| with [a,, b]:
a + b
)
assert.deepEqual(
[2, 3, 1],
match [1, 2, 3]:
| with [a, ...b]:
b.concat(a)
)
assert.deepEqual(
[1, 4],
match [4]:
| with [a, b = 1, ...c]:
c.concat([b, a])
)
assert.deepEqual(
[6, 7, 5, 4],
match [4, 5, 6, 7]:
| with [a, b = 1, ...c]:
c.concat([b, a])
)
assert.deepEqual(
[1, 2, 4, 6, 7, 8],
match [[1], [4, 5, 6], 7, 8]:
| with [
[
b
d = 2
]
[ g, , h ]
...j
]:
[b, d, g, h, ...j]
)
assert.deepEqual(
undefined,
match [[1], [4, 5], 7, 8]:
| with [
[
b
d = 2
]
[ g, , h ]
...j
]:
[b, d, g, h, ...j]
)
23 changes: 23 additions & 0 deletions test/fixtures/match/arr-pattern/expected.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
function _hasLength(arr, minLength, maxLength) { minLength = minLength || 0; maxLength = maxLength != null ? maxLength : Number.MAX_SAFE_INTEGER; return arr != null && typeof arr !== "function" && arr.length === arr.length | 0 && arr.length >= minLength && arr.length <= maxLength; }

if (_hasLength(x, 0, 0)) {
const [] = x;

"empty";
} else if (_hasLength(x, 2, 2)) {
const [a, b] = x;

a - b;
} else if (_hasLength(x, 1, 2)) {
const [a, b = 2] = x;

a + b - 2;
} else if (_hasLength(x, 1)) {
const [a, ...b] = x;

b.concat(a);
} else if (_hasLength(x, 2) && _hasLength(x[0], 1, 2) && _hasLength(x[1], 3, 3)) {
const [[b, d = 'e'], [g,, h], ...j] = x;

[b, d, g, ...j].join('');
}
7 changes: 7 additions & 0 deletions test/fixtures/match/as-call-expression/actual.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
z = match foo.bar() as y:
| y < 1: "lt one"
| y + 1 == 1: "eq zero"
| y == 2: "eq two"
| y~f(): "f(x) truthy"
| y.prop: "has prop"
| y.0: "has first child"
15 changes: 15 additions & 0 deletions test/fixtures/match/as-call-expression/expected.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const z = (y => {
if (y < 1) {
return "lt one";
} else if (y + 1 === 1) {
return "eq zero";
} else if (y === 2) {
return "eq two";
} else if (f(y)) {
return "f(x) truthy";
} else if (y.prop) {
return "has prop";
} else if (y[0]) {
return "has first child";
}
})(foo.bar());
7 changes: 7 additions & 0 deletions test/fixtures/match/as-call-statement/actual.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
match foo() as y:
| y < 1: "lt one"
| y + 1 == 1: "eq zero"
| y == 2: "eq two"
| y~f(): "f(y) truthy"
| y.prop: "has prop"
| y.0: "has first child"
15 changes: 15 additions & 0 deletions test/fixtures/match/as-call-statement/expected.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const y = foo();

if (y < 1) {
"lt one";
} else if (y + 1 === 1) {
"eq zero";
} else if (y === 2) {
"eq two";
} else if (f(y)) {
"f(y) truthy";
} else if (y.prop) {
"has prop";
} else if (y[0]) {
"has first child";
}
7 changes: 7 additions & 0 deletions test/fixtures/match/as-identifier-expression/actual.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
z = match x as y:
| y < 1: "lt one"
| y + 1 == 1: "eq zero"
| y == 2: "eq two"
| y~f(): "f(x) truthy"
| y.prop: "has prop"
| y.0: "has first child"
15 changes: 15 additions & 0 deletions test/fixtures/match/as-identifier-expression/expected.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const z = (y => {
if (y < 1) {
return "lt one";
} else if (y + 1 === 1) {
return "eq zero";
} else if (y === 2) {
return "eq two";
} else if (f(y)) {
return "f(x) truthy";
} else if (y.prop) {
return "has prop";
} else if (y[0]) {
return "has first child";
}
})(x);
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
match x:
| 1: "foo"
| "1": it
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const it = x;

if (it === 1) {
"foo";
} else if (it === "1") {
it;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
match x:
| 1: "foo"
| "1": "bar"
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
if (x === 1) {
"foo";
} else if (x === "1") {
"bar";
}
7 changes: 7 additions & 0 deletions test/fixtures/match/as-identifier-statement/actual.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
match x as y:
| y < 1: "lt one"
| y + 1 == 1: "eq zero"
| y == 2: "eq two"
| y~f(): "f(x) truthy"
| y.prop: "has prop"
| y.0: "has first child"
15 changes: 15 additions & 0 deletions test/fixtures/match/as-identifier-statement/expected.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const y = x;

if (y < 1) {
"lt one";
} else if (y + 1 === 1) {
"eq zero";
} else if (y === 2) {
"eq two";
} else if (f(y)) {
"f(x) truthy";
} else if (y.prop) {
"has prop";
} else if (y[0]) {
"has first child";
}
7 changes: 7 additions & 0 deletions test/fixtures/match/as-it-call-expression/actual.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
z = match foo.bar():
| it < 1: "lt one"
| it + 1 == 1: "eq zero"
| it == 2: "eq two"
| it~f(): "f(x) truthy"
| it.prop: "has prop"
| it.0: "has first child"
15 changes: 15 additions & 0 deletions test/fixtures/match/as-it-call-expression/expected.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const z = (it => {
if (it < 1) {
return "lt one";
} else if (it + 1 === 1) {
return "eq zero";
} else if (it === 2) {
return "eq two";
} else if (f(it)) {
return "f(x) truthy";
} else if (it.prop) {
return "has prop";
} else if (it[0]) {
return "has first child";
}
})(foo.bar());
7 changes: 7 additions & 0 deletions test/fixtures/match/as-it-call-statement/actual.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
match foo():
| it < 1: "lt one"
| it + 1 == 1: "eq zero"
| it == 2: "eq two"
| it~f(): "f(x) truthy"
| it.prop: "has prop"
| it.0: "has first child"
15 changes: 15 additions & 0 deletions test/fixtures/match/as-it-call-statement/expected.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const it = foo();

if (it < 1) {
"lt one";
} else if (it + 1 === 1) {
"eq zero";
} else if (it === 2) {
"eq two";
} else if (f(it)) {
"f(x) truthy";
} else if (it.prop) {
"has prop";
} else if (it[0]) {
"has first child";
}
7 changes: 7 additions & 0 deletions test/fixtures/match/as-it-identifier-expression/actual.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
z = match x:
| it < 1: "lt one"
| it + 1 == 1: "eq zero"
| it == 2: "eq two"
| it~f(): "f(x) truthy"
| it.prop: "has prop"
| it.0: "has first child"
15 changes: 15 additions & 0 deletions test/fixtures/match/as-it-identifier-expression/expected.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const z = (it => {
if (it < 1) {
return "lt one";
} else if (it + 1 === 1) {
return "eq zero";
} else if (it === 2) {
return "eq two";
} else if (f(it)) {
return "f(x) truthy";
} else if (it.prop) {
return "has prop";
} else if (it[0]) {
return "has first child";
}
})(x);
7 changes: 7 additions & 0 deletions test/fixtures/match/as-it-identifier-statement/actual.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
match x:
| it < 1: "lt one"
| it + 1 == 1: "eq zero"
| it == 2: "eq two"
| it~f(): "f(x) truthy"
| it.prop: "has prop"
| it.0: "has first child"
15 changes: 15 additions & 0 deletions test/fixtures/match/as-it-identifier-statement/expected.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const it = x;

if (it < 1) {
"lt one";
} else if (it + 1 === 1) {
"eq zero";
} else if (it === 2) {
"eq two";
} else if (f(it)) {
"f(x) truthy";
} else if (it.prop) {
"has prop";
} else if (it[0]) {
"has first child";
}
7 changes: 7 additions & 0 deletions test/fixtures/match/basic-statement-call/actual.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
match foo():
| 1:
"one"
| 2:
"two"
| else:
"idk"
9 changes: 9 additions & 0 deletions test/fixtures/match/basic-statement-call/expected.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
const it = foo();

if (it === 1) {
"one";
} else if (it === 2) {
"two";
} else {
"idk";
}
Loading