From 50dd2c43abf1aeb94e584dbd498c0d8e286bc989 Mon Sep 17 00:00:00 2001 From: hazzard993 Date: Wed, 26 Jun 2019 15:26:04 +1000 Subject: [PATCH 1/6] Omitted expression support --- src/LuaTransformer.ts | 6 ++++++ test/unit/array.spec.ts | 9 +++++++++ 2 files changed, 15 insertions(+) diff --git a/src/LuaTransformer.ts b/src/LuaTransformer.ts index 11e79fb8d..5a14eccce 100644 --- a/src/LuaTransformer.ts +++ b/src/LuaTransformer.ts @@ -2683,6 +2683,8 @@ export class LuaTransformer { return this.transformArrayLiteral(expression as ts.ArrayLiteralExpression); case ts.SyntaxKind.ObjectLiteralExpression: return this.transformObjectLiteral(expression as ts.ObjectLiteralExpression); + case ts.SyntaxKind.OmittedExpression: + return this.transformOmittedExpression(expression as ts.OmittedExpression); case ts.SyntaxKind.DeleteExpression: return this.transformDeleteExpression(expression as ts.DeleteExpression); case ts.SyntaxKind.FunctionExpression: @@ -3466,6 +3468,10 @@ export class LuaTransformer { return tstl.createTableExpression(properties, expression); } + public transformOmittedExpression(node: ts.OmittedExpression): ExpressionVisitResult { + return tstl.createNilLiteral(node); + } + public transformDeleteExpression(expression: ts.DeleteExpression): ExpressionVisitResult { const lhs = this.transformExpression(expression.expression) as tstl.AssignmentLeftHandSideExpression; const assignment = tstl.createAssignmentStatement(lhs, tstl.createNilLiteral(), expression); diff --git a/test/unit/array.spec.ts b/test/unit/array.spec.ts index 44d3cb3d6..3e401fad3 100644 --- a/test/unit/array.spec.ts +++ b/test/unit/array.spec.ts @@ -191,3 +191,12 @@ test.each([ `; expect(() => util.transpileAndExecute(code)).toThrowError(`invalid array length: ${result}`); }); + +test("Array OmittedExpression", () => { + const result = util.transpileAndExecute( + `const myarray = [1, , 2]; + return myarray[2];` + ); + + expect(result).toBe(2); +}); From 435a395e8f3440b90e25eb316f12e680ee947e59 Mon Sep 17 00:00:00 2001 From: hazzard993 Date: Wed, 26 Jun 2019 20:55:10 +1000 Subject: [PATCH 2/6] Add test for result of omitted expression --- test/unit/array.spec.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/test/unit/array.spec.ts b/test/unit/array.spec.ts index 3e401fad3..09cf8f61a 100644 --- a/test/unit/array.spec.ts +++ b/test/unit/array.spec.ts @@ -193,6 +193,15 @@ test.each([ }); test("Array OmittedExpression", () => { + const result = util.transpileAndExecute( + `const myarray = [,]; + return myarray[0];` + ); + + expect(result).toBe(undefined); +}); + +test("Part of Array can be an OmittedExpression", () => { const result = util.transpileAndExecute( `const myarray = [1, , 2]; return myarray[2];` From c3144543cb58a580ef7fbf0a1bbe80409178243c Mon Sep 17 00:00:00 2001 From: hazzard993 Date: Wed, 26 Jun 2019 21:43:31 +1000 Subject: [PATCH 3/6] Check the contents of the same array --- test/unit/array.spec.ts | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/test/unit/array.spec.ts b/test/unit/array.spec.ts index 09cf8f61a..f14473a39 100644 --- a/test/unit/array.spec.ts +++ b/test/unit/array.spec.ts @@ -192,20 +192,14 @@ test.each([ expect(() => util.transpileAndExecute(code)).toThrowError(`invalid array length: ${result}`); }); -test("Array OmittedExpression", () => { - const result = util.transpileAndExecute( - `const myarray = [,]; - return myarray[0];` - ); - - expect(result).toBe(undefined); -}); - -test("Part of Array can be an OmittedExpression", () => { - const result = util.transpileAndExecute( - `const myarray = [1, , 2]; - return myarray[2];` - ); - - expect(result).toBe(2); -}); +test.each([{ index: 0, expectedResult: 1 }, { index: 1, expectedResult: undefined }, { index: 2, expectedResult: 2 }])( + "Array with OmittedExpression", + ({ index, expectedResult }) => { + const result = util.transpileAndExecute( + `const myarray = [1, , 2]; + return myarray[${index}];` + ); + + expect(result).toBe(expectedResult); + } +); From aec6b9800a030376de5d9217683e2afe5498ef5b Mon Sep 17 00:00:00 2001 From: hazzard993 Date: Wed, 26 Jun 2019 22:00:50 +1000 Subject: [PATCH 4/6] Neaten up test --- test/unit/array.spec.ts | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/test/unit/array.spec.ts b/test/unit/array.spec.ts index f14473a39..7d1befc1b 100644 --- a/test/unit/array.spec.ts +++ b/test/unit/array.spec.ts @@ -192,14 +192,11 @@ test.each([ expect(() => util.transpileAndExecute(code)).toThrowError(`invalid array length: ${result}`); }); -test.each([{ index: 0, expectedResult: 1 }, { index: 1, expectedResult: undefined }, { index: 2, expectedResult: 2 }])( - "Array with OmittedExpression", - ({ index, expectedResult }) => { - const result = util.transpileAndExecute( - `const myarray = [1, , 2]; +test.each([0, 1, 2])("Array with OmittedExpression", index => { + const result = util.transpileAndExecute( + `const myarray = [1, , 2]; return myarray[${index}];` - ); + ); - expect(result).toBe(expectedResult); - } -); + expect(result).toBe([1, , 2][index]); +}); From 4af62391f0a4549e4786510ae300f10303a21103 Mon Sep 17 00:00:00 2001 From: hazzard993 Date: Wed, 26 Jun 2019 22:54:43 +1000 Subject: [PATCH 5/6] Support OmittedExpressions in array binding assignments --- src/LuaTransformer.ts | 7 ++++++- test/unit/array.spec.ts | 10 ++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/LuaTransformer.ts b/src/LuaTransformer.ts index 5a14eccce..43fbbcb2c 100644 --- a/src/LuaTransformer.ts +++ b/src/LuaTransformer.ts @@ -2909,9 +2909,14 @@ export class LuaTransformer { if (ts.isArrayLiteralExpression(expression.left)) { // Destructuring assignment + const omittedExpressionAssignmentIdentifier = tstl.createAnonymousIdentifier(); const left = expression.left.elements.length > 0 - ? expression.left.elements.map(e => this.transformExpression(e)) + ? expression.left.elements.map(e => + ts.isOmittedExpression(e) + ? omittedExpressionAssignmentIdentifier + : this.transformExpression(e) + ) : [tstl.createAnonymousIdentifier(expression.left)]; let right: tstl.Expression[]; if (ts.isArrayLiteralExpression(expression.right)) { diff --git a/test/unit/array.spec.ts b/test/unit/array.spec.ts index 7d1befc1b..d3949620f 100644 --- a/test/unit/array.spec.ts +++ b/test/unit/array.spec.ts @@ -200,3 +200,13 @@ test.each([0, 1, 2])("Array with OmittedExpression", index => { expect(result).toBe([1, , 2][index]); }); + +test("OmittedExpression in Array Binding Assignment Statement", () => { + const result = util.transpileAndExecute( + `let a, c; + [a, , c] = [1, 2, 3]; + return a + c;` + ); + + expect(result).toBe(4); +}); From fc345fa0dde71f5a70063076e0698856273be35c Mon Sep 17 00:00:00 2001 From: hazzard993 Date: Thu, 27 Jun 2019 13:43:57 +1000 Subject: [PATCH 6/6] Make transformOmittedExpression context aware and use transformBindingExpression --- src/LuaTransformer.ts | 18 +++++++++--------- src/TSHelper.ts | 13 +++++++++++++ 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/src/LuaTransformer.ts b/src/LuaTransformer.ts index 255e78cbc..e13a9a831 100644 --- a/src/LuaTransformer.ts +++ b/src/LuaTransformer.ts @@ -2909,14 +2909,9 @@ export class LuaTransformer { if (ts.isArrayLiteralExpression(expression.left)) { // Destructuring assignment - const omittedExpressionAssignmentIdentifier = tstl.createAnonymousIdentifier(); const left = expression.left.elements.length > 0 - ? expression.left.elements.map(e => - ts.isOmittedExpression(e) - ? omittedExpressionAssignmentIdentifier - : this.transformExpression(e) - ) + ? expression.left.elements.map(e => this.transformArrayBindingExpression(e)) : [tstl.createAnonymousIdentifier(expression.left)]; let right: tstl.Expression[]; if (ts.isArrayLiteralExpression(expression.right)) { @@ -3474,7 +3469,8 @@ export class LuaTransformer { } public transformOmittedExpression(node: ts.OmittedExpression): ExpressionVisitResult { - return tstl.createNilLiteral(node); + const isWithinBindingAssignmentStatement = tsHelper.isWithinLiteralAssignmentStatement(node); + return isWithinBindingAssignmentStatement ? tstl.createAnonymousIdentifier() : tstl.createNilLiteral(node); } public transformDeleteExpression(expression: ts.DeleteExpression): ExpressionVisitResult { @@ -4588,14 +4584,18 @@ export class LuaTransformer { } public transformArrayBindingElement(name: ts.ArrayBindingElement): ExpressionVisitResult { + return this.transformArrayBindingExpression(name as ts.Expression); + } + + public transformArrayBindingExpression(name: ts.Expression): ExpressionVisitResult { if (ts.isOmittedExpression(name)) { - return tstl.createIdentifier("__", name); + return this.transformOmittedExpression(name); } else if (ts.isIdentifier(name)) { return this.transformIdentifier(name); } else if (ts.isBindingElement(name) && ts.isIdentifier(name.name)) { return this.transformIdentifier(name.name); } else { - throw TSTLErrors.UnsupportedKind("array binding element", name.kind, name); + throw TSTLErrors.UnsupportedKind("array binding expression", name.kind, name); } } diff --git a/src/TSHelper.ts b/src/TSHelper.ts index aa21e8698..c6573521a 100644 --- a/src/TSHelper.ts +++ b/src/TSHelper.ts @@ -793,6 +793,19 @@ export function isEnumMember( } } +export function isWithinLiteralAssignmentStatement(node: ts.Node): boolean { + if (!node.parent) { + return false; + } + if (ts.isArrayLiteralExpression(node.parent) || ts.isObjectLiteralExpression(node.parent)) { + return isWithinLiteralAssignmentStatement(node.parent); + } else if (ts.isBinaryExpression(node.parent) && node.parent.operatorToken.kind === ts.SyntaxKind.EqualsToken) { + return true; + } else { + return false; + } +} + export function moduleHasEmittedBody( statement: ts.ModuleDeclaration ): statement is ts.ModuleDeclaration & { body: ts.ModuleBlock | ts.ModuleDeclaration } {