roblox-ts
Version:
A TypeScript-to-Luau Compiler for Roblox
155 lines • 8.45 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.transformVariable = transformVariable;
exports.transformVariableDeclaration = transformVariableDeclaration;
exports.isVarDeclaration = isVarDeclaration;
exports.transformVariableDeclarationList = transformVariableDeclarationList;
exports.transformVariableStatement = transformVariableStatement;
const luau_ast_1 = __importDefault(require("@roblox-ts/luau-ast"));
const diagnostics_1 = require("../../../Shared/diagnostics");
const assert_1 = require("../../../Shared/util/assert");
const DiagnosticService_1 = require("../../classes/DiagnosticService");
const transformArrayBindingPattern_1 = require("../binding/transformArrayBindingPattern");
const transformObjectBindingPattern_1 = require("../binding/transformObjectBindingPattern");
const transformExpression_1 = require("../expressions/transformExpression");
const transformIdentifier_1 = require("../expressions/transformIdentifier");
const transformInitializer_1 = require("../transformInitializer");
const arrayBindingPatternContainsHoists_1 = require("../../util/arrayBindingPatternContainsHoists");
const checkVariableHoist_1 = require("../../util/checkVariableHoist");
const isSymbolMutable_1 = require("../../util/isSymbolMutable");
const types_1 = require("../../util/types");
const validateIdentifier_1 = require("../../util/validateIdentifier");
const wrapExpressionStatement_1 = require("../../util/wrapExpressionStatement");
const typescript_1 = __importDefault(require("typescript"));
function transformVariable(state, identifier, right) {
(0, validateIdentifier_1.validateIdentifier)(state, identifier);
const symbol = state.typeChecker.getSymbolAtLocation(identifier);
(0, assert_1.assert)(symbol);
if ((0, isSymbolMutable_1.isSymbolMutable)(state, symbol)) {
const exportAccess = state.getModuleIdPropertyAccess(symbol);
if (exportAccess) {
if (right) {
state.prereq(luau_ast_1.default.create(luau_ast_1.default.SyntaxKind.Assignment, {
left: exportAccess,
operator: "=",
right,
}));
}
return exportAccess;
}
}
const left = (0, transformIdentifier_1.transformIdentifierDefined)(state, identifier);
(0, checkVariableHoist_1.checkVariableHoist)(state, identifier, symbol);
if (state.isHoisted.get(symbol) === true) {
if (right) {
state.prereq(luau_ast_1.default.create(luau_ast_1.default.SyntaxKind.Assignment, { left, operator: "=", right }));
}
}
else {
state.prereq(luau_ast_1.default.create(luau_ast_1.default.SyntaxKind.VariableDeclaration, { left, right }));
}
return left;
}
function transformOptimizedArrayBindingPattern(state, bindingPattern, rhs) {
return state.capturePrereqs(() => {
const ids = luau_ast_1.default.list.make();
const statements = state.capturePrereqs(() => {
for (const element of bindingPattern.elements) {
if (typescript_1.default.isOmittedExpression(element)) {
luau_ast_1.default.list.push(ids, luau_ast_1.default.tempId());
}
else {
if (element.dotDotDotToken) {
DiagnosticService_1.DiagnosticService.addDiagnostic(diagnostics_1.errors.noSpreadDestructuring(element));
return;
}
if (typescript_1.default.isIdentifier(element.name)) {
(0, validateIdentifier_1.validateIdentifier)(state, element.name);
const id = (0, transformIdentifier_1.transformIdentifierDefined)(state, element.name);
luau_ast_1.default.list.push(ids, id);
if (element.initializer) {
state.prereq((0, transformInitializer_1.transformInitializer)(state, id, element.initializer));
}
}
else {
const id = luau_ast_1.default.tempId("binding");
luau_ast_1.default.list.push(ids, id);
if (element.initializer) {
state.prereq((0, transformInitializer_1.transformInitializer)(state, id, element.initializer));
}
if (typescript_1.default.isArrayBindingPattern(element.name)) {
(0, transformArrayBindingPattern_1.transformArrayBindingPattern)(state, element.name, id);
}
else {
(0, transformObjectBindingPattern_1.transformObjectBindingPattern)(state, element.name, id);
}
}
}
}
});
(0, assert_1.assert)(!luau_ast_1.default.list.isEmpty(ids));
state.prereq(luau_ast_1.default.create(luau_ast_1.default.SyntaxKind.VariableDeclaration, { left: ids, right: rhs }));
state.prereqList(statements);
});
}
function transformVariableDeclaration(state, node) {
const statements = luau_ast_1.default.list.make();
let value;
if (node.initializer) {
luau_ast_1.default.list.pushList(statements, state.capturePrereqs(() => (value = (0, transformExpression_1.transformExpression)(state, node.initializer))));
}
const name = node.name;
if (typescript_1.default.isIdentifier(name)) {
luau_ast_1.default.list.pushList(statements, state.capturePrereqs(() => transformVariable(state, name, value)));
}
else {
(0, assert_1.assert)(node.initializer && value);
if (name.elements.length === 0) {
if (!luau_ast_1.default.isArray(value) || !luau_ast_1.default.list.isEmpty(value.members)) {
luau_ast_1.default.list.pushList(statements, (0, wrapExpressionStatement_1.wrapExpressionStatement)(value));
}
return statements;
}
if (typescript_1.default.isArrayBindingPattern(name)) {
if (luau_ast_1.default.isCall(value) &&
(0, types_1.isLuaTupleType)(state)(state.getType(node.initializer)) &&
!(0, arrayBindingPatternContainsHoists_1.arrayBindingPatternContainsHoists)(state, name)) {
luau_ast_1.default.list.pushList(statements, transformOptimizedArrayBindingPattern(state, name, value));
}
else if (luau_ast_1.default.isArray(value) &&
!luau_ast_1.default.list.isEmpty(value.members) &&
!(0, arrayBindingPatternContainsHoists_1.arrayBindingPatternContainsHoists)(state, name)) {
luau_ast_1.default.list.pushList(statements, transformOptimizedArrayBindingPattern(state, name, value.members));
}
else {
luau_ast_1.default.list.pushList(statements, state.capturePrereqs(() => (0, transformArrayBindingPattern_1.transformArrayBindingPattern)(state, name, state.pushToVar(value, "binding"))));
}
}
else {
luau_ast_1.default.list.pushList(statements, state.capturePrereqs(() => (0, transformObjectBindingPattern_1.transformObjectBindingPattern)(state, name, state.pushToVar(value, "binding"))));
}
}
return statements;
}
function isVarDeclaration(node) {
return !(node.flags & typescript_1.default.NodeFlags.Const) && !(node.flags & typescript_1.default.NodeFlags.Let);
}
function transformVariableDeclarationList(state, node) {
if (isVarDeclaration(node)) {
DiagnosticService_1.DiagnosticService.addDiagnostic(diagnostics_1.errors.noVar(node));
}
const statements = luau_ast_1.default.list.make();
for (const declaration of node.declarations) {
const [variableStatements, prereqs] = state.capture(() => transformVariableDeclaration(state, declaration));
luau_ast_1.default.list.pushList(statements, prereqs);
luau_ast_1.default.list.pushList(statements, variableStatements);
}
return statements;
}
function transformVariableStatement(state, node) {
return transformVariableDeclarationList(state, node.declarationList);
}
//# sourceMappingURL=transformVariableStatement.js.map