typescript-to-lua 0.42.0 → 1.1.1

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 (129) hide show
  1. package/CHANGELOG.md +31 -1
  2. package/dist/CompilerOptions.d.ts +4 -3
  3. package/dist/LuaAST.js +4 -4
  4. package/dist/LuaLib.d.ts +7 -0
  5. package/dist/LuaLib.js +32 -1
  6. package/dist/LuaPrinter.d.ts +6 -2
  7. package/dist/LuaPrinter.js +25 -16
  8. package/dist/cli/diagnostics.js +2 -2
  9. package/dist/cli/parse.d.ts +1 -1
  10. package/dist/cli/parse.js +14 -0
  11. package/dist/cli/report.js +1 -1
  12. package/dist/cli/tsconfig.js +4 -4
  13. package/dist/lualib/Await.lua +59 -0
  14. package/dist/lualib/OptionalMethodCall.lua +3 -1
  15. package/dist/lualib/Promise.lua +172 -0
  16. package/dist/lualib/PromiseAll.lua +44 -0
  17. package/dist/lualib/PromiseAllSettled.lua +48 -0
  18. package/dist/lualib/PromiseAny.lua +41 -0
  19. package/dist/lualib/PromiseRace.lua +28 -0
  20. package/dist/lualib/SourceMapTraceBack.lua +20 -10
  21. package/dist/lualib/StringReplace.lua +8 -13
  22. package/dist/lualib/StringReplaceAll.lua +35 -0
  23. package/dist/lualib/lualib_bundle.lua +503 -62
  24. package/dist/transformation/builtins/array.js +29 -29
  25. package/dist/transformation/builtins/console.js +2 -2
  26. package/dist/transformation/builtins/function.js +9 -9
  27. package/dist/transformation/builtins/global.js +8 -8
  28. package/dist/transformation/builtins/index.js +35 -32
  29. package/dist/transformation/builtins/math.js +4 -4
  30. package/dist/transformation/builtins/number.js +7 -7
  31. package/dist/transformation/builtins/object.js +11 -11
  32. package/dist/transformation/builtins/promise.d.ts +7 -0
  33. package/dist/transformation/builtins/promise.js +46 -0
  34. package/dist/transformation/builtins/string.js +32 -30
  35. package/dist/transformation/builtins/symbol.js +3 -3
  36. package/dist/transformation/context/context.js +5 -5
  37. package/dist/transformation/index.js +1 -1
  38. package/dist/transformation/utils/annotations.d.ts +1 -4
  39. package/dist/transformation/utils/annotations.js +2 -39
  40. package/dist/transformation/utils/assignment-validation.js +8 -7
  41. package/dist/transformation/utils/diagnostics.d.ts +3 -0
  42. package/dist/transformation/utils/diagnostics.js +6 -5
  43. package/dist/transformation/utils/export.d.ts +3 -2
  44. package/dist/transformation/utils/export.js +14 -7
  45. package/dist/transformation/utils/function-context.js +19 -13
  46. package/dist/transformation/utils/lua-ast.js +18 -19
  47. package/dist/transformation/utils/lualib.js +1 -1
  48. package/dist/transformation/utils/safe-names.js +5 -5
  49. package/dist/transformation/utils/scope.d.ts +6 -0
  50. package/dist/transformation/utils/scope.js +70 -40
  51. package/dist/transformation/utils/symbols.js +6 -6
  52. package/dist/transformation/utils/transform.js +3 -3
  53. package/dist/transformation/utils/typescript/nodes.d.ts +2 -0
  54. package/dist/transformation/utils/typescript/nodes.js +21 -1
  55. package/dist/transformation/visitors/access.js +16 -16
  56. package/dist/transformation/visitors/async-await.d.ts +6 -0
  57. package/dist/transformation/visitors/async-await.js +38 -0
  58. package/dist/transformation/visitors/binary-expression/assignments.js +29 -29
  59. package/dist/transformation/visitors/binary-expression/bit.js +4 -4
  60. package/dist/transformation/visitors/binary-expression/compound.js +18 -18
  61. package/dist/transformation/visitors/binary-expression/destructuring-assignments.js +17 -17
  62. package/dist/transformation/visitors/binary-expression/index.js +21 -21
  63. package/dist/transformation/visitors/block.js +6 -6
  64. package/dist/transformation/visitors/break-continue.js +4 -9
  65. package/dist/transformation/visitors/call.js +38 -33
  66. package/dist/transformation/visitors/class/decorators.js +3 -3
  67. package/dist/transformation/visitors/class/index.js +41 -34
  68. package/dist/transformation/visitors/class/members/accessors.js +6 -6
  69. package/dist/transformation/visitors/class/members/constructor.js +7 -7
  70. package/dist/transformation/visitors/class/members/fields.js +6 -6
  71. package/dist/transformation/visitors/class/members/method.js +6 -6
  72. package/dist/transformation/visitors/class/new.js +13 -13
  73. package/dist/transformation/visitors/class/setup.js +11 -11
  74. package/dist/transformation/visitors/class/utils.js +2 -2
  75. package/dist/transformation/visitors/conditional.js +6 -6
  76. package/dist/transformation/visitors/delete.js +4 -4
  77. package/dist/transformation/visitors/enum.js +8 -8
  78. package/dist/transformation/visitors/errors.js +30 -31
  79. package/dist/transformation/visitors/expression-statement.js +10 -6
  80. package/dist/transformation/visitors/function.js +33 -21
  81. package/dist/transformation/visitors/identifier.js +25 -19
  82. package/dist/transformation/visitors/index.js +4 -2
  83. package/dist/transformation/visitors/language-extensions/iterable.js +7 -7
  84. package/dist/transformation/visitors/language-extensions/multi.d.ts +1 -1
  85. package/dist/transformation/visitors/language-extensions/multi.js +5 -7
  86. package/dist/transformation/visitors/language-extensions/operators.js +6 -6
  87. package/dist/transformation/visitors/language-extensions/range.js +6 -6
  88. package/dist/transformation/visitors/language-extensions/table.js +5 -5
  89. package/dist/transformation/visitors/literal.d.ts +1 -2
  90. package/dist/transformation/visitors/literal.js +19 -42
  91. package/dist/transformation/visitors/loops/do-while.js +2 -2
  92. package/dist/transformation/visitors/loops/for-in.js +4 -4
  93. package/dist/transformation/visitors/loops/for-of.js +13 -13
  94. package/dist/transformation/visitors/loops/for.js +3 -3
  95. package/dist/transformation/visitors/loops/utils.js +9 -9
  96. package/dist/transformation/visitors/modules/export.js +13 -14
  97. package/dist/transformation/visitors/modules/import.js +10 -10
  98. package/dist/transformation/visitors/namespace.js +13 -13
  99. package/dist/transformation/visitors/return.d.ts +1 -0
  100. package/dist/transformation/visitors/return.js +41 -49
  101. package/dist/transformation/visitors/sourceFile.js +8 -8
  102. package/dist/transformation/visitors/spread.js +16 -11
  103. package/dist/transformation/visitors/switch.js +132 -30
  104. package/dist/transformation/visitors/template.js +5 -5
  105. package/dist/transformation/visitors/typeof.js +2 -2
  106. package/dist/transformation/visitors/typescript.js +1 -1
  107. package/dist/transformation/visitors/unary-expression.js +9 -9
  108. package/dist/transformation/visitors/variable-declaration.js +28 -28
  109. package/dist/transformation/visitors/void.d.ts +6 -0
  110. package/dist/transformation/visitors/void.js +23 -0
  111. package/dist/transpilation/bundle.d.ts +3 -0
  112. package/dist/transpilation/bundle.js +56 -13
  113. package/dist/transpilation/diagnostics.js +3 -3
  114. package/dist/transpilation/index.js +2 -2
  115. package/dist/transpilation/output-collector.js +2 -2
  116. package/dist/transpilation/plugins.js +1 -1
  117. package/dist/transpilation/resolve.js +28 -15
  118. package/dist/transpilation/transformers.d.ts +1 -0
  119. package/dist/transpilation/transformers.js +61 -25
  120. package/dist/transpilation/transpile.js +7 -7
  121. package/dist/transpilation/transpiler.js +8 -8
  122. package/dist/transpilation/utils.js +3 -2
  123. package/dist/tstl.js +8 -8
  124. package/dist/utils.js +2 -2
  125. package/package.json +15 -12
  126. package/dist/transformation/visitors/jsx/jsx.d.ts +0 -9
  127. package/dist/transformation/visitors/jsx/jsx.js +0 -237
  128. package/dist/transformation/visitors/jsx/xhtml.d.ts +0 -3
  129. package/dist/transformation/visitors/jsx/xhtml.js +0 -260
@@ -13,11 +13,11 @@ const symbols_1 = require("../utils/symbols");
13
13
  const identifier_1 = require("./identifier");
14
14
  function createModuleLocalNameIdentifier(context, declaration) {
15
15
  const moduleSymbol = context.checker.getSymbolAtLocation(declaration.name);
16
- if (moduleSymbol !== undefined && safe_names_1.isUnsafeName(moduleSymbol.name)) {
17
- return lua.createIdentifier(safe_names_1.createSafeName(declaration.name.text), declaration.name, moduleSymbol && symbols_1.getSymbolIdOfSymbol(context, moduleSymbol), declaration.name.text);
16
+ if (moduleSymbol !== undefined && (0, safe_names_1.isUnsafeName)(moduleSymbol.name)) {
17
+ return lua.createIdentifier((0, safe_names_1.createSafeName)(declaration.name.text), declaration.name, moduleSymbol && (0, symbols_1.getSymbolIdOfSymbol)(context, moduleSymbol), declaration.name.text);
18
18
  }
19
19
  // TODO: Should synthetic name nodes be escaped as well?
20
- return identifier_1.transformIdentifier(context, declaration.name);
20
+ return (0, identifier_1.transformIdentifier)(context, declaration.name);
21
21
  }
22
22
  exports.createModuleLocalNameIdentifier = createModuleLocalNameIdentifier;
23
23
  // TODO: Do it based on transform result?
@@ -37,17 +37,17 @@ function moduleHasEmittedBody(node) {
37
37
  const currentNamespaces = new WeakMap();
38
38
  const transformModuleDeclaration = (node, context) => {
39
39
  var _a, _b;
40
- const annotations = annotations_1.getTypeAnnotations(context.checker.getTypeAtLocation(node));
40
+ const annotations = (0, annotations_1.getTypeAnnotations)(context.checker.getTypeAtLocation(node));
41
41
  // If phantom namespace elide the declaration and return the body
42
42
  if (annotations.has(annotations_1.AnnotationKind.Phantom)) {
43
- context.diagnostics.push(diagnostics_1.annotationRemoved(node, annotations_1.AnnotationKind.Phantom));
43
+ context.diagnostics.push((0, diagnostics_1.annotationRemoved)(node, annotations_1.AnnotationKind.Phantom));
44
44
  }
45
45
  const currentNamespace = currentNamespaces.get(context);
46
46
  const result = [];
47
47
  const symbol = context.checker.getSymbolAtLocation(node.name);
48
48
  const hasExports = symbol !== undefined && context.checker.getExportsOfModule(symbol).length > 0;
49
- const nameIdentifier = identifier_1.transformIdentifier(context, node.name);
50
- const exportScope = export_1.getIdentifierExportScope(context, nameIdentifier);
49
+ const nameIdentifier = (0, identifier_1.transformIdentifier)(context, node.name);
50
+ const exportScope = (0, export_1.getIdentifierExportScope)(context, nameIdentifier);
51
51
  // Non-module namespace could be merged if:
52
52
  // - is top level
53
53
  // - is nested and exported
@@ -60,17 +60,17 @@ const transformModuleDeclaration = (node, context) => {
60
60
  ts.getOriginalNode(node) === ((_b = symbol.declarations) === null || _b === void 0 ? void 0 : _b.find(ts.isModuleDeclaration)));
61
61
  if (isNonModuleMergeable) {
62
62
  // 'local NS = NS or {}' or 'exportTable.NS = exportTable.NS or {}'
63
- const localDeclaration = lua_ast_1.createLocalOrExportedOrGlobalDeclaration(context, nameIdentifier, lua.createBinaryExpression(export_1.addExportToIdentifier(context, nameIdentifier), lua.createTableExpression(), lua.SyntaxKind.OrOperator));
63
+ const localDeclaration = (0, lua_ast_1.createLocalOrExportedOrGlobalDeclaration)(context, nameIdentifier, lua.createBinaryExpression((0, export_1.addExportToIdentifier)(context, nameIdentifier), lua.createTableExpression(), lua.SyntaxKind.OrOperator));
64
64
  result.push(...localDeclaration);
65
65
  }
66
66
  else if (isFirstDeclaration) {
67
67
  // local NS = {} or exportTable.NS = {}
68
- const localDeclaration = lua_ast_1.createLocalOrExportedOrGlobalDeclaration(context, nameIdentifier, lua.createTableExpression());
68
+ const localDeclaration = (0, lua_ast_1.createLocalOrExportedOrGlobalDeclaration)(context, nameIdentifier, lua.createTableExpression());
69
69
  result.push(...localDeclaration);
70
70
  }
71
71
  if ((isNonModuleMergeable || isFirstDeclaration) && exportScope && hasExports && moduleHasEmittedBody(node)) {
72
72
  // local NS = exportTable.NS
73
- const localDeclaration = lua_ast_1.createHoistableVariableDeclarationStatement(context, createModuleLocalNameIdentifier(context, node), export_1.createExportedIdentifier(context, nameIdentifier, exportScope));
73
+ const localDeclaration = (0, lua_ast_1.createHoistableVariableDeclarationStatement)(context, createModuleLocalNameIdentifier(context, node), (0, export_1.createExportedIdentifier)(context, nameIdentifier, exportScope));
74
74
  result.push(localDeclaration);
75
75
  }
76
76
  // Set current namespace for nested NS
@@ -78,9 +78,9 @@ const transformModuleDeclaration = (node, context) => {
78
78
  currentNamespaces.set(context, node);
79
79
  // Transform moduleblock to block and visit it
80
80
  if (moduleHasEmittedBody(node)) {
81
- scope_1.pushScope(context, scope_1.ScopeType.Block);
82
- const statements = scope_1.performHoisting(context, context.transformStatements(ts.isModuleBlock(node.body) ? node.body.statements : node.body));
83
- scope_1.popScope(context);
81
+ (0, scope_1.pushScope)(context, scope_1.ScopeType.Block);
82
+ const statements = (0, scope_1.performHoisting)(context, context.transformStatements(ts.isModuleBlock(node.body) ? node.body.statements : node.body));
83
+ (0, scope_1.popScope)(context);
84
84
  result.push(lua.createDoStatement(statements));
85
85
  }
86
86
  currentNamespaces.set(context, currentNamespace);
@@ -3,3 +3,4 @@ import * as lua from "../../LuaAST";
3
3
  import { FunctionVisitor, TransformationContext } from "../context";
4
4
  export declare function transformExpressionBodyToReturnStatement(context: TransformationContext, node: ts.Expression): lua.Statement;
5
5
  export declare const transformReturnStatement: FunctionVisitor<ts.ReturnStatement>;
6
+ export declare function createReturnStatement(context: TransformationContext, values: lua.Expression[], node: ts.Node): lua.ReturnStatement;
@@ -1,95 +1,87 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.transformReturnStatement = exports.transformExpressionBodyToReturnStatement = void 0;
3
+ exports.createReturnStatement = exports.transformReturnStatement = exports.transformExpressionBodyToReturnStatement = void 0;
4
4
  const ts = require("typescript");
5
5
  const lua = require("../../LuaAST");
6
- const annotations_1 = require("../utils/annotations");
7
6
  const assignment_validation_1 = require("../utils/assignment-validation");
8
7
  const lua_ast_1 = require("../utils/lua-ast");
9
8
  const scope_1 = require("../utils/scope");
10
- const typescript_1 = require("../utils/typescript");
11
9
  const call_1 = require("./call");
12
10
  const multi_1 = require("./language-extensions/multi");
13
11
  const diagnostics_1 = require("../utils/diagnostics");
12
+ const typescript_1 = require("../utils/typescript");
14
13
  function transformExpressionsInReturn(context, node, insideTryCatch) {
15
14
  const expressionType = context.checker.getTypeAtLocation(node);
16
15
  if (ts.isCallExpression(node)) {
17
16
  // $multi(...)
18
- if (multi_1.isMultiFunctionCall(context, node)) {
17
+ if ((0, multi_1.isMultiFunctionCall)(context, node)) {
19
18
  // Don't allow $multi to be implicitly cast to something other than LuaMultiReturn
20
19
  const type = context.checker.getContextualType(node);
21
- if (type && !multi_1.canBeMultiReturnType(type)) {
22
- context.diagnostics.push(diagnostics_1.invalidMultiFunctionReturnType(node));
20
+ if (type && !(0, multi_1.canBeMultiReturnType)(type)) {
21
+ context.diagnostics.push((0, diagnostics_1.invalidMultiFunctionReturnType)(node));
23
22
  }
24
- let returnValues = call_1.transformArguments(context, node.arguments);
23
+ let returnValues = (0, call_1.transformArguments)(context, node.arguments);
25
24
  if (insideTryCatch) {
26
- returnValues = [lua_ast_1.wrapInTable(...returnValues)]; // Wrap results when returning inside try/catch
25
+ returnValues = [(0, lua_ast_1.wrapInTable)(...returnValues)]; // Wrap results when returning inside try/catch
27
26
  }
28
27
  return returnValues;
29
28
  }
30
29
  // Force-wrap LuaMultiReturn when returning inside try/catch
31
- if (insideTryCatch && multi_1.returnsMultiType(context, node) && !multi_1.shouldMultiReturnCallBeWrapped(context, node)) {
32
- return [lua_ast_1.wrapInTable(context.transformExpression(node))];
30
+ if (insideTryCatch && (0, multi_1.returnsMultiType)(context, node) && !(0, multi_1.shouldMultiReturnCallBeWrapped)(context, node)) {
31
+ return [(0, lua_ast_1.wrapInTable)(context.transformExpression(node))];
33
32
  }
34
33
  }
35
- else if (multi_1.isInMultiReturnFunction(context, node) && multi_1.isMultiReturnType(expressionType)) {
34
+ else if ((0, multi_1.isInMultiReturnFunction)(context, node) && (0, multi_1.isMultiReturnType)(expressionType)) {
36
35
  // Unpack objects typed as LuaMultiReturn
37
- return [lua_ast_1.createUnpackCall(context, context.transformExpression(node), node)];
38
- }
39
- if (!annotations_1.isInTupleReturnFunction(context, node)) {
40
- return [context.transformExpression(node)];
41
- }
42
- let results;
43
- // Parent function is a TupleReturn function
44
- if (ts.isArrayLiteralExpression(node)) {
45
- // If return expression is an array literal, leave out brackets.
46
- results = node.elements.map(e => context.transformExpression(e));
47
- }
48
- else if (!multi_1.isMultiReturnCall(context, node) && typescript_1.isArrayType(context, expressionType)) {
49
- // If return expression is an array-type and not another TupleReturn call, unpack it
50
- results = [lua_ast_1.createUnpackCall(context, context.transformExpression(node), node)];
51
- }
52
- else {
53
- results = [context.transformExpression(node)];
36
+ return [(0, lua_ast_1.createUnpackCall)(context, context.transformExpression(node), node)];
54
37
  }
55
- // Wrap tupleReturn results when returning inside try/catch
56
- if (insideTryCatch) {
57
- results = [lua_ast_1.wrapInTable(...results)];
58
- }
59
- return results;
38
+ return [context.transformExpression(node)];
60
39
  }
61
40
  function transformExpressionBodyToReturnStatement(context, node) {
62
41
  const expressions = transformExpressionsInReturn(context, node, false);
63
- return lua.createReturnStatement(expressions, node);
42
+ return createReturnStatement(context, expressions, node);
64
43
  }
65
44
  exports.transformExpressionBodyToReturnStatement = transformExpressionBodyToReturnStatement;
66
45
  const transformReturnStatement = (statement, context) => {
67
- // Bubble up explicit return flag and check if we're inside a try/catch block
68
- let insideTryCatch = false;
69
- for (const scope of scope_1.walkScopesUp(context)) {
70
- scope.functionReturned = true;
71
- if (scope.type === scope_1.ScopeType.Function) {
72
- break;
73
- }
74
- insideTryCatch = insideTryCatch || scope.type === scope_1.ScopeType.Try || scope.type === scope_1.ScopeType.Catch;
75
- }
76
46
  let results;
77
47
  if (statement.expression) {
78
48
  const expressionType = context.checker.getTypeAtLocation(statement.expression);
79
49
  const returnType = context.checker.getContextualType(statement.expression);
80
50
  if (returnType) {
81
- assignment_validation_1.validateAssignment(context, statement, expressionType, returnType);
51
+ (0, assignment_validation_1.validateAssignment)(context, statement, expressionType, returnType);
82
52
  }
83
- results = transformExpressionsInReturn(context, statement.expression, insideTryCatch);
53
+ results = transformExpressionsInReturn(context, statement.expression, isInTryCatch(context));
84
54
  }
85
55
  else {
86
56
  // Empty return
87
57
  results = [];
88
58
  }
89
- if (insideTryCatch) {
90
- results.unshift(lua.createBooleanLiteral(true));
91
- }
92
- return lua.createReturnStatement(results, statement);
59
+ return createReturnStatement(context, results, statement);
93
60
  };
94
61
  exports.transformReturnStatement = transformReturnStatement;
62
+ function createReturnStatement(context, values, node) {
63
+ const results = [...values];
64
+ if (isInTryCatch(context)) {
65
+ // Bubble up explicit return flag and check if we're inside a try/catch block
66
+ results.unshift(lua.createBooleanLiteral(true));
67
+ }
68
+ else if ((0, typescript_1.isInAsyncFunction)(node)) {
69
+ // Add nil error handler in async function and not in try
70
+ results.unshift(lua.createNilLiteral());
71
+ }
72
+ return lua.createReturnStatement(results, node);
73
+ }
74
+ exports.createReturnStatement = createReturnStatement;
75
+ function isInTryCatch(context) {
76
+ // Check if context is in a try or catch
77
+ let insideTryCatch = false;
78
+ for (const scope of (0, scope_1.walkScopesUp)(context)) {
79
+ scope.functionReturned = true;
80
+ if (scope.type === scope_1.ScopeType.Function) {
81
+ break;
82
+ }
83
+ insideTryCatch = insideTryCatch || scope.type === scope_1.ScopeType.Try || scope.type === scope_1.ScopeType.Catch;
84
+ }
85
+ return insideTryCatch;
86
+ }
95
87
  //# sourceMappingURL=return.js.map
@@ -14,7 +14,7 @@ const transformSourceFileNode = (node, context) => {
14
14
  if (node.flags & ts.NodeFlags.JsonFile) {
15
15
  const [statement] = node.statements;
16
16
  if (statement) {
17
- utils_1.assert(ts.isExpressionStatement(statement));
17
+ (0, utils_1.assert)(ts.isExpressionStatement(statement));
18
18
  statements.push(lua.createReturnStatement([context.transformExpression(statement.expression)]));
19
19
  }
20
20
  else {
@@ -25,21 +25,21 @@ const transformSourceFileNode = (node, context) => {
25
25
  }
26
26
  }
27
27
  else {
28
- scope_1.pushScope(context, scope_1.ScopeType.File);
29
- statements = scope_1.performHoisting(context, context.transformStatements(node.statements));
30
- scope_1.popScope(context);
28
+ (0, scope_1.pushScope)(context, scope_1.ScopeType.File);
29
+ statements = (0, scope_1.performHoisting)(context, context.transformStatements(node.statements));
30
+ (0, scope_1.popScope)(context);
31
31
  if (context.isModule) {
32
32
  // If export equals was not used. Create the exports table.
33
33
  // local ____exports = {}
34
- if (!typescript_1.hasExportEquals(node)) {
35
- statements.unshift(lua.createVariableDeclarationStatement(lua_ast_1.createExportsIdentifier(), lua.createTableExpression()));
34
+ if (!(0, typescript_1.hasExportEquals)(node)) {
35
+ statements.unshift(lua.createVariableDeclarationStatement((0, lua_ast_1.createExportsIdentifier)(), lua.createTableExpression()));
36
36
  }
37
37
  // return ____exports
38
- statements.push(lua.createReturnStatement([lua_ast_1.createExportsIdentifier()]));
38
+ statements.push(lua.createReturnStatement([(0, lua_ast_1.createExportsIdentifier)()]));
39
39
  }
40
40
  }
41
41
  const trivia = (_b = (_a = node.getFullText().match(/^#!.*\r?\n/)) === null || _a === void 0 ? void 0 : _a[0]) !== null && _b !== void 0 ? _b : "";
42
- return lua.createFile(statements, lualib_1.getUsedLuaLibFeatures(context), trivia, node);
42
+ return lua.createFile(statements, (0, lualib_1.getUsedLuaLibFeatures)(context), trivia, node);
43
43
  };
44
44
  exports.transformSourceFileNode = transformSourceFileNode;
45
45
  //# sourceMappingURL=sourceFile.js.map
@@ -12,20 +12,25 @@ const multi_1 = require("./language-extensions/multi");
12
12
  const diagnostics_1 = require("../utils/diagnostics");
13
13
  const vararg_1 = require("./language-extensions/vararg");
14
14
  function isOptimizedVarArgSpread(context, symbol, identifier) {
15
+ var _a;
15
16
  if (!ts.isSpreadElement(identifier.parent)) {
16
17
  return false;
17
18
  }
18
19
  // Walk up, stopping at any scope types which could stop optimization
19
- const scope = scope_1.findScope(context, scope_1.ScopeType.Function | scope_1.ScopeType.Try | scope_1.ScopeType.Catch | scope_1.ScopeType.File);
20
+ const scope = (0, scope_1.findScope)(context, scope_1.ScopeType.Function | scope_1.ScopeType.Try | scope_1.ScopeType.Catch | scope_1.ScopeType.File);
20
21
  if (!scope) {
21
22
  return;
22
23
  }
23
24
  // $vararg global constant
24
- if (vararg_1.isGlobalVarargConstant(context, symbol, scope)) {
25
+ if ((0, vararg_1.isGlobalVarargConstant)(context, symbol, scope)) {
25
26
  return true;
26
27
  }
27
28
  // Scope must be a function scope associated with a real ts function
28
- if (!scope_1.isFunctionScopeWithDefinition(scope)) {
29
+ if (!(0, scope_1.isFunctionScopeWithDefinition)(scope)) {
30
+ return false;
31
+ }
32
+ // Scope cannot be an async function
33
+ if ((_a = scope.node.modifiers) === null || _a === void 0 ? void 0 : _a.some(m => m.kind === ts.SyntaxKind.AsyncKeyword)) {
29
34
  return false;
30
35
  }
31
36
  // Identifier must be a vararg in the local function scope's parameters
@@ -34,11 +39,11 @@ function isOptimizedVarArgSpread(context, symbol, identifier) {
34
39
  return false;
35
40
  }
36
41
  // De-optimize if already referenced outside of a spread, as the array may have been modified
37
- if (scope_1.hasReferencedSymbol(context, scope, symbol)) {
42
+ if ((0, scope_1.hasReferencedSymbol)(context, scope, symbol)) {
38
43
  return false;
39
44
  }
40
45
  // De-optimize if a function is being hoisted from below to above, as it may have modified the array
41
- if (scope_1.hasReferencedUndefinedLocalFunction(context, scope)) {
46
+ if ((0, scope_1.hasReferencedUndefinedLocalFunction)(context, scope)) {
42
47
  return false;
43
48
  }
44
49
  return true;
@@ -47,8 +52,8 @@ exports.isOptimizedVarArgSpread = isOptimizedVarArgSpread;
47
52
  // TODO: Currently it's also used as an array member
48
53
  const transformSpreadElement = (node, context) => {
49
54
  if (ts.isIdentifier(node.expression)) {
50
- if (annotations_1.isVarargType(context, node.expression)) {
51
- context.diagnostics.push(diagnostics_1.annotationRemoved(node, annotations_1.AnnotationKind.Vararg));
55
+ if ((0, annotations_1.isVarargType)(context, node.expression)) {
56
+ context.diagnostics.push((0, diagnostics_1.annotationRemoved)(node, annotations_1.AnnotationKind.Vararg));
52
57
  }
53
58
  const symbol = context.checker.getSymbolAtLocation(node.expression);
54
59
  if (symbol && isOptimizedVarArgSpread(context, symbol, node.expression)) {
@@ -56,13 +61,13 @@ const transformSpreadElement = (node, context) => {
56
61
  }
57
62
  }
58
63
  const innerExpression = context.transformExpression(node.expression);
59
- if (multi_1.isMultiReturnCall(context, node.expression))
64
+ if ((0, multi_1.isMultiReturnCall)(context, node.expression))
60
65
  return innerExpression;
61
66
  const type = context.checker.getTypeAtLocation(node.expression);
62
- if (typescript_1.isArrayType(context, type)) {
63
- return lua_ast_1.createUnpackCall(context, innerExpression, node);
67
+ if ((0, typescript_1.isArrayType)(context, type)) {
68
+ return (0, lua_ast_1.createUnpackCall)(context, innerExpression, node);
64
69
  }
65
- return lualib_1.transformLuaLibFunction(context, lualib_1.LuaLibFeature.Spread, node, innerExpression);
70
+ return (0, lualib_1.transformLuaLibFunction)(context, lualib_1.LuaLibFeature.Spread, node, innerExpression);
66
71
  };
67
72
  exports.transformSpreadElement = transformSpreadElement;
68
73
  //# sourceMappingURL=spread.js.map
@@ -2,46 +2,148 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.transformSwitchStatement = void 0;
4
4
  const ts = require("typescript");
5
- const CompilerOptions_1 = require("../../CompilerOptions");
6
5
  const lua = require("../../LuaAST");
7
- const diagnostics_1 = require("../utils/diagnostics");
8
6
  const scope_1 = require("../utils/scope");
9
- const transformSwitchStatement = (statement, context) => {
10
- if (context.luaTarget === CompilerOptions_1.LuaTarget.Universal || context.luaTarget === CompilerOptions_1.LuaTarget.Lua51) {
11
- context.diagnostics.push(diagnostics_1.unsupportedForTarget(statement, "Switch statements", CompilerOptions_1.LuaTarget.Lua51));
7
+ const containsBreakOrReturn = (nodes) => {
8
+ for (const s of nodes) {
9
+ if (ts.isBreakStatement(s) || ts.isReturnStatement(s)) {
10
+ return true;
11
+ }
12
+ else if (ts.isBlock(s) && containsBreakOrReturn(s.getChildren())) {
13
+ return true;
14
+ }
15
+ else if (s.kind === ts.SyntaxKind.SyntaxList && containsBreakOrReturn(s.getChildren())) {
16
+ return true;
17
+ }
18
+ }
19
+ return false;
20
+ };
21
+ const coalesceCondition = (condition, switchVariable, expression, context) => {
22
+ // Coalesce skipped statements
23
+ if (condition) {
24
+ return lua.createBinaryExpression(condition, lua.createBinaryExpression(switchVariable, context.transformExpression(expression), lua.SyntaxKind.EqualityOperator), lua.SyntaxKind.OrOperator);
12
25
  }
13
- const scope = scope_1.pushScope(context, scope_1.ScopeType.Switch);
14
- // Give the switch a unique name to prevent nested switches from acting up.
26
+ // Next condition
27
+ return lua.createBinaryExpression(switchVariable, context.transformExpression(expression), lua.SyntaxKind.EqualityOperator);
28
+ };
29
+ const transformSwitchStatement = (statement, context) => {
30
+ const scope = (0, scope_1.pushScope)(context, scope_1.ScopeType.Switch);
31
+ // Give the switch and condition accumulator a unique name to prevent nested switches from acting up.
15
32
  const switchName = `____switch${scope.id}`;
33
+ const conditionName = `____cond${scope.id}`;
16
34
  const switchVariable = lua.createIdentifier(switchName);
17
- let statements = [];
18
- // Starting from the back, concatenating ifs into one big if/elseif statement
19
- const concatenatedIf = statement.caseBlock.clauses.reduceRight((previousCondition, clause, index) => {
20
- if (ts.isDefaultClause(clause)) {
21
- // Skip default clause here (needs to be included to ensure index lines up with index later)
22
- return previousCondition;
35
+ const conditionVariable = lua.createIdentifier(conditionName);
36
+ // If the switch only has a default clause, wrap it in a single do.
37
+ // Otherwise, we need to generate a set of if statements to emulate the switch.
38
+ const statements = [];
39
+ const hoistedStatements = [];
40
+ const hoistedIdentifiers = [];
41
+ const clauses = statement.caseBlock.clauses;
42
+ if (clauses.length === 1 && ts.isDefaultClause(clauses[0])) {
43
+ const defaultClause = clauses[0].statements;
44
+ if (defaultClause.length) {
45
+ const { statements: defaultStatements, hoistedStatements: defaultHoistedStatements, hoistedIdentifiers: defaultHoistedIdentifiers, } = (0, scope_1.separateHoistedStatements)(context, context.transformStatements(defaultClause));
46
+ hoistedStatements.push(...defaultHoistedStatements);
47
+ hoistedIdentifiers.push(...defaultHoistedIdentifiers);
48
+ statements.push(lua.createDoStatement(defaultStatements));
49
+ }
50
+ }
51
+ else {
52
+ // Build up the condition for each if statement
53
+ let defaultTransformed = false;
54
+ let isInitialCondition = true;
55
+ let condition = undefined;
56
+ for (let i = 0; i < clauses.length; i++) {
57
+ const clause = clauses[i];
58
+ const previousClause = clauses[i - 1];
59
+ // Skip redundant default clauses, will be handled in final default case
60
+ if (i === 0 && ts.isDefaultClause(clause))
61
+ continue;
62
+ if (ts.isDefaultClause(clause) && previousClause && containsBreakOrReturn(previousClause.statements)) {
63
+ continue;
64
+ }
65
+ // Compute the condition for the if statement
66
+ if (!ts.isDefaultClause(clause)) {
67
+ condition = coalesceCondition(condition, switchVariable, clause.expression, context);
68
+ // Skip empty clauses unless final clause (i.e side-effects)
69
+ if (i !== clauses.length - 1 && clause.statements.length === 0)
70
+ continue;
71
+ // Declare or assign condition variable
72
+ statements.push(isInitialCondition
73
+ ? lua.createVariableDeclarationStatement(conditionVariable, condition)
74
+ : lua.createAssignmentStatement(conditionVariable, lua.createBinaryExpression(conditionVariable, condition, lua.SyntaxKind.OrOperator)));
75
+ isInitialCondition = false;
76
+ }
77
+ else {
78
+ // If the default is proceeded by empty clauses and will be emitted we may need to initialize the condition
79
+ if (isInitialCondition) {
80
+ statements.push(lua.createVariableDeclarationStatement(conditionVariable, condition !== null && condition !== void 0 ? condition : lua.createBooleanLiteral(false)));
81
+ // Clear condition ot ensure it is not evaluated twice
82
+ condition = undefined;
83
+ isInitialCondition = false;
84
+ }
85
+ // Allow default to fallthrough to final default clause
86
+ if (i === clauses.length - 1) {
87
+ // Evaluate the final condition that we may be skipping
88
+ if (condition) {
89
+ statements.push(lua.createAssignmentStatement(conditionVariable, lua.createBinaryExpression(conditionVariable, condition, lua.SyntaxKind.OrOperator)));
90
+ }
91
+ continue;
92
+ }
93
+ }
94
+ // Transform the clause and append the final break statement if necessary
95
+ const { statements: clauseStatements, hoistedStatements: clauseHoistedStatements, hoistedIdentifiers: clauseHoistedIdentifiers, } = (0, scope_1.separateHoistedStatements)(context, context.transformStatements(clause.statements));
96
+ if (i === clauses.length - 1 && !containsBreakOrReturn(clause.statements)) {
97
+ clauseStatements.push(lua.createBreakStatement());
98
+ }
99
+ hoistedStatements.push(...clauseHoistedStatements);
100
+ hoistedIdentifiers.push(...clauseHoistedIdentifiers);
101
+ // Remember that we transformed default clause so we don't duplicate hoisted statements later
102
+ if (ts.isDefaultClause(clause)) {
103
+ defaultTransformed = true;
104
+ }
105
+ // Push if statement for case
106
+ statements.push(lua.createIfStatement(conditionVariable, lua.createBlock(clauseStatements)));
107
+ // Clear condition for next clause
108
+ condition = undefined;
109
+ }
110
+ // If no conditions above match, we need to create the final default case code-path,
111
+ // as we only handle fallthrough into defaults in the previous if statement chain
112
+ const start = clauses.findIndex(c => ts.isDefaultClause(c));
113
+ if (start >= 0) {
114
+ // Find the last clause that we can fallthrough to
115
+ const end = clauses.findIndex((clause, index) => index >= start && containsBreakOrReturn(clause.statements));
116
+ const { statements: defaultStatements, hoistedStatements: defaultHoistedStatements, hoistedIdentifiers: defaultHoistedIdentifiers, } = (0, scope_1.separateHoistedStatements)(context, context.transformStatements(clauses[start].statements));
117
+ // Only push hoisted statements if this is the first time we're transforming the default clause
118
+ if (!defaultTransformed) {
119
+ hoistedStatements.push(...defaultHoistedStatements);
120
+ hoistedIdentifiers.push(...defaultHoistedIdentifiers);
121
+ }
122
+ // Combine the fallthrough statements
123
+ for (const clause of clauses.slice(start + 1, end >= 0 ? end + 1 : undefined)) {
124
+ let statements = context.transformStatements(clause.statements);
125
+ // Drop hoisted statements as they were already added when clauses were initially transformed above
126
+ ({ statements } = (0, scope_1.separateHoistedStatements)(context, statements));
127
+ defaultStatements.push(...statements);
128
+ }
129
+ // Add the default clause if it has any statements
130
+ // The switch will always break on the final clause and skip execution if valid to do so
131
+ if (defaultStatements.length) {
132
+ statements.push(lua.createDoStatement(defaultStatements));
133
+ }
23
134
  }
24
- // If the clause condition holds, go to the correct label
25
- const condition = lua.createBinaryExpression(switchVariable, context.transformExpression(clause.expression), lua.SyntaxKind.EqualityOperator);
26
- const goto = lua.createGotoStatement(`${switchName}_case_${index}`);
27
- return lua.createIfStatement(condition, lua.createBlock([goto]), previousCondition);
28
- }, undefined);
29
- if (concatenatedIf) {
30
- statements.push(concatenatedIf);
31
135
  }
32
- const hasDefaultCase = statement.caseBlock.clauses.some(ts.isDefaultClause);
33
- statements.push(lua.createGotoStatement(`${switchName}_${hasDefaultCase ? "case_default" : "end"}`));
34
- for (const [index, clause] of statement.caseBlock.clauses.entries()) {
35
- const labelName = `${switchName}_case_${ts.isCaseClause(clause) ? index : "default"}`;
36
- statements.push(lua.createLabelStatement(labelName));
37
- statements.push(lua.createDoStatement(context.transformStatements(clause.statements)));
136
+ // Hoist the variable, function, and import statements to the top of the switch
137
+ statements.unshift(...hoistedStatements);
138
+ if (hoistedIdentifiers.length > 0) {
139
+ statements.unshift(lua.createVariableDeclarationStatement(hoistedIdentifiers));
38
140
  }
39
- statements.push(lua.createLabelStatement(`${switchName}_end`));
40
- statements = scope_1.performHoisting(context, statements);
41
- scope_1.popScope(context);
141
+ (0, scope_1.popScope)(context);
142
+ // Add the switch expression after hoisting
42
143
  const expression = context.transformExpression(statement.expression);
43
144
  statements.unshift(lua.createVariableDeclarationStatement(switchVariable, expression));
44
- return statements;
145
+ // Wrap the statements in a repeat until true statement to facilitate dynamic break/returns
146
+ return lua.createRepeatStatement(lua.createBlock(statements), lua.createBooleanLiteral(true));
45
147
  };
46
148
  exports.transformSwitchStatement = transformSwitchStatement;
47
149
  //# sourceMappingURL=switch.js.map
@@ -24,11 +24,11 @@ const transformTemplateExpression = (node, context) => {
24
24
  for (const span of node.templateSpans) {
25
25
  const expression = context.transformExpression(span.expression);
26
26
  const spanType = context.checker.getTypeAtLocation(span.expression);
27
- if (types_1.isStringType(context, spanType)) {
27
+ if ((0, types_1.isStringType)(context, spanType)) {
28
28
  parts.push(expression);
29
29
  }
30
30
  else {
31
- parts.push(lua_ast_1.wrapInToStringForConcat(expression));
31
+ parts.push((0, lua_ast_1.wrapInToStringForConcat)(expression));
32
32
  }
33
33
  const text = span.literal.text;
34
34
  if (text.length > 0) {
@@ -65,12 +65,12 @@ const transformTaggedTemplateExpression = (expression, context) => {
65
65
  // Evaluate if there is a self parameter to be used.
66
66
  const signature = context.checker.getResolvedSignature(expression);
67
67
  const signatureDeclaration = signature === null || signature === void 0 ? void 0 : signature.getDeclaration();
68
- const useSelfParameter = signatureDeclaration && function_context_1.getDeclarationContextType(context, signatureDeclaration) !== function_context_1.ContextType.Void;
68
+ const useSelfParameter = signatureDeclaration && (0, function_context_1.getDeclarationContextType)(context, signatureDeclaration) !== function_context_1.ContextType.Void;
69
69
  if (useSelfParameter) {
70
- return call_1.transformContextualCallExpression(context, expression, expressions, signature);
70
+ return (0, call_1.transformContextualCallExpression)(context, expression, expressions, signature);
71
71
  }
72
72
  // Argument evaluation.
73
- const callArguments = call_1.transformArguments(context, expressions, signature);
73
+ const callArguments = (0, call_1.transformArguments)(context, expressions, signature);
74
74
  const leftHandSideExpression = context.transformExpression(expression.tag);
75
75
  return lua.createCallExpression(leftHandSideExpression, callArguments);
76
76
  };
@@ -8,7 +8,7 @@ const lualib_1 = require("../utils/lualib");
8
8
  const binary_expression_1 = require("./binary-expression");
9
9
  const transformTypeOfExpression = (node, context) => {
10
10
  const innerExpression = context.transformExpression(node.expression);
11
- return lualib_1.transformLuaLibFunction(context, LuaLib_1.LuaLibFeature.TypeOf, node, innerExpression);
11
+ return (0, lualib_1.transformLuaLibFunction)(context, LuaLib_1.LuaLibFeature.TypeOf, node, innerExpression);
12
12
  };
13
13
  exports.transformTypeOfExpression = transformTypeOfExpression;
14
14
  function transformTypeOfBinaryExpression(context, node) {
@@ -43,7 +43,7 @@ function transformTypeOfBinaryExpression(context, node) {
43
43
  }
44
44
  const innerExpression = context.transformExpression(typeOfExpression.expression);
45
45
  const typeCall = lua.createCallExpression(lua.createIdentifier("type"), [innerExpression], typeOfExpression);
46
- return binary_expression_1.transformBinaryOperation(context, typeCall, comparedExpression, operator, node);
46
+ return (0, binary_expression_1.transformBinaryOperation)(context, typeCall, comparedExpression, operator, node);
47
47
  }
48
48
  exports.transformTypeOfBinaryExpression = transformTypeOfBinaryExpression;
49
49
  //# sourceMappingURL=typeof.js.map
@@ -5,7 +5,7 @@ const ts = require("typescript");
5
5
  const assignment_validation_1 = require("../utils/assignment-validation");
6
6
  const transformAssertionExpression = (expression, context) => {
7
7
  if (!ts.isConstTypeReference(expression.type)) {
8
- assignment_validation_1.validateAssignment(context, expression, context.checker.getTypeAtLocation(expression.expression), context.checker.getTypeAtLocation(expression.type));
8
+ (0, assignment_validation_1.validateAssignment)(context, expression, context.checker.getTypeAtLocation(expression.expression), context.checker.getTypeAtLocation(expression.type));
9
9
  }
10
10
  return context.transformExpression(expression.expression);
11
11
  };
@@ -12,32 +12,32 @@ function transformUnaryExpressionStatement(context, node) {
12
12
  (expression.operator === ts.SyntaxKind.PlusPlusToken || expression.operator === ts.SyntaxKind.MinusMinusToken)) {
13
13
  // ++i, --i
14
14
  const replacementOperator = expression.operator === ts.SyntaxKind.PlusPlusToken ? ts.SyntaxKind.PlusToken : ts.SyntaxKind.MinusToken;
15
- return compound_1.transformCompoundAssignmentStatement(context, expression, expression.operand, ts.factory.createNumericLiteral(1), replacementOperator);
15
+ return (0, compound_1.transformCompoundAssignmentStatement)(context, expression, expression.operand, ts.factory.createNumericLiteral(1), replacementOperator);
16
16
  }
17
17
  else if (ts.isPostfixUnaryExpression(expression)) {
18
18
  // i++, i--
19
19
  const replacementOperator = expression.operator === ts.SyntaxKind.PlusPlusToken ? ts.SyntaxKind.PlusToken : ts.SyntaxKind.MinusToken;
20
- return compound_1.transformCompoundAssignmentStatement(context, expression, expression.operand, ts.factory.createNumericLiteral(1), replacementOperator);
20
+ return (0, compound_1.transformCompoundAssignmentStatement)(context, expression, expression.operand, ts.factory.createNumericLiteral(1), replacementOperator);
21
21
  }
22
22
  }
23
23
  exports.transformUnaryExpressionStatement = transformUnaryExpressionStatement;
24
24
  const transformPostfixUnaryExpression = (expression, context) => {
25
25
  switch (expression.operator) {
26
26
  case ts.SyntaxKind.PlusPlusToken:
27
- return compound_1.transformCompoundAssignmentExpression(context, expression, expression.operand, ts.factory.createNumericLiteral(1), ts.SyntaxKind.PlusToken, true);
27
+ return (0, compound_1.transformCompoundAssignmentExpression)(context, expression, expression.operand, ts.factory.createNumericLiteral(1), ts.SyntaxKind.PlusToken, true);
28
28
  case ts.SyntaxKind.MinusMinusToken:
29
- return compound_1.transformCompoundAssignmentExpression(context, expression, expression.operand, ts.factory.createNumericLiteral(1), ts.SyntaxKind.MinusToken, true);
29
+ return (0, compound_1.transformCompoundAssignmentExpression)(context, expression, expression.operand, ts.factory.createNumericLiteral(1), ts.SyntaxKind.MinusToken, true);
30
30
  default:
31
- utils_1.assertNever(expression.operator);
31
+ (0, utils_1.assertNever)(expression.operator);
32
32
  }
33
33
  };
34
34
  exports.transformPostfixUnaryExpression = transformPostfixUnaryExpression;
35
35
  const transformPrefixUnaryExpression = (expression, context) => {
36
36
  switch (expression.operator) {
37
37
  case ts.SyntaxKind.PlusPlusToken:
38
- return compound_1.transformCompoundAssignmentExpression(context, expression, expression.operand, ts.factory.createNumericLiteral(1), ts.SyntaxKind.PlusToken, false);
38
+ return (0, compound_1.transformCompoundAssignmentExpression)(context, expression, expression.operand, ts.factory.createNumericLiteral(1), ts.SyntaxKind.PlusToken, false);
39
39
  case ts.SyntaxKind.MinusMinusToken:
40
- return compound_1.transformCompoundAssignmentExpression(context, expression, expression.operand, ts.factory.createNumericLiteral(1), ts.SyntaxKind.MinusToken, false);
40
+ return (0, compound_1.transformCompoundAssignmentExpression)(context, expression, expression.operand, ts.factory.createNumericLiteral(1), ts.SyntaxKind.MinusToken, false);
41
41
  case ts.SyntaxKind.PlusToken:
42
42
  // TODO: Wrap with `Number`
43
43
  return context.transformExpression(expression.operand);
@@ -46,9 +46,9 @@ const transformPrefixUnaryExpression = (expression, context) => {
46
46
  case ts.SyntaxKind.ExclamationToken:
47
47
  return lua.createUnaryExpression(context.transformExpression(expression.operand), lua.SyntaxKind.NotOperator);
48
48
  case ts.SyntaxKind.TildeToken:
49
- return bit_1.transformUnaryBitOperation(context, expression, context.transformExpression(expression.operand), lua.SyntaxKind.BitwiseNotOperator);
49
+ return (0, bit_1.transformUnaryBitOperation)(context, expression, context.transformExpression(expression.operand), lua.SyntaxKind.BitwiseNotOperator);
50
50
  default:
51
- utils_1.assertNever(expression.operator);
51
+ (0, utils_1.assertNever)(expression.operator);
52
52
  }
53
53
  };
54
54
  exports.transformPrefixUnaryExpression = transformPrefixUnaryExpression;