typescript-to-lua 1.0.1 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (194) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/dist/CompilerOptions.d.ts +4 -3
  3. package/dist/LuaAST.d.ts +1 -0
  4. package/dist/LuaAST.js +14 -6
  5. package/dist/LuaLib.d.ts +4 -3
  6. package/dist/LuaLib.js +6 -5
  7. package/dist/LuaPrinter.d.ts +15 -4
  8. package/dist/LuaPrinter.js +81 -29
  9. package/dist/cli/diagnostics.js +2 -2
  10. package/dist/cli/parse.d.ts +1 -1
  11. package/dist/cli/parse.js +14 -0
  12. package/dist/cli/report.js +1 -1
  13. package/dist/cli/tsconfig.js +4 -4
  14. package/dist/lualib/ArrayFlat.lua +1 -1
  15. package/dist/lualib/ArrayFlatMap.lua +1 -1
  16. package/dist/lualib/ArrayIsArray.lua +1 -1
  17. package/dist/lualib/ArrayReduce.lua +7 -1
  18. package/dist/lualib/ArrayReduceRight.lua +7 -1
  19. package/dist/lualib/ArraySetLength.lua +1 -1
  20. package/dist/lualib/ArraySplice.lua +5 -5
  21. package/dist/lualib/Await.lua +43 -19
  22. package/dist/lualib/CloneDescriptor.lua +7 -7
  23. package/dist/lualib/Decorate.lua +1 -1
  24. package/dist/lualib/DelegatedYield.lua +1 -3
  25. package/dist/lualib/Delete.lua +6 -6
  26. package/dist/lualib/Error.lua +47 -44
  27. package/dist/lualib/Generator.lua +1 -5
  28. package/dist/lualib/InstanceOf.lua +1 -1
  29. package/dist/lualib/InstanceOfObject.lua +1 -1
  30. package/dist/lualib/Map.lua +130 -134
  31. package/dist/lualib/Number.lua +1 -1
  32. package/dist/lualib/NumberIsFinite.lua +1 -1
  33. package/dist/lualib/NumberToString.lua +3 -5
  34. package/dist/lualib/ObjectDefineProperty.lua +40 -8
  35. package/dist/lualib/ParseFloat.lua +9 -5
  36. package/dist/lualib/ParseInt.lua +15 -3
  37. package/dist/lualib/Promise.lua +44 -26
  38. package/dist/lualib/Set.lua +119 -123
  39. package/dist/lualib/SetDescriptor.lua +7 -1
  40. package/dist/lualib/SourceMapTraceBack.lua +19 -9
  41. package/dist/lualib/SparseArrayNew.lua +5 -0
  42. package/dist/lualib/SparseArrayPush.lua +9 -0
  43. package/dist/lualib/SparseArraySpread.lua +4 -0
  44. package/dist/lualib/StringAccess.lua +1 -1
  45. package/dist/lualib/StringCharCodeAt.lua +1 -1
  46. package/dist/lualib/StringEndsWith.lua +2 -2
  47. package/dist/lualib/StringPadEnd.lua +2 -2
  48. package/dist/lualib/StringPadStart.lua +2 -2
  49. package/dist/lualib/StringReplace.lua +12 -11
  50. package/dist/lualib/StringReplaceAll.lua +35 -0
  51. package/dist/lualib/StringSlice.lua +2 -2
  52. package/dist/lualib/StringSplit.lua +3 -3
  53. package/dist/lualib/StringStartsWith.lua +1 -1
  54. package/dist/lualib/StringSubstr.lua +1 -1
  55. package/dist/lualib/StringSubstring.lua +2 -2
  56. package/dist/lualib/Symbol.lua +3 -5
  57. package/dist/lualib/WeakMap.lua +40 -42
  58. package/dist/lualib/WeakSet.lua +36 -38
  59. package/dist/lualib/lualib_bundle.lua +876 -745
  60. package/dist/transformation/builtins/array.js +29 -30
  61. package/dist/transformation/builtins/console.js +2 -2
  62. package/dist/transformation/builtins/function.js +14 -12
  63. package/dist/transformation/builtins/global.js +8 -8
  64. package/dist/transformation/builtins/index.d.ts +1 -1
  65. package/dist/transformation/builtins/index.js +69 -36
  66. package/dist/transformation/builtins/math.js +4 -4
  67. package/dist/transformation/builtins/number.js +7 -7
  68. package/dist/transformation/builtins/object.d.ts +2 -1
  69. package/dist/transformation/builtins/object.js +12 -13
  70. package/dist/transformation/builtins/promise.js +9 -9
  71. package/dist/transformation/builtins/string.js +32 -31
  72. package/dist/transformation/builtins/symbol.js +3 -3
  73. package/dist/transformation/context/context.d.ts +12 -0
  74. package/dist/transformation/context/context.js +105 -6
  75. package/dist/transformation/index.js +1 -1
  76. package/dist/transformation/utils/annotations.d.ts +1 -3
  77. package/dist/transformation/utils/annotations.js +0 -2
  78. package/dist/transformation/utils/assignment-validation.js +8 -7
  79. package/dist/transformation/utils/diagnostics.d.ts +9 -0
  80. package/dist/transformation/utils/diagnostics.js +8 -5
  81. package/dist/transformation/utils/export.d.ts +3 -2
  82. package/dist/transformation/utils/export.js +14 -7
  83. package/dist/transformation/utils/function-context.js +8 -8
  84. package/dist/transformation/utils/language-extensions.d.ts +2 -0
  85. package/dist/transformation/utils/language-extensions.js +7 -1
  86. package/dist/transformation/utils/lua-ast.d.ts +0 -1
  87. package/dist/transformation/utils/lua-ast.js +25 -35
  88. package/dist/transformation/utils/lualib.js +1 -1
  89. package/dist/transformation/utils/preceding-statements.d.ts +3 -0
  90. package/dist/transformation/utils/preceding-statements.js +11 -0
  91. package/dist/transformation/utils/safe-names.d.ts +4 -2
  92. package/dist/transformation/utils/safe-names.js +13 -7
  93. package/dist/transformation/utils/scope.d.ts +9 -1
  94. package/dist/transformation/utils/scope.js +78 -40
  95. package/dist/transformation/utils/symbols.js +6 -6
  96. package/dist/transformation/utils/typescript/index.d.ts +1 -0
  97. package/dist/transformation/utils/typescript/index.js +16 -1
  98. package/dist/transformation/utils/typescript/nodes.d.ts +2 -0
  99. package/dist/transformation/utils/typescript/nodes.js +21 -1
  100. package/dist/transformation/utils/typescript/types.d.ts +3 -1
  101. package/dist/transformation/utils/typescript/types.js +40 -13
  102. package/dist/transformation/visitors/access.d.ts +3 -0
  103. package/dist/transformation/visitors/access.js +74 -47
  104. package/dist/transformation/visitors/async-await.js +5 -4
  105. package/dist/transformation/visitors/binary-expression/assignments.d.ts +3 -2
  106. package/dist/transformation/visitors/binary-expression/assignments.js +86 -77
  107. package/dist/transformation/visitors/binary-expression/bit.js +4 -4
  108. package/dist/transformation/visitors/binary-expression/compound.d.ts +5 -4
  109. package/dist/transformation/visitors/binary-expression/compound.js +69 -71
  110. package/dist/transformation/visitors/binary-expression/destructuring-assignments.d.ts +2 -2
  111. package/dist/transformation/visitors/binary-expression/destructuring-assignments.js +65 -36
  112. package/dist/transformation/visitors/binary-expression/index.d.ts +3 -1
  113. package/dist/transformation/visitors/binary-expression/index.js +84 -42
  114. package/dist/transformation/visitors/block.js +6 -6
  115. package/dist/transformation/visitors/break-continue.js +2 -2
  116. package/dist/transformation/visitors/call.d.ts +3 -2
  117. package/dist/transformation/visitors/call.js +130 -143
  118. package/dist/transformation/visitors/class/decorators.js +3 -3
  119. package/dist/transformation/visitors/class/index.js +43 -39
  120. package/dist/transformation/visitors/class/members/accessors.js +6 -6
  121. package/dist/transformation/visitors/class/members/constructor.js +7 -7
  122. package/dist/transformation/visitors/class/members/fields.js +6 -6
  123. package/dist/transformation/visitors/class/members/method.js +6 -6
  124. package/dist/transformation/visitors/class/new.js +14 -16
  125. package/dist/transformation/visitors/class/setup.js +11 -11
  126. package/dist/transformation/visitors/class/utils.js +2 -2
  127. package/dist/transformation/visitors/conditional.js +36 -43
  128. package/dist/transformation/visitors/delete.js +8 -4
  129. package/dist/transformation/visitors/enum.js +8 -8
  130. package/dist/transformation/visitors/errors.js +35 -33
  131. package/dist/transformation/visitors/expression-list.d.ts +7 -0
  132. package/dist/transformation/visitors/expression-list.js +120 -0
  133. package/dist/transformation/visitors/expression-statement.js +10 -6
  134. package/dist/transformation/visitors/function.d.ts +2 -0
  135. package/dist/transformation/visitors/function.js +80 -33
  136. package/dist/transformation/visitors/identifier.js +26 -22
  137. package/dist/transformation/visitors/index.js +2 -2
  138. package/dist/transformation/visitors/language-extensions/iterable.js +7 -7
  139. package/dist/transformation/visitors/language-extensions/multi.d.ts +1 -1
  140. package/dist/transformation/visitors/language-extensions/multi.js +3 -3
  141. package/dist/transformation/visitors/language-extensions/operators.js +6 -6
  142. package/dist/transformation/visitors/language-extensions/pairsIterable.d.ts +5 -0
  143. package/dist/transformation/visitors/language-extensions/pairsIterable.js +53 -0
  144. package/dist/transformation/visitors/language-extensions/range.js +6 -6
  145. package/dist/transformation/visitors/language-extensions/table.js +5 -5
  146. package/dist/transformation/visitors/literal.d.ts +1 -2
  147. package/dist/transformation/visitors/literal.js +87 -57
  148. package/dist/transformation/visitors/loops/do-while.js +35 -9
  149. package/dist/transformation/visitors/loops/for-in.js +4 -4
  150. package/dist/transformation/visitors/loops/for-of.js +17 -13
  151. package/dist/transformation/visitors/loops/for.js +28 -8
  152. package/dist/transformation/visitors/loops/utils.d.ts +1 -0
  153. package/dist/transformation/visitors/loops/utils.js +26 -10
  154. package/dist/transformation/visitors/modules/export.js +14 -15
  155. package/dist/transformation/visitors/modules/import.js +10 -10
  156. package/dist/transformation/visitors/namespace.js +13 -13
  157. package/dist/transformation/visitors/optional-chaining.d.ts +16 -0
  158. package/dist/transformation/visitors/optional-chaining.js +172 -0
  159. package/dist/transformation/visitors/return.d.ts +1 -0
  160. package/dist/transformation/visitors/return.js +40 -26
  161. package/dist/transformation/visitors/sourceFile.js +12 -9
  162. package/dist/transformation/visitors/spread.js +23 -16
  163. package/dist/transformation/visitors/switch.js +63 -20
  164. package/dist/transformation/visitors/template.js +10 -7
  165. package/dist/transformation/visitors/typeof.js +4 -2
  166. package/dist/transformation/visitors/typescript.js +1 -1
  167. package/dist/transformation/visitors/unary-expression.js +9 -9
  168. package/dist/transformation/visitors/variable-declaration.js +55 -32
  169. package/dist/transformation/visitors/void.d.ts +6 -0
  170. package/dist/transformation/visitors/void.js +20 -0
  171. package/dist/transpilation/bundle.d.ts +3 -0
  172. package/dist/transpilation/bundle.js +52 -10
  173. package/dist/transpilation/diagnostics.js +3 -3
  174. package/dist/transpilation/index.js +2 -2
  175. package/dist/transpilation/output-collector.js +2 -2
  176. package/dist/transpilation/plugins.js +1 -1
  177. package/dist/transpilation/resolve.js +20 -13
  178. package/dist/transpilation/transformers.js +45 -25
  179. package/dist/transpilation/transpile.js +6 -6
  180. package/dist/transpilation/transpiler.js +8 -8
  181. package/dist/transpilation/utils.js +5 -3
  182. package/dist/tstl.js +8 -8
  183. package/dist/utils.js +2 -2
  184. package/language-extensions/index.d.ts +11 -1
  185. package/package.json +15 -12
  186. package/dist/lualib/OptionalChainAccess.lua +0 -6
  187. package/dist/lualib/OptionalFunctionCall.lua +0 -6
  188. package/dist/lualib/OptionalMethodCall.lua +0 -11
  189. package/dist/transformation/utils/transform.d.ts +0 -8
  190. package/dist/transformation/utils/transform.js +0 -14
  191. package/dist/transformation/visitors/jsx/jsx.d.ts +0 -9
  192. package/dist/transformation/visitors/jsx/jsx.js +0 -237
  193. package/dist/transformation/visitors/jsx/xhtml.d.ts +0 -3
  194. package/dist/transformation/visitors/jsx/xhtml.js +0 -260
@@ -1,7 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isFirstDeclaration = exports.getSymbolOfNode = exports.isInDestructingAssignment = exports.isAmbientNode = exports.isDestructuringAssignment = exports.isAssignmentPattern = void 0;
3
+ exports.isFirstDeclaration = exports.getSymbolOfNode = exports.isInGeneratorFunction = exports.isInAsyncFunction = exports.isInDestructingAssignment = exports.isAmbientNode = exports.isDestructuringAssignment = exports.isAssignmentPattern = void 0;
4
4
  const ts = require("typescript");
5
+ const _1 = require(".");
5
6
  function isAssignmentPattern(node) {
6
7
  return ts.isObjectLiteralExpression(node) || ts.isArrayLiteralExpression(node);
7
8
  }
@@ -22,6 +23,25 @@ function isInDestructingAssignment(node) {
22
23
  (ts.isBinaryExpression(node.parent) && ts.isArrayLiteralExpression(node.parent.left))));
23
24
  }
24
25
  exports.isInDestructingAssignment = isInDestructingAssignment;
26
+ function isInAsyncFunction(node) {
27
+ var _a, _b;
28
+ // Check if node is in function declaration with `async`
29
+ const declaration = (0, _1.findFirstNodeAbove)(node, ts.isFunctionLike);
30
+ if (!declaration) {
31
+ return false;
32
+ }
33
+ return (_b = (_a = declaration.modifiers) === null || _a === void 0 ? void 0 : _a.some(m => m.kind === ts.SyntaxKind.AsyncKeyword)) !== null && _b !== void 0 ? _b : false;
34
+ }
35
+ exports.isInAsyncFunction = isInAsyncFunction;
36
+ function isInGeneratorFunction(node) {
37
+ // Check if node is in function declaration with `async`
38
+ const declaration = (0, _1.findFirstNodeAbove)(node, ts.isFunctionDeclaration);
39
+ if (!declaration) {
40
+ return false;
41
+ }
42
+ return declaration.asteriskToken !== undefined;
43
+ }
44
+ exports.isInGeneratorFunction = isInGeneratorFunction;
25
45
  /**
26
46
  * Quite hacky, avoid unless absolutely necessary!
27
47
  */
@@ -10,4 +10,6 @@ export declare function isNumberType(context: TransformationContext, type: ts.Ty
10
10
  */
11
11
  export declare function forTypeOrAnySupertype(context: TransformationContext, type: ts.Type, predicate: (type: ts.Type) => boolean): boolean;
12
12
  export declare function isArrayType(context: TransformationContext, type: ts.Type): boolean;
13
- export declare function isFunctionType(context: TransformationContext, type: ts.Type): boolean;
13
+ export declare function isFunctionType(type: ts.Type): boolean;
14
+ export declare function canBeFalsy(context: TransformationContext, type: ts.Type): boolean;
15
+ export declare function canBeFalsyWhenNotNull(context: TransformationContext, type: ts.Type): boolean;
@@ -1,21 +1,17 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isFunctionType = exports.isArrayType = exports.forTypeOrAnySupertype = exports.isNumberType = exports.isStringType = exports.typeCanSatisfy = exports.typeAlwaysSatisfies = exports.isTypeWithFlags = void 0;
3
+ exports.canBeFalsyWhenNotNull = exports.canBeFalsy = exports.isFunctionType = exports.isArrayType = exports.forTypeOrAnySupertype = exports.isNumberType = exports.isStringType = exports.typeCanSatisfy = exports.typeAlwaysSatisfies = exports.isTypeWithFlags = void 0;
4
4
  const ts = require("typescript");
5
5
  function isTypeWithFlags(context, type, flags) {
6
- const predicate = (type) => {
7
- if (type.symbol) {
8
- const baseConstraint = context.checker.getBaseConstraintOfType(type);
9
- if (baseConstraint && baseConstraint !== type) {
10
- return isTypeWithFlags(context, baseConstraint, flags);
11
- }
12
- }
13
- return (type.flags & flags) !== 0;
14
- };
6
+ const predicate = (type) => (type.flags & flags) !== 0;
15
7
  return typeAlwaysSatisfies(context, type, predicate);
16
8
  }
17
9
  exports.isTypeWithFlags = isTypeWithFlags;
18
10
  function typeAlwaysSatisfies(context, type, predicate) {
11
+ const baseConstraint = context.checker.getBaseConstraintOfType(type);
12
+ if (baseConstraint) {
13
+ type = baseConstraint;
14
+ }
19
15
  if (predicate(type)) {
20
16
  return true;
21
17
  }
@@ -29,6 +25,15 @@ function typeAlwaysSatisfies(context, type, predicate) {
29
25
  }
30
26
  exports.typeAlwaysSatisfies = typeAlwaysSatisfies;
31
27
  function typeCanSatisfy(context, type, predicate) {
28
+ const baseConstraint = context.checker.getBaseConstraintOfType(type);
29
+ if (!baseConstraint) {
30
+ // type parameter with no constraint can be anything, assume it might satisfy predicate
31
+ if (type.isTypeParameter())
32
+ return true;
33
+ }
34
+ else {
35
+ type = baseConstraint;
36
+ }
32
37
  if (predicate(type)) {
33
38
  return true;
34
39
  }
@@ -84,9 +89,31 @@ function isArrayType(context, type) {
84
89
  return forTypeOrAnySupertype(context, type, t => isExplicitArrayType(context, t));
85
90
  }
86
91
  exports.isArrayType = isArrayType;
87
- function isFunctionType(context, type) {
88
- const typeNode = context.checker.typeToTypeNode(type, undefined, ts.NodeBuilderFlags.InTypeAlias);
89
- return typeNode !== undefined && ts.isFunctionTypeNode(typeNode);
92
+ function isFunctionType(type) {
93
+ return type.getCallSignatures().length > 0;
90
94
  }
91
95
  exports.isFunctionType = isFunctionType;
96
+ function canBeFalsy(context, type) {
97
+ const strictNullChecks = context.options.strict === true || context.options.strictNullChecks === true;
98
+ const falsyFlags = ts.TypeFlags.Boolean |
99
+ ts.TypeFlags.BooleanLiteral |
100
+ ts.TypeFlags.Never |
101
+ ts.TypeFlags.Void |
102
+ ts.TypeFlags.Unknown |
103
+ ts.TypeFlags.Any |
104
+ ts.TypeFlags.Undefined |
105
+ ts.TypeFlags.Null;
106
+ return typeCanSatisfy(context, type, type => (type.flags & falsyFlags) !== 0 || (!strictNullChecks && !type.isLiteral()));
107
+ }
108
+ exports.canBeFalsy = canBeFalsy;
109
+ function canBeFalsyWhenNotNull(context, type) {
110
+ const falsyFlags = ts.TypeFlags.Boolean |
111
+ ts.TypeFlags.BooleanLiteral |
112
+ ts.TypeFlags.Never |
113
+ ts.TypeFlags.Void |
114
+ ts.TypeFlags.Unknown |
115
+ ts.TypeFlags.Any;
116
+ return typeCanSatisfy(context, type, type => (type.flags & falsyFlags) !== 0);
117
+ }
118
+ exports.canBeFalsyWhenNotNull = canBeFalsyWhenNotNull;
92
119
  //# sourceMappingURL=types.js.map
@@ -1,7 +1,10 @@
1
1
  import * as ts from "typescript";
2
2
  import * as lua from "../../LuaAST";
3
3
  import { FunctionVisitor, TransformationContext } from "../context";
4
+ import { ExpressionWithThisValue } from "./optional-chaining";
4
5
  export declare function transformElementAccessArgument(context: TransformationContext, node: ts.ElementAccessExpression): lua.Expression;
5
6
  export declare const transformElementAccessExpression: FunctionVisitor<ts.ElementAccessExpression>;
7
+ export declare function transformElementAccessExpressionWithCapture(context: TransformationContext, node: ts.ElementAccessExpression, thisValueCapture: lua.Identifier | undefined): ExpressionWithThisValue;
6
8
  export declare const transformPropertyAccessExpression: FunctionVisitor<ts.PropertyAccessExpression>;
9
+ export declare function transformPropertyAccessExpressionWithCapture(context: TransformationContext, node: ts.PropertyAccessExpression, thisValueCapture: lua.Identifier | undefined): ExpressionWithThisValue;
7
10
  export declare const transformQualifiedName: FunctionVisitor<ts.QualifiedName>;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.transformQualifiedName = exports.transformPropertyAccessExpression = exports.transformElementAccessExpression = exports.transformElementAccessArgument = void 0;
3
+ exports.transformQualifiedName = exports.transformPropertyAccessExpressionWithCapture = exports.transformPropertyAccessExpression = exports.transformElementAccessExpressionWithCapture = exports.transformElementAccessExpression = exports.transformElementAccessArgument = void 0;
4
4
  const ts = require("typescript");
5
5
  const lua = require("../../LuaAST");
6
6
  const builtins_1 = require("../builtins");
@@ -10,92 +10,119 @@ const lua_ast_1 = require("../utils/lua-ast");
10
10
  const lualib_1 = require("../utils/lualib");
11
11
  const typescript_1 = require("../utils/typescript");
12
12
  const enum_1 = require("./enum");
13
+ const expression_list_1 = require("./expression-list");
13
14
  const multi_1 = require("./language-extensions/multi");
14
- function transformElementAccessArgument(context, node) {
15
- const index = context.transformExpression(node.argumentExpression);
15
+ const optional_chaining_1 = require("./optional-chaining");
16
+ function addOneToArrayAccessArgument(context, node, index) {
16
17
  const type = context.checker.getTypeAtLocation(node.expression);
17
18
  const argumentType = context.checker.getTypeAtLocation(node.argumentExpression);
18
- if (typescript_1.isArrayType(context, type) && typescript_1.isNumberType(context, argumentType)) {
19
- return lua_ast_1.addToNumericExpression(index, 1);
19
+ if ((0, typescript_1.isArrayType)(context, type) && (0, typescript_1.isNumberType)(context, argumentType)) {
20
+ return (0, lua_ast_1.addToNumericExpression)(index, 1);
20
21
  }
21
22
  return index;
22
23
  }
24
+ function transformElementAccessArgument(context, node) {
25
+ const index = context.transformExpression(node.argumentExpression);
26
+ return addOneToArrayAccessArgument(context, node, index);
27
+ }
23
28
  exports.transformElementAccessArgument = transformElementAccessArgument;
24
- const transformElementAccessExpression = (node, context) => {
25
- const constEnumValue = enum_1.tryGetConstEnumValue(context, node);
29
+ const transformElementAccessExpression = (node, context) => transformElementAccessExpressionWithCapture(context, node, undefined).expression;
30
+ exports.transformElementAccessExpression = transformElementAccessExpression;
31
+ function transformElementAccessExpressionWithCapture(context, node, thisValueCapture) {
32
+ const constEnumValue = (0, enum_1.tryGetConstEnumValue)(context, node);
26
33
  if (constEnumValue) {
27
- return constEnumValue;
34
+ return { expression: constEnumValue };
28
35
  }
29
- const table = context.transformExpression(node.expression);
36
+ if (ts.isOptionalChain(node)) {
37
+ return (0, optional_chaining_1.transformOptionalChainWithCapture)(context, node, thisValueCapture);
38
+ }
39
+ const [table, accessExpression] = (0, expression_list_1.transformOrderedExpressions)(context, [node.expression, node.argumentExpression]);
30
40
  const type = context.checker.getTypeAtLocation(node.expression);
31
41
  const argumentType = context.checker.getTypeAtLocation(node.argumentExpression);
32
- if (typescript_1.isStringType(context, type) && typescript_1.isNumberType(context, argumentType)) {
33
- const index = context.transformExpression(node.argumentExpression);
34
- return lualib_1.transformLuaLibFunction(context, lualib_1.LuaLibFeature.StringAccess, node, table, index);
42
+ if ((0, typescript_1.isStringType)(context, type) && (0, typescript_1.isNumberType)(context, argumentType)) {
43
+ // strings are not callable, so ignore thisValueCapture
44
+ return {
45
+ expression: (0, lualib_1.transformLuaLibFunction)(context, lualib_1.LuaLibFeature.StringAccess, node, table, accessExpression),
46
+ };
35
47
  }
36
- const accessExpression = transformElementAccessArgument(context, node);
37
- if (multi_1.isMultiReturnCall(context, node.expression)) {
48
+ const updatedAccessExpression = addOneToArrayAccessArgument(context, node, accessExpression);
49
+ if ((0, multi_1.isMultiReturnCall)(context, node.expression)) {
38
50
  const accessType = context.checker.getTypeAtLocation(node.argumentExpression);
39
- if (!typescript_1.isNumberType(context, accessType)) {
40
- context.diagnostics.push(diagnostics_1.invalidMultiReturnAccess(node));
51
+ if (!(0, typescript_1.isNumberType)(context, accessType)) {
52
+ context.diagnostics.push((0, diagnostics_1.invalidMultiReturnAccess)(node));
41
53
  }
42
54
  // When selecting the first element, we can shortcut
43
55
  if (ts.isNumericLiteral(node.argumentExpression) && node.argumentExpression.text === "0") {
44
- return table;
56
+ return { expression: table };
45
57
  }
46
58
  else {
47
59
  const selectIdentifier = lua.createIdentifier("select");
48
- const selectCall = lua.createCallExpression(selectIdentifier, [accessExpression, table]);
49
- return selectCall;
60
+ return { expression: lua.createCallExpression(selectIdentifier, [updatedAccessExpression, table]) };
50
61
  }
51
62
  }
52
- if (ts.isOptionalChain(node)) {
53
- return lualib_1.transformLuaLibFunction(context, lualib_1.LuaLibFeature.OptionalChainAccess, node, table, accessExpression);
63
+ if (thisValueCapture) {
64
+ const thisValue = (0, optional_chaining_1.captureThisValue)(context, table, thisValueCapture, node.expression);
65
+ return {
66
+ expression: lua.createTableIndexExpression(thisValue, updatedAccessExpression, node),
67
+ thisValue,
68
+ };
54
69
  }
55
- return lua.createTableIndexExpression(table, accessExpression, node);
56
- };
57
- exports.transformElementAccessExpression = transformElementAccessExpression;
58
- const transformPropertyAccessExpression = (node, context) => {
70
+ return { expression: lua.createTableIndexExpression(table, updatedAccessExpression, node) };
71
+ }
72
+ exports.transformElementAccessExpressionWithCapture = transformElementAccessExpressionWithCapture;
73
+ const transformPropertyAccessExpression = (node, context) => transformPropertyAccessExpressionWithCapture(context, node, undefined).expression;
74
+ exports.transformPropertyAccessExpression = transformPropertyAccessExpression;
75
+ function transformPropertyAccessExpressionWithCapture(context, node, thisValueCapture) {
59
76
  const property = node.name.text;
60
77
  const type = context.checker.getTypeAtLocation(node.expression);
61
- const annotations = annotations_1.getTypeAnnotations(type);
78
+ const isOptionalLeft = (0, optional_chaining_1.isOptionalContinuation)(node.expression);
79
+ const annotations = (0, annotations_1.getTypeAnnotations)(type);
62
80
  if (annotations.has(annotations_1.AnnotationKind.LuaTable)) {
63
- context.diagnostics.push(diagnostics_1.annotationRemoved(node, annotations_1.AnnotationKind.LuaTable));
81
+ context.diagnostics.push((0, diagnostics_1.annotationRemoved)(node, annotations_1.AnnotationKind.LuaTable));
64
82
  }
65
- const constEnumValue = enum_1.tryGetConstEnumValue(context, node);
83
+ const constEnumValue = (0, enum_1.tryGetConstEnumValue)(context, node);
66
84
  if (constEnumValue) {
67
- return constEnumValue;
85
+ return { expression: constEnumValue };
68
86
  }
69
- const builtinResult = builtins_1.transformBuiltinPropertyAccessExpression(context, node);
70
- if (builtinResult) {
71
- return builtinResult;
87
+ if (ts.isCallExpression(node.expression) && (0, multi_1.returnsMultiType)(context, node.expression)) {
88
+ context.diagnostics.push((0, diagnostics_1.invalidMultiReturnAccess)(node));
72
89
  }
73
- if (ts.isCallExpression(node.expression) && multi_1.returnsMultiType(context, node.expression)) {
74
- context.diagnostics.push(diagnostics_1.invalidMultiReturnAccess(node));
90
+ if (ts.isOptionalChain(node)) {
91
+ return (0, optional_chaining_1.transformOptionalChainWithCapture)(context, node, thisValueCapture);
75
92
  }
76
93
  // Do not output path for member only enums
77
94
  if (annotations.has(annotations_1.AnnotationKind.CompileMembersOnly)) {
95
+ if (isOptionalLeft) {
96
+ context.diagnostics.push((0, diagnostics_1.unsupportedOptionalCompileMembersOnly)(node));
97
+ }
78
98
  if (ts.isPropertyAccessExpression(node.expression)) {
79
99
  // in case of ...x.enum.y transform to ...x.y
80
- return lua.createTableIndexExpression(context.transformExpression(node.expression.expression), lua.createStringLiteral(property), node);
100
+ const expression = lua.createTableIndexExpression(context.transformExpression(node.expression.expression), lua.createStringLiteral(property), node);
101
+ return { expression };
81
102
  }
82
103
  else {
83
- return lua.createIdentifier(property, node);
104
+ return { expression: lua.createIdentifier(property, node) };
84
105
  }
85
106
  }
86
- if (ts.isOptionalChain(node)) {
87
- // Only handle full optional chains separately, not partial ones
88
- return transformOptionalChain(context, node);
107
+ const builtinResult = (0, builtins_1.transformBuiltinPropertyAccessExpression)(context, node);
108
+ if (builtinResult) {
109
+ // Ignore thisValueCapture.
110
+ // This assumes that nothing returned by builtin property accesses are callable.
111
+ // If this assumption is no longer true, this may need to be updated.
112
+ return { expression: builtinResult };
89
113
  }
90
- const callPath = context.transformExpression(node.expression);
91
- return lua.createTableIndexExpression(callPath, lua.createStringLiteral(property), node);
92
- };
93
- exports.transformPropertyAccessExpression = transformPropertyAccessExpression;
94
- function transformOptionalChain(context, node) {
95
- const left = context.transformExpression(node.expression);
96
- const right = lua.createStringLiteral(node.name.text, node.name);
97
- return lualib_1.transformLuaLibFunction(context, lualib_1.LuaLibFeature.OptionalChainAccess, node, left, right);
114
+ const table = context.transformExpression(node.expression);
115
+ if (thisValueCapture) {
116
+ const thisValue = (0, optional_chaining_1.captureThisValue)(context, table, thisValueCapture, node.expression);
117
+ const expression = lua.createTableIndexExpression(thisValue, lua.createStringLiteral(property), node);
118
+ return {
119
+ expression,
120
+ thisValue,
121
+ };
122
+ }
123
+ return { expression: lua.createTableIndexExpression(table, lua.createStringLiteral(property), node) };
98
124
  }
125
+ exports.transformPropertyAccessExpressionWithCapture = transformPropertyAccessExpressionWithCapture;
99
126
  const transformQualifiedName = (node, context) => {
100
127
  const right = lua.createStringLiteral(node.right.text, node.right);
101
128
  const left = context.transformExpression(node.left);
@@ -9,13 +9,14 @@ const typescript_1 = require("../utils/typescript");
9
9
  const transformAwaitExpression = (node, context) => {
10
10
  var _a;
11
11
  // Check if await is inside an async function, it is not allowed at top level or in non-async functions
12
- const containingFunction = typescript_1.findFirstNodeAbove(node, ts.isFunctionLike);
12
+ const containingFunction = (0, typescript_1.findFirstNodeAbove)(node, ts.isFunctionLike);
13
13
  if (containingFunction === undefined ||
14
14
  !((_a = containingFunction.modifiers) === null || _a === void 0 ? void 0 : _a.some(m => m.kind === ts.SyntaxKind.AsyncKeyword))) {
15
- context.diagnostics.push(diagnostics_1.awaitMustBeInAsyncFunction(node));
15
+ context.diagnostics.push((0, diagnostics_1.awaitMustBeInAsyncFunction)(node));
16
16
  }
17
17
  const expression = context.transformExpression(node.expression);
18
- return lualib_1.transformLuaLibFunction(context, lualib_1.LuaLibFeature.Await, node, expression);
18
+ const catchIdentifier = lua.createIdentifier("____catch");
19
+ return (0, lualib_1.transformLuaLibFunction)(context, lualib_1.LuaLibFeature.Await, node, catchIdentifier, expression);
19
20
  };
20
21
  exports.transformAwaitExpression = transformAwaitExpression;
21
22
  function isAsyncFunction(declaration) {
@@ -24,7 +25,7 @@ function isAsyncFunction(declaration) {
24
25
  }
25
26
  exports.isAsyncFunction = isAsyncFunction;
26
27
  function wrapInAsyncAwaiter(context, statements) {
27
- lualib_1.importLuaLibFeature(context, lualib_1.LuaLibFeature.Await);
28
+ (0, lualib_1.importLuaLibFeature)(context, lualib_1.LuaLibFeature.Await);
28
29
  return [
29
30
  lua.createReturnStatement([
30
31
  lua.createCallExpression(lua.createIdentifier("__TS__AsyncAwaiter"), [
@@ -1,7 +1,8 @@
1
1
  import * as ts from "typescript";
2
2
  import * as lua from "../../../LuaAST";
3
3
  import { TransformationContext } from "../../context";
4
- export declare function transformAssignmentLeftHandSideExpression(context: TransformationContext, node: ts.Expression): lua.AssignmentLeftHandSideExpression;
5
- export declare function transformAssignment(context: TransformationContext, lhs: ts.Expression, right: lua.Expression, parent?: ts.Expression): lua.Statement[];
4
+ export declare function transformAssignmentLeftHandSideExpression(context: TransformationContext, node: ts.Expression, rightHasPrecedingStatements?: boolean): lua.AssignmentLeftHandSideExpression;
5
+ export declare function transformAssignment(context: TransformationContext, lhs: ts.Expression, right: lua.Expression, rightHasPrecedingStatements?: boolean, parent?: ts.Expression): lua.Statement[];
6
+ export declare function transformAssignmentWithRightPrecedingStatements(context: TransformationContext, lhs: ts.Expression, right: lua.Expression, rightPrecedingStatements: lua.Statement[], parent?: ts.Expression): lua.Statement[];
6
7
  export declare function transformAssignmentExpression(context: TransformationContext, expression: ts.AssignmentExpression<ts.EqualsToken>): lua.Expression;
7
8
  export declare function transformAssignmentStatement(context: TransformationContext, expression: ts.AssignmentExpression<ts.EqualsToken>): lua.Statement[];
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.transformAssignmentStatement = exports.transformAssignmentExpression = exports.transformAssignment = exports.transformAssignmentLeftHandSideExpression = void 0;
3
+ exports.transformAssignmentStatement = exports.transformAssignmentExpression = exports.transformAssignmentWithRightPrecedingStatements = exports.transformAssignment = exports.transformAssignmentLeftHandSideExpression = void 0;
4
4
  const ts = require("typescript");
5
5
  const lua = require("../../../LuaAST");
6
6
  const utils_1 = require("../../../utils");
@@ -9,56 +9,78 @@ const export_1 = require("../../utils/export");
9
9
  const lua_ast_1 = require("../../utils/lua-ast");
10
10
  const lualib_1 = require("../../utils/lualib");
11
11
  const typescript_1 = require("../../utils/typescript");
12
- const access_1 = require("../access");
13
12
  const destructuring_assignments_1 = require("./destructuring-assignments");
14
13
  const multi_1 = require("../language-extensions/multi");
15
- const scope_1 = require("../../utils/scope");
16
- const transform_1 = require("../../utils/transform");
17
14
  const diagnostics_1 = require("../../utils/diagnostics");
18
- function transformAssignmentLeftHandSideExpression(context, node) {
15
+ const access_1 = require("../access");
16
+ const expression_list_1 = require("../expression-list");
17
+ const preceding_statements_1 = require("../../utils/preceding-statements");
18
+ function transformAssignmentLeftHandSideExpression(context, node, rightHasPrecedingStatements) {
19
+ // Access expressions need the components of the left side cached in temps before the right side's preceding statements
20
+ if (rightHasPrecedingStatements && (ts.isElementAccessExpression(node) || ts.isPropertyAccessExpression(node))) {
21
+ let table = context.transformExpression(node.expression);
22
+ table = (0, expression_list_1.moveToPrecedingTemp)(context, table, node.expression);
23
+ let index;
24
+ if (ts.isElementAccessExpression(node)) {
25
+ index = (0, access_1.transformElementAccessArgument)(context, node);
26
+ index = (0, expression_list_1.moveToPrecedingTemp)(context, index, node.argumentExpression);
27
+ }
28
+ else {
29
+ index = lua.createStringLiteral(node.name.text, node.name);
30
+ }
31
+ return lua.createTableIndexExpression(table, index, node);
32
+ }
19
33
  const symbol = context.checker.getSymbolAtLocation(node);
20
34
  const left = context.transformExpression(node);
21
- return lua.isIdentifier(left) && symbol && export_1.isSymbolExported(context, symbol)
22
- ? export_1.createExportedIdentifier(context, left)
23
- : utils_1.cast(left, lua.isAssignmentLeftHandSideExpression);
35
+ return lua.isIdentifier(left) && symbol && (0, export_1.isSymbolExported)(context, symbol)
36
+ ? (0, export_1.createExportedIdentifier)(context, left)
37
+ : (0, utils_1.cast)(left, lua.isAssignmentLeftHandSideExpression);
24
38
  }
25
39
  exports.transformAssignmentLeftHandSideExpression = transformAssignmentLeftHandSideExpression;
26
40
  function transformAssignment(context,
27
41
  // TODO: Change type to ts.LeftHandSideExpression?
28
- lhs, right, parent) {
42
+ lhs, right, rightHasPrecedingStatements, parent) {
29
43
  if (ts.isOptionalChain(lhs)) {
30
- context.diagnostics.push(diagnostics_1.notAllowedOptionalAssignment(lhs));
44
+ context.diagnostics.push((0, diagnostics_1.notAllowedOptionalAssignment)(lhs));
31
45
  return [];
32
46
  }
33
- if (destructuring_assignments_1.isArrayLength(context, lhs)) {
34
- const arrayLengthAssignment = lua.createExpressionStatement(lualib_1.transformLuaLibFunction(context, lualib_1.LuaLibFeature.ArraySetLength, parent, context.transformExpression(lhs.expression), right));
47
+ if ((0, destructuring_assignments_1.isArrayLength)(context, lhs)) {
48
+ const arrayLengthAssignment = lua.createExpressionStatement((0, lualib_1.transformLuaLibFunction)(context, lualib_1.LuaLibFeature.ArraySetLength, parent, context.transformExpression(lhs.expression), right));
35
49
  return [arrayLengthAssignment];
36
50
  }
37
- const symbol = ts.isShorthandPropertyAssignment(lhs.parent)
51
+ const symbol = lhs.parent && ts.isShorthandPropertyAssignment(lhs.parent)
38
52
  ? context.checker.getShorthandAssignmentValueSymbol(lhs.parent)
39
53
  : context.checker.getSymbolAtLocation(lhs);
40
- const dependentSymbols = symbol ? export_1.getDependenciesOfSymbol(context, symbol) : [];
41
- const left = transformAssignmentLeftHandSideExpression(context, lhs);
54
+ const dependentSymbols = symbol ? (0, export_1.getDependenciesOfSymbol)(context, symbol) : [];
55
+ const left = transformAssignmentLeftHandSideExpression(context, lhs, rightHasPrecedingStatements);
42
56
  const rootAssignment = lua.createAssignmentStatement(left, right, lhs.parent);
43
57
  return [
44
58
  rootAssignment,
45
59
  ...dependentSymbols.map(symbol => {
46
60
  const [left] = rootAssignment.left;
47
- const identifierToAssign = export_1.createExportedIdentifier(context, lua.createIdentifier(symbol.name));
61
+ const identifierToAssign = (0, export_1.createExportedIdentifier)(context, lua.createIdentifier(symbol.name));
48
62
  return lua.createAssignmentStatement(identifierToAssign, left);
49
63
  }),
50
64
  ];
51
65
  }
52
66
  exports.transformAssignment = transformAssignment;
67
+ function transformAssignmentWithRightPrecedingStatements(context, lhs, right, rightPrecedingStatements, parent) {
68
+ return [
69
+ ...rightPrecedingStatements,
70
+ ...transformAssignment(context, lhs, right, rightPrecedingStatements.length > 0, parent),
71
+ ];
72
+ }
73
+ exports.transformAssignmentWithRightPrecedingStatements = transformAssignmentWithRightPrecedingStatements;
53
74
  function transformDestructuredAssignmentExpression(context, expression) {
54
- const rootIdentifier = lua.createAnonymousIdentifier(expression.left);
55
- let right = context.transformExpression(expression.right);
56
- if (multi_1.isMultiReturnCall(context, expression.right)) {
57
- right = lua_ast_1.wrapInTable(right);
75
+ const rootIdentifier = context.createTempNameForNode(expression.right);
76
+ let [rightPrecedingStatements, right] = (0, preceding_statements_1.transformInPrecedingStatementScope)(context, () => context.transformExpression(expression.right));
77
+ context.addPrecedingStatements(rightPrecedingStatements);
78
+ if ((0, multi_1.isMultiReturnCall)(context, expression.right)) {
79
+ right = (0, lua_ast_1.wrapInTable)(right);
58
80
  }
59
81
  const statements = [
60
82
  lua.createVariableDeclarationStatement(rootIdentifier, right),
61
- ...destructuring_assignments_1.transformDestructuringAssignment(context, expression, rootIdentifier),
83
+ ...(0, destructuring_assignments_1.transformDestructuringAssignment)(context, expression, rootIdentifier, rightPrecedingStatements.length > 0),
62
84
  ];
63
85
  return { statements, result: rootIdentifier };
64
86
  }
@@ -66,69 +88,51 @@ function transformAssignmentExpression(context, expression) {
66
88
  // Validate assignment
67
89
  const rightType = context.checker.getTypeAtLocation(expression.right);
68
90
  const leftType = context.checker.getTypeAtLocation(expression.left);
69
- assignment_validation_1.validateAssignment(context, expression.right, rightType, leftType);
70
- if (destructuring_assignments_1.isArrayLength(context, expression.left)) {
91
+ (0, assignment_validation_1.validateAssignment)(context, expression.right, rightType, leftType);
92
+ if ((0, destructuring_assignments_1.isArrayLength)(context, expression.left)) {
71
93
  // array.length = x
72
- return lualib_1.transformLuaLibFunction(context, lualib_1.LuaLibFeature.ArraySetLength, expression, context.transformExpression(expression.left.expression), context.transformExpression(expression.right));
94
+ return (0, lualib_1.transformLuaLibFunction)(context, lualib_1.LuaLibFeature.ArraySetLength, expression, context.transformExpression(expression.left.expression), context.transformExpression(expression.right));
73
95
  }
74
- if (typescript_1.isDestructuringAssignment(expression)) {
75
- return transform_1.transformToImmediatelyInvokedFunctionExpression(context, () => transformDestructuredAssignmentExpression(context, expression), expression);
96
+ if ((0, typescript_1.isDestructuringAssignment)(expression)) {
97
+ const { statements, result } = transformDestructuredAssignmentExpression(context, expression);
98
+ context.addPrecedingStatements(statements);
99
+ return result;
76
100
  }
77
101
  if (ts.isPropertyAccessExpression(expression.left) || ts.isElementAccessExpression(expression.left)) {
78
- // Left is property/element access: cache result while maintaining order of evaluation
79
- // (function(o, i, v) o[i] = v; return v end)(${objExpression}, ${indexExpression}, ${right})
80
- const objParameter = lua.createIdentifier("o");
81
- const indexParameter = lua.createIdentifier("i");
82
- const valueParameter = lua.createIdentifier("v");
83
- const indexStatement = lua.createTableIndexExpression(objParameter, indexParameter);
84
- const statements = [
85
- lua.createAssignmentStatement(indexStatement, valueParameter),
86
- lua.createReturnStatement([valueParameter]),
87
- ];
88
- const iife = lua.createFunctionExpression(lua.createBlock(statements), [
89
- objParameter,
90
- indexParameter,
91
- valueParameter,
102
+ const tempVar = context.createTempNameForNode(expression.right);
103
+ const [precedingStatements, right] = (0, preceding_statements_1.transformInPrecedingStatementScope)(context, () => context.transformExpression(expression.right));
104
+ const left = transformAssignmentLeftHandSideExpression(context, expression.left, precedingStatements.length > 0);
105
+ context.addPrecedingStatements([
106
+ ...precedingStatements,
107
+ lua.createVariableDeclarationStatement(tempVar, right, expression.right),
108
+ lua.createAssignmentStatement(left, lua.cloneIdentifier(tempVar), expression.left),
92
109
  ]);
93
- scope_1.pushScope(context, scope_1.ScopeType.Function);
94
- const objExpression = context.transformExpression(expression.left.expression);
95
- let indexExpression;
96
- if (ts.isPropertyAccessExpression(expression.left)) {
97
- // Property access
98
- indexExpression = lua.createStringLiteral(expression.left.name.text);
99
- }
100
- else {
101
- // Element access
102
- indexExpression = access_1.transformElementAccessArgument(context, expression.left);
103
- }
104
- const args = [objExpression, indexExpression, context.transformExpression(expression.right)];
105
- scope_1.popScope(context);
106
- return lua.createCallExpression(iife, args, expression);
110
+ return lua.cloneIdentifier(tempVar);
107
111
  }
108
112
  else {
109
- return transform_1.transformToImmediatelyInvokedFunctionExpression(context, () => {
110
- // Simple assignment
111
- // (function() ${left} = ${right}; return ${left} end)()
112
- const left = context.transformExpression(expression.left);
113
- const right = context.transformExpression(expression.right);
114
- const statements = transformAssignment(context, expression.left, right);
115
- return { statements, result: left };
116
- }, expression);
113
+ // Simple assignment
114
+ // ${left} = ${right}; return ${left}
115
+ const left = context.transformExpression(expression.left);
116
+ const right = context.transformExpression(expression.right);
117
+ context.addPrecedingStatements(transformAssignment(context, expression.left, right));
118
+ return left;
117
119
  }
118
120
  }
119
121
  exports.transformAssignmentExpression = transformAssignmentExpression;
120
122
  const canBeTransformedToLuaAssignmentStatement = (context, node) => ts.isArrayLiteralExpression(node.left) &&
121
123
  node.left.elements.every(element => {
122
- if (destructuring_assignments_1.isArrayLength(context, element)) {
124
+ if ((0, destructuring_assignments_1.isArrayLength)(context, element)) {
123
125
  return false;
124
126
  }
125
127
  if (ts.isPropertyAccessExpression(element) || ts.isElementAccessExpression(element)) {
126
- return true;
128
+ // Lua's execution order for multi-assignments is not the same as JS's, so we should always
129
+ // break these down when the left side may have side effects.
130
+ return false;
127
131
  }
128
132
  if (ts.isIdentifier(element)) {
129
133
  const symbol = context.checker.getSymbolAtLocation(element);
130
134
  if (symbol) {
131
- const aliases = export_1.getDependenciesOfSymbol(context, symbol);
135
+ const aliases = (0, export_1.getDependenciesOfSymbol)(context, symbol);
132
136
  return aliases.length === 0;
133
137
  }
134
138
  }
@@ -137,32 +141,37 @@ function transformAssignmentStatement(context, expression) {
137
141
  // Validate assignment
138
142
  const rightType = context.checker.getTypeAtLocation(expression.right);
139
143
  const leftType = context.checker.getTypeAtLocation(expression.left);
140
- assignment_validation_1.validateAssignment(context, expression.right, rightType, leftType);
141
- if (typescript_1.isDestructuringAssignment(expression)) {
144
+ (0, assignment_validation_1.validateAssignment)(context, expression.right, rightType, leftType);
145
+ if ((0, typescript_1.isDestructuringAssignment)(expression)) {
142
146
  if (canBeTransformedToLuaAssignmentStatement(context, expression)) {
143
147
  const rightType = context.checker.getTypeAtLocation(expression.right);
144
- let right = context.transformExpression(expression.right);
148
+ let right;
145
149
  if (ts.isArrayLiteralExpression(expression.right)) {
146
- right = expression.right.elements.map(e => context.transformExpression(e));
150
+ right = (0, expression_list_1.transformExpressionList)(context, expression.right.elements);
147
151
  }
148
- else if (!multi_1.isMultiReturnCall(context, expression.right) && typescript_1.isArrayType(context, rightType)) {
149
- right = lua_ast_1.createUnpackCall(context, right, expression.right);
152
+ else {
153
+ right = context.transformExpression(expression.right);
154
+ if (!(0, multi_1.isMultiReturnCall)(context, expression.right) && (0, typescript_1.isArrayType)(context, rightType)) {
155
+ right = (0, lua_ast_1.createUnpackCall)(context, right, expression.right);
156
+ }
150
157
  }
151
158
  const left = expression.left.elements.map(e => transformAssignmentLeftHandSideExpression(context, e));
152
159
  return [lua.createAssignmentStatement(left, right, expression)];
153
160
  }
154
- let right = context.transformExpression(expression.right);
155
- if (multi_1.isMultiReturnCall(context, expression.right)) {
156
- right = lua_ast_1.wrapInTable(right);
161
+ let [rightPrecedingStatements, right] = (0, preceding_statements_1.transformInPrecedingStatementScope)(context, () => context.transformExpression(expression.right));
162
+ context.addPrecedingStatements(rightPrecedingStatements);
163
+ if ((0, multi_1.isMultiReturnCall)(context, expression.right)) {
164
+ right = (0, lua_ast_1.wrapInTable)(right);
157
165
  }
158
- const rootIdentifier = lua.createAnonymousIdentifier(expression.left);
166
+ const rootIdentifier = context.createTempNameForNode(expression.left);
159
167
  return [
160
168
  lua.createVariableDeclarationStatement(rootIdentifier, right),
161
- ...destructuring_assignments_1.transformDestructuringAssignment(context, expression, rootIdentifier),
169
+ ...(0, destructuring_assignments_1.transformDestructuringAssignment)(context, expression, rootIdentifier, rightPrecedingStatements.length > 0),
162
170
  ];
163
171
  }
164
172
  else {
165
- return transformAssignment(context, expression.left, context.transformExpression(expression.right));
173
+ const [precedingStatements, right] = (0, preceding_statements_1.transformInPrecedingStatementScope)(context, () => context.transformExpression(expression.right));
174
+ return transformAssignmentWithRightPrecedingStatements(context, expression.left, right, precedingStatements);
166
175
  }
167
176
  }
168
177
  exports.transformAssignmentStatement = transformAssignmentStatement;