typescript-to-lua 1.0.1 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +46 -0
- package/dist/CompilerOptions.d.ts +4 -3
- package/dist/LuaAST.d.ts +1 -0
- package/dist/LuaAST.js +14 -6
- package/dist/LuaLib.d.ts +4 -3
- package/dist/LuaLib.js +6 -5
- package/dist/LuaPrinter.d.ts +15 -4
- package/dist/LuaPrinter.js +81 -29
- package/dist/cli/diagnostics.js +2 -2
- package/dist/cli/parse.d.ts +1 -1
- package/dist/cli/parse.js +14 -0
- package/dist/cli/report.js +1 -1
- package/dist/cli/tsconfig.js +4 -4
- package/dist/lualib/ArrayFlat.lua +1 -1
- package/dist/lualib/ArrayFlatMap.lua +1 -1
- package/dist/lualib/ArrayIsArray.lua +1 -1
- package/dist/lualib/ArrayReduce.lua +7 -1
- package/dist/lualib/ArrayReduceRight.lua +7 -1
- package/dist/lualib/ArraySetLength.lua +1 -1
- package/dist/lualib/ArraySplice.lua +5 -5
- package/dist/lualib/Await.lua +43 -19
- package/dist/lualib/CloneDescriptor.lua +7 -7
- package/dist/lualib/Decorate.lua +1 -1
- package/dist/lualib/DelegatedYield.lua +1 -3
- package/dist/lualib/Delete.lua +6 -6
- package/dist/lualib/Error.lua +47 -44
- package/dist/lualib/Generator.lua +1 -5
- package/dist/lualib/InstanceOf.lua +1 -1
- package/dist/lualib/InstanceOfObject.lua +1 -1
- package/dist/lualib/Map.lua +130 -134
- package/dist/lualib/Number.lua +1 -1
- package/dist/lualib/NumberIsFinite.lua +1 -1
- package/dist/lualib/NumberToString.lua +3 -5
- package/dist/lualib/ObjectDefineProperty.lua +40 -8
- package/dist/lualib/ParseFloat.lua +9 -5
- package/dist/lualib/ParseInt.lua +15 -3
- package/dist/lualib/Promise.lua +44 -26
- package/dist/lualib/Set.lua +119 -123
- package/dist/lualib/SetDescriptor.lua +7 -1
- package/dist/lualib/SourceMapTraceBack.lua +19 -9
- package/dist/lualib/SparseArrayNew.lua +5 -0
- package/dist/lualib/SparseArrayPush.lua +9 -0
- package/dist/lualib/SparseArraySpread.lua +4 -0
- package/dist/lualib/StringAccess.lua +1 -1
- package/dist/lualib/StringCharCodeAt.lua +1 -1
- package/dist/lualib/StringEndsWith.lua +2 -2
- package/dist/lualib/StringPadEnd.lua +2 -2
- package/dist/lualib/StringPadStart.lua +2 -2
- package/dist/lualib/StringReplace.lua +12 -11
- package/dist/lualib/StringReplaceAll.lua +35 -0
- package/dist/lualib/StringSlice.lua +2 -2
- package/dist/lualib/StringSplit.lua +3 -3
- package/dist/lualib/StringStartsWith.lua +1 -1
- package/dist/lualib/StringSubstr.lua +1 -1
- package/dist/lualib/StringSubstring.lua +2 -2
- package/dist/lualib/Symbol.lua +3 -5
- package/dist/lualib/WeakMap.lua +40 -42
- package/dist/lualib/WeakSet.lua +36 -38
- package/dist/lualib/lualib_bundle.lua +876 -745
- package/dist/transformation/builtins/array.js +29 -30
- package/dist/transformation/builtins/console.js +2 -2
- package/dist/transformation/builtins/function.js +14 -12
- package/dist/transformation/builtins/global.js +8 -8
- package/dist/transformation/builtins/index.d.ts +1 -1
- package/dist/transformation/builtins/index.js +69 -36
- package/dist/transformation/builtins/math.js +4 -4
- package/dist/transformation/builtins/number.js +7 -7
- package/dist/transformation/builtins/object.d.ts +2 -1
- package/dist/transformation/builtins/object.js +12 -13
- package/dist/transformation/builtins/promise.js +9 -9
- package/dist/transformation/builtins/string.js +32 -31
- package/dist/transformation/builtins/symbol.js +3 -3
- package/dist/transformation/context/context.d.ts +12 -0
- package/dist/transformation/context/context.js +105 -6
- package/dist/transformation/index.js +1 -1
- package/dist/transformation/utils/annotations.d.ts +1 -3
- package/dist/transformation/utils/annotations.js +0 -2
- package/dist/transformation/utils/assignment-validation.js +8 -7
- package/dist/transformation/utils/diagnostics.d.ts +9 -0
- package/dist/transformation/utils/diagnostics.js +8 -5
- package/dist/transformation/utils/export.d.ts +3 -2
- package/dist/transformation/utils/export.js +14 -7
- package/dist/transformation/utils/function-context.js +8 -8
- package/dist/transformation/utils/language-extensions.d.ts +2 -0
- package/dist/transformation/utils/language-extensions.js +7 -1
- package/dist/transformation/utils/lua-ast.d.ts +0 -1
- package/dist/transformation/utils/lua-ast.js +25 -35
- package/dist/transformation/utils/lualib.js +1 -1
- package/dist/transformation/utils/preceding-statements.d.ts +3 -0
- package/dist/transformation/utils/preceding-statements.js +11 -0
- package/dist/transformation/utils/safe-names.d.ts +4 -2
- package/dist/transformation/utils/safe-names.js +13 -7
- package/dist/transformation/utils/scope.d.ts +9 -1
- package/dist/transformation/utils/scope.js +78 -40
- package/dist/transformation/utils/symbols.js +6 -6
- package/dist/transformation/utils/typescript/index.d.ts +1 -0
- package/dist/transformation/utils/typescript/index.js +16 -1
- package/dist/transformation/utils/typescript/nodes.d.ts +2 -0
- package/dist/transformation/utils/typescript/nodes.js +21 -1
- package/dist/transformation/utils/typescript/types.d.ts +3 -1
- package/dist/transformation/utils/typescript/types.js +40 -13
- package/dist/transformation/visitors/access.d.ts +3 -0
- package/dist/transformation/visitors/access.js +74 -47
- package/dist/transformation/visitors/async-await.js +5 -4
- package/dist/transformation/visitors/binary-expression/assignments.d.ts +3 -2
- package/dist/transformation/visitors/binary-expression/assignments.js +86 -77
- package/dist/transformation/visitors/binary-expression/bit.js +4 -4
- package/dist/transformation/visitors/binary-expression/compound.d.ts +5 -4
- package/dist/transformation/visitors/binary-expression/compound.js +69 -71
- package/dist/transformation/visitors/binary-expression/destructuring-assignments.d.ts +2 -2
- package/dist/transformation/visitors/binary-expression/destructuring-assignments.js +65 -36
- package/dist/transformation/visitors/binary-expression/index.d.ts +3 -1
- package/dist/transformation/visitors/binary-expression/index.js +84 -42
- package/dist/transformation/visitors/block.js +6 -6
- package/dist/transformation/visitors/break-continue.js +2 -2
- package/dist/transformation/visitors/call.d.ts +3 -2
- package/dist/transformation/visitors/call.js +130 -143
- package/dist/transformation/visitors/class/decorators.js +3 -3
- package/dist/transformation/visitors/class/index.js +43 -39
- package/dist/transformation/visitors/class/members/accessors.js +6 -6
- package/dist/transformation/visitors/class/members/constructor.js +7 -7
- package/dist/transformation/visitors/class/members/fields.js +6 -6
- package/dist/transformation/visitors/class/members/method.js +6 -6
- package/dist/transformation/visitors/class/new.js +14 -16
- package/dist/transformation/visitors/class/setup.js +11 -11
- package/dist/transformation/visitors/class/utils.js +2 -2
- package/dist/transformation/visitors/conditional.js +36 -43
- package/dist/transformation/visitors/delete.js +8 -4
- package/dist/transformation/visitors/enum.js +8 -8
- package/dist/transformation/visitors/errors.js +35 -33
- package/dist/transformation/visitors/expression-list.d.ts +7 -0
- package/dist/transformation/visitors/expression-list.js +120 -0
- package/dist/transformation/visitors/expression-statement.js +10 -6
- package/dist/transformation/visitors/function.d.ts +2 -0
- package/dist/transformation/visitors/function.js +80 -33
- package/dist/transformation/visitors/identifier.js +26 -22
- package/dist/transformation/visitors/index.js +2 -2
- package/dist/transformation/visitors/language-extensions/iterable.js +7 -7
- package/dist/transformation/visitors/language-extensions/multi.d.ts +1 -1
- package/dist/transformation/visitors/language-extensions/multi.js +3 -3
- package/dist/transformation/visitors/language-extensions/operators.js +6 -6
- package/dist/transformation/visitors/language-extensions/pairsIterable.d.ts +5 -0
- package/dist/transformation/visitors/language-extensions/pairsIterable.js +53 -0
- package/dist/transformation/visitors/language-extensions/range.js +6 -6
- package/dist/transformation/visitors/language-extensions/table.js +5 -5
- package/dist/transformation/visitors/literal.d.ts +1 -2
- package/dist/transformation/visitors/literal.js +87 -57
- package/dist/transformation/visitors/loops/do-while.js +35 -9
- package/dist/transformation/visitors/loops/for-in.js +4 -4
- package/dist/transformation/visitors/loops/for-of.js +17 -13
- package/dist/transformation/visitors/loops/for.js +28 -8
- package/dist/transformation/visitors/loops/utils.d.ts +1 -0
- package/dist/transformation/visitors/loops/utils.js +26 -10
- package/dist/transformation/visitors/modules/export.js +14 -15
- package/dist/transformation/visitors/modules/import.js +10 -10
- package/dist/transformation/visitors/namespace.js +13 -13
- package/dist/transformation/visitors/optional-chaining.d.ts +16 -0
- package/dist/transformation/visitors/optional-chaining.js +172 -0
- package/dist/transformation/visitors/return.d.ts +1 -0
- package/dist/transformation/visitors/return.js +40 -26
- package/dist/transformation/visitors/sourceFile.js +12 -9
- package/dist/transformation/visitors/spread.js +23 -16
- package/dist/transformation/visitors/switch.js +63 -20
- package/dist/transformation/visitors/template.js +10 -7
- package/dist/transformation/visitors/typeof.js +4 -2
- package/dist/transformation/visitors/typescript.js +1 -1
- package/dist/transformation/visitors/unary-expression.js +9 -9
- package/dist/transformation/visitors/variable-declaration.js +55 -32
- package/dist/transformation/visitors/void.d.ts +6 -0
- package/dist/transformation/visitors/void.js +20 -0
- package/dist/transpilation/bundle.d.ts +3 -0
- package/dist/transpilation/bundle.js +52 -10
- package/dist/transpilation/diagnostics.js +3 -3
- package/dist/transpilation/index.js +2 -2
- package/dist/transpilation/output-collector.js +2 -2
- package/dist/transpilation/plugins.js +1 -1
- package/dist/transpilation/resolve.js +20 -13
- package/dist/transpilation/transformers.js +45 -25
- package/dist/transpilation/transpile.js +6 -6
- package/dist/transpilation/transpiler.js +8 -8
- package/dist/transpilation/utils.js +5 -3
- package/dist/tstl.js +8 -8
- package/dist/utils.js +2 -2
- package/language-extensions/index.d.ts +11 -1
- package/package.json +15 -12
- package/dist/lualib/OptionalChainAccess.lua +0 -6
- package/dist/lualib/OptionalFunctionCall.lua +0 -6
- package/dist/lualib/OptionalMethodCall.lua +0 -11
- package/dist/transformation/utils/transform.d.ts +0 -8
- package/dist/transformation/utils/transform.js +0 -14
- package/dist/transformation/visitors/jsx/jsx.d.ts +0 -9
- package/dist/transformation/visitors/jsx/jsx.js +0 -237
- package/dist/transformation/visitors/jsx/xhtml.d.ts +0 -3
- package/dist/transformation/visitors/jsx/xhtml.js +0 -260
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.transformOptionalDeleteExpression = exports.transformOptionalChainWithCapture = exports.transformOptionalChain = exports.getOptionalContinuationData = exports.isOptionalContinuation = exports.captureThisValue = void 0;
|
|
4
|
+
const ts = require("typescript");
|
|
5
|
+
const lua = require("../../LuaAST");
|
|
6
|
+
const context_1 = require("../context");
|
|
7
|
+
const utils_1 = require("../../utils");
|
|
8
|
+
const preceding_statements_1 = require("../utils/preceding-statements");
|
|
9
|
+
const access_1 = require("./access");
|
|
10
|
+
const expression_list_1 = require("./expression-list");
|
|
11
|
+
function skipNonNullChains(chain) {
|
|
12
|
+
while (ts.isNonNullChain(chain)) {
|
|
13
|
+
chain = chain.expression;
|
|
14
|
+
}
|
|
15
|
+
return chain;
|
|
16
|
+
}
|
|
17
|
+
function flattenChain(chain) {
|
|
18
|
+
chain = skipNonNullChains(chain);
|
|
19
|
+
const links = [chain];
|
|
20
|
+
while (!chain.questionDotToken && !ts.isTaggedTemplateExpression(chain)) {
|
|
21
|
+
const nextLink = chain.expression;
|
|
22
|
+
(0, utils_1.assert)(ts.isOptionalChain(nextLink));
|
|
23
|
+
chain = skipNonNullChains(nextLink);
|
|
24
|
+
links.unshift(chain);
|
|
25
|
+
}
|
|
26
|
+
return { expression: chain.expression, chain: links };
|
|
27
|
+
}
|
|
28
|
+
function transformExpressionWithThisValueCapture(context, node, thisValueCapture) {
|
|
29
|
+
if (ts.isParenthesizedExpression(node)) {
|
|
30
|
+
return transformExpressionWithThisValueCapture(context, node.expression, thisValueCapture);
|
|
31
|
+
}
|
|
32
|
+
if (ts.isPropertyAccessExpression(node)) {
|
|
33
|
+
return (0, access_1.transformPropertyAccessExpressionWithCapture)(context, node, thisValueCapture);
|
|
34
|
+
}
|
|
35
|
+
if (ts.isElementAccessExpression(node)) {
|
|
36
|
+
return (0, access_1.transformElementAccessExpressionWithCapture)(context, node, thisValueCapture);
|
|
37
|
+
}
|
|
38
|
+
return { expression: context.transformExpression(node) };
|
|
39
|
+
}
|
|
40
|
+
// returns thisValueCapture exactly if a temp variable was used.
|
|
41
|
+
function captureThisValue(context, expression, thisValueCapture, tsOriginal) {
|
|
42
|
+
if (!(0, expression_list_1.shouldMoveToTemp)(context, expression, tsOriginal) && !isOptionalContinuation(tsOriginal)) {
|
|
43
|
+
return expression;
|
|
44
|
+
}
|
|
45
|
+
const tempAssignment = lua.createAssignmentStatement(thisValueCapture, expression, tsOriginal);
|
|
46
|
+
context.addPrecedingStatements(tempAssignment);
|
|
47
|
+
return thisValueCapture;
|
|
48
|
+
}
|
|
49
|
+
exports.captureThisValue = captureThisValue;
|
|
50
|
+
const optionalContinuations = new WeakMap();
|
|
51
|
+
// should be translated verbatim to lua
|
|
52
|
+
function createOptionalContinuationIdentifier(text, tsOriginal) {
|
|
53
|
+
const identifier = ts.factory.createIdentifier(text);
|
|
54
|
+
ts.setOriginalNode(identifier, tsOriginal);
|
|
55
|
+
optionalContinuations.set(identifier, {});
|
|
56
|
+
return identifier;
|
|
57
|
+
}
|
|
58
|
+
function isOptionalContinuation(node) {
|
|
59
|
+
return ts.isIdentifier(node) && optionalContinuations.has(node);
|
|
60
|
+
}
|
|
61
|
+
exports.isOptionalContinuation = isOptionalContinuation;
|
|
62
|
+
function getOptionalContinuationData(identifier) {
|
|
63
|
+
return optionalContinuations.get(identifier);
|
|
64
|
+
}
|
|
65
|
+
exports.getOptionalContinuationData = getOptionalContinuationData;
|
|
66
|
+
function transformOptionalChain(context, node) {
|
|
67
|
+
return transformOptionalChainWithCapture(context, node, undefined).expression;
|
|
68
|
+
}
|
|
69
|
+
exports.transformOptionalChain = transformOptionalChain;
|
|
70
|
+
function transformOptionalChainWithCapture(context, node, thisValueCapture, isDelete) {
|
|
71
|
+
var _a;
|
|
72
|
+
const luaTemp = context.createTempNameForNode(node);
|
|
73
|
+
const { expression: tsLeftExpression, chain } = flattenChain(node);
|
|
74
|
+
// build temp.b.c.d
|
|
75
|
+
const tsTemp = createOptionalContinuationIdentifier(luaTemp.text, tsLeftExpression);
|
|
76
|
+
let tsRightExpression = tsTemp;
|
|
77
|
+
for (const link of chain) {
|
|
78
|
+
if (ts.isPropertyAccessExpression(link)) {
|
|
79
|
+
tsRightExpression = ts.factory.createPropertyAccessExpression(tsRightExpression, link.name);
|
|
80
|
+
}
|
|
81
|
+
else if (ts.isElementAccessExpression(link)) {
|
|
82
|
+
tsRightExpression = ts.factory.createElementAccessExpression(tsRightExpression, link.argumentExpression);
|
|
83
|
+
}
|
|
84
|
+
else if (ts.isCallExpression(link)) {
|
|
85
|
+
tsRightExpression = ts.factory.createCallExpression(tsRightExpression, undefined, link.arguments);
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
(0, utils_1.assertNever)(link);
|
|
89
|
+
}
|
|
90
|
+
ts.setOriginalNode(tsRightExpression, link);
|
|
91
|
+
}
|
|
92
|
+
if (isDelete) {
|
|
93
|
+
tsRightExpression = ts.factory.createDeleteExpression(tsRightExpression);
|
|
94
|
+
ts.setOriginalNode(tsRightExpression, isDelete);
|
|
95
|
+
}
|
|
96
|
+
// transform right expression first to check if thisValue capture is needed
|
|
97
|
+
// capture and return thisValue if requested from outside
|
|
98
|
+
let returnThisValue;
|
|
99
|
+
const [rightPrecedingStatements, rightAssignment] = (0, preceding_statements_1.transformInPrecedingStatementScope)(context, () => {
|
|
100
|
+
let result;
|
|
101
|
+
if (thisValueCapture) {
|
|
102
|
+
({ expression: result, thisValue: returnThisValue } = transformExpressionWithThisValueCapture(context, tsRightExpression, thisValueCapture));
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
result = context.transformExpression(tsRightExpression);
|
|
106
|
+
}
|
|
107
|
+
return lua.createAssignmentStatement(luaTemp, result);
|
|
108
|
+
});
|
|
109
|
+
// transform left expression, handle thisValue if needed by rightExpression
|
|
110
|
+
const thisValueCaptureName = context.createTempName("this");
|
|
111
|
+
const leftThisValueTemp = lua.createIdentifier(thisValueCaptureName, undefined, context_1.tempSymbolId);
|
|
112
|
+
let capturedThisValue;
|
|
113
|
+
const rightContextualCall = (_a = getOptionalContinuationData(tsTemp)) === null || _a === void 0 ? void 0 : _a.contextualCall;
|
|
114
|
+
const [leftPrecedingStatements, leftExpression] = (0, preceding_statements_1.transformInPrecedingStatementScope)(context, () => {
|
|
115
|
+
let result;
|
|
116
|
+
if (rightContextualCall) {
|
|
117
|
+
({ expression: result, thisValue: capturedThisValue } = transformExpressionWithThisValueCapture(context, tsLeftExpression, leftThisValueTemp));
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
result = context.transformExpression(tsLeftExpression);
|
|
121
|
+
}
|
|
122
|
+
return result;
|
|
123
|
+
});
|
|
124
|
+
// handle context
|
|
125
|
+
if (rightContextualCall) {
|
|
126
|
+
if (capturedThisValue) {
|
|
127
|
+
rightContextualCall.params[0] = capturedThisValue;
|
|
128
|
+
if (capturedThisValue === leftThisValueTemp) {
|
|
129
|
+
context.addPrecedingStatements(lua.createVariableDeclarationStatement(leftThisValueTemp));
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
if (context.isStrict) {
|
|
134
|
+
rightContextualCall.params[0] = lua.createNilLiteral();
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
const identifier = lua.createIdentifier("_G");
|
|
138
|
+
if (rightPrecedingStatements.length === 0) {
|
|
139
|
+
rightContextualCall.params[0] = identifier;
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
const tempContext = context.createTempNameForLuaExpression(identifier);
|
|
143
|
+
rightPrecedingStatements.unshift(lua.createVariableDeclarationStatement(tempContext, identifier));
|
|
144
|
+
rightContextualCall.params[0] = tempContext;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
// <left preceding statements>
|
|
150
|
+
// local temp = <left>
|
|
151
|
+
// if temp ~= nil then
|
|
152
|
+
// <right preceding statements>
|
|
153
|
+
// temp = temp.b.c.d
|
|
154
|
+
// end
|
|
155
|
+
// return temp
|
|
156
|
+
context.addPrecedingStatements([
|
|
157
|
+
...leftPrecedingStatements,
|
|
158
|
+
lua.createVariableDeclarationStatement(luaTemp, leftExpression),
|
|
159
|
+
lua.createIfStatement(lua.createBinaryExpression(luaTemp, lua.createNilLiteral(), lua.SyntaxKind.InequalityOperator), lua.createBlock([...rightPrecedingStatements, rightAssignment])),
|
|
160
|
+
]);
|
|
161
|
+
return {
|
|
162
|
+
expression: luaTemp,
|
|
163
|
+
thisValue: returnThisValue,
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
exports.transformOptionalChainWithCapture = transformOptionalChainWithCapture;
|
|
167
|
+
function transformOptionalDeleteExpression(context, node, innerExpression) {
|
|
168
|
+
transformOptionalChainWithCapture(context, innerExpression, undefined, node);
|
|
169
|
+
return lua.createBooleanLiteral(true, node);
|
|
170
|
+
}
|
|
171
|
+
exports.transformOptionalDeleteExpression = transformOptionalDeleteExpression;
|
|
172
|
+
//# sourceMappingURL=optional-chaining.js.map
|
|
@@ -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,6 +1,6 @@
|
|
|
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
6
|
const assignment_validation_1 = require("../utils/assignment-validation");
|
|
@@ -9,65 +9,79 @@ const scope_1 = require("../utils/scope");
|
|
|
9
9
|
const call_1 = require("./call");
|
|
10
10
|
const multi_1 = require("./language-extensions/multi");
|
|
11
11
|
const diagnostics_1 = require("../utils/diagnostics");
|
|
12
|
+
const typescript_1 = require("../utils/typescript");
|
|
12
13
|
function transformExpressionsInReturn(context, node, insideTryCatch) {
|
|
13
14
|
const expressionType = context.checker.getTypeAtLocation(node);
|
|
14
15
|
if (ts.isCallExpression(node)) {
|
|
15
16
|
// $multi(...)
|
|
16
|
-
if (multi_1.isMultiFunctionCall(context, node)) {
|
|
17
|
+
if ((0, multi_1.isMultiFunctionCall)(context, node)) {
|
|
17
18
|
// Don't allow $multi to be implicitly cast to something other than LuaMultiReturn
|
|
18
19
|
const type = context.checker.getContextualType(node);
|
|
19
|
-
if (type && !multi_1.canBeMultiReturnType(type)) {
|
|
20
|
-
context.diagnostics.push(diagnostics_1.invalidMultiFunctionReturnType(node));
|
|
20
|
+
if (type && !(0, multi_1.canBeMultiReturnType)(type)) {
|
|
21
|
+
context.diagnostics.push((0, diagnostics_1.invalidMultiFunctionReturnType)(node));
|
|
21
22
|
}
|
|
22
|
-
let returnValues = call_1.transformArguments(context, node.arguments);
|
|
23
|
+
let returnValues = (0, call_1.transformArguments)(context, node.arguments);
|
|
23
24
|
if (insideTryCatch) {
|
|
24
|
-
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
|
|
25
26
|
}
|
|
26
27
|
return returnValues;
|
|
27
28
|
}
|
|
28
29
|
// Force-wrap LuaMultiReturn when returning inside try/catch
|
|
29
|
-
if (insideTryCatch && multi_1.returnsMultiType(context, node) && !multi_1.shouldMultiReturnCallBeWrapped(context, node)) {
|
|
30
|
-
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))];
|
|
31
32
|
}
|
|
32
33
|
}
|
|
33
|
-
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)) {
|
|
34
35
|
// Unpack objects typed as LuaMultiReturn
|
|
35
|
-
return [lua_ast_1.createUnpackCall(context, context.transformExpression(node), node)];
|
|
36
|
+
return [(0, lua_ast_1.createUnpackCall)(context, context.transformExpression(node), node)];
|
|
36
37
|
}
|
|
37
38
|
return [context.transformExpression(node)];
|
|
38
39
|
}
|
|
39
40
|
function transformExpressionBodyToReturnStatement(context, node) {
|
|
40
41
|
const expressions = transformExpressionsInReturn(context, node, false);
|
|
41
|
-
return
|
|
42
|
+
return createReturnStatement(context, expressions, node);
|
|
42
43
|
}
|
|
43
44
|
exports.transformExpressionBodyToReturnStatement = transformExpressionBodyToReturnStatement;
|
|
44
45
|
const transformReturnStatement = (statement, context) => {
|
|
45
|
-
// Bubble up explicit return flag and check if we're inside a try/catch block
|
|
46
|
-
let insideTryCatch = false;
|
|
47
|
-
for (const scope of scope_1.walkScopesUp(context)) {
|
|
48
|
-
scope.functionReturned = true;
|
|
49
|
-
if (scope.type === scope_1.ScopeType.Function) {
|
|
50
|
-
break;
|
|
51
|
-
}
|
|
52
|
-
insideTryCatch = insideTryCatch || scope.type === scope_1.ScopeType.Try || scope.type === scope_1.ScopeType.Catch;
|
|
53
|
-
}
|
|
54
46
|
let results;
|
|
55
47
|
if (statement.expression) {
|
|
56
48
|
const expressionType = context.checker.getTypeAtLocation(statement.expression);
|
|
57
49
|
const returnType = context.checker.getContextualType(statement.expression);
|
|
58
50
|
if (returnType) {
|
|
59
|
-
assignment_validation_1.validateAssignment(context, statement, expressionType, returnType);
|
|
51
|
+
(0, assignment_validation_1.validateAssignment)(context, statement, expressionType, returnType);
|
|
60
52
|
}
|
|
61
|
-
results = transformExpressionsInReturn(context, statement.expression,
|
|
53
|
+
results = transformExpressionsInReturn(context, statement.expression, isInTryCatch(context));
|
|
62
54
|
}
|
|
63
55
|
else {
|
|
64
56
|
// Empty return
|
|
65
57
|
results = [];
|
|
66
58
|
}
|
|
67
|
-
|
|
68
|
-
results.unshift(lua.createBooleanLiteral(true));
|
|
69
|
-
}
|
|
70
|
-
return lua.createReturnStatement(results, statement);
|
|
59
|
+
return createReturnStatement(context, results, statement);
|
|
71
60
|
};
|
|
72
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
|
+
}
|
|
73
87
|
//# sourceMappingURL=return.js.map
|
|
@@ -6,6 +6,7 @@ const lua = require("../../LuaAST");
|
|
|
6
6
|
const utils_1 = require("../../utils");
|
|
7
7
|
const lua_ast_1 = require("../utils/lua-ast");
|
|
8
8
|
const lualib_1 = require("../utils/lualib");
|
|
9
|
+
const preceding_statements_1 = require("../utils/preceding-statements");
|
|
9
10
|
const scope_1 = require("../utils/scope");
|
|
10
11
|
const typescript_1 = require("../utils/typescript");
|
|
11
12
|
const transformSourceFileNode = (node, context) => {
|
|
@@ -14,8 +15,10 @@ const transformSourceFileNode = (node, context) => {
|
|
|
14
15
|
if (node.flags & ts.NodeFlags.JsonFile) {
|
|
15
16
|
const [statement] = node.statements;
|
|
16
17
|
if (statement) {
|
|
17
|
-
utils_1.assert(ts.isExpressionStatement(statement));
|
|
18
|
-
|
|
18
|
+
(0, utils_1.assert)(ts.isExpressionStatement(statement));
|
|
19
|
+
const [precedingStatements, expression] = (0, preceding_statements_1.transformInPrecedingStatementScope)(context, () => context.transformExpression(statement.expression));
|
|
20
|
+
statements.push(...precedingStatements);
|
|
21
|
+
statements.push(lua.createReturnStatement([expression]));
|
|
19
22
|
}
|
|
20
23
|
else {
|
|
21
24
|
const errorCall = lua.createCallExpression(lua.createIdentifier("error"), [
|
|
@@ -25,21 +28,21 @@ const transformSourceFileNode = (node, context) => {
|
|
|
25
28
|
}
|
|
26
29
|
}
|
|
27
30
|
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);
|
|
31
|
+
(0, scope_1.pushScope)(context, scope_1.ScopeType.File);
|
|
32
|
+
statements = (0, scope_1.performHoisting)(context, context.transformStatements(node.statements));
|
|
33
|
+
(0, scope_1.popScope)(context);
|
|
31
34
|
if (context.isModule) {
|
|
32
35
|
// If export equals was not used. Create the exports table.
|
|
33
36
|
// local ____exports = {}
|
|
34
|
-
if (!typescript_1.hasExportEquals(node)) {
|
|
35
|
-
statements.unshift(lua.createVariableDeclarationStatement(lua_ast_1.createExportsIdentifier(), lua.createTableExpression()));
|
|
37
|
+
if (!(0, typescript_1.hasExportEquals)(node)) {
|
|
38
|
+
statements.unshift(lua.createVariableDeclarationStatement((0, lua_ast_1.createExportsIdentifier)(), lua.createTableExpression()));
|
|
36
39
|
}
|
|
37
40
|
// return ____exports
|
|
38
|
-
statements.push(lua.createReturnStatement([lua_ast_1.createExportsIdentifier()]));
|
|
41
|
+
statements.push(lua.createReturnStatement([(0, lua_ast_1.createExportsIdentifier)()]));
|
|
39
42
|
}
|
|
40
43
|
}
|
|
41
44
|
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);
|
|
45
|
+
return lua.createFile(statements, (0, lualib_1.getUsedLuaLibFeatures)(context), trivia, node);
|
|
43
46
|
};
|
|
44
47
|
exports.transformSourceFileNode = transformSourceFileNode;
|
|
45
48
|
//# sourceMappingURL=sourceFile.js.map
|
|
@@ -11,22 +11,28 @@ const typescript_1 = require("../utils/typescript");
|
|
|
11
11
|
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
|
+
function skipOuterExpressionParents(node) {
|
|
15
|
+
while (ts.isOuterExpression(node)) {
|
|
16
|
+
node = node.parent;
|
|
17
|
+
}
|
|
18
|
+
return node;
|
|
19
|
+
}
|
|
14
20
|
function isOptimizedVarArgSpread(context, symbol, identifier) {
|
|
15
21
|
var _a;
|
|
16
|
-
if (!ts.isSpreadElement(identifier.parent)) {
|
|
22
|
+
if (!ts.isSpreadElement(skipOuterExpressionParents(identifier.parent))) {
|
|
17
23
|
return false;
|
|
18
24
|
}
|
|
19
25
|
// Walk up, stopping at any scope types which could stop optimization
|
|
20
|
-
const scope = scope_1.findScope(context, scope_1.ScopeType.Function | scope_1.ScopeType.Try | scope_1.ScopeType.Catch | scope_1.ScopeType.File);
|
|
26
|
+
const scope = (0, scope_1.findScope)(context, scope_1.ScopeType.Function | scope_1.ScopeType.Try | scope_1.ScopeType.Catch | scope_1.ScopeType.File);
|
|
21
27
|
if (!scope) {
|
|
22
28
|
return;
|
|
23
29
|
}
|
|
24
30
|
// $vararg global constant
|
|
25
|
-
if (vararg_1.isGlobalVarargConstant(context, symbol, scope)) {
|
|
31
|
+
if ((0, vararg_1.isGlobalVarargConstant)(context, symbol, scope)) {
|
|
26
32
|
return true;
|
|
27
33
|
}
|
|
28
34
|
// Scope must be a function scope associated with a real ts function
|
|
29
|
-
if (!scope_1.isFunctionScopeWithDefinition(scope)) {
|
|
35
|
+
if (!(0, scope_1.isFunctionScopeWithDefinition)(scope)) {
|
|
30
36
|
return false;
|
|
31
37
|
}
|
|
32
38
|
// Scope cannot be an async function
|
|
@@ -39,11 +45,11 @@ function isOptimizedVarArgSpread(context, symbol, identifier) {
|
|
|
39
45
|
return false;
|
|
40
46
|
}
|
|
41
47
|
// De-optimize if already referenced outside of a spread, as the array may have been modified
|
|
42
|
-
if (scope_1.hasReferencedSymbol(context, scope, symbol)) {
|
|
48
|
+
if ((0, scope_1.hasReferencedSymbol)(context, scope, symbol)) {
|
|
43
49
|
return false;
|
|
44
50
|
}
|
|
45
51
|
// De-optimize if a function is being hoisted from below to above, as it may have modified the array
|
|
46
|
-
if (scope_1.hasReferencedUndefinedLocalFunction(context, scope)) {
|
|
52
|
+
if ((0, scope_1.hasReferencedUndefinedLocalFunction)(context, scope)) {
|
|
47
53
|
return false;
|
|
48
54
|
}
|
|
49
55
|
return true;
|
|
@@ -51,23 +57,24 @@ function isOptimizedVarArgSpread(context, symbol, identifier) {
|
|
|
51
57
|
exports.isOptimizedVarArgSpread = isOptimizedVarArgSpread;
|
|
52
58
|
// TODO: Currently it's also used as an array member
|
|
53
59
|
const transformSpreadElement = (node, context) => {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
60
|
+
const tsInnerExpression = ts.skipOuterExpressions(node.expression);
|
|
61
|
+
if (ts.isIdentifier(tsInnerExpression)) {
|
|
62
|
+
if ((0, annotations_1.isVarargType)(context, tsInnerExpression)) {
|
|
63
|
+
context.diagnostics.push((0, diagnostics_1.annotationRemoved)(node, annotations_1.AnnotationKind.Vararg));
|
|
57
64
|
}
|
|
58
|
-
const symbol = context.checker.getSymbolAtLocation(
|
|
59
|
-
if (symbol && isOptimizedVarArgSpread(context, symbol,
|
|
65
|
+
const symbol = context.checker.getSymbolAtLocation(tsInnerExpression);
|
|
66
|
+
if (symbol && isOptimizedVarArgSpread(context, symbol, tsInnerExpression)) {
|
|
60
67
|
return lua.createDotsLiteral(node);
|
|
61
68
|
}
|
|
62
69
|
}
|
|
63
70
|
const innerExpression = context.transformExpression(node.expression);
|
|
64
|
-
if (multi_1.isMultiReturnCall(context,
|
|
71
|
+
if ((0, multi_1.isMultiReturnCall)(context, tsInnerExpression))
|
|
65
72
|
return innerExpression;
|
|
66
|
-
const type = context.checker.getTypeAtLocation(node.expression);
|
|
67
|
-
if (typescript_1.isArrayType(context, type)) {
|
|
68
|
-
return lua_ast_1.createUnpackCall(context, innerExpression, node);
|
|
73
|
+
const type = context.checker.getTypeAtLocation(node.expression); // not ts-inner expression, in case of casts
|
|
74
|
+
if ((0, typescript_1.isArrayType)(context, type)) {
|
|
75
|
+
return (0, lua_ast_1.createUnpackCall)(context, innerExpression, node);
|
|
69
76
|
}
|
|
70
|
-
return lualib_1.transformLuaLibFunction(context, lualib_1.LuaLibFeature.Spread, node, innerExpression);
|
|
77
|
+
return (0, lualib_1.transformLuaLibFunction)(context, lualib_1.LuaLibFeature.Spread, node, innerExpression);
|
|
71
78
|
};
|
|
72
79
|
exports.transformSpreadElement = transformSpreadElement;
|
|
73
80
|
//# sourceMappingURL=spread.js.map
|
|
@@ -3,7 +3,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.transformSwitchStatement = void 0;
|
|
4
4
|
const ts = require("typescript");
|
|
5
5
|
const lua = require("../../LuaAST");
|
|
6
|
+
const preceding_statements_1 = require("../utils/preceding-statements");
|
|
6
7
|
const scope_1 = require("../utils/scope");
|
|
8
|
+
const binary_expression_1 = require("./binary-expression");
|
|
7
9
|
const containsBreakOrReturn = (nodes) => {
|
|
8
10
|
for (const s of nodes) {
|
|
9
11
|
if (ts.isBreakStatement(s) || ts.isReturnStatement(s)) {
|
|
@@ -18,16 +20,26 @@ const containsBreakOrReturn = (nodes) => {
|
|
|
18
20
|
}
|
|
19
21
|
return false;
|
|
20
22
|
};
|
|
21
|
-
const
|
|
23
|
+
const createOrExpression = (context, left, right, rightPrecedingStatements) => {
|
|
24
|
+
if (rightPrecedingStatements.length > 0) {
|
|
25
|
+
return (0, binary_expression_1.createShortCircuitBinaryExpressionPrecedingStatements)(context, left, right, rightPrecedingStatements, ts.SyntaxKind.BarBarToken);
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
return [rightPrecedingStatements, lua.createBinaryExpression(left, right, lua.SyntaxKind.OrOperator)];
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
const coalesceCondition = (condition, conditionPrecedingStatements, switchVariable, expression, context) => {
|
|
32
|
+
const [precedingStatements, transformedExpression] = (0, preceding_statements_1.transformInPrecedingStatementScope)(context, () => context.transformExpression(expression));
|
|
22
33
|
// Coalesce skipped statements
|
|
34
|
+
const comparison = lua.createBinaryExpression(switchVariable, transformedExpression, lua.SyntaxKind.EqualityOperator);
|
|
23
35
|
if (condition) {
|
|
24
|
-
return
|
|
36
|
+
return createOrExpression(context, condition, comparison, precedingStatements);
|
|
25
37
|
}
|
|
26
38
|
// Next condition
|
|
27
|
-
return
|
|
39
|
+
return [[...conditionPrecedingStatements, ...precedingStatements], comparison];
|
|
28
40
|
};
|
|
29
41
|
const transformSwitchStatement = (statement, context) => {
|
|
30
|
-
const scope = scope_1.pushScope(context, scope_1.ScopeType.Switch);
|
|
42
|
+
const scope = (0, scope_1.pushScope)(context, scope_1.ScopeType.Switch);
|
|
31
43
|
// Give the switch and condition accumulator a unique name to prevent nested switches from acting up.
|
|
32
44
|
const switchName = `____switch${scope.id}`;
|
|
33
45
|
const conditionName = `____cond${scope.id}`;
|
|
@@ -35,18 +47,25 @@ const transformSwitchStatement = (statement, context) => {
|
|
|
35
47
|
const conditionVariable = lua.createIdentifier(conditionName);
|
|
36
48
|
// If the switch only has a default clause, wrap it in a single do.
|
|
37
49
|
// Otherwise, we need to generate a set of if statements to emulate the switch.
|
|
38
|
-
|
|
50
|
+
const statements = [];
|
|
51
|
+
const hoistedStatements = [];
|
|
52
|
+
const hoistedIdentifiers = [];
|
|
39
53
|
const clauses = statement.caseBlock.clauses;
|
|
40
54
|
if (clauses.length === 1 && ts.isDefaultClause(clauses[0])) {
|
|
41
55
|
const defaultClause = clauses[0].statements;
|
|
42
56
|
if (defaultClause.length) {
|
|
43
|
-
statements
|
|
57
|
+
const { statements: defaultStatements, hoistedStatements: defaultHoistedStatements, hoistedIdentifiers: defaultHoistedIdentifiers, } = (0, scope_1.separateHoistedStatements)(context, context.transformStatements(defaultClause));
|
|
58
|
+
hoistedStatements.push(...defaultHoistedStatements);
|
|
59
|
+
hoistedIdentifiers.push(...defaultHoistedIdentifiers);
|
|
60
|
+
statements.push(lua.createDoStatement(defaultStatements));
|
|
44
61
|
}
|
|
45
62
|
}
|
|
46
63
|
else {
|
|
47
64
|
// Build up the condition for each if statement
|
|
65
|
+
let defaultTransformed = false;
|
|
48
66
|
let isInitialCondition = true;
|
|
49
67
|
let condition = undefined;
|
|
68
|
+
let conditionPrecedingStatements = [];
|
|
50
69
|
for (let i = 0; i < clauses.length; i++) {
|
|
51
70
|
const clause = clauses[i];
|
|
52
71
|
const previousClause = clauses[i - 1];
|
|
@@ -58,42 +77,55 @@ const transformSwitchStatement = (statement, context) => {
|
|
|
58
77
|
}
|
|
59
78
|
// Compute the condition for the if statement
|
|
60
79
|
if (!ts.isDefaultClause(clause)) {
|
|
61
|
-
condition = coalesceCondition(condition, switchVariable, clause.expression, context);
|
|
80
|
+
[conditionPrecedingStatements, condition] = coalesceCondition(condition, conditionPrecedingStatements, switchVariable, clause.expression, context);
|
|
62
81
|
// Skip empty clauses unless final clause (i.e side-effects)
|
|
63
82
|
if (i !== clauses.length - 1 && clause.statements.length === 0)
|
|
64
83
|
continue;
|
|
65
84
|
// Declare or assign condition variable
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
85
|
+
if (isInitialCondition) {
|
|
86
|
+
statements.push(...conditionPrecedingStatements, lua.createVariableDeclarationStatement(conditionVariable, condition));
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
[conditionPrecedingStatements, condition] = createOrExpression(context, conditionVariable, condition, conditionPrecedingStatements);
|
|
90
|
+
statements.push(...conditionPrecedingStatements, lua.createAssignmentStatement(conditionVariable, condition));
|
|
91
|
+
}
|
|
69
92
|
isInitialCondition = false;
|
|
70
93
|
}
|
|
71
94
|
else {
|
|
72
95
|
// If the default is proceeded by empty clauses and will be emitted we may need to initialize the condition
|
|
73
96
|
if (isInitialCondition) {
|
|
74
|
-
statements.push(lua.createVariableDeclarationStatement(conditionVariable, condition !== null && condition !== void 0 ? condition : lua.createBooleanLiteral(false)));
|
|
97
|
+
statements.push(...conditionPrecedingStatements, lua.createVariableDeclarationStatement(conditionVariable, condition !== null && condition !== void 0 ? condition : lua.createBooleanLiteral(false)));
|
|
75
98
|
// Clear condition ot ensure it is not evaluated twice
|
|
76
99
|
condition = undefined;
|
|
100
|
+
conditionPrecedingStatements = [];
|
|
77
101
|
isInitialCondition = false;
|
|
78
102
|
}
|
|
79
103
|
// Allow default to fallthrough to final default clause
|
|
80
104
|
if (i === clauses.length - 1) {
|
|
81
105
|
// Evaluate the final condition that we may be skipping
|
|
82
106
|
if (condition) {
|
|
83
|
-
|
|
107
|
+
[conditionPrecedingStatements, condition] = createOrExpression(context, conditionVariable, condition, conditionPrecedingStatements);
|
|
108
|
+
statements.push(...conditionPrecedingStatements, lua.createAssignmentStatement(conditionVariable, condition));
|
|
84
109
|
}
|
|
85
110
|
continue;
|
|
86
111
|
}
|
|
87
112
|
}
|
|
88
113
|
// Transform the clause and append the final break statement if necessary
|
|
89
|
-
const clauseStatements = context.transformStatements(clause.statements);
|
|
114
|
+
const { statements: clauseStatements, hoistedStatements: clauseHoistedStatements, hoistedIdentifiers: clauseHoistedIdentifiers, } = (0, scope_1.separateHoistedStatements)(context, context.transformStatements(clause.statements));
|
|
90
115
|
if (i === clauses.length - 1 && !containsBreakOrReturn(clause.statements)) {
|
|
91
116
|
clauseStatements.push(lua.createBreakStatement());
|
|
92
117
|
}
|
|
118
|
+
hoistedStatements.push(...clauseHoistedStatements);
|
|
119
|
+
hoistedIdentifiers.push(...clauseHoistedIdentifiers);
|
|
120
|
+
// Remember that we transformed default clause so we don't duplicate hoisted statements later
|
|
121
|
+
if (ts.isDefaultClause(clause)) {
|
|
122
|
+
defaultTransformed = true;
|
|
123
|
+
}
|
|
93
124
|
// Push if statement for case
|
|
94
125
|
statements.push(lua.createIfStatement(conditionVariable, lua.createBlock(clauseStatements)));
|
|
95
126
|
// Clear condition for next clause
|
|
96
127
|
condition = undefined;
|
|
128
|
+
conditionPrecedingStatements = [];
|
|
97
129
|
}
|
|
98
130
|
// If no conditions above match, we need to create the final default case code-path,
|
|
99
131
|
// as we only handle fallthrough into defaults in the previous if statement chain
|
|
@@ -101,11 +133,19 @@ const transformSwitchStatement = (statement, context) => {
|
|
|
101
133
|
if (start >= 0) {
|
|
102
134
|
// Find the last clause that we can fallthrough to
|
|
103
135
|
const end = clauses.findIndex((clause, index) => index >= start && containsBreakOrReturn(clause.statements));
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
.
|
|
108
|
-
.
|
|
136
|
+
const { statements: defaultStatements, hoistedStatements: defaultHoistedStatements, hoistedIdentifiers: defaultHoistedIdentifiers, } = (0, scope_1.separateHoistedStatements)(context, context.transformStatements(clauses[start].statements));
|
|
137
|
+
// Only push hoisted statements if this is the first time we're transforming the default clause
|
|
138
|
+
if (!defaultTransformed) {
|
|
139
|
+
hoistedStatements.push(...defaultHoistedStatements);
|
|
140
|
+
hoistedIdentifiers.push(...defaultHoistedIdentifiers);
|
|
141
|
+
}
|
|
142
|
+
// Combine the fallthrough statements
|
|
143
|
+
for (const clause of clauses.slice(start + 1, end >= 0 ? end + 1 : undefined)) {
|
|
144
|
+
let statements = context.transformStatements(clause.statements);
|
|
145
|
+
// Drop hoisted statements as they were already added when clauses were initially transformed above
|
|
146
|
+
({ statements } = (0, scope_1.separateHoistedStatements)(context, statements));
|
|
147
|
+
defaultStatements.push(...statements);
|
|
148
|
+
}
|
|
109
149
|
// Add the default clause if it has any statements
|
|
110
150
|
// The switch will always break on the final clause and skip execution if valid to do so
|
|
111
151
|
if (defaultStatements.length) {
|
|
@@ -114,8 +154,11 @@ const transformSwitchStatement = (statement, context) => {
|
|
|
114
154
|
}
|
|
115
155
|
}
|
|
116
156
|
// Hoist the variable, function, and import statements to the top of the switch
|
|
117
|
-
statements
|
|
118
|
-
|
|
157
|
+
statements.unshift(...hoistedStatements);
|
|
158
|
+
if (hoistedIdentifiers.length > 0) {
|
|
159
|
+
statements.unshift(lua.createVariableDeclarationStatement(hoistedIdentifiers));
|
|
160
|
+
}
|
|
161
|
+
(0, scope_1.popScope)(context);
|
|
119
162
|
// Add the switch expression after hoisting
|
|
120
163
|
const expression = context.transformExpression(statement.expression);
|
|
121
164
|
statements.unshift(lua.createVariableDeclarationStatement(switchVariable, expression));
|
|
@@ -7,6 +7,7 @@ const function_context_1 = require("../utils/function-context");
|
|
|
7
7
|
const lua_ast_1 = require("../utils/lua-ast");
|
|
8
8
|
const types_1 = require("../utils/typescript/types");
|
|
9
9
|
const call_1 = require("./call");
|
|
10
|
+
const expression_list_1 = require("./expression-list");
|
|
10
11
|
// TODO: Source positions
|
|
11
12
|
function getRawLiteral(node) {
|
|
12
13
|
let text = node.getText();
|
|
@@ -21,14 +22,16 @@ const transformTemplateExpression = (node, context) => {
|
|
|
21
22
|
if (head.length > 0) {
|
|
22
23
|
parts.push(lua.createStringLiteral(head, node.head));
|
|
23
24
|
}
|
|
24
|
-
|
|
25
|
-
|
|
25
|
+
const transformedExpressions = (0, expression_list_1.transformOrderedExpressions)(context, node.templateSpans.map(s => s.expression));
|
|
26
|
+
for (let i = 0; i < node.templateSpans.length; ++i) {
|
|
27
|
+
const span = node.templateSpans[i];
|
|
28
|
+
const expression = transformedExpressions[i];
|
|
26
29
|
const spanType = context.checker.getTypeAtLocation(span.expression);
|
|
27
|
-
if (types_1.isStringType(context, spanType)) {
|
|
30
|
+
if ((0, types_1.isStringType)(context, spanType)) {
|
|
28
31
|
parts.push(expression);
|
|
29
32
|
}
|
|
30
33
|
else {
|
|
31
|
-
parts.push(lua_ast_1.wrapInToStringForConcat(expression));
|
|
34
|
+
parts.push((0, lua_ast_1.wrapInToStringForConcat)(expression));
|
|
32
35
|
}
|
|
33
36
|
const text = span.literal.text;
|
|
34
37
|
if (text.length > 0) {
|
|
@@ -65,12 +68,12 @@ const transformTaggedTemplateExpression = (expression, context) => {
|
|
|
65
68
|
// Evaluate if there is a self parameter to be used.
|
|
66
69
|
const signature = context.checker.getResolvedSignature(expression);
|
|
67
70
|
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;
|
|
71
|
+
const useSelfParameter = signatureDeclaration && (0, function_context_1.getDeclarationContextType)(context, signatureDeclaration) !== function_context_1.ContextType.Void;
|
|
69
72
|
if (useSelfParameter) {
|
|
70
|
-
return call_1.transformContextualCallExpression(context, expression, expressions, signature);
|
|
73
|
+
return (0, call_1.transformContextualCallExpression)(context, expression, expressions, signature);
|
|
71
74
|
}
|
|
72
75
|
// Argument evaluation.
|
|
73
|
-
const callArguments = call_1.transformArguments(context, expressions, signature);
|
|
76
|
+
const callArguments = (0, call_1.transformArguments)(context, expressions, signature);
|
|
74
77
|
const leftHandSideExpression = context.transformExpression(expression.tag);
|
|
75
78
|
return lua.createCallExpression(leftHandSideExpression, callArguments);
|
|
76
79
|
};
|