typescript-to-lua 1.0.0 → 1.2.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 (185) hide show
  1. package/CHANGELOG.md +34 -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 +5 -4
  7. package/dist/LuaPrinter.d.ts +15 -4
  8. package/dist/LuaPrinter.js +79 -27
  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 +39 -19
  22. package/dist/lualib/CloneDescriptor.lua +8 -8
  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 +36 -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 +705 -586
  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 +9 -10
  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 +6 -0
  80. package/dist/transformation/utils/diagnostics.js +7 -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/lua-ast.d.ts +0 -1
  85. package/dist/transformation/utils/lua-ast.js +25 -35
  86. package/dist/transformation/utils/lualib.js +1 -1
  87. package/dist/transformation/utils/preceding-statements.d.ts +3 -0
  88. package/dist/transformation/utils/preceding-statements.js +11 -0
  89. package/dist/transformation/utils/safe-names.js +5 -5
  90. package/dist/transformation/utils/scope.d.ts +7 -0
  91. package/dist/transformation/utils/scope.js +77 -40
  92. package/dist/transformation/utils/symbols.js +6 -6
  93. package/dist/transformation/utils/typescript/index.d.ts +1 -0
  94. package/dist/transformation/utils/typescript/index.js +16 -1
  95. package/dist/transformation/utils/typescript/nodes.d.ts +2 -0
  96. package/dist/transformation/utils/typescript/nodes.js +21 -1
  97. package/dist/transformation/visitors/access.d.ts +3 -0
  98. package/dist/transformation/visitors/access.js +74 -47
  99. package/dist/transformation/visitors/async-await.js +5 -4
  100. package/dist/transformation/visitors/binary-expression/assignments.d.ts +3 -2
  101. package/dist/transformation/visitors/binary-expression/assignments.js +86 -77
  102. package/dist/transformation/visitors/binary-expression/bit.js +4 -4
  103. package/dist/transformation/visitors/binary-expression/compound.d.ts +5 -4
  104. package/dist/transformation/visitors/binary-expression/compound.js +69 -71
  105. package/dist/transformation/visitors/binary-expression/destructuring-assignments.d.ts +2 -2
  106. package/dist/transformation/visitors/binary-expression/destructuring-assignments.js +65 -36
  107. package/dist/transformation/visitors/binary-expression/index.d.ts +3 -1
  108. package/dist/transformation/visitors/binary-expression/index.js +84 -40
  109. package/dist/transformation/visitors/block.js +6 -6
  110. package/dist/transformation/visitors/break-continue.js +4 -9
  111. package/dist/transformation/visitors/call.d.ts +3 -2
  112. package/dist/transformation/visitors/call.js +130 -143
  113. package/dist/transformation/visitors/class/decorators.js +3 -3
  114. package/dist/transformation/visitors/class/index.js +43 -39
  115. package/dist/transformation/visitors/class/members/accessors.js +6 -6
  116. package/dist/transformation/visitors/class/members/constructor.js +7 -7
  117. package/dist/transformation/visitors/class/members/fields.js +6 -6
  118. package/dist/transformation/visitors/class/members/method.js +6 -6
  119. package/dist/transformation/visitors/class/new.js +14 -16
  120. package/dist/transformation/visitors/class/setup.js +11 -11
  121. package/dist/transformation/visitors/class/utils.js +2 -2
  122. package/dist/transformation/visitors/conditional.js +34 -20
  123. package/dist/transformation/visitors/delete.js +8 -4
  124. package/dist/transformation/visitors/enum.js +8 -8
  125. package/dist/transformation/visitors/errors.js +30 -30
  126. package/dist/transformation/visitors/expression-list.d.ts +7 -0
  127. package/dist/transformation/visitors/expression-list.js +120 -0
  128. package/dist/transformation/visitors/expression-statement.js +10 -6
  129. package/dist/transformation/visitors/function.js +30 -32
  130. package/dist/transformation/visitors/identifier.js +26 -22
  131. package/dist/transformation/visitors/index.js +2 -2
  132. package/dist/transformation/visitors/language-extensions/iterable.js +7 -7
  133. package/dist/transformation/visitors/language-extensions/multi.d.ts +1 -1
  134. package/dist/transformation/visitors/language-extensions/multi.js +3 -3
  135. package/dist/transformation/visitors/language-extensions/operators.js +6 -6
  136. package/dist/transformation/visitors/language-extensions/range.js +6 -6
  137. package/dist/transformation/visitors/language-extensions/table.js +5 -5
  138. package/dist/transformation/visitors/literal.d.ts +1 -2
  139. package/dist/transformation/visitors/literal.js +87 -57
  140. package/dist/transformation/visitors/loops/do-while.js +35 -9
  141. package/dist/transformation/visitors/loops/for-in.js +4 -4
  142. package/dist/transformation/visitors/loops/for-of.js +13 -13
  143. package/dist/transformation/visitors/loops/for.js +28 -8
  144. package/dist/transformation/visitors/loops/utils.d.ts +1 -0
  145. package/dist/transformation/visitors/loops/utils.js +21 -10
  146. package/dist/transformation/visitors/modules/export.js +14 -15
  147. package/dist/transformation/visitors/modules/import.js +10 -10
  148. package/dist/transformation/visitors/namespace.js +13 -13
  149. package/dist/transformation/visitors/optional-chaining.d.ts +16 -0
  150. package/dist/transformation/visitors/optional-chaining.js +172 -0
  151. package/dist/transformation/visitors/return.d.ts +1 -0
  152. package/dist/transformation/visitors/return.js +40 -26
  153. package/dist/transformation/visitors/sourceFile.js +12 -9
  154. package/dist/transformation/visitors/spread.js +11 -11
  155. package/dist/transformation/visitors/switch.js +152 -30
  156. package/dist/transformation/visitors/template.js +10 -7
  157. package/dist/transformation/visitors/typeof.js +4 -2
  158. package/dist/transformation/visitors/typescript.js +1 -1
  159. package/dist/transformation/visitors/unary-expression.js +9 -9
  160. package/dist/transformation/visitors/variable-declaration.js +46 -32
  161. package/dist/transformation/visitors/void.d.ts +6 -0
  162. package/dist/transformation/visitors/void.js +20 -0
  163. package/dist/transpilation/bundle.d.ts +3 -0
  164. package/dist/transpilation/bundle.js +56 -13
  165. package/dist/transpilation/diagnostics.js +3 -3
  166. package/dist/transpilation/index.js +2 -2
  167. package/dist/transpilation/output-collector.js +2 -2
  168. package/dist/transpilation/plugins.js +1 -1
  169. package/dist/transpilation/resolve.js +26 -14
  170. package/dist/transpilation/transformers.js +45 -25
  171. package/dist/transpilation/transpile.js +6 -6
  172. package/dist/transpilation/transpiler.js +8 -8
  173. package/dist/transpilation/utils.js +5 -3
  174. package/dist/tstl.js +8 -8
  175. package/dist/utils.js +2 -2
  176. package/package.json +15 -12
  177. package/dist/lualib/OptionalChainAccess.lua +0 -6
  178. package/dist/lualib/OptionalFunctionCall.lua +0 -6
  179. package/dist/lualib/OptionalMethodCall.lua +0 -11
  180. package/dist/transformation/utils/transform.d.ts +0 -8
  181. package/dist/transformation/utils/transform.js +0 -14
  182. package/dist/transformation/visitors/jsx/jsx.d.ts +0 -9
  183. package/dist/transformation/visitors/jsx/jsx.js +0 -237
  184. package/dist/transformation/visitors/jsx/xhtml.d.ts +0 -3
  185. package/dist/transformation/visitors/jsx/xhtml.js +0 -260
@@ -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;
@@ -31,7 +31,7 @@ function transformBitOperatorToLuaOperator(context, node, operator) {
31
31
  case ts.SyntaxKind.LessThanLessThanToken:
32
32
  return lua.SyntaxKind.BitwiseLeftShiftOperator;
33
33
  case ts.SyntaxKind.GreaterThanGreaterThanToken:
34
- context.diagnostics.push(diagnostics_1.unsupportedRightShiftOperator(node));
34
+ context.diagnostics.push((0, diagnostics_1.unsupportedRightShiftOperator)(node));
35
35
  case ts.SyntaxKind.GreaterThanGreaterThanGreaterThanToken:
36
36
  return lua.SyntaxKind.BitwiseRightShiftOperator;
37
37
  }
@@ -40,7 +40,7 @@ function transformBinaryBitOperation(context, node, left, right, operator) {
40
40
  switch (context.luaTarget) {
41
41
  case CompilerOptions_1.LuaTarget.Universal:
42
42
  case CompilerOptions_1.LuaTarget.Lua51:
43
- context.diagnostics.push(diagnostics_1.unsupportedForTarget(node, "Bitwise operations", CompilerOptions_1.LuaTarget.Lua51));
43
+ context.diagnostics.push((0, diagnostics_1.unsupportedForTarget)(node, "Bitwise operations", CompilerOptions_1.LuaTarget.Lua51));
44
44
  case CompilerOptions_1.LuaTarget.LuaJIT:
45
45
  return transformBinaryBitLibOperation(node, left, right, operator, "bit");
46
46
  case CompilerOptions_1.LuaTarget.Lua52:
@@ -58,7 +58,7 @@ function transformUnaryBitLibOperation(node, expression, operator, lib) {
58
58
  bitFunction = "bnot";
59
59
  break;
60
60
  default:
61
- utils_1.assertNever(operator);
61
+ (0, utils_1.assertNever)(operator);
62
62
  }
63
63
  return lua.createCallExpression(lua.createTableIndexExpression(lua.createIdentifier(lib), lua.createStringLiteral(bitFunction)), [expression], node);
64
64
  }
@@ -66,7 +66,7 @@ function transformUnaryBitOperation(context, node, expression, operator) {
66
66
  switch (context.luaTarget) {
67
67
  case CompilerOptions_1.LuaTarget.Universal:
68
68
  case CompilerOptions_1.LuaTarget.Lua51:
69
- context.diagnostics.push(diagnostics_1.unsupportedForTarget(node, "Bitwise operations", CompilerOptions_1.LuaTarget.Lua51));
69
+ context.diagnostics.push((0, diagnostics_1.unsupportedForTarget)(node, "Bitwise operations", CompilerOptions_1.LuaTarget.Lua51));
70
70
  case CompilerOptions_1.LuaTarget.LuaJIT:
71
71
  return transformUnaryBitLibOperation(node, expression, operator, "bit");
72
72
  case CompilerOptions_1.LuaTarget.Lua52:
@@ -1,12 +1,13 @@
1
1
  import * as ts from "typescript";
2
2
  import * as lua from "../../../LuaAST";
3
3
  import { TransformationContext } from "../../context";
4
- import { ImmediatelyInvokedFunctionParameters } from "../../utils/transform";
5
- export declare function parseAccessExpressionWithEvaluationEffects(context: TransformationContext, node: ts.Expression): [ts.Expression, ts.Expression] | [];
6
4
  declare type CompoundAssignmentToken = ts.SyntaxKind.BarToken | ts.SyntaxKind.PlusToken | ts.SyntaxKind.CaretToken | ts.SyntaxKind.MinusToken | ts.SyntaxKind.SlashToken | ts.SyntaxKind.PercentToken | ts.SyntaxKind.AsteriskToken | ts.SyntaxKind.AmpersandToken | ts.SyntaxKind.AsteriskAsteriskToken | ts.SyntaxKind.LessThanLessThanToken | ts.SyntaxKind.GreaterThanGreaterThanToken | ts.SyntaxKind.GreaterThanGreaterThanGreaterThanToken | ts.SyntaxKind.BarBarToken | ts.SyntaxKind.AmpersandAmpersandToken | ts.SyntaxKind.QuestionQuestionToken;
7
5
  export declare const isCompoundAssignmentToken: (token: ts.BinaryOperator) => token is ts.CompoundAssignmentOperator;
8
6
  export declare const unwrapCompoundAssignmentToken: (token: ts.CompoundAssignmentOperator) => CompoundAssignmentToken;
9
- export declare function transformCompoundAssignment(context: TransformationContext, expression: ts.Expression, lhs: ts.Expression, rhs: ts.Expression, operator: CompoundAssignmentToken, isPostfix: boolean): ImmediatelyInvokedFunctionParameters;
10
- export declare function transformCompoundAssignmentExpression(context: TransformationContext, expression: ts.Expression, lhs: ts.Expression, rhs: ts.Expression, operator: CompoundAssignmentToken, isPostfix: boolean): lua.CallExpression;
7
+ export declare function transformCompoundAssignment(context: TransformationContext, expression: ts.Expression, lhs: ts.Expression, rhs: ts.Expression, operator: CompoundAssignmentToken, isPostfix: boolean): {
8
+ statements: lua.Statement[];
9
+ result: lua.AssignmentLeftHandSideExpression;
10
+ };
11
+ export declare function transformCompoundAssignmentExpression(context: TransformationContext, expression: ts.Expression, lhs: ts.Expression, rhs: ts.Expression, operator: CompoundAssignmentToken, isPostfix: boolean): lua.Expression;
11
12
  export declare function transformCompoundAssignmentStatement(context: TransformationContext, node: ts.Node, lhs: ts.Expression, rhs: ts.Expression, operator: CompoundAssignmentToken): lua.Statement[];
12
13
  export {};