From 6738618e2eb3caf661ca78cf53ef9e3e2b60f671 Mon Sep 17 00:00:00 2001 From: Jan Klaas Kollhof Date: Sat, 24 Oct 2020 13:53:58 +0200 Subject: [PATCH] fix(iterables): iterables are non-stateful BREAKING CHANGE: iterables were stateful and one could only iterate over them once, refferential transparency could not be guaranteed and extra care had to be taken, caching their items using `[...iterable]`. Now iterables are not stateful anymore and can be reused and iterated over multiple times. --- src/js/async.fnk | 10 +- src/js/types.fnk | 26 ++- src/lang/async/init.test.fnk.snap | 64 +++--- src/lang/call/pipe.test.fnk | 2 +- src/lang/call/pipe.test.fnk.snap | 17 +- src/lang/iterable/filter.test.fnk.snap | 151 ++++++++------ src/lang/iterable/find.fnk | 37 ---- src/lang/iterable/find.test.fnk | 52 ----- src/lang/iterable/find.test.fnk.snap | 107 ---------- src/lang/iterable/map.test.fnk.snap | 270 +++++++++++++++---------- src/lang/iterable/unfold.test.fnk.snap | 192 +++++++++++------- src/lang/iterable/until.test.fnk.snap | 136 ++++++++----- src/lang/iterable/while.test.fnk.snap | 163 +++++++++------ 13 files changed, 636 insertions(+), 591 deletions(-) delete mode 100644 src/lang/iterable/find.fnk delete mode 100644 src/lang/iterable/find.test.fnk delete mode 100644 src/lang/iterable/find.test.fnk.snap diff --git a/src/js/async.fnk b/src/js/async.fnk index e9c760a..9e3419c 100644 --- a/src/js/async.fnk +++ b/src/js/async.fnk @@ -1,5 +1,7 @@ babel_types = import '@babel/types' -{isArrowFunctionExpression, isFunctionExpression, isForOfStatement} = babel_types +{ + isArrowFunctionExpression, isForOfStatement, isObjectMethod +} = babel_types {set_props} = import '@fink/js-interop/reflect.fnk' @@ -12,8 +14,12 @@ transform_async = fn path: isArrowFunctionExpression ?: set_props path.node, {async: true} - isFunctionExpression ?: + # generators for iterables + isObjectMethod ?: set_props path.node, {async: true} + match path.node: + {key: {property: {name: 'iterator'}}}: + set_props path.node.key.property, {name: 'asyncIterator'} isForOfStatement ?: set_props path.node, {await: true} diff --git a/src/js/types.fnk b/src/js/types.fnk index fb39534..aadaac3 100644 --- a/src/js/types.fnk +++ b/src/js/types.fnk @@ -10,7 +10,8 @@ babe_types = import '@babel/types' expressionStatement, functionExpression blockStatement, identifier, arrowFunctionExpression logicalExpression, binaryExpression, unaryExpression - doExpression, assignmentExpression, isIdentifier + doExpression, assignmentExpression, isIdentifier, objectExpression, + returnStatement, objectMethod, memberExpression } = babe_types @@ -101,10 +102,29 @@ func = fn args, ...expressions: expr_block ...expressions +symbol = fn symb: + memberExpression + identifier 'Symbol' + identifier symb + + +computed = true +async = true + + generator = fn name, args, ...statements: func_name = ident name - body = blockStatement statements - functionExpression func_name, args, body, true + + functionExpression func_name, args, + blockStatement list: + returnStatement + objectExpression list: + objectMethod + 'method', (symbol 'iterator'), [] + blockStatement list: + ...statements + computed + async for_of = fn [item, items], ...expressions: diff --git a/src/lang/async/init.test.fnk.snap b/src/lang/async/init.test.fnk.snap index c4c2980..f1f1aad 100644 --- a/src/lang/async/init.test.fnk.snap +++ b/src/lang/async/init.test.fnk.snap @@ -8,33 +8,38 @@ export const task3 = async (foo) => { const spam = await foo(); return bar + 123; }; -export const a_gen = async function* unfold(ˆinitial_2) { - let ˆaccu_3 = 0; +export const a_gen = function unfold(ˆinitial_2) { + return { + async *[Symbol.asyncIterator]() { + let ˆaccu_3 = 0; - while (true) { - const curr = ˆaccu_3; + while (true) { + const curr = ˆaccu_3; - let _do_result; + let _do_result; - ˆmatch_5: { - const ˆvalue_4 = shrub; + ˆmatch_5: { + const ˆvalue_4 = shrub; - if (ˆvalue_4 === spam) { - _do_result = await ni(curr); - break ˆmatch_5; - } + if (ˆvalue_4 === spam) { + _do_result = await ni(curr); + break ˆmatch_5; + } - { - _do_result = curr + 1; - break ˆmatch_5; + { + _do_result = curr + 1; + break ˆmatch_5; + } + } + + const ˆresult_1 = _do_result; + _do_result = undefined; + yield ˆresult_1; + ˆaccu_3 = ˆresult_1; } } - const ˆresult_1 = _do_result; - _do_result = undefined; - yield ˆresult_1; - ˆaccu_3 = ˆresult_1; - } + }; }; await ni;" `; @@ -48,15 +53,20 @@ exports[`await handles awaiting async iterables 1`] = ` { let ˆpipe_result_3 = undefined; - _do_result2 = ˆpipe_result_3 = async function* unfold(ˆinitial_5) { - let ˆaccu_6 = 0; + _do_result2 = ˆpipe_result_3 = function unfold(ˆinitial_5) { + return { + async *[Symbol.asyncIterator]() { + let ˆaccu_6 = 0; - while (true) { - const cntr = ˆaccu_6; - const ˆresult_4 = (await cntr) + 1; - yield ˆresult_4; - ˆaccu_6 = ˆresult_4; - } + while (true) { + const cntr = ˆaccu_6; + const ˆresult_4 = (await cntr) + 1; + yield ˆresult_4; + ˆaccu_6 = ˆresult_4; + } + } + + }; }(ˆpipe_result_3); } const ˆitems_1 = _do_result2; diff --git a/src/lang/call/pipe.test.fnk b/src/lang/call/pipe.test.fnk index 398452f..d5b58d9 100644 --- a/src/lang/call/pipe.test.fnk +++ b/src/lang/call/pipe.test.fnk @@ -13,13 +13,13 @@ describe 'pipe', fn: spam [...?] - pipe [1, 2, 3]: map item: item * 2 ' to_match_snapshot + describe 'small pipe |', fn: it 'pipes', fn: expect diff --git a/src/lang/call/pipe.test.fnk.snap b/src/lang/call/pipe.test.fnk.snap index 7a4b9af..961a842 100644 --- a/src/lang/call/pipe.test.fnk.snap +++ b/src/lang/call/pipe.test.fnk.snap @@ -17,12 +17,17 @@ exports[`pipe compiles 1`] = ` { let ˆpipe_result_2 = [1, 2, 3]; - ˆpipe_result_2 = function* map(ˆitems_4) { - for (const ˆitem_3 of ˆitems_4) { - const item = ˆitem_3; - const ˆresult_5 = item * 2; - yield ˆresult_5; - } + ˆpipe_result_2 = function map(ˆitems_4) { + return { + *[Symbol.iterator]() { + for (const ˆitem_3 of ˆitems_4) { + const item = ˆitem_3; + const ˆresult_5 = item * 2; + yield ˆresult_5; + } + } + + }; }(ˆpipe_result_2); }" `; diff --git a/src/lang/iterable/filter.test.fnk.snap b/src/lang/iterable/filter.test.fnk.snap index 54d36d9..8817b09 100644 --- a/src/lang/iterable/filter.test.fnk.snap +++ b/src/lang/iterable/filter.test.fnk.snap @@ -1,85 +1,120 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`filter async compiles 1`] = ` -"(async function* filter(ˆitems_2) { - for await (const ˆitem_1 of ˆitems_2) { - const item = ˆitem_1; - const ˆresult_3 = (await item) % 2 === 0; - if (ˆresult_3) yield ˆitem_1; - } +"(function filter(ˆitems_2) { + return { + async *[Symbol.asyncIterator]() { + for await (const ˆitem_1 of ˆitems_2) { + const item = ˆitem_1; + const ˆresult_3 = (await item) % 2 === 0; + if (ˆresult_3) yield ˆitem_1; + } + } + + }; });" `; exports[`filter compiles 1`] = ` -"(function* filter(ˆitems_2) { - for (const ˆitem_1 of ˆitems_2) { - const item = ˆitem_1; - const ˆresult_3 = item % 2 === 0; - if (ˆresult_3) yield ˆitem_1; - } +"(function filter(ˆitems_2) { + return { + *[Symbol.iterator]() { + for (const ˆitem_1 of ˆitems_2) { + const item = ˆitem_1; + const ˆresult_3 = item % 2 === 0; + if (ˆresult_3) yield ˆitem_1; + } + } + + }; }); -(function* filter(ˆitems_5) { - for (const ˆitem_4 of ˆitems_5) { - const [a, ...b] = ˆitem_4; - const a_alone = a(andis_empty(b)); - const ˆresult_6 = a_alone; - if (ˆresult_6) yield ˆitem_4; - } +(function filter(ˆitems_5) { + return { + *[Symbol.iterator]() { + for (const ˆitem_4 of ˆitems_5) { + const [a, ...b] = ˆitem_4; + const a_alone = a(andis_empty(b)); + const ˆresult_6 = a_alone; + if (ˆresult_6) yield ˆitem_4; + } + } + + }; }); -(function* filter(ˆitems_9) { - for (const ˆitem_7 of ˆitems_9) { - let _do_result; +(function filter(ˆitems_9) { + return { + *[Symbol.iterator]() { + for (const ˆitem_7 of ˆitems_9) { + let _do_result; - { - const [...ˆitems_8] = ˆitem_7; - _do_result = [ˆitems_8.slice(0, -1), ˆitems_8.slice(-1)]; + { + const [...ˆitems_8] = ˆitem_7; + _do_result = [ˆitems_8.slice(0, -1), ˆitems_8.slice(-1)]; + } + const [a, [b]] = _do_result; + _do_result = undefined; + const ˆresult_10 = b && is_empty(a); + if (ˆresult_10) yield ˆitem_7; + } } - const [a, [b]] = _do_result; - _do_result = undefined; - const ˆresult_10 = b && is_empty(a); - if (ˆresult_10) yield ˆitem_7; - } + + }; });" `; exports[`filter compiles with accu 1`] = ` -"(function* filter(ˆitems_3) { - let ˆaccu_2 = 0; - - for (const ˆitem_1 of ˆitems_3) { - const item = ˆitem_1; - const cntr = ˆaccu_2; - const ˆresult_4 = item < 1 && cntr % 2 === 0; - if (ˆresult_4) yield ˆitem_1; - ˆaccu_2 = cntr + 1; - } +"(function filter(ˆitems_3) { + return { + *[Symbol.iterator]() { + let ˆaccu_2 = 0; + + for (const ˆitem_1 of ˆitems_3) { + const item = ˆitem_1; + const cntr = ˆaccu_2; + const ˆresult_4 = item < 1 && cntr % 2 === 0; + if (ˆresult_4) yield ˆitem_1; + ˆaccu_2 = cntr + 1; + } + } + + }; });" `; exports[`filter compiles with accu 2`] = ` -"(function* filter(ˆitems_3) { - let ˆaccu_2 = false; - - for (const ˆitem_1 of ˆitems_3) { - const is_even = ˆaccu_2; - const ˆresult_4 = is_even; - if (ˆresult_4) yield ˆitem_1; - ˆaccu_2 = !is_even; - } +"(function filter(ˆitems_3) { + return { + *[Symbol.iterator]() { + let ˆaccu_2 = false; + + for (const ˆitem_1 of ˆitems_3) { + const is_even = ˆaccu_2; + const ˆresult_4 = is_even; + if (ˆresult_4) yield ˆitem_1; + ˆaccu_2 = !is_even; + } + } + + }; });" `; exports[`filter compiles with accu 3`] = ` -"(function* filter(ˆitems_3) { - let ˆaccu_2 = false; - - for (const ˆitem_1 of ˆitems_3) { - const is_even = ˆaccu_2; - const ˆresult_4 = is_even; - if (ˆresult_4) yield ˆitem_1; - ˆaccu_2 = !is_even; - } +"(function filter(ˆitems_3) { + return { + *[Symbol.iterator]() { + let ˆaccu_2 = false; + + for (const ˆitem_1 of ˆitems_3) { + const is_even = ˆaccu_2; + const ˆresult_4 = is_even; + if (ˆresult_4) yield ˆitem_1; + ˆaccu_2 = !is_even; + } + } + + }; });" `; diff --git a/src/lang/iterable/find.fnk b/src/lang/iterable/find.fnk deleted file mode 100644 index 5abc2f2..0000000 --- a/src/lang/iterable/find.fnk +++ /dev/null @@ -1,37 +0,0 @@ -babel_types = import '@babel/types' -{returnStatement, ifStatement} = babel_types - -{func, for_of, undef} = import '../../js/types.fnk' - -{get_iter_helpers} = import './common.fnk' - - - -transform_find = fn node, ctx: - { - acc_init - item, items - item_acc_assign - expressions - result - next_accu - } = get_iter_helpers node, ctx - - - func [items], - ...acc_init - - for_of [item, items], - ...item_acc_assign - - ...expressions - - ifStatement - result - returnStatement item - - ...next_accu - - undef _ - - diff --git a/src/lang/iterable/find.test.fnk b/src/lang/iterable/find.test.fnk deleted file mode 100644 index 2dcbb70..0000000 --- a/src/lang/iterable/find.test.fnk +++ /dev/null @@ -1,52 +0,0 @@ -{fink2js} = import '../../testing/generate.fnk' -{describe, it, expect, to_match_snapshot} = import '@fink/jest/test.fnk' - - -describe 'find', fn: - it 'compiles simple find', fn: - expect - fink2js ' - find item: - item > 3 - ' - to_match_snapshot - - - it 'compiles complex find', fn: - expect - fink2js ' - find {item}: - match item: - {spam}: shrub - else: ni - - find [foo, ...bar]: - foo_alone = foo and is_empty bar - foo_alone - - find [...foo, bar]: - bar and is_empty foo - ' - to_match_snapshot - - - it 'compiles find with accu', fn: - expect - fink2js ' - find item, is_even_elem=false: - (item > 123 and is_even_elem, not is_even_elem) - ' - to_match_snapshot - - - -describe 'find async', fn: - it 'compiles', fn: - expect - fink2js ' - find item: - await item > 3 - ' - to_match_snapshot - - diff --git a/src/lang/iterable/find.test.fnk.snap b/src/lang/iterable/find.test.fnk.snap deleted file mode 100644 index 38c7987..0000000 --- a/src/lang/iterable/find.test.fnk.snap +++ /dev/null @@ -1,107 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`find async compiles 1`] = ` -"async ˆitems_2 => { - for await (const ˆitem_1 of ˆitems_2) { - const item = ˆitem_1; - const ˆresult_3 = (await item) > 3; - if (ˆresult_3) return ˆitem_1; - } - - return undefined; -};" -`; - -exports[`find compiles complex find 1`] = ` -"ˆitems_2 => { - for (const ˆitem_1 of ˆitems_2) { - const { - \\"item\\": item - } = ˆitem_1; - - let _do_result; - - ˆmatch_5: { - const ˆvalue_4 = item; - - if (ˆvalue_4 !== undefined && ˆvalue_4 !== null) { - const { - \\"spam\\": ˆp_6 - } = ˆvalue_4; - - if (ˆp_6 === spam) { - _do_result = shrub; - break ˆmatch_5; - } - } - - { - _do_result = ni; - break ˆmatch_5; - } - } - - const ˆresult_3 = _do_result; - _do_result = undefined; - if (ˆresult_3) return ˆitem_1; - } - - return undefined; -}; - -ˆitems_8 => { - for (const ˆitem_7 of ˆitems_8) { - const [foo, ...bar] = ˆitem_7; - const foo_alone = foo && is_empty(bar); - const ˆresult_9 = foo_alone; - if (ˆresult_9) return ˆitem_7; - } - - return undefined; -}; - -ˆitems_12 => { - for (const ˆitem_10 of ˆitems_12) { - let _do_result2; - - { - const [...ˆitems_11] = ˆitem_10; - _do_result2 = [ˆitems_11.slice(0, -1), ˆitems_11.slice(-1)]; - } - const [foo, [bar]] = _do_result2; - _do_result2 = undefined; - const ˆresult_13 = bar && is_empty(foo); - if (ˆresult_13) return ˆitem_10; - } - - return undefined; -};" -`; - -exports[`find compiles find with accu 1`] = ` -"ˆitems_3 => { - let ˆaccu_2 = false; - - for (const ˆitem_1 of ˆitems_3) { - const item = ˆitem_1; - const is_even_elem = ˆaccu_2; - const ˆresult_4 = item > 123 && is_even_elem; - if (ˆresult_4) return ˆitem_1; - ˆaccu_2 = !is_even_elem; - } - - return undefined; -};" -`; - -exports[`find compiles simple find 1`] = ` -"ˆitems_2 => { - for (const ˆitem_1 of ˆitems_2) { - const item = ˆitem_1; - const ˆresult_3 = item > 3; - if (ˆresult_3) return ˆitem_1; - } - - return undefined; -};" -`; diff --git a/src/lang/iterable/map.test.fnk.snap b/src/lang/iterable/map.test.fnk.snap index 13c9570..d87045c 100644 --- a/src/lang/iterable/map.test.fnk.snap +++ b/src/lang/iterable/map.test.fnk.snap @@ -1,156 +1,216 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`map async compiles 1`] = ` -"(async function* map(ˆitems_2) { - for await (const ˆitem_1 of ˆitems_2) { - const item = ˆitem_1; - const ˆresult_3 = (await item) * 2; - yield ˆresult_3; - } +"(function map(ˆitems_2) { + return { + async *[Symbol.asyncIterator]() { + for await (const ˆitem_1 of ˆitems_2) { + const item = ˆitem_1; + const ˆresult_3 = (await item) * 2; + yield ˆresult_3; + } + } + + }; });" `; exports[`map compiles as flat map 1`] = ` -"(function* map(ˆitems_2) { - for (const ˆitem_1 of ˆitems_2) { - const [x, y] = ˆitem_1; - const ˆresult_3 = [x, y]; - yield* ˆresult_3; - } +"(function map(ˆitems_2) { + return { + *[Symbol.iterator]() { + for (const ˆitem_1 of ˆitems_2) { + const [x, y] = ˆitem_1; + const ˆresult_3 = [x, y]; + yield* ˆresult_3; + } + } + + }; });" `; exports[`map compiles destructuring 1`] = ` -"(function* map(ˆitems_2) { - for (const ˆitem_1 of ˆitems_2) { - const [x, ...rest] = ˆitem_1; - const ˆresult_3 = rest; - yield ˆresult_3; - } -}); +"(function map(ˆitems_2) { + return { + *[Symbol.iterator]() { + for (const ˆitem_1 of ˆitems_2) { + const [x, ...rest] = ˆitem_1; + const ˆresult_3 = rest; + yield ˆresult_3; + } + } -(function* map(ˆitems_6) { - for (const ˆitem_4 of ˆitems_6) { - let _do_result; + }; +}); - { - const [...ˆitems_5] = ˆitem_4; - _do_result = [ˆitems_5.slice(0, -1), ˆitems_5.slice(-1)]; +(function map(ˆitems_6) { + return { + *[Symbol.iterator]() { + for (const ˆitem_4 of ˆitems_6) { + let _do_result; + + { + const [...ˆitems_5] = ˆitem_4; + _do_result = [ˆitems_5.slice(0, -1), ˆitems_5.slice(-1)]; + } + const [ignored, [last]] = _do_result; + _do_result = undefined; + const ˆresult_7 = last; + yield ˆresult_7; + } } - const [ignored, [last]] = _do_result; - _do_result = undefined; - const ˆresult_7 = last; - yield ˆresult_7; - } + + }; });" `; exports[`map compiles multi line 1`] = ` -"(function* map(ˆitems_2) { - for (const ˆitem_1 of ˆitems_2) { - const item = ˆitem_1; - const ni = foo(item); - const ˆresult_3 = ni + 2; - yield ˆresult_3; - } +"(function map(ˆitems_2) { + return { + *[Symbol.iterator]() { + for (const ˆitem_1 of ˆitems_2) { + const item = ˆitem_1; + const ni = foo(item); + const ˆresult_3 = ni + 2; + yield ˆresult_3; + } + } + + }; });" `; exports[`map compiles single line 1`] = ` -"(function* map(ˆitems_2) { - for (const ˆitem_1 of ˆitems_2) { - const item = ˆitem_1; - const ˆresult_3 = item * 2; - yield ˆresult_3; - } +"(function map(ˆitems_2) { + return { + *[Symbol.iterator]() { + for (const ˆitem_1 of ˆitems_2) { + const item = ˆitem_1; + const ˆresult_3 = item * 2; + yield ˆresult_3; + } + } + + }; });" `; exports[`map compiles single line with default value 1`] = ` -"(function* map(ˆitems_2) { - for (const ˆitem_1 of ˆitems_2) { - const item = 123 = ˆitem_1; - const ˆresult_3 = item * 2; - yield ˆresult_3; - } +"(function map(ˆitems_2) { + return { + *[Symbol.iterator]() { + for (const ˆitem_1 of ˆitems_2) { + const item = 123 = ˆitem_1; + const ˆresult_3 = item * 2; + yield ˆresult_3; + } + } + + }; });" `; exports[`map compiles single line with destructured list 1`] = ` -"(function* map(ˆitems_2) { - for (const ˆitem_1 of ˆitems_2) { - const [x, y] = ˆitem_1; - const ˆresult_3 = x + y; - yield ˆresult_3; - } +"(function map(ˆitems_2) { + return { + *[Symbol.iterator]() { + for (const ˆitem_1 of ˆitems_2) { + const [x, y] = ˆitem_1; + const ˆresult_3 = x + y; + yield ˆresult_3; + } + } + + }; });" `; exports[`map compiles single line with destructured obj 1`] = ` -"(function* map(ˆitems_2) { - for (const ˆitem_1 of ˆitems_2) { - const { - \\"item\\": item - } = ˆitem_1; - const ˆresult_3 = item * 2; - yield ˆresult_3; - } +"(function map(ˆitems_2) { + return { + *[Symbol.iterator]() { + for (const ˆitem_1 of ˆitems_2) { + const { + \\"item\\": item + } = ˆitem_1; + const ˆresult_3 = item * 2; + yield ˆresult_3; + } + } + + }; });" `; exports[`map compiles with acc 1`] = ` -"(function* map(ˆitems_3) { - let ˆaccu_2 = 0; - - for (const ˆitem_1 of ˆitems_3) { - const { - \\"foo\\": foo - } = ˆitem_1; - const acc = ˆaccu_2; - const ˆresult_4 = foo + acc; - yield ˆresult_4; - ˆaccu_2 = acc + 1; - } +"(function map(ˆitems_3) { + return { + *[Symbol.iterator]() { + let ˆaccu_2 = 0; + + for (const ˆitem_1 of ˆitems_3) { + const { + \\"foo\\": foo + } = ˆitem_1; + const acc = ˆaccu_2; + const ˆresult_4 = foo + acc; + yield ˆresult_4; + ˆaccu_2 = acc + 1; + } + } + + }; });" `; exports[`map compiles with acc 2`] = ` -"(function* map(ˆitems_3) { - let ˆaccu_2 = 0; - - for (const ˆitem_1 of ˆitems_3) { - const { - \\"foo\\": foo - } = ˆitem_1; - const acc = ˆaccu_2; - const ˆresult_4 = [acc, foo]; - yield* ˆresult_4; - ˆaccu_2 = acc + 1; - } +"(function map(ˆitems_3) { + return { + *[Symbol.iterator]() { + let ˆaccu_2 = 0; + + for (const ˆitem_1 of ˆitems_3) { + const { + \\"foo\\": foo + } = ˆitem_1; + const acc = ˆaccu_2; + const ˆresult_4 = [acc, foo]; + yield* ˆresult_4; + ˆaccu_2 = acc + 1; + } + } + + }; });" `; exports[`map compiles with foo 1`] = ` -"(function* map(ˆitems_2) { - for (const ˆitem_1 of ˆitems_2) { - const { - \\"foo\\": foo - } = ˆitem_1; - - let _do_result; - - ˆmatch_5: { - const ˆvalue_4 = foo; - - if (ˆvalue_4 === bar) { - _do_result = spam; - break ˆmatch_5; +"(function map(ˆitems_2) { + return { + *[Symbol.iterator]() { + for (const ˆitem_1 of ˆitems_2) { + const { + \\"foo\\": foo + } = ˆitem_1; + + let _do_result; + + ˆmatch_5: { + const ˆvalue_4 = foo; + + if (ˆvalue_4 === bar) { + _do_result = spam; + break ˆmatch_5; + } + } + + const ˆresult_3 = _do_result; + _do_result = undefined; + yield ˆresult_3; } } - const ˆresult_3 = _do_result; - _do_result = undefined; - yield ˆresult_3; - } + }; });" `; diff --git a/src/lang/iterable/unfold.test.fnk.snap b/src/lang/iterable/unfold.test.fnk.snap index b65e334..30b028e 100644 --- a/src/lang/iterable/unfold.test.fnk.snap +++ b/src/lang/iterable/unfold.test.fnk.snap @@ -1,99 +1,134 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`unfold compiles destructured accus 1`] = ` -"(function* unfold(ˆinitial_2) { - let ˆaccu_3 = ˆinitial_2; - - while (true) { - const [foo, ...bar] = ˆaccu_3; - const ˆresult_1 = foo; - yield ˆresult_1; - ˆaccu_3 = bar; - } +"(function unfold(ˆinitial_2) { + return { + *[Symbol.iterator]() { + let ˆaccu_3 = ˆinitial_2; + + while (true) { + const [foo, ...bar] = ˆaccu_3; + const ˆresult_1 = foo; + yield ˆresult_1; + ˆaccu_3 = bar; + } + } + + }; });" `; exports[`unfold compiles destructured accus 2`] = ` -"(function* unfold(ˆinitial_2) { - let ˆaccu_3 = ˆinitial_2; - - while (true) { - let _do_result; - - { - const [...ˆitems_4] = ˆaccu_3; - _do_result = [ˆitems_4.slice(0, -1), ˆitems_4.slice(-1)]; +"(function unfold(ˆinitial_2) { + return { + *[Symbol.iterator]() { + let ˆaccu_3 = ˆinitial_2; + + while (true) { + let _do_result; + + { + const [...ˆitems_4] = ˆaccu_3; + _do_result = [ˆitems_4.slice(0, -1), ˆitems_4.slice(-1)]; + } + const [foo, [bar]] = _do_result; + _do_result = undefined; + const ˆresult_1 = bar; + yield ˆresult_1; + ˆaccu_3 = foo; + } } - const [foo, [bar]] = _do_result; - _do_result = undefined; - const ˆresult_1 = bar; - yield ˆresult_1; - ˆaccu_3 = foo; - } + + }; });" `; exports[`unfold compiles destructured accus 3`] = ` -"(function* unfold(ˆinitial_2) { - let ˆaccu_3 = ˆinitial_2; - - while (true) { - const [foo, ...bar] = ˆaccu_3; - const ˆresult_1 = foo; - yield* ˆresult_1; - ˆaccu_3 = bar; - } +"(function unfold(ˆinitial_2) { + return { + *[Symbol.iterator]() { + let ˆaccu_3 = ˆinitial_2; + + while (true) { + const [foo, ...bar] = ˆaccu_3; + const ˆresult_1 = foo; + yield* ˆresult_1; + ˆaccu_3 = bar; + } + } + + }; });" `; exports[`unfold compiles item is accu 1`] = ` -"(function* unfold(ˆinitial_2) { - let ˆaccu_3 = 0; - - while (true) { - const prev = ˆaccu_3; - const ˆresult_1 = prev + 1; - yield ˆresult_1; - ˆaccu_3 = ˆresult_1; - } +"(function unfold(ˆinitial_2) { + return { + *[Symbol.iterator]() { + let ˆaccu_3 = 0; + + while (true) { + const prev = ˆaccu_3; + const ˆresult_1 = prev + 1; + yield ˆresult_1; + ˆaccu_3 = ˆresult_1; + } + } + + }; });" `; exports[`unfold compiles with separate item and accu result 1`] = ` -"(function* unfold(ˆinitial_2) { - let ˆaccu_3 = {}; - - while (true) { - const { - \\"prev\\": prev = 0, - \\"acc\\": acc = 0 - } = ˆaccu_3; - const item = prev + accu; - const ˆresult_1 = item; - yield ˆresult_1; - ˆaccu_3 = { - \\"prev\\": item, - \\"accu\\": accu + 1 - }; - } +"(function unfold(ˆinitial_2) { + return { + *[Symbol.iterator]() { + let ˆaccu_3 = {}; + + while (true) { + const { + \\"prev\\": prev = 0, + \\"acc\\": acc = 0 + } = ˆaccu_3; + const item = prev + accu; + const ˆresult_1 = item; + yield ˆresult_1; + ˆaccu_3 = { + \\"prev\\": item, + \\"accu\\": accu + 1 + }; + } + } + + }; });" `; exports[`unfold compiles with spread 1`] = ` -"(function* unfold() { - while (true) { - const ˆresult_1 = [1, 2, 3]; - yield* ˆresult_1; - } +"(function unfold() { + return { + *[Symbol.iterator]() { + while (true) { + const ˆresult_1 = [1, 2, 3]; + yield* ˆresult_1; + } + } + + }; });" `; exports[`unfold compiles without accus 1`] = ` -"(function* unfold() { - while (true) { - const ˆresult_1 = 1234; - yield ˆresult_1; - } +"(function unfold() { + return { + *[Symbol.iterator]() { + while (true) { + const ˆresult_1 = 1234; + yield ˆresult_1; + } + } + + }; });" `; @@ -101,15 +136,20 @@ exports[`unfold compiles without default assignment 1`] = ` "{ let ˆpipe_result_1 = 0; - ˆpipe_result_1 = function* unfold(ˆinitial_3) { - let ˆaccu_4 = ˆinitial_3; + ˆpipe_result_1 = function unfold(ˆinitial_3) { + return { + *[Symbol.iterator]() { + let ˆaccu_4 = ˆinitial_3; - while (true) { - const prev = ˆaccu_4; - const ˆresult_2 = prev + 1; - yield ˆresult_2; - ˆaccu_4 = ˆresult_2; - } + while (true) { + const prev = ˆaccu_4; + const ˆresult_2 = prev + 1; + yield ˆresult_2; + ˆaccu_4 = ˆresult_2; + } + } + + }; }(ˆpipe_result_1); }" `; diff --git a/src/lang/iterable/until.test.fnk.snap b/src/lang/iterable/until.test.fnk.snap index 52b2780..3c7de2a 100644 --- a/src/lang/iterable/until.test.fnk.snap +++ b/src/lang/iterable/until.test.fnk.snap @@ -1,78 +1,108 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`until compiles 1`] = ` -"(function* filter_until(ˆitems_2) { - for (const ˆitem_1 of ˆitems_2) { - yield ˆitem_1; - const item = ˆitem_1; - const ˆresult_3 = item < 10; - if (ˆresult_3 === true) return; - } +"(function filter_until(ˆitems_2) { + return { + *[Symbol.iterator]() { + for (const ˆitem_1 of ˆitems_2) { + yield ˆitem_1; + const item = ˆitem_1; + const ˆresult_3 = item < 10; + if (ˆresult_3 === true) return; + } + } + + }; });" `; exports[`until compiles destructuring 1`] = ` -"(function* filter_until(ˆitems_2) { - for (const ˆitem_1 of ˆitems_2) { - yield ˆitem_1; - const [foo, ...bar] = ˆitem_1; - const foo_alone = foo && is_empty(bar); - const ˆresult_3 = foo_alone; - if (ˆresult_3 === true) return; - } +"(function filter_until(ˆitems_2) { + return { + *[Symbol.iterator]() { + for (const ˆitem_1 of ˆitems_2) { + yield ˆitem_1; + const [foo, ...bar] = ˆitem_1; + const foo_alone = foo && is_empty(bar); + const ˆresult_3 = foo_alone; + if (ˆresult_3 === true) return; + } + } + + }; }); -(function* filter_until(ˆitems_6) { - for (const ˆitem_4 of ˆitems_6) { - yield ˆitem_4; +(function filter_until(ˆitems_6) { + return { + *[Symbol.iterator]() { + for (const ˆitem_4 of ˆitems_6) { + yield ˆitem_4; - let _do_result; + let _do_result; - { - const [...ˆitems_5] = ˆitem_4; - _do_result = [ˆitems_5.slice(0, -1), ˆitems_5.slice(-1)]; + { + const [...ˆitems_5] = ˆitem_4; + _do_result = [ˆitems_5.slice(0, -1), ˆitems_5.slice(-1)]; + } + const [foo, [bar]] = _do_result; + _do_result = undefined; + const ˆresult_7 = bar && is_empty(foo); + if (ˆresult_7 === true) return; + } } - const [foo, [bar]] = _do_result; - _do_result = undefined; - const ˆresult_7 = bar && is_empty(foo); - if (ˆresult_7 === true) return; - } + + }; });" `; exports[`until compiles with accu 1`] = ` -"(function* filter_until(ˆitems_3) { - let ˆaccu_2 = 0; - - for (const ˆitem_1 of ˆitems_3) { - yield ˆitem_1; - const cntr = ˆaccu_2; - const ˆresult_4 = cntr > 2; - if (ˆresult_4 === true) return; - ˆaccu_2 = cntr + 1; - } +"(function filter_until(ˆitems_3) { + return { + *[Symbol.iterator]() { + let ˆaccu_2 = 0; + + for (const ˆitem_1 of ˆitems_3) { + yield ˆitem_1; + const cntr = ˆaccu_2; + const ˆresult_4 = cntr > 2; + if (ˆresult_4 === true) return; + ˆaccu_2 = cntr + 1; + } + } + + }; }); -(function* filter_until(ˆitems_7) { - let ˆaccu_6 = 0; +(function filter_until(ˆitems_7) { + return { + *[Symbol.iterator]() { + let ˆaccu_6 = 0; + + for (const ˆitem_5 of ˆitems_7) { + yield ˆitem_5; + const cntr = ˆaccu_6; + const ˆresult_8 = cntr > 2; + if (ˆresult_8 === true) return; + ˆaccu_6 = cntr + 1; + } + } - for (const ˆitem_5 of ˆitems_7) { - yield ˆitem_5; - const cntr = ˆaccu_6; - const ˆresult_8 = cntr > 2; - if (ˆresult_8 === true) return; - ˆaccu_6 = cntr + 1; - } + }; });" `; exports[`while async compiles 1`] = ` -"(async function* filter_until(ˆitems_2) { - for await (const ˆitem_1 of ˆitems_2) { - yield ˆitem_1; - const item = ˆitem_1; - const ˆresult_3 = (await item) < 10; - if (ˆresult_3 === true) return; - } +"(function filter_until(ˆitems_2) { + return { + async *[Symbol.asyncIterator]() { + for await (const ˆitem_1 of ˆitems_2) { + yield ˆitem_1; + const item = ˆitem_1; + const ˆresult_3 = (await item) < 10; + if (ˆresult_3 === true) return; + } + } + + }; });" `; diff --git a/src/lang/iterable/while.test.fnk.snap b/src/lang/iterable/while.test.fnk.snap index 404c55c..7320ddc 100644 --- a/src/lang/iterable/while.test.fnk.snap +++ b/src/lang/iterable/while.test.fnk.snap @@ -1,90 +1,125 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`while async compiles 1`] = ` -"(async function* filter_while(ˆitems_2) { - for await (const ˆitem_1 of ˆitems_2) { - const item = ˆitem_1; - const ˆresult_3 = (await item) < 10; - if (ˆresult_3 !== true) return; - yield ˆitem_1; - } +"(function filter_while(ˆitems_2) { + return { + async *[Symbol.asyncIterator]() { + for await (const ˆitem_1 of ˆitems_2) { + const item = ˆitem_1; + const ˆresult_3 = (await item) < 10; + if (ˆresult_3 !== true) return; + yield ˆitem_1; + } + } + + }; });" `; exports[`while compiles 1`] = ` -"(function* filter_while(ˆitems_2) { - for (const ˆitem_1 of ˆitems_2) { - const item = ˆitem_1; - const ˆresult_3 = item < 10; - if (ˆresult_3 !== true) return; - yield ˆitem_1; - } +"(function filter_while(ˆitems_2) { + return { + *[Symbol.iterator]() { + for (const ˆitem_1 of ˆitems_2) { + const item = ˆitem_1; + const ˆresult_3 = item < 10; + if (ˆresult_3 !== true) return; + yield ˆitem_1; + } + } + + }; });" `; exports[`while compiles destructuring 1`] = ` -"(function* filter_while(ˆitems_2) { - for (const ˆitem_1 of ˆitems_2) { - const [foo, ...bar] = ˆitem_1; - const foo_alone = foo && is_empty(bar); - const ˆresult_3 = foo_alone; - if (ˆresult_3 !== true) return; - yield ˆitem_1; - } +"(function filter_while(ˆitems_2) { + return { + *[Symbol.iterator]() { + for (const ˆitem_1 of ˆitems_2) { + const [foo, ...bar] = ˆitem_1; + const foo_alone = foo && is_empty(bar); + const ˆresult_3 = foo_alone; + if (ˆresult_3 !== true) return; + yield ˆitem_1; + } + } + + }; }); -(function* filter_while(ˆitems_6) { - for (const ˆitem_4 of ˆitems_6) { - let _do_result; +(function filter_while(ˆitems_6) { + return { + *[Symbol.iterator]() { + for (const ˆitem_4 of ˆitems_6) { + let _do_result; - { - const [...ˆitems_5] = ˆitem_4; - _do_result = [ˆitems_5.slice(0, -1), ˆitems_5.slice(-1)]; + { + const [...ˆitems_5] = ˆitem_4; + _do_result = [ˆitems_5.slice(0, -1), ˆitems_5.slice(-1)]; + } + const [foo, [bar]] = _do_result; + _do_result = undefined; + const ˆresult_7 = bar && is_empty(foo); + if (ˆresult_7 !== true) return; + yield ˆitem_4; + } } - const [foo, [bar]] = _do_result; - _do_result = undefined; - const ˆresult_7 = bar && is_empty(foo); - if (ˆresult_7 !== true) return; - yield ˆitem_4; - } + + }; });" `; exports[`while compiles with accu 1`] = ` -"(function* filter_while(ˆitems_3) { - let ˆaccu_2 = 0; - - for (const ˆitem_1 of ˆitems_3) { - const cntr = ˆaccu_2; - const ˆresult_4 = cntr < 2; - if (ˆresult_4 !== true) return; - yield ˆitem_1; - ˆaccu_2 = cntr + 1; - } +"(function filter_while(ˆitems_3) { + return { + *[Symbol.iterator]() { + let ˆaccu_2 = 0; + + for (const ˆitem_1 of ˆitems_3) { + const cntr = ˆaccu_2; + const ˆresult_4 = cntr < 2; + if (ˆresult_4 !== true) return; + yield ˆitem_1; + ˆaccu_2 = cntr + 1; + } + } + + }; }); -(function* filter_while(ˆitems_7) { - let ˆaccu_6 = 0; +(function filter_while(ˆitems_7) { + return { + *[Symbol.iterator]() { + let ˆaccu_6 = 0; + + for (const ˆitem_5 of ˆitems_7) { + const cntr = ˆaccu_6; + const ˆresult_8 = cntr < 2; + if (ˆresult_8 !== true) return; + yield ˆitem_5; + ˆaccu_6 = cntr + 1; + } + } - for (const ˆitem_5 of ˆitems_7) { - const cntr = ˆaccu_6; - const ˆresult_8 = cntr < 2; - if (ˆresult_8 !== true) return; - yield ˆitem_5; - ˆaccu_6 = cntr + 1; - } + }; }); -(function* filter_while(ˆitems_11) { - let ˆaccu_10 = 0; - - for (const ˆitem_9 of ˆitems_11) { - const item = ˆitem_9; - const cntr = ˆaccu_10; - const ˆresult_12 = item && cntr < 2; - if (ˆresult_12 !== true) return; - yield ˆitem_9; - ˆaccu_10 = cntr + 1; - } +(function filter_while(ˆitems_11) { + return { + *[Symbol.iterator]() { + let ˆaccu_10 = 0; + + for (const ˆitem_9 of ˆitems_11) { + const item = ˆitem_9; + const cntr = ˆaccu_10; + const ˆresult_12 = item && cntr < 2; + if (ˆresult_12 !== true) return; + yield ˆitem_9; + ˆaccu_10 = cntr + 1; + } + } + + }; });" `;