typescript-to-lua 1.1.1 → 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 (113) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/LuaAST.d.ts +1 -0
  3. package/dist/LuaAST.js +10 -2
  4. package/dist/LuaLib.d.ts +3 -3
  5. package/dist/LuaLib.js +4 -4
  6. package/dist/LuaPrinter.d.ts +11 -4
  7. package/dist/LuaPrinter.js +54 -11
  8. package/dist/lualib/ArrayFlat.lua +1 -1
  9. package/dist/lualib/ArrayFlatMap.lua +1 -1
  10. package/dist/lualib/ArrayIsArray.lua +1 -1
  11. package/dist/lualib/ArrayReduce.lua +7 -1
  12. package/dist/lualib/ArrayReduceRight.lua +7 -1
  13. package/dist/lualib/ArraySetLength.lua +1 -1
  14. package/dist/lualib/ArraySplice.lua +5 -5
  15. package/dist/lualib/Await.lua +14 -10
  16. package/dist/lualib/CloneDescriptor.lua +8 -8
  17. package/dist/lualib/Decorate.lua +1 -1
  18. package/dist/lualib/DelegatedYield.lua +1 -3
  19. package/dist/lualib/Delete.lua +6 -6
  20. package/dist/lualib/Error.lua +47 -44
  21. package/dist/lualib/Generator.lua +1 -5
  22. package/dist/lualib/InstanceOf.lua +1 -1
  23. package/dist/lualib/InstanceOfObject.lua +1 -1
  24. package/dist/lualib/Map.lua +130 -134
  25. package/dist/lualib/Number.lua +1 -1
  26. package/dist/lualib/NumberIsFinite.lua +1 -1
  27. package/dist/lualib/NumberToString.lua +3 -5
  28. package/dist/lualib/ObjectDefineProperty.lua +40 -8
  29. package/dist/lualib/ParseFloat.lua +9 -5
  30. package/dist/lualib/ParseInt.lua +15 -3
  31. package/dist/lualib/Promise.lua +18 -22
  32. package/dist/lualib/Set.lua +119 -123
  33. package/dist/lualib/SetDescriptor.lua +7 -1
  34. package/dist/lualib/SourceMapTraceBack.lua +1 -1
  35. package/dist/lualib/SparseArrayNew.lua +5 -0
  36. package/dist/lualib/SparseArrayPush.lua +9 -0
  37. package/dist/lualib/SparseArraySpread.lua +4 -0
  38. package/dist/lualib/StringAccess.lua +1 -1
  39. package/dist/lualib/StringCharCodeAt.lua +1 -1
  40. package/dist/lualib/StringEndsWith.lua +2 -2
  41. package/dist/lualib/StringPadEnd.lua +2 -2
  42. package/dist/lualib/StringPadStart.lua +2 -2
  43. package/dist/lualib/StringReplace.lua +7 -1
  44. package/dist/lualib/StringSlice.lua +2 -2
  45. package/dist/lualib/StringSplit.lua +3 -3
  46. package/dist/lualib/StringStartsWith.lua +1 -1
  47. package/dist/lualib/StringSubstr.lua +1 -1
  48. package/dist/lualib/StringSubstring.lua +2 -2
  49. package/dist/lualib/Symbol.lua +3 -5
  50. package/dist/lualib/WeakMap.lua +40 -42
  51. package/dist/lualib/WeakSet.lua +36 -38
  52. package/dist/lualib/lualib_bundle.lua +603 -555
  53. package/dist/transformation/builtins/array.js +1 -2
  54. package/dist/transformation/builtins/function.js +1 -2
  55. package/dist/transformation/builtins/index.d.ts +1 -1
  56. package/dist/transformation/builtins/index.js +37 -4
  57. package/dist/transformation/builtins/object.d.ts +2 -1
  58. package/dist/transformation/builtins/object.js +1 -2
  59. package/dist/transformation/builtins/string.js +1 -2
  60. package/dist/transformation/context/context.d.ts +12 -0
  61. package/dist/transformation/context/context.js +102 -3
  62. package/dist/transformation/utils/diagnostics.d.ts +6 -0
  63. package/dist/transformation/utils/diagnostics.js +3 -1
  64. package/dist/transformation/utils/lua-ast.d.ts +0 -1
  65. package/dist/transformation/utils/lua-ast.js +13 -22
  66. package/dist/transformation/utils/preceding-statements.d.ts +3 -0
  67. package/dist/transformation/utils/preceding-statements.js +11 -0
  68. package/dist/transformation/utils/scope.d.ts +1 -0
  69. package/dist/transformation/utils/scope.js +8 -1
  70. package/dist/transformation/utils/typescript/index.d.ts +1 -0
  71. package/dist/transformation/utils/typescript/index.js +16 -1
  72. package/dist/transformation/visitors/access.d.ts +3 -0
  73. package/dist/transformation/visitors/access.js +63 -36
  74. package/dist/transformation/visitors/binary-expression/assignments.d.ts +3 -2
  75. package/dist/transformation/visitors/binary-expression/assignments.js +66 -57
  76. package/dist/transformation/visitors/binary-expression/compound.d.ts +5 -4
  77. package/dist/transformation/visitors/binary-expression/compound.js +66 -68
  78. package/dist/transformation/visitors/binary-expression/destructuring-assignments.d.ts +2 -2
  79. package/dist/transformation/visitors/binary-expression/destructuring-assignments.js +54 -25
  80. package/dist/transformation/visitors/binary-expression/index.d.ts +3 -1
  81. package/dist/transformation/visitors/binary-expression/index.js +64 -20
  82. package/dist/transformation/visitors/call.d.ts +3 -2
  83. package/dist/transformation/visitors/call.js +109 -122
  84. package/dist/transformation/visitors/class/index.js +4 -7
  85. package/dist/transformation/visitors/class/new.js +4 -6
  86. package/dist/transformation/visitors/conditional.js +28 -14
  87. package/dist/transformation/visitors/delete.js +4 -0
  88. package/dist/transformation/visitors/expression-list.d.ts +7 -0
  89. package/dist/transformation/visitors/expression-list.js +120 -0
  90. package/dist/transformation/visitors/function.js +6 -8
  91. package/dist/transformation/visitors/identifier.js +4 -0
  92. package/dist/transformation/visitors/literal.js +69 -16
  93. package/dist/transformation/visitors/loops/do-while.js +34 -8
  94. package/dist/transformation/visitors/loops/for.js +25 -5
  95. package/dist/transformation/visitors/loops/utils.d.ts +1 -0
  96. package/dist/transformation/visitors/loops/utils.js +13 -2
  97. package/dist/transformation/visitors/modules/export.js +1 -1
  98. package/dist/transformation/visitors/optional-chaining.d.ts +16 -0
  99. package/dist/transformation/visitors/optional-chaining.js +172 -0
  100. package/dist/transformation/visitors/sourceFile.js +4 -1
  101. package/dist/transformation/visitors/switch.js +29 -9
  102. package/dist/transformation/visitors/template.js +5 -2
  103. package/dist/transformation/visitors/typeof.js +3 -1
  104. package/dist/transformation/visitors/variable-declaration.js +21 -7
  105. package/dist/transformation/visitors/void.js +4 -7
  106. package/dist/transpilation/transformers.js +4 -1
  107. package/dist/transpilation/utils.js +2 -1
  108. package/package.json +5 -5
  109. package/dist/lualib/OptionalChainAccess.lua +0 -6
  110. package/dist/lualib/OptionalFunctionCall.lua +0 -6
  111. package/dist/lualib/OptionalMethodCall.lua +0 -11
  112. package/dist/transformation/utils/transform.d.ts +0 -8
  113. package/dist/transformation/utils/transform.js +0 -14
@@ -22,8 +22,7 @@ exports.transformArrayConstructorCall = transformArrayConstructorCall;
22
22
  function transformArrayPrototypeCall(context, node) {
23
23
  const expression = node.expression;
24
24
  const signature = context.checker.getResolvedSignature(node);
25
- const params = (0, call_1.transformArguments)(context, node.arguments, signature);
26
- const caller = context.transformExpression(expression.expression);
25
+ const [caller, params] = (0, call_1.transformCallAndArguments)(context, expression.expression, node.arguments, signature);
27
26
  const expressionName = expression.name.text;
28
27
  switch (expressionName) {
29
28
  case "concat":
@@ -15,8 +15,7 @@ function transformFunctionPrototypeCall(context, node) {
15
15
  context.diagnostics.push((0, diagnostics_1.unsupportedSelfFunctionConversion)(node));
16
16
  }
17
17
  const signature = context.checker.getResolvedSignature(node);
18
- const params = (0, call_1.transformArguments)(context, node.arguments, signature);
19
- const caller = context.transformExpression(expression.expression);
18
+ const [caller, params] = (0, call_1.transformCallAndArguments)(context, expression.expression, node.arguments, signature);
20
19
  const expressionName = expression.name.text;
21
20
  switch (expressionName) {
22
21
  case "apply":
@@ -2,5 +2,5 @@ import * as ts from "typescript";
2
2
  import * as lua from "../../LuaAST";
3
3
  import { TransformationContext } from "../context";
4
4
  export declare function transformBuiltinPropertyAccessExpression(context: TransformationContext, node: ts.PropertyAccessExpression): lua.Expression | undefined;
5
- export declare function transformBuiltinCallExpression(context: TransformationContext, node: ts.CallExpression): lua.Expression | undefined;
5
+ export declare function transformBuiltinCallExpression(context: TransformationContext, node: ts.CallExpression, isOptionalCall: boolean): lua.Expression | undefined;
6
6
  export declare function transformBuiltinIdentifierExpression(context: TransformationContext, node: ts.Identifier): lua.Expression | undefined;
@@ -19,6 +19,7 @@ const object_1 = require("./object");
19
19
  const promise_1 = require("./promise");
20
20
  const string_1 = require("./string");
21
21
  const symbol_1 = require("./symbol");
22
+ const diagnostics_1 = require("../utils/diagnostics");
22
23
  function transformBuiltinPropertyAccessExpression(context, node) {
23
24
  const ownerType = context.checker.getTypeAtLocation(node.expression);
24
25
  if ((0, typescript_1.isStringType)(context, ownerType)) {
@@ -40,7 +41,7 @@ function transformBuiltinPropertyAccessExpression(context, node) {
40
41
  }
41
42
  }
42
43
  exports.transformBuiltinPropertyAccessExpression = transformBuiltinPropertyAccessExpression;
43
- function transformBuiltinCallExpression(context, node) {
44
+ function transformBuiltinCallExpression(context, node, isOptionalCall) {
44
45
  const expressionType = context.checker.getTypeAtLocation(node.expression);
45
46
  if (ts.isIdentifier(node.expression) && (0, typescript_1.isStandardLibraryType)(context, expressionType, undefined)) {
46
47
  // TODO:
@@ -50,47 +51,79 @@ function transformBuiltinCallExpression(context, node) {
50
51
  return result;
51
52
  }
52
53
  }
53
- if (!ts.isPropertyAccessExpression(node.expression)) {
54
+ const expression = ts.getOriginalNode(node.expression);
55
+ if (!ts.isPropertyAccessExpression(expression)) {
54
56
  return;
55
57
  }
56
58
  (0, utils_1.assume)(node);
59
+ const isOptionalAccess = expression.questionDotToken;
60
+ const unsupportedOptionalCall = () => {
61
+ context.diagnostics.push((0, diagnostics_1.unsupportedBuiltinOptionalCall)(node));
62
+ return lua.createNilLiteral();
63
+ };
57
64
  // If the function being called is of type owner.func, get the type of owner
58
- const ownerType = context.checker.getTypeAtLocation(node.expression.expression);
65
+ const ownerType = context.checker.getTypeAtLocation(expression.expression);
59
66
  if ((0, typescript_1.isStandardLibraryType)(context, ownerType, undefined)) {
60
67
  const symbol = ownerType.getSymbol();
61
68
  switch (symbol === null || symbol === void 0 ? void 0 : symbol.name) {
62
69
  case "ArrayConstructor":
70
+ if (isOptionalCall || isOptionalAccess)
71
+ return unsupportedOptionalCall();
63
72
  return (0, array_1.transformArrayConstructorCall)(context, node);
64
73
  case "Console":
74
+ if (isOptionalCall || isOptionalAccess)
75
+ return unsupportedOptionalCall();
65
76
  return (0, console_1.transformConsoleCall)(context, node);
66
77
  case "Math":
78
+ if (isOptionalCall || isOptionalAccess)
79
+ return unsupportedOptionalCall();
67
80
  return (0, math_1.transformMathCall)(context, node);
68
81
  case "StringConstructor":
82
+ if (isOptionalCall || isOptionalAccess)
83
+ return unsupportedOptionalCall();
69
84
  return (0, string_1.transformStringConstructorCall)(context, node);
70
85
  case "ObjectConstructor":
86
+ if (isOptionalCall || isOptionalAccess)
87
+ return unsupportedOptionalCall();
71
88
  return (0, object_1.transformObjectConstructorCall)(context, node);
72
89
  case "SymbolConstructor":
90
+ if (isOptionalCall || isOptionalAccess)
91
+ return unsupportedOptionalCall();
73
92
  return (0, symbol_1.transformSymbolConstructorCall)(context, node);
74
93
  case "NumberConstructor":
94
+ if (isOptionalCall || isOptionalAccess)
95
+ return unsupportedOptionalCall();
75
96
  return (0, number_1.transformNumberConstructorCall)(context, node);
76
97
  case "PromiseConstructor":
98
+ if (isOptionalCall || isOptionalAccess)
99
+ return unsupportedOptionalCall();
77
100
  return (0, promise_1.transformPromiseConstructorCall)(context, node);
78
101
  }
79
102
  }
80
103
  if ((0, typescript_1.isStringType)(context, ownerType) && (0, typescript_1.hasStandardLibrarySignature)(context, node)) {
104
+ if (isOptionalCall)
105
+ return unsupportedOptionalCall();
81
106
  return (0, string_1.transformStringPrototypeCall)(context, node);
82
107
  }
83
108
  if ((0, typescript_1.isNumberType)(context, ownerType) && (0, typescript_1.hasStandardLibrarySignature)(context, node)) {
109
+ if (isOptionalCall)
110
+ return unsupportedOptionalCall();
84
111
  return (0, number_1.transformNumberPrototypeCall)(context, node);
85
112
  }
86
113
  if ((0, typescript_1.isArrayType)(context, ownerType) && (0, typescript_1.hasStandardLibrarySignature)(context, node)) {
114
+ if (isOptionalCall)
115
+ return unsupportedOptionalCall();
87
116
  return (0, array_1.transformArrayPrototypeCall)(context, node);
88
117
  }
89
118
  if ((0, typescript_1.isFunctionType)(context, ownerType) && (0, typescript_1.hasStandardLibrarySignature)(context, node)) {
119
+ if (isOptionalCall)
120
+ return unsupportedOptionalCall();
90
121
  return (0, function_1.transformFunctionPrototypeCall)(context, node);
91
122
  }
92
- const objectResult = (0, object_1.transformObjectPrototypeCall)(context, node);
123
+ const objectResult = (0, object_1.transformObjectPrototypeCall)(context, node, expression);
93
124
  if (objectResult) {
125
+ if (isOptionalCall)
126
+ return unsupportedOptionalCall();
94
127
  return objectResult;
95
128
  }
96
129
  }
@@ -1,5 +1,6 @@
1
1
  import * as lua from "../../LuaAST";
2
+ import * as ts from "typescript";
2
3
  import { TransformationContext } from "../context";
3
4
  import { PropertyCallExpression } from "../visitors/call";
4
5
  export declare function transformObjectConstructorCall(context: TransformationContext, expression: PropertyCallExpression): lua.Expression | undefined;
5
- export declare function transformObjectPrototypeCall(context: TransformationContext, node: PropertyCallExpression): lua.Expression | undefined;
6
+ export declare function transformObjectPrototypeCall(context: TransformationContext, node: ts.CallExpression, expression: ts.PropertyAccessExpression): lua.Expression | undefined;
@@ -31,8 +31,7 @@ function transformObjectConstructorCall(context, expression) {
31
31
  }
32
32
  }
33
33
  exports.transformObjectConstructorCall = transformObjectConstructorCall;
34
- function transformObjectPrototypeCall(context, node) {
35
- const expression = node.expression;
34
+ function transformObjectPrototypeCall(context, node, expression) {
36
35
  const signature = context.checker.getResolvedSignature(node);
37
36
  const name = expression.name.text;
38
37
  switch (name) {
@@ -13,8 +13,7 @@ function createStringCall(methodName, tsOriginal, ...params) {
13
13
  function transformStringPrototypeCall(context, node) {
14
14
  const expression = node.expression;
15
15
  const signature = context.checker.getResolvedSignature(node);
16
- const params = (0, call_1.transformArguments)(context, node.arguments, signature);
17
- const caller = context.transformExpression(expression.expression);
16
+ const [caller, params] = (0, call_1.transformCallAndArguments)(context, expression.expression, node.arguments, signature);
18
17
  const expressionName = expression.name.text;
19
18
  switch (expressionName) {
20
19
  case "replace":
@@ -2,6 +2,7 @@ import * as ts from "typescript";
2
2
  import { CompilerOptions, LuaTarget } from "../../CompilerOptions";
3
3
  import * as lua from "../../LuaAST";
4
4
  import { ExpressionLikeNode, StatementLikeNode, VisitorMap } from "./visitors";
5
+ export declare const tempSymbolId: lua.SymbolId;
5
6
  export interface AllAccessorDeclarations {
6
7
  firstAccessor: ts.AccessorDeclaration;
7
8
  secondAccessor: ts.AccessorDeclaration | undefined;
@@ -25,16 +26,27 @@ export declare class TransformationContext {
25
26
  readonly diagnostics: ts.Diagnostic[];
26
27
  readonly checker: DiagnosticsProducingTypeChecker;
27
28
  readonly resolver: EmitResolver;
29
+ readonly precedingStatementsStack: lua.Statement[][];
28
30
  readonly options: CompilerOptions;
29
31
  readonly luaTarget: LuaTarget;
30
32
  readonly isModule: boolean;
31
33
  readonly isStrict: boolean;
32
34
  constructor(program: ts.Program, sourceFile: ts.SourceFile, visitorMap: VisitorMap);
33
35
  private currentNodeVisitors;
36
+ private nextTempId;
34
37
  transformNode(node: ts.Node): lua.Node[];
35
38
  superTransformNode(node: ts.Node): lua.Node[];
36
39
  transformExpression(node: ExpressionLikeNode): lua.Expression;
37
40
  superTransformExpression(node: ExpressionLikeNode): lua.Expression;
38
41
  transformStatements(node: StatementLikeNode | readonly StatementLikeNode[]): lua.Statement[];
39
42
  superTransformStatements(node: StatementLikeNode | readonly StatementLikeNode[]): lua.Statement[];
43
+ pushPrecedingStatements(): void;
44
+ popPrecedingStatements(): lua.Statement[];
45
+ addPrecedingStatements(statements: lua.Statement | lua.Statement[]): void;
46
+ prependPrecedingStatements(statements: lua.Statement | lua.Statement[]): void;
47
+ createTempName(prefix?: string): string;
48
+ private getTempNameForLuaExpression;
49
+ createTempNameForLuaExpression(expression: lua.Expression): lua.Identifier;
50
+ private getTempNameForNode;
51
+ createTempNameForNode(node: ts.Node): lua.Identifier;
40
52
  }
@@ -1,12 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.TransformationContext = void 0;
3
+ exports.TransformationContext = exports.tempSymbolId = void 0;
4
4
  const ts = require("typescript");
5
5
  const CompilerOptions_1 = require("../../CompilerOptions");
6
6
  const lua = require("../../LuaAST");
7
7
  const utils_1 = require("../../utils");
8
8
  const diagnostics_1 = require("../utils/diagnostics");
9
9
  const lua_ast_1 = require("../utils/lua-ast");
10
+ const safe_names_1 = require("../utils/safe-names");
11
+ exports.tempSymbolId = -1;
10
12
  class TransformationContext {
11
13
  constructor(program, sourceFile, visitorMap) {
12
14
  var _a, _b, _c;
@@ -15,12 +17,14 @@ class TransformationContext {
15
17
  this.visitorMap = visitorMap;
16
18
  this.diagnostics = [];
17
19
  this.checker = this.program.getDiagnosticsProducingTypeChecker();
20
+ this.precedingStatementsStack = [];
18
21
  this.options = this.program.getCompilerOptions();
19
22
  this.luaTarget = (_a = this.options.luaTarget) !== null && _a !== void 0 ? _a : CompilerOptions_1.LuaTarget.Universal;
20
23
  this.isModule = ts.isExternalModule(this.sourceFile);
21
24
  this.isStrict = ((_b = this.options.alwaysStrict) !== null && _b !== void 0 ? _b : this.options.strict) ||
22
25
  (this.isModule && this.options.target !== undefined && this.options.target >= ts.ScriptTarget.ES2015);
23
26
  this.currentNodeVisitors = [];
27
+ this.nextTempId = 0;
24
28
  // Use `getParseTreeNode` to get original SourceFile node, before it was substituted by custom transformers.
25
29
  // It's required because otherwise `getEmitResolver` won't use cached diagnostics, produced in `emitWorker`
26
30
  // and would try to re-analyze the file, which would fail because of replaced nodes.
@@ -67,10 +71,105 @@ class TransformationContext {
67
71
  return result;
68
72
  }
69
73
  transformStatements(node) {
70
- return (0, utils_1.castArray)(node).flatMap(n => this.transformNode(n));
74
+ return (0, utils_1.castArray)(node).flatMap(n => {
75
+ this.pushPrecedingStatements();
76
+ const statements = this.transformNode(n);
77
+ statements.unshift(...this.popPrecedingStatements());
78
+ return statements;
79
+ });
71
80
  }
72
81
  superTransformStatements(node) {
73
- return (0, utils_1.castArray)(node).flatMap(n => this.superTransformNode(n));
82
+ return (0, utils_1.castArray)(node).flatMap(n => {
83
+ this.pushPrecedingStatements();
84
+ const statements = this.superTransformNode(n);
85
+ statements.unshift(...this.popPrecedingStatements());
86
+ return statements;
87
+ });
88
+ }
89
+ pushPrecedingStatements() {
90
+ this.precedingStatementsStack.push([]);
91
+ }
92
+ popPrecedingStatements() {
93
+ const precedingStatements = this.precedingStatementsStack.pop();
94
+ (0, utils_1.assert)(precedingStatements);
95
+ return precedingStatements;
96
+ }
97
+ addPrecedingStatements(statements) {
98
+ const precedingStatements = this.precedingStatementsStack[this.precedingStatementsStack.length - 1];
99
+ (0, utils_1.assert)(precedingStatements);
100
+ if (!Array.isArray(statements)) {
101
+ statements = [statements];
102
+ }
103
+ precedingStatements.push(...statements);
104
+ }
105
+ prependPrecedingStatements(statements) {
106
+ const precedingStatements = this.precedingStatementsStack[this.precedingStatementsStack.length - 1];
107
+ (0, utils_1.assert)(precedingStatements);
108
+ if (!Array.isArray(statements)) {
109
+ statements = [statements];
110
+ }
111
+ precedingStatements.unshift(...statements);
112
+ }
113
+ createTempName(prefix = "temp") {
114
+ prefix = prefix.replace(/^_*/, ""); // Strip leading underscores because createSafeName will add them again
115
+ return (0, safe_names_1.createSafeName)(`${prefix}_${this.nextTempId++}`);
116
+ }
117
+ getTempNameForLuaExpression(expression) {
118
+ if (lua.isStringLiteral(expression)) {
119
+ return expression.value;
120
+ }
121
+ else if (lua.isNumericLiteral(expression)) {
122
+ return `_${expression.value.toString()}`;
123
+ }
124
+ else if (lua.isIdentifier(expression)) {
125
+ return expression.text;
126
+ }
127
+ else if (lua.isCallExpression(expression)) {
128
+ const name = this.getTempNameForLuaExpression(expression.expression);
129
+ if (name) {
130
+ return `${name}_result`;
131
+ }
132
+ }
133
+ else if (lua.isTableIndexExpression(expression)) {
134
+ const tableName = this.getTempNameForLuaExpression(expression.table);
135
+ const indexName = this.getTempNameForLuaExpression(expression.index);
136
+ if (tableName || indexName) {
137
+ return `${tableName !== null && tableName !== void 0 ? tableName : "table"}_${indexName !== null && indexName !== void 0 ? indexName : "index"}`;
138
+ }
139
+ }
140
+ }
141
+ createTempNameForLuaExpression(expression) {
142
+ const name = this.getTempNameForLuaExpression(expression);
143
+ const identifier = lua.createIdentifier(this.createTempName(name), undefined, exports.tempSymbolId);
144
+ lua.setNodePosition(identifier, lua.getOriginalPos(expression));
145
+ return identifier;
146
+ }
147
+ getTempNameForNode(node) {
148
+ if (ts.isStringLiteral(node) || ts.isIdentifier(node) || ts.isMemberName(node)) {
149
+ return node.text;
150
+ }
151
+ else if (ts.isNumericLiteral(node)) {
152
+ return `_${node.text}`;
153
+ }
154
+ else if (ts.isCallExpression(node)) {
155
+ const name = this.getTempNameForNode(node.expression);
156
+ if (name) {
157
+ return `${name}_result`;
158
+ }
159
+ }
160
+ else if (ts.isElementAccessExpression(node) || ts.isPropertyAccessExpression(node)) {
161
+ const tableName = this.getTempNameForNode(node.expression);
162
+ const indexName = ts.isElementAccessExpression(node)
163
+ ? this.getTempNameForNode(node.argumentExpression)
164
+ : node.name.text;
165
+ if (tableName || indexName) {
166
+ return `${tableName !== null && tableName !== void 0 ? tableName : "table"}_${indexName !== null && indexName !== void 0 ? indexName : "index"}`;
167
+ }
168
+ }
169
+ }
170
+ createTempNameForNode(node) {
171
+ const name = this.getTempNameForNode(node);
172
+ return lua.createIdentifier(this.createTempName(name), node, exports.tempSymbolId);
74
173
  }
75
174
  }
76
175
  exports.TransformationContext = TransformationContext;
@@ -91,3 +91,9 @@ export declare const notAllowedOptionalAssignment: ((node: ts.Node, ...args: any
91
91
  export declare const awaitMustBeInAsyncFunction: ((node: ts.Node, ...args: any[]) => ts.Diagnostic) & {
92
92
  code: number;
93
93
  };
94
+ export declare const unsupportedBuiltinOptionalCall: ((node: ts.Node, ...args: any[]) => ts.Diagnostic) & {
95
+ code: number;
96
+ };
97
+ export declare const unsupportedOptionalCompileMembersOnly: ((node: ts.Node, ...args: any[]) => ts.Diagnostic) & {
98
+ code: number;
99
+ };
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.awaitMustBeInAsyncFunction = exports.notAllowedOptionalAssignment = exports.annotationDeprecated = exports.annotationRemoved = exports.invalidTableSetExpression = exports.invalidTableDeleteExpression = exports.invalidTableExtensionUse = exports.invalidOperatorMappingUse = exports.invalidMultiReturnAccess = exports.invalidMultiTypeToEmptyPatternOrArrayLiteral = exports.invalidMultiTypeToNonArrayLiteral = exports.invalidMultiFunctionReturnType = exports.invalidMultiFunctionUse = exports.unsupportedVarDeclaration = exports.invalidAmbientIdentifierName = exports.unsupportedProperty = exports.unsupportedForTarget = exports.unsupportedRightShiftOperator = exports.unsupportedAccessorInObjectLiteral = exports.invalidMultiIterableWithoutDestructuring = exports.invalidRangeControlVariable = exports.invalidVarargUse = exports.invalidRangeUse = exports.annotationInvalidArgumentCount = exports.decoratorInvalidContext = exports.unsupportedOverloadAssignment = exports.unsupportedSelfFunctionConversion = exports.unsupportedNoSelfFunctionConversion = exports.forbiddenForIn = exports.unsupportedNodeKind = void 0;
3
+ exports.unsupportedOptionalCompileMembersOnly = exports.unsupportedBuiltinOptionalCall = exports.awaitMustBeInAsyncFunction = exports.notAllowedOptionalAssignment = exports.annotationDeprecated = exports.annotationRemoved = exports.invalidTableSetExpression = exports.invalidTableDeleteExpression = exports.invalidTableExtensionUse = exports.invalidOperatorMappingUse = exports.invalidMultiReturnAccess = exports.invalidMultiTypeToEmptyPatternOrArrayLiteral = exports.invalidMultiTypeToNonArrayLiteral = exports.invalidMultiFunctionReturnType = exports.invalidMultiFunctionUse = exports.unsupportedVarDeclaration = exports.invalidAmbientIdentifierName = exports.unsupportedProperty = exports.unsupportedForTarget = exports.unsupportedRightShiftOperator = exports.unsupportedAccessorInObjectLiteral = exports.invalidMultiIterableWithoutDestructuring = exports.invalidRangeControlVariable = exports.invalidVarargUse = exports.invalidRangeUse = exports.annotationInvalidArgumentCount = exports.decoratorInvalidContext = exports.unsupportedOverloadAssignment = exports.unsupportedSelfFunctionConversion = exports.unsupportedNoSelfFunctionConversion = exports.forbiddenForIn = exports.unsupportedNodeKind = void 0;
4
4
  const ts = require("typescript");
5
5
  const CompilerOptions_1 = require("../../CompilerOptions");
6
6
  const utils_1 = require("../../utils");
@@ -58,4 +58,6 @@ exports.annotationDeprecated = createWarningDiagnosticFactory((kind) => `'@${kin
58
58
  `See https://typescripttolua.github.io/docs/advanced/compiler-annotations#${kind.toLowerCase()} for more information.`);
59
59
  exports.notAllowedOptionalAssignment = createErrorDiagnosticFactory("The left-hand side of an assignment expression may not be an optional property access.");
60
60
  exports.awaitMustBeInAsyncFunction = createErrorDiagnosticFactory("Await can only be used inside async functions.");
61
+ exports.unsupportedBuiltinOptionalCall = createErrorDiagnosticFactory("Optional calls are not supported for builtin or language extension functions.");
62
+ exports.unsupportedOptionalCompileMembersOnly = createErrorDiagnosticFactory("Optional calls are not supported on enums marked with @compileMembersOnly.");
61
63
  //# sourceMappingURL=diagnostics.js.map
@@ -7,7 +7,6 @@ export declare function createSelfIdentifier(tsOriginal?: ts.Node): lua.Identifi
7
7
  export declare function createExportsIdentifier(): lua.Identifier;
8
8
  export declare function addToNumericExpression(expression: lua.Expression, change: number): lua.Expression;
9
9
  export declare function getNumberLiteralValue(expression?: lua.Expression): number | undefined;
10
- export declare function createImmediatelyInvokedFunctionExpression(statements: lua.Statement[], result: lua.Expression | lua.Expression[], tsOriginal?: ts.Node): lua.CallExpression;
11
10
  export declare function createUnpackCall(context: TransformationContext, expression: lua.Expression, tsOriginal?: ts.Node): lua.Expression;
12
11
  export declare function wrapInTable(...expressions: lua.Expression[]): lua.TableExpression;
13
12
  export declare function wrapInToStringForConcat(expression: lua.Expression): lua.Expression;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createNaN = exports.createLocalOrExportedOrGlobalDeclaration = exports.createHoistableVariableDeclarationStatement = exports.wrapInToStringForConcat = exports.wrapInTable = exports.createUnpackCall = exports.createImmediatelyInvokedFunctionExpression = exports.getNumberLiteralValue = exports.addToNumericExpression = exports.createExportsIdentifier = exports.createSelfIdentifier = exports.unwrapVisitorResult = void 0;
3
+ exports.createNaN = exports.createLocalOrExportedOrGlobalDeclaration = exports.createHoistableVariableDeclarationStatement = exports.wrapInToStringForConcat = exports.wrapInTable = exports.createUnpackCall = exports.getNumberLiteralValue = exports.addToNumericExpression = exports.createExportsIdentifier = exports.createSelfIdentifier = exports.unwrapVisitorResult = void 0;
4
4
  const ts = require("typescript");
5
5
  const CompilerOptions_1 = require("../../CompilerOptions");
6
6
  const lua = require("../../LuaAST");
@@ -55,15 +55,6 @@ function getNumberLiteralValue(expression) {
55
55
  return undefined;
56
56
  }
57
57
  exports.getNumberLiteralValue = getNumberLiteralValue;
58
- // Prefer use of transformToImmediatelyInvokedFunctionExpression to maintain correct scope. If you use this directly,
59
- // ensure you push/pop a function scope appropriately to avoid incorrect vararg optimization.
60
- function createImmediatelyInvokedFunctionExpression(statements, result, tsOriginal) {
61
- const body = [...statements, lua.createReturnStatement((0, utils_1.castArray)(result))];
62
- const flags = statements.length === 0 ? lua.FunctionExpressionFlags.Inline : lua.FunctionExpressionFlags.None;
63
- const iife = lua.createFunctionExpression(lua.createBlock(body), undefined, undefined, flags);
64
- return lua.createCallExpression(iife, [], tsOriginal);
65
- }
66
- exports.createImmediatelyInvokedFunctionExpression = createImmediatelyInvokedFunctionExpression;
67
58
  function createUnpackCall(context, expression, tsOriginal) {
68
59
  if (context.luaTarget === CompilerOptions_1.LuaTarget.Universal) {
69
60
  return (0, lualib_1.transformLuaLibFunction)(context, LuaLib_1.LuaLibFeature.Unpack, tsOriginal, expression);
@@ -93,10 +84,7 @@ function createHoistableVariableDeclarationStatement(context, identifier, initia
93
84
  if (identifier.symbolId !== undefined) {
94
85
  const scope = (0, scope_1.peekScope)(context);
95
86
  (0, utils_1.assert)(scope.type !== scope_1.ScopeType.Switch);
96
- if (!scope.variableDeclarations) {
97
- scope.variableDeclarations = [];
98
- }
99
- scope.variableDeclarations.push(declaration);
87
+ (0, scope_1.addScopeVariableDeclaration)(scope, declaration);
100
88
  }
101
89
  return declaration;
102
90
  }
@@ -132,21 +120,24 @@ function createLocalOrExportedOrGlobalDeclaration(context, lhs, rhs, tsOriginal,
132
120
  const isTopLevelVariable = scope.type === scope_1.ScopeType.File;
133
121
  if (context.isModule || !isTopLevelVariable) {
134
122
  if (!isFunctionDeclaration && hasMultipleReferences(scope, lhs)) {
135
- // Split declaration and assignment of identifiers that reference themselves in their declaration
136
- declaration = lua.createVariableDeclarationStatement(lhs, undefined, tsOriginal);
123
+ // Split declaration and assignment of identifiers that reference themselves in their declaration.
124
+ // Put declaration above preceding statements in case the identifier is referenced in those.
125
+ const precedingDeclaration = lua.createVariableDeclarationStatement(lhs, undefined, tsOriginal);
126
+ context.prependPrecedingStatements(precedingDeclaration);
137
127
  if (rhs) {
138
128
  assignment = lua.createAssignmentStatement(lhs, rhs, tsOriginal);
139
129
  }
130
+ if (!isFunctionDeclaration) {
131
+ // Remember local variable declarations for hoisting later
132
+ (0, scope_1.addScopeVariableDeclaration)(scope, precedingDeclaration);
133
+ }
140
134
  }
141
135
  else {
142
136
  declaration = lua.createVariableDeclarationStatement(lhs, rhs, tsOriginal);
143
- }
144
- if (!isFunctionDeclaration) {
145
- // Remember local variable declarations for hoisting later
146
- if (!scope.variableDeclarations) {
147
- scope.variableDeclarations = [];
137
+ if (!isFunctionDeclaration) {
138
+ // Remember local variable declarations for hoisting later
139
+ (0, scope_1.addScopeVariableDeclaration)(scope, declaration);
148
140
  }
149
- scope.variableDeclarations.push(declaration);
150
141
  }
151
142
  }
152
143
  else if (rhs) {
@@ -0,0 +1,3 @@
1
+ import * as lua from "../../LuaAST";
2
+ import { TransformationContext } from "../context";
3
+ export declare function transformInPrecedingStatementScope<TReturn extends lua.Statement | lua.Statement[] | lua.Expression | lua.Expression[]>(context: TransformationContext, transformer: () => TReturn): [lua.Statement[], TReturn];
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.transformInPrecedingStatementScope = void 0;
4
+ function transformInPrecedingStatementScope(context, transformer) {
5
+ context.pushPrecedingStatements();
6
+ const statementOrStatements = transformer();
7
+ const precedingStatements = context.popPrecedingStatements();
8
+ return [precedingStatements, statementOrStatements];
9
+ }
10
+ exports.transformInPrecedingStatementScope = transformInPrecedingStatementScope;
11
+ //# sourceMappingURL=preceding-statements.js.map
@@ -37,6 +37,7 @@ export declare function peekScope(context: TransformationContext): Scope;
37
37
  export declare function findScope(context: TransformationContext, scopeTypes: ScopeType): Scope | undefined;
38
38
  export declare function pushScope(context: TransformationContext, scopeType: ScopeType): Scope;
39
39
  export declare function popScope(context: TransformationContext): Scope;
40
+ export declare function addScopeVariableDeclaration(scope: Scope, declaration: lua.VariableDeclarationStatement): void;
40
41
  export declare function hasReferencedUndefinedLocalFunction(context: TransformationContext, scope: Scope): boolean;
41
42
  export declare function hasReferencedSymbol(context: TransformationContext, scope: Scope, symbol: ts.Symbol): boolean | undefined;
42
43
  export declare function isFunctionScopeWithDefinition(scope: Scope): scope is Scope & {
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.performHoisting = exports.separateHoistedStatements = exports.isFunctionScopeWithDefinition = exports.hasReferencedSymbol = exports.hasReferencedUndefinedLocalFunction = exports.popScope = exports.pushScope = exports.findScope = exports.peekScope = exports.markSymbolAsReferencedInCurrentScopes = exports.walkScopesUp = exports.ScopeType = void 0;
3
+ exports.performHoisting = exports.separateHoistedStatements = exports.isFunctionScopeWithDefinition = exports.hasReferencedSymbol = exports.hasReferencedUndefinedLocalFunction = exports.addScopeVariableDeclaration = exports.popScope = exports.pushScope = exports.findScope = exports.peekScope = exports.markSymbolAsReferencedInCurrentScopes = exports.walkScopesUp = exports.ScopeType = void 0;
4
4
  const ts = require("typescript");
5
5
  const lua = require("../../LuaAST");
6
6
  const utils_1 = require("../../utils");
@@ -68,6 +68,13 @@ function popScope(context) {
68
68
  return scope;
69
69
  }
70
70
  exports.popScope = popScope;
71
+ function addScopeVariableDeclaration(scope, declaration) {
72
+ if (!scope.variableDeclarations) {
73
+ scope.variableDeclarations = [];
74
+ }
75
+ scope.variableDeclarations.push(declaration);
76
+ }
77
+ exports.addScopeVariableDeclaration = addScopeVariableDeclaration;
71
78
  function isHoistableFunctionDeclaredInScope(symbol, scopeNode) {
72
79
  var _a;
73
80
  return (_a = symbol === null || symbol === void 0 ? void 0 : symbol.declarations) === null || _a === void 0 ? void 0 : _a.some(d => ts.isFunctionDeclaration(d) && (0, typescript_1.findFirstNodeAbove)(d, (n) => n === scopeNode));
@@ -14,3 +14,4 @@ export declare function inferAssignedType(context: TransformationContext, expres
14
14
  export declare function getAllCallSignatures(type: ts.Type): readonly ts.Signature[];
15
15
  export declare function isExpressionWithEvaluationEffect(node: ts.Expression): boolean;
16
16
  export declare function getFunctionTypeForCall(context: TransformationContext, node: ts.CallExpression): ts.Type | undefined;
17
+ export declare function isConstIdentifier(context: TransformationContext, node: ts.Node): boolean;
@@ -10,7 +10,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
10
10
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
11
11
  };
12
12
  Object.defineProperty(exports, "__esModule", { value: true });
13
- exports.getFunctionTypeForCall = exports.isExpressionWithEvaluationEffect = exports.getAllCallSignatures = exports.inferAssignedType = exports.hasStandardLibrarySignature = exports.isStandardLibraryType = exports.getFirstDeclarationInFile = exports.findFirstNodeAbove = exports.hasExportEquals = void 0;
13
+ exports.isConstIdentifier = exports.getFunctionTypeForCall = exports.isExpressionWithEvaluationEffect = exports.getAllCallSignatures = exports.inferAssignedType = exports.hasStandardLibrarySignature = exports.isStandardLibraryType = exports.getFirstDeclarationInFile = exports.findFirstNodeAbove = exports.hasExportEquals = void 0;
14
14
  const ts = require("typescript");
15
15
  __exportStar(require("./nodes"), exports);
16
16
  __exportStar(require("./types"), exports);
@@ -94,4 +94,19 @@ function getFunctionTypeForCall(context, node) {
94
94
  return context.checker.getTypeFromTypeNode(typeDeclaration.type);
95
95
  }
96
96
  exports.getFunctionTypeForCall = getFunctionTypeForCall;
97
+ function isConstIdentifier(context, node) {
98
+ let identifier = node;
99
+ if (ts.isComputedPropertyName(identifier)) {
100
+ identifier = identifier.expression;
101
+ }
102
+ if (!ts.isIdentifier(identifier)) {
103
+ return false;
104
+ }
105
+ const symbol = context.checker.getSymbolAtLocation(identifier);
106
+ if (!symbol || !symbol.declarations) {
107
+ return false;
108
+ }
109
+ return symbol.declarations.some(d => ts.isVariableDeclarationList(d.parent) && (d.parent.flags & ts.NodeFlags.Const) !== 0);
110
+ }
111
+ exports.isConstIdentifier = isConstIdentifier;
97
112
  //# sourceMappingURL=index.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>;