roblox-ts
Version:
A TypeScript-to-Luau Compiler for Roblox
148 lines • 7.23 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.transformTryStatement = transformTryStatement;
const luau_ast_1 = __importDefault(require("@roblox-ts/luau-ast"));
const assert_1 = require("../../../Shared/util/assert");
const transformBindingName_1 = require("../binding/transformBindingName");
const transformStatementList_1 = require("../transformStatementList");
const isBlockedByTryStatement_1 = require("../../util/isBlockedByTryStatement");
function transformCatchClause(state, node) {
const parameters = luau_ast_1.default.list.make();
const statements = luau_ast_1.default.list.make();
if (node.variableDeclaration) {
luau_ast_1.default.list.push(parameters, (0, transformBindingName_1.transformBindingName)(state, node.variableDeclaration.name, statements));
}
luau_ast_1.default.list.pushList(statements, (0, transformStatementList_1.transformStatementList)(state, node.block, node.block.statements));
const catchFunction = luau_ast_1.default.create(luau_ast_1.default.SyntaxKind.FunctionExpression, {
parameters,
hasDotDotDot: false,
statements,
});
return catchFunction;
}
function transformIntoTryCall(state, node, exitTypeId, returnsId, tryUses) {
const tryCallArgs = new Array();
tryCallArgs.push(luau_ast_1.default.create(luau_ast_1.default.SyntaxKind.FunctionExpression, {
parameters: luau_ast_1.default.list.make(),
hasDotDotDot: false,
statements: (0, transformStatementList_1.transformStatementList)(state, node.tryBlock, node.tryBlock.statements),
}));
if (node.catchClause) {
tryCallArgs.push(transformCatchClause(state, node.catchClause));
}
else {
(0, assert_1.assert)(node.finallyBlock);
tryCallArgs.push(luau_ast_1.default.nil());
}
if (node.finallyBlock) {
tryCallArgs.push(luau_ast_1.default.create(luau_ast_1.default.SyntaxKind.FunctionExpression, {
parameters: luau_ast_1.default.list.make(),
hasDotDotDot: false,
statements: (0, transformStatementList_1.transformStatementList)(state, node.finallyBlock, node.finallyBlock.statements),
}));
}
if (!tryUses.usesReturn && !tryUses.usesBreak && !tryUses.usesContinue) {
return luau_ast_1.default.create(luau_ast_1.default.SyntaxKind.CallStatement, {
expression: luau_ast_1.default.call(state.TS(node, "try"), tryCallArgs),
});
}
return luau_ast_1.default.create(luau_ast_1.default.SyntaxKind.VariableDeclaration, {
left: luau_ast_1.default.list.make(exitTypeId, returnsId),
right: luau_ast_1.default.call(state.TS(node, "try"), tryCallArgs),
});
}
function createFlowControlCondition(state, node, exitTypeId, flowControlConstant) {
return luau_ast_1.default.binary(exitTypeId, "==", state.TS(node, flowControlConstant));
}
function collapseFlowControlCases(exitTypeId, cases) {
(0, assert_1.assert)(cases.length > 0);
let nextStatements = luau_ast_1.default.create(luau_ast_1.default.SyntaxKind.IfStatement, {
condition: exitTypeId,
statements: cases[cases.length - 1].statements,
elseBody: luau_ast_1.default.list.make(),
});
for (let i = cases.length - 2; i >= 0; i--) {
nextStatements = luau_ast_1.default.create(luau_ast_1.default.SyntaxKind.IfStatement, {
condition: cases[i].condition || exitTypeId,
statements: cases[i].statements,
elseBody: nextStatements,
});
}
return luau_ast_1.default.list.make(nextStatements);
}
function transformFlowControl(state, node, exitTypeId, returnsId, tryUses) {
const flowControlCases = new Array();
if (!tryUses.usesReturn && !tryUses.usesBreak && !tryUses.usesContinue) {
return luau_ast_1.default.list.make();
}
const returnBlocked = (0, isBlockedByTryStatement_1.isReturnBlockedByTryStatement)(node.parent);
const breakBlocked = (0, isBlockedByTryStatement_1.isBreakBlockedByTryStatement)(node.parent);
if (tryUses.usesReturn && returnBlocked) {
state.markTryUses("usesReturn");
}
if (tryUses.usesBreak && breakBlocked) {
state.markTryUses("usesBreak");
}
if (tryUses.usesContinue && breakBlocked) {
state.markTryUses("usesContinue");
}
if (tryUses.usesReturn) {
if (returnBlocked) {
flowControlCases.push({
condition: createFlowControlCondition(state, node, exitTypeId, "TRY_RETURN"),
statements: luau_ast_1.default.list.make(luau_ast_1.default.create(luau_ast_1.default.SyntaxKind.ReturnStatement, {
expression: luau_ast_1.default.list.make(exitTypeId, returnsId),
})),
});
if (breakBlocked) {
return collapseFlowControlCases(exitTypeId, flowControlCases);
}
}
else {
flowControlCases.push({
condition: createFlowControlCondition(state, node, exitTypeId, "TRY_RETURN"),
statements: luau_ast_1.default.list.make(luau_ast_1.default.create(luau_ast_1.default.SyntaxKind.ReturnStatement, {
expression: luau_ast_1.default.call(luau_ast_1.default.globals.unpack, [returnsId]),
})),
});
}
}
if (tryUses.usesBreak || tryUses.usesContinue) {
if (breakBlocked) {
flowControlCases.push({
statements: luau_ast_1.default.list.make(luau_ast_1.default.create(luau_ast_1.default.SyntaxKind.ReturnStatement, {
expression: exitTypeId,
})),
});
}
else {
if (tryUses.usesBreak) {
flowControlCases.push({
condition: createFlowControlCondition(state, node, exitTypeId, "TRY_BREAK"),
statements: luau_ast_1.default.list.make(luau_ast_1.default.create(luau_ast_1.default.SyntaxKind.BreakStatement, {})),
});
}
if (tryUses.usesContinue) {
flowControlCases.push({
condition: createFlowControlCondition(state, node, exitTypeId, "TRY_CONTINUE"),
statements: luau_ast_1.default.list.make(luau_ast_1.default.create(luau_ast_1.default.SyntaxKind.ContinueStatement, {})),
});
}
}
}
return collapseFlowControlCases(exitTypeId, flowControlCases);
}
function transformTryStatement(state, node) {
const statements = luau_ast_1.default.list.make();
const exitTypeId = luau_ast_1.default.tempId("exitType");
const returnsId = luau_ast_1.default.tempId("returns");
const tryUses = state.pushTryUsesStack();
luau_ast_1.default.list.push(statements, transformIntoTryCall(state, node, exitTypeId, returnsId, tryUses));
state.popTryUsesStack();
luau_ast_1.default.list.pushList(statements, transformFlowControl(state, node, exitTypeId, returnsId, tryUses));
return statements;
}
//# sourceMappingURL=transformTryStatement.js.map