From 9e3f9fda6b211e7ea24a0b40cb995ebba86a8cce Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Wed, 12 Nov 2014 18:26:22 +1100 Subject: [PATCH] add support for generator comprehensions - fixes #149 --- FEATURES.md | 5 ++ lib/6to5/generation/generator.js | 21 ++++--- ...ay-comprehensions.js => comprehensions.js} | 6 +- lib/6to5/register.js | 1 + lib/6to5/transformation/transform.js | 1 + lib/6to5/transformation/transformer.js | 1 + .../transformers/array-comprehension.js | 57 ++++++++++--------- .../generator-comprehension/simple/exec.js | 6 ++ 8 files changed, 58 insertions(+), 40 deletions(-) rename lib/6to5/generation/generators/{array-comprehensions.js => comprehensions.js} (84%) create mode 100644 test/fixtures/transformation/generator-comprehension/simple/exec.js diff --git a/FEATURES.md b/FEATURES.md index 04e1b1d1f0..0683569590 100644 --- a/FEATURES.md +++ b/FEATURES.md @@ -95,6 +95,11 @@ for (var i of [1, 2, 3]) { ```javascript ``` +## Generator comprehension + +```javascript +``` + ## Modules ```javascript diff --git a/lib/6to5/generation/generator.js b/lib/6to5/generation/generator.js index b3661a2241..ba146331f4 100644 --- a/lib/6to5/generation/generator.js +++ b/lib/6to5/generation/generator.js @@ -53,16 +53,16 @@ CodeGenerator.normaliseOptions = function (opts) { }; CodeGenerator.generators = { - arrayComprehensions: require("./generators/array-comprehensions"), - templateLiterals: require("./generators/template-literals"), - expressions: require("./generators/expressions"), - statements: require("./generators/statements"), - classes: require("./generators/classes"), - methods: require("./generators/methods"), - modules: require("./generators/modules"), - types: require("./generators/types"), - base: require("./generators/base"), - jsx: require("./generators/jsx") + templateLiterals: require("./generators/template-literals"), + comprehensions: require("./generators/comprehensions"), + expressions: require("./generators/expressions"), + statements: require("./generators/statements"), + classes: require("./generators/classes"), + methods: require("./generators/methods"), + modules: require("./generators/modules"), + types: require("./generators/types"), + base: require("./generators/base"), + jsx: require("./generators/jsx") }; _.each(CodeGenerator.generators, function (generator) { @@ -76,7 +76,6 @@ CodeGenerator.prototype.generate = function () { return { map: this.map.get(), - ast: ast, code: this.buffer.get() }; }; diff --git a/lib/6to5/generation/generators/array-comprehensions.js b/lib/6to5/generation/generators/comprehensions.js similarity index 84% rename from lib/6to5/generation/generators/array-comprehensions.js rename to lib/6to5/generation/generators/comprehensions.js index 5e2b165564..1fe81bbbe4 100644 --- a/lib/6to5/generation/generators/array-comprehensions.js +++ b/lib/6to5/generation/generators/comprehensions.js @@ -8,7 +8,8 @@ exports.ComprehensionBlock = function (node, print) { }; exports.ComprehensionExpression = function (node, print) { - this.push("["); + this.push(node.generator ? "(" : "["); + print.join(node.blocks, { separator: " " }); this.space(); @@ -21,5 +22,6 @@ exports.ComprehensionExpression = function (node, print) { } print(node.body); - this.push("]"); + + this.push(node.generator ? ")" : "]"); }; diff --git a/lib/6to5/register.js b/lib/6to5/register.js index 81f74afa3b..d34f447533 100644 --- a/lib/6to5/register.js +++ b/lib/6to5/register.js @@ -36,6 +36,7 @@ var blacklistTest = function (transformer, code) { }; blacklistTest("arrayComprehension", "var foo = [for (foo of bar) foo * foo];"); +//blacklistTest("generatorComprehension", ""); blacklistTest("arrowFunctions", "var foo = x => x * x;"); blacklistTest("classes", "class Foo {}"); blacklistTest("computedPropertyNames", "var foo = { [foo]: bar };"); diff --git a/lib/6to5/transformation/transform.js b/lib/6to5/transformation/transform.js index ed67956519..35922f68e8 100644 --- a/lib/6to5/transformation/transform.js +++ b/lib/6to5/transformation/transform.js @@ -31,6 +31,7 @@ _.each({ propertyNameShorthand: require("./transformers/property-name-shorthand"), constants: require("./transformers/constants"), arrayComprehension: require("./transformers/array-comprehension"), + generatorComprehension: require("./transformers/generator-comprehension"), arrowFunctions: require("./transformers/arrow-functions"), classes: require("./transformers/classes"), diff --git a/lib/6to5/transformation/transformer.js b/lib/6to5/transformation/transformer.js index 06cd8debae..9def8f1912 100644 --- a/lib/6to5/transformation/transformer.js +++ b/lib/6to5/transformation/transformer.js @@ -15,6 +15,7 @@ Transformer.normalise = function (transformer) { } _.each(transformer, function (fns, type) { + if (type[0] === "_") return; if (_.isFunction(fns)) fns = { enter: fns }; transformer[type] = fns; }); diff --git a/lib/6to5/transformation/transformers/array-comprehension.js b/lib/6to5/transformation/transformers/array-comprehension.js index 5d5e087088..5e874e07df 100644 --- a/lib/6to5/transformation/transformers/array-comprehension.js +++ b/lib/6to5/transformation/transformers/array-comprehension.js @@ -37,39 +37,42 @@ var multiple = function (node, file) { var returnStatement = body.pop(); - var build = function () { - var self = node.blocks.shift(); - if (!self) return; - - var child = build(); - if (!child) { - // last item - - child = util.template("array-push", { - STATEMENT: node.body, - KEY: uid - }, true); - - // add a filter as this is our final stop - if (node.filter) { - child = t.ifStatement(node.filter, t.blockStatement([child])); - } - } - - return t.forOfStatement( - t.variableDeclaration("var", [t.variableDeclarator(self.left)]), - self.right, - t.blockStatement([child]) - ); - }; - - body.push(build()); + body.push(exports._build(node, function () { + return util.template("array-push", { + STATEMENT: node.body, + KEY: uid + }, true); + })); body.push(returnStatement); return container; }; +exports._build = function (node, buildBody) { + var self = node.blocks.shift(); + if (!self) return; + + var child = exports._build(node, buildBody); + if (!child) { + // last item + child = buildBody(); + + // add a filter as this is our final stop + if (node.filter) { + child = t.ifStatement(node.filter, t.blockStatement([child])); + } + } + + return t.forOfStatement( + t.variableDeclaration("var", [t.variableDeclarator(self.left)]), + self.right, + t.blockStatement([child]) + ); +}; + exports.ComprehensionExpression = function (node, parent, file) { + if (node.generator) return; + if (node.blocks.length === 1 && t.isArrayExpression(node.blocks[0].right)) { return singleArrayExpression(node); } else { diff --git a/test/fixtures/transformation/generator-comprehension/simple/exec.js b/test/fixtures/transformation/generator-comprehension/simple/exec.js new file mode 100644 index 0000000000..dd7ef4da0a --- /dev/null +++ b/test/fixtures/transformation/generator-comprehension/simple/exec.js @@ -0,0 +1,6 @@ +var nums = [1, 2, 3, 4, 5, 6]; +var multiples = (for (i of nums) if (i % 2) i * i); +assert.equal(multiples.next().value, 1); +assert.equal(multiples.next().value, 9); +assert.equal(multiples.next().value, 25); +assert.ok(multiples.next().done);