From 5c3819517768e2ca76d837bf64335e8034cf8da1 Mon Sep 17 00:00:00 2001 From: Perryvw Date: Sat, 20 Oct 2018 18:38:41 +0200 Subject: [PATCH 1/3] Cleaned up forOf loop, made it use numeric loop instead of ipairs --- src/Transpiler.ts | 28 +++++++++++++++++++--------- test/unit/loops.spec.ts | 20 ++++++++++++++++++++ 2 files changed, 39 insertions(+), 9 deletions(-) diff --git a/src/Transpiler.ts b/src/Transpiler.ts index f4882b363..8d3af52a2 100644 --- a/src/Transpiler.ts +++ b/src/Transpiler.ts @@ -562,17 +562,25 @@ export abstract class LuaTranspiler { // Use ipairs for array types, pairs otherwise const isArray = tsHelper.isArrayType(this.checker.getTypeAtLocation(node.expression), this.checker); - const pairs = isArray ? "ipairs" : "pairs"; - // Make header let result = ""; - if (ts.isIdentifier(variable.name)) { - result = this.indent + `for _, ${this.transpileIdentifier(variable.name)} in ${pairs}(${expression}) do\n`; - } else if (ts.isArrayBindingPattern(variable.name)) { - const valueVar = "__forOfValue" + this.genVarCounter; - result = this.indent + `for _, ${valueVar} in ${pairs}(${expression}) do\n`; - const declaration = ts.createVariableDeclaration(variable.name, undefined, ts.createIdentifier(valueVar)); - result += this.indent + this.transpileVariableDeclaration(declaration); + + if (!isArray && ts.isIdentifier(variable.name)) { + result = this.indent + `for _, ${this.transpileIdentifier(variable.name)} in pairs(${expression}) do\n`; + } else { + let itemVariable: ts.Identifier; + if (isArray) { + // Cache the expression result + result += this.indent + `local __loopVariable${this.genVarCounter} = ${expression};\n`; + result += this.indent + `for i${this.genVarCounter}=1, #__loopVariable${this.genVarCounter} do\n`; + itemVariable = ts.createIdentifier(`__loopVariable${this.genVarCounter}[i${this.genVarCounter}]`); + } else { + itemVariable = ts.createIdentifier(`__forOfValue${this.genVarCounter}`); + result += this.indent + `for _, ${itemVariable} in pairs(${expression}) do\n`; + } + + const declaration = ts.createVariableDeclaration(variable.name, undefined, itemVariable); + result += this.indent + " " + this.transpileVariableDeclaration(declaration) + ";\n"; } // For body @@ -580,6 +588,8 @@ export abstract class LuaTranspiler { result += this.transpileLoopBody(node); this.popIndent(); + this.genVarCounter++; + return result + this.indent + "end\n"; } diff --git a/test/unit/loops.spec.ts b/test/unit/loops.spec.ts index 007127d33..4d6d6e985 100644 --- a/test/unit/loops.spec.ts +++ b/test/unit/loops.spec.ts @@ -286,6 +286,26 @@ export class LuaLoopTests { Expect(result).toBe(JSON.stringify(expected)); } + @TestCase([[1, 2], [2, 3], [3, 4]], [3, 5, 7]) + @Test("forof destructing") + public forofDestructing(inp: number[][], expected: any): void { + // Transpile + const lua = util.transpileString( + `let objTest = ${JSON.stringify(inp)}; + let arrResultTest = []; + for (let [a,b] of objTest) { + arrResultTest.push(a + b) + } + return JSONStringify(arrResultTest);` + ); + + // Execute + const result = util.executeLua(lua); + + // Assert + Expect(result).toBe(JSON.stringify(expected)); + } + @TestCase([0, 1, 2, 3, 4], [0, 0, 2, 0, 4]) @Test("forof with continue") public forofWithContinue(inp: number[], expected: number[]): void { From 93068f20c6c00b179ad0256bdb6c61c8ded2a659 Mon Sep 17 00:00:00 2001 From: Perryvw Date: Sat, 20 Oct 2018 19:50:58 +0200 Subject: [PATCH 2/3] Fixed bug in non-array loop header and fixed tests --- src/Transpiler.ts | 5 +++-- test/translation/lua/forOf.lua | 4 +++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Transpiler.ts b/src/Transpiler.ts index 8d3af52a2..591f8518a 100644 --- a/src/Transpiler.ts +++ b/src/Transpiler.ts @@ -575,8 +575,9 @@ export abstract class LuaTranspiler { result += this.indent + `for i${this.genVarCounter}=1, #__loopVariable${this.genVarCounter} do\n`; itemVariable = ts.createIdentifier(`__loopVariable${this.genVarCounter}[i${this.genVarCounter}]`); } else { - itemVariable = ts.createIdentifier(`__forOfValue${this.genVarCounter}`); - result += this.indent + `for _, ${itemVariable} in pairs(${expression}) do\n`; + const variableName = `__forOfValue${this.genVarCounter}`; + itemVariable = ts.createIdentifier(variableName); + result += this.indent + `for _, ${variableName} in pairs(${expression}) do\n`; } const declaration = ts.createVariableDeclaration(variable.name, undefined, itemVariable); diff --git a/test/translation/lua/forOf.lua b/test/translation/lua/forOf.lua index 79c0a9fed..4a7ca76a9 100644 --- a/test/translation/lua/forOf.lua +++ b/test/translation/lua/forOf.lua @@ -1,4 +1,6 @@ -for _, i in ipairs({1,2,3,4,5,6,7,8,9,10}) do +local __loopVariable0 = {1,2,3,4,5,6,7,8,9,10}; +for i0=1, #__loopVariable0 do + local i = __loopVariable0[i0]; do end ::__continue0:: From 50b4e9446a854dc6e65a23733f2bf1784897f1f6 Mon Sep 17 00:00:00 2001 From: Perryvw Date: Sun, 21 Oct 2018 12:02:50 +0200 Subject: [PATCH 3/3] Fixed up some PR comments --- src/Transpiler.ts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/Transpiler.ts b/src/Transpiler.ts index 591f8518a..17509b8ce 100644 --- a/src/Transpiler.ts +++ b/src/Transpiler.ts @@ -558,7 +558,7 @@ export abstract class LuaTranspiler { const variable = (node.initializer as ts.VariableDeclarationList).declarations[0]; // Transpile expression - const expression = this.transpileExpression(node.expression); + const iterable = this.transpileExpression(node.expression); // Use ipairs for array types, pairs otherwise const isArray = tsHelper.isArrayType(this.checker.getTypeAtLocation(node.expression), this.checker); @@ -566,22 +566,24 @@ export abstract class LuaTranspiler { let result = ""; if (!isArray && ts.isIdentifier(variable.name)) { - result = this.indent + `for _, ${this.transpileIdentifier(variable.name)} in pairs(${expression}) do\n`; + result = this.indent + `for _, ${this.transpileIdentifier(variable.name)} in pairs(${iterable}) do\n`; } else { let itemVariable: ts.Identifier; if (isArray) { // Cache the expression result - result += this.indent + `local __loopVariable${this.genVarCounter} = ${expression};\n`; + result += this.indent + `local __loopVariable${this.genVarCounter} = ${iterable};\n`; result += this.indent + `for i${this.genVarCounter}=1, #__loopVariable${this.genVarCounter} do\n`; itemVariable = ts.createIdentifier(`__loopVariable${this.genVarCounter}[i${this.genVarCounter}]`); } else { const variableName = `__forOfValue${this.genVarCounter}`; itemVariable = ts.createIdentifier(variableName); - result += this.indent + `for _, ${variableName} in pairs(${expression}) do\n`; + result += this.indent + `for _, ${variableName} in pairs(${iterable}) do\n`; } const declaration = ts.createVariableDeclaration(variable.name, undefined, itemVariable); - result += this.indent + " " + this.transpileVariableDeclaration(declaration) + ";\n"; + this.pushIndent(); + result += this.indent + this.transpileVariableDeclaration(declaration) + ";\n"; + this.popIndent(); } // For body