From 62a6cb804663c7e10c92167d9bcb28cf7c232152 Mon Sep 17 00:00:00 2001 From: Tom <26638278+tomblind@users.noreply.github.com> Date: Sun, 5 May 2019 07:22:48 -0600 Subject: [PATCH 1/2] Support for spread operator on iterables fixes #534 --- src/LuaLib.ts | 2 ++ src/LuaTransformer.ts | 7 ++++++- src/lualib/Spread.ts | 13 +++++++++++++ test/unit/spreadElement.spec.ts | 20 ++++++++++++++++++++ 4 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 src/lualib/Spread.ts diff --git a/src/LuaLib.ts b/src/LuaLib.ts index 08a02e9c3..e1bd6981e 100644 --- a/src/LuaLib.ts +++ b/src/LuaLib.ts @@ -43,6 +43,7 @@ export enum LuaLibFeature { WeakMap = "WeakMap", WeakSet = "WeakSet", SourceMapTraceBack = "SourceMapTraceBack", + Spread = "Spread", StringConcat = "StringConcat", StringEndsWith = "StringEndsWith", StringReplace = "StringReplace", @@ -62,6 +63,7 @@ const luaLibDependencies: {[lib in LuaLibFeature]?: LuaLibFeature[]} = { Set: [LuaLibFeature.InstanceOf, LuaLibFeature.Iterator, LuaLibFeature.Symbol], WeakMap: [LuaLibFeature.InstanceOf, LuaLibFeature.Iterator, LuaLibFeature.Symbol], WeakSet: [LuaLibFeature.InstanceOf, LuaLibFeature.Iterator, LuaLibFeature.Symbol], + Spread: [LuaLibFeature.Iterator], SymbolRegistry: [LuaLibFeature.Symbol], }; diff --git a/src/LuaTransformer.ts b/src/LuaTransformer.ts index 9aee708ba..3f452107c 100644 --- a/src/LuaTransformer.ts +++ b/src/LuaTransformer.ts @@ -4561,9 +4561,14 @@ export class LuaTransformer { const innerExpression = this.expectExpression(this.transformExpression(expression.expression)); if (tsHelper.isTupleReturnCall(expression.expression, this.checker)) { return innerExpression; - } else { + } + + const type = this.checker.getTypeAtLocation(expression.expression); + if (tsHelper.isArrayType(type, this.checker, this.program)) { return this.createUnpackCall(innerExpression, expression); } + + return this.transformLuaLibFunction(LuaLibFeature.Spread, expression, innerExpression); } public transformStringLiteral(literal: ts.StringLiteralLike): ExpressionVisitResult { diff --git a/src/lualib/Spread.ts b/src/lualib/Spread.ts new file mode 100644 index 000000000..316f34ef5 --- /dev/null +++ b/src/lualib/Spread.ts @@ -0,0 +1,13 @@ +declare function unpack(this: void, list: T[], i?: number, j?: number): T[]; + +declare namespace table { + export function unpack(this: void, list: T[], i?: number, j?: number): T[]; +} + +function __TS__Spread(this: void, iterable: Iterable): T[] { + const arr: T[] = []; + for (const item of iterable) { + arr[arr.length] = item; + } + return (table.unpack || unpack)(arr); +} diff --git a/test/unit/spreadElement.spec.ts b/test/unit/spreadElement.spec.ts index dfcb345d1..fcce3b1f2 100644 --- a/test/unit/spreadElement.spec.ts +++ b/test/unit/spreadElement.spec.ts @@ -47,3 +47,23 @@ test("Spread Element Lua JIT", () => { const lua = util.transpileString(`[...[0, 1, 2]]`, options); expect(lua).toBe("local ____ = {unpack({\n 0,\n 1,\n 2,\n})}"); }); + +test("Spread Element Iterable", () => { + const code = ` + const it = { + i: 10, + [Symbol.iterator]() { + return this; + }, + next() { + --this.i; + return { + value: this.i, + done: this.i < 0, + } + } + }; + const arr = [...it]; + return JSONStringify(arr)`; + expect(util.transpileAndExecute(code)).toBe(JSON.stringify([9, 8, 7, 6, 5, 4, 3, 2, 1, 0])); +}); From d143dad4755dd16a4f4a624b7d1fae180f699c7a Mon Sep 17 00:00:00 2001 From: Tom <26638278+tomblind@users.noreply.github.com> Date: Sun, 5 May 2019 08:16:52 -0600 Subject: [PATCH 2/2] adressing feedback on test --- test/unit/spreadElement.spec.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/unit/spreadElement.spec.ts b/test/unit/spreadElement.spec.ts index fcce3b1f2..ad50137ef 100644 --- a/test/unit/spreadElement.spec.ts +++ b/test/unit/spreadElement.spec.ts @@ -51,19 +51,19 @@ test("Spread Element Lua JIT", () => { test("Spread Element Iterable", () => { const code = ` const it = { - i: 10, + i: -1, [Symbol.iterator]() { return this; }, next() { - --this.i; + ++this.i; return { - value: this.i, - done: this.i < 0, + value: 2 ** this.i, + done: this.i == 9, } } }; const arr = [...it]; return JSONStringify(arr)`; - expect(util.transpileAndExecute(code)).toBe(JSON.stringify([9, 8, 7, 6, 5, 4, 3, 2, 1, 0])); + expect(JSON.parse(util.transpileAndExecute(code))).toEqual([1, 2, 4, 8, 16, 32, 64, 128, 256]); });