From 74a661bf44d5288bd67b290c436125235b9aa0ca Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Mon, 29 Sep 2014 15:35:03 +1000 Subject: [PATCH] implement array comprehension --- README.md | 8 ++- .../array-comprehension-container.js | 5 ++ .../templates/array-comprehension-for-each.js | 3 + lib/6to5/templates/array-push.js | 1 + lib/6to5/templates/if.js | 3 + lib/6to5/transformers/array-comprehension.js | 55 +++++++++++++++++++ .../fixtures/array-comprehension/if/actual.js | 1 + .../array-comprehension/if/expected.js | 12 ++++ .../array-comprehension/multiple/actual.js | 1 + .../array-comprehension/multiple/expected.js | 11 ++++ .../array-comprehension/no-in/actual.js | 1 + .../array-comprehension/no-in/options.json | 3 + .../array-comprehension/single/actual.js | 1 + .../array-comprehension/single/expected.js | 9 +++ 14 files changed, 112 insertions(+), 2 deletions(-) create mode 100644 lib/6to5/templates/array-comprehension-container.js create mode 100644 lib/6to5/templates/array-comprehension-for-each.js create mode 100644 lib/6to5/templates/array-push.js create mode 100644 lib/6to5/templates/if.js create mode 100644 test/fixtures/array-comprehension/if/actual.js create mode 100644 test/fixtures/array-comprehension/if/expected.js create mode 100644 test/fixtures/array-comprehension/multiple/actual.js create mode 100644 test/fixtures/array-comprehension/multiple/expected.js create mode 100644 test/fixtures/array-comprehension/no-in/actual.js create mode 100644 test/fixtures/array-comprehension/no-in/options.json create mode 100644 test/fixtures/array-comprehension/single/actual.js create mode 100644 test/fixtures/array-comprehension/single/expected.js diff --git a/README.md b/README.md index be2504c82f..7397b83490 100644 --- a/README.md +++ b/README.md @@ -45,9 +45,9 @@ | [Computed property names](FEATURES.md#computed-property-names) | ✓ | | | [Constants](FEATURES.md#constants) | ✓ | | | [Binary and Octal Literals](FEATURES.md#binary-and-octal-literals) | ✓ | | -| [Iterators](FEATURES.md#iterators) | | ✓ | +| [Iterators](FEATURES.md#iterators) | ✓ | ✓ | +| [Array comprehension](FEATURES.md#array-comprehension) | ✓ | | | [Destructuring assignment](FEATURES.md#destructuring-assignment) | | | -| [Array comprehension](FEATURES.md#array-comprehension) | | | | [Generators](FEATURES.md#generators) | | | ## Installation @@ -157,6 +157,10 @@ browserify() Cannot subclass built-ins such as `Date`, `Array`, `DOM` etc. +### Generator comprehension + +Not supported. + ## Comparison to Traceur ### Performance diff --git a/lib/6to5/templates/array-comprehension-container.js b/lib/6to5/templates/array-comprehension-container.js new file mode 100644 index 0000000000..e32bc59595 --- /dev/null +++ b/lib/6to5/templates/array-comprehension-container.js @@ -0,0 +1,5 @@ +(function () { + var KEY = []; + + return KEY; +})(); diff --git a/lib/6to5/templates/array-comprehension-for-each.js b/lib/6to5/templates/array-comprehension-for-each.js new file mode 100644 index 0000000000..8e63c3d497 --- /dev/null +++ b/lib/6to5/templates/array-comprehension-for-each.js @@ -0,0 +1,3 @@ +OBJECT.forEach(function (KEY) { + +}); diff --git a/lib/6to5/templates/array-push.js b/lib/6to5/templates/array-push.js new file mode 100644 index 0000000000..2fe96db95b --- /dev/null +++ b/lib/6to5/templates/array-push.js @@ -0,0 +1 @@ +KEY.push(STATEMENT); diff --git a/lib/6to5/templates/if.js b/lib/6to5/templates/if.js new file mode 100644 index 0000000000..6b01d35606 --- /dev/null +++ b/lib/6to5/templates/if.js @@ -0,0 +1,3 @@ +if (STATEMENT) { + +} diff --git a/lib/6to5/transformers/array-comprehension.js b/lib/6to5/transformers/array-comprehension.js index e69de29bb2..3ebc80d65a 100644 --- a/lib/6to5/transformers/array-comprehension.js +++ b/lib/6to5/transformers/array-comprehension.js @@ -0,0 +1,55 @@ +var util = require("../util"); + +exports.ComprehensionExpression = function (node, parent, opts, generateUid) { + var uid = generateUid("arr"); + + var container = util.template("array-comprehension-container", { + KEY: uid + }); + + var block = container.callee.body; + var body = block.body; + + var returnStatement = body.pop(); + + var build = function () { + var self = node.blocks.shift(); + if (!self) return; + + if (!self.of) { + throw util.errorWithNode(self, "for-in array comprehension is not supported"); + } + + var child = build(); + if (!child) { + // last item + + child = util.template("array-push", { + KEY: uid, + STATEMENT: node.body + }, true); + + if (node.filter) { + var filter = util.template("if", { + STATEMENT: node.filter + }); + filter.consequent.body = [child]; + child = filter; + } + } + + var container2 = util.template("array-comprehension-for-each", { + OBJECT: self.right, + KEY: self.left, + }, true); + + container2.expression.arguments[0].body.body = [child]; + + return container2; + }; + + body.push(build()); + body.push(returnStatement); + + return container; +}; diff --git a/test/fixtures/array-comprehension/if/actual.js b/test/fixtures/array-comprehension/if/actual.js new file mode 100644 index 0000000000..135634779e --- /dev/null +++ b/test/fixtures/array-comprehension/if/actual.js @@ -0,0 +1 @@ +var seattlers = [for (c of customers) if (c.city == "Seattle") { name: c.name, age: c.age }]; diff --git a/test/fixtures/array-comprehension/if/expected.js b/test/fixtures/array-comprehension/if/expected.js new file mode 100644 index 0000000000..77129e256a --- /dev/null +++ b/test/fixtures/array-comprehension/if/expected.js @@ -0,0 +1,12 @@ +var seattlers = function () { + var _arr = []; + customers.forEach(function (c) { + if (c.city == "Seattle") { + _arr.push({ + name: c.name, + age: c.age + }); + } + }); + return _arr; +}(); diff --git a/test/fixtures/array-comprehension/multiple/actual.js b/test/fixtures/array-comprehension/multiple/actual.js new file mode 100644 index 0000000000..2928479d70 --- /dev/null +++ b/test/fixtures/array-comprehension/multiple/actual.js @@ -0,0 +1 @@ +var arr = [for (x of "abcdefgh".split("")) for (y of "12345678".split("")) (x + y)]; diff --git a/test/fixtures/array-comprehension/multiple/expected.js b/test/fixtures/array-comprehension/multiple/expected.js new file mode 100644 index 0000000000..0e1a5ed400 --- /dev/null +++ b/test/fixtures/array-comprehension/multiple/expected.js @@ -0,0 +1,11 @@ +var arr = (function () { + var _arr = []; + + "abcdefgh".split("").forEach(function (x) { + "12345678".split("").forEach(function (y) { + _arr.push(x + y); + }); + }); + + return _arr; +})(); diff --git a/test/fixtures/array-comprehension/no-in/actual.js b/test/fixtures/array-comprehension/no-in/actual.js new file mode 100644 index 0000000000..7737a13f4a --- /dev/null +++ b/test/fixtures/array-comprehension/no-in/actual.js @@ -0,0 +1 @@ +var arr = [for (i in [1, 2, 3]) i * i]; diff --git a/test/fixtures/array-comprehension/no-in/options.json b/test/fixtures/array-comprehension/no-in/options.json new file mode 100644 index 0000000000..765cdaab02 --- /dev/null +++ b/test/fixtures/array-comprehension/no-in/options.json @@ -0,0 +1,3 @@ +{ + "throws": "for-in array comprehension is not supported" +} diff --git a/test/fixtures/array-comprehension/single/actual.js b/test/fixtures/array-comprehension/single/actual.js new file mode 100644 index 0000000000..2087ae351b --- /dev/null +++ b/test/fixtures/array-comprehension/single/actual.js @@ -0,0 +1 @@ +var arr = [for (i of [1, 2, 3]) i * i]; diff --git a/test/fixtures/array-comprehension/single/expected.js b/test/fixtures/array-comprehension/single/expected.js new file mode 100644 index 0000000000..3af9227589 --- /dev/null +++ b/test/fixtures/array-comprehension/single/expected.js @@ -0,0 +1,9 @@ +var arr = (function () { + var _arr = []; + + [1, 2, 3].forEach(function (i) { + _arr.push(i * i); + }); + + return _arr; +})();