roblox-ts
Version:
<div align="center"><img width=25% src="https://i.imgur.com/yCjHmng.png"></div> <h1 align="center"><a href="https://roblox-ts.github.io/">roblox-ts</a></h1> <div align="center">A TypeScript-to-Lua Compiler for Roblox</div> <br> <div align="center"> <a hr
192 lines • 8.63 kB
JavaScript
"use strict";
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const ts = __importStar(require("ts-morph"));
const _1 = require(".");
const CompilerError_1 = require("../errors/CompilerError");
const utility_1 = require("../utility");
function compileExpression(state, node) {
if (ts.TypeGuards.isStringLiteral(node) || ts.TypeGuards.isNoSubstitutionTemplateLiteral(node)) {
return _1.compileStringLiteral(state, node);
}
else if (ts.TypeGuards.isNumericLiteral(node)) {
return _1.compileNumericLiteral(state, node);
}
else if (ts.TypeGuards.isBooleanLiteral(node)) {
return _1.compileBooleanLiteral(state, node);
}
else if (ts.TypeGuards.isArrayLiteralExpression(node)) {
return _1.compileArrayLiteralExpression(state, node);
}
else if (ts.TypeGuards.isObjectLiteralExpression(node)) {
return _1.compileObjectLiteralExpression(state, node);
}
else if (ts.TypeGuards.isFunctionExpression(node) || ts.TypeGuards.isArrowFunction(node)) {
return _1.compileFunctionExpression(state, node);
}
else if (ts.TypeGuards.isCallExpression(node)) {
return _1.compileCallExpression(state, node);
}
else if (ts.TypeGuards.isIdentifier(node)) {
return _1.compileIdentifier(state, node);
}
else if (ts.TypeGuards.isBinaryExpression(node)) {
return _1.compileBinaryExpression(state, node);
}
else if (ts.TypeGuards.isPrefixUnaryExpression(node)) {
return _1.compilePrefixUnaryExpression(state, node);
}
else if (ts.TypeGuards.isPostfixUnaryExpression(node)) {
return _1.compilePostfixUnaryExpression(state, node);
}
else if (ts.TypeGuards.isPropertyAccessExpression(node)) {
return _1.compilePropertyAccessExpression(state, node);
}
else if (ts.TypeGuards.isNewExpression(node)) {
return _1.compileNewExpression(state, node);
}
else if (ts.TypeGuards.isParenthesizedExpression(node)) {
return _1.compileParenthesizedExpression(state, node);
}
else if (ts.TypeGuards.isTemplateExpression(node)) {
return _1.compileTemplateExpression(state, node);
}
else if (ts.TypeGuards.isTaggedTemplateExpression(node)) {
return _1.compileTaggedTemplateExpression(state, node);
}
else if (ts.TypeGuards.isElementAccessExpression(node)) {
return _1.compileElementAccessExpression(state, node);
}
else if (ts.TypeGuards.isAwaitExpression(node)) {
return _1.compileAwaitExpression(state, node);
}
else if (ts.TypeGuards.isConditionalExpression(node)) {
return _1.compileConditionalExpression(state, node);
}
else if (ts.TypeGuards.isJsxExpression(node)) {
return compileExpression(state, node.getExpressionOrThrow());
}
else if (ts.TypeGuards.isJsxSelfClosingElement(node)) {
return _1.compileJsxSelfClosingElement(state, node);
}
else if (ts.TypeGuards.isJsxElement(node)) {
return _1.compileJsxElement(state, node);
}
else if (ts.TypeGuards.isSpreadElement(node)) {
return _1.compileSpreadElement(state, node);
}
else if (ts.TypeGuards.isClassExpression(node)) {
return _1.compileClassExpression(state, node);
}
else if (ts.TypeGuards.isYieldExpression(node)) {
return _1.compileYieldExpression(state, node);
}
else if (ts.TypeGuards.isOmittedExpression(node)) {
return "nil";
}
else if (ts.TypeGuards.isThisExpression(node)) {
if (!node.getFirstAncestorByKind(ts.SyntaxKind.ClassDeclaration) &&
!node.getFirstAncestorByKind(ts.SyntaxKind.ObjectLiteralExpression) &&
!node.getFirstAncestorByKind(ts.SyntaxKind.ClassExpression)) {
throw new CompilerError_1.CompilerError("'this' may only be used inside a class definition or object literal", node, CompilerError_1.CompilerErrorType.NoThisOutsideClass);
}
return "self";
}
else if (ts.TypeGuards.isSuperExpression(node)) {
return _1.compileSuperExpression(state, node);
}
else if (ts.TypeGuards.isAsExpression(node) ||
ts.TypeGuards.isTypeAssertion(node) ||
ts.TypeGuards.isNonNullExpression(node)) {
return compileExpression(state, utility_1.skipNodesDownwards(node.getExpression()));
}
else if (ts.TypeGuards.isNullLiteral(node)) {
throw new CompilerError_1.CompilerError("'null' is not supported! Use 'undefined' instead.", node, CompilerError_1.CompilerErrorType.NoNull);
}
else if (ts.TypeGuards.isTypeOfExpression(node)) {
throw new CompilerError_1.CompilerError("'typeof' operator is not supported! Use `typeIs(value, type)` or `typeOf(value)` instead.", node, CompilerError_1.CompilerErrorType.NoTypeOf);
}
else {
throw new CompilerError_1.CompilerError(`Unexpected expression ( ${node.getKindName()} ) in compileExpression`, node, CompilerError_1.CompilerErrorType.BadExpression, true);
}
}
exports.compileExpression = compileExpression;
function compileExpressionStatement(state, node) {
state.enterPrecedingStatementContext();
let expStr;
const expression = utility_1.skipNodesDownwards(node.getExpression());
if (ts.TypeGuards.isCallExpression(expression)) {
expStr = _1.compileCallExpression(state, expression, true);
}
else {
expStr = compileExpression(state, expression);
// big set of rules for expression statements
if (!ts.TypeGuards.isNewExpression(expression) &&
!ts.TypeGuards.isAwaitExpression(expression) &&
!ts.TypeGuards.isPostfixUnaryExpression(expression) &&
!(ts.TypeGuards.isPrefixUnaryExpression(expression) &&
(expression.getOperatorToken() === ts.SyntaxKind.PlusPlusToken ||
expression.getOperatorToken() === ts.SyntaxKind.MinusMinusToken)) &&
!(ts.TypeGuards.isBinaryExpression(expression) && _1.isSetToken(expression.getOperatorToken().getKind())) &&
!ts.TypeGuards.isYieldExpression(expression)) {
expStr = `local _ = ${expStr}`;
}
}
const result = state.exitPrecedingStatementContextAndJoin();
// this is a hack for the time being, to prevent double indenting
// situations like these: ({ length } = "Hello, world!")
const indent = expStr.match(/^\s+/) ? "" : state.indent;
return expStr ? result + indent + expStr + ";\n" : result;
}
exports.compileExpressionStatement = compileExpressionStatement;
function expressionModifiesVariable(node, lhs) {
if (ts.TypeGuards.isPostfixUnaryExpression(node) ||
(ts.TypeGuards.isPrefixUnaryExpression(node) &&
(node.getOperatorToken() === ts.SyntaxKind.PlusPlusToken ||
node.getOperatorToken() === ts.SyntaxKind.MinusMinusToken))) {
if (lhs) {
return utility_1.isIdentifierWhoseDefinitionMatchesNode(node.getOperand(), lhs);
}
else {
return true;
}
}
else if (ts.TypeGuards.isBinaryExpression(node) && _1.isSetToken(node.getOperatorToken().getKind())) {
if (lhs) {
return utility_1.isIdentifierWhoseDefinitionMatchesNode(node.getLeft(), lhs);
}
else {
return true;
}
}
return false;
}
exports.expressionModifiesVariable = expressionModifiesVariable;
function appendDeclarationIfMissing(state, possibleExpressionStatement, compiledNode) {
if (compiledNode.match(/^_d+$/) ||
ts.TypeGuards.isExpressionStatement(utility_1.skipNodesUpwards(possibleExpressionStatement))) {
return "local _ = " + compiledNode;
}
else {
return compiledNode;
}
}
exports.appendDeclarationIfMissing = appendDeclarationIfMissing;
function placeIncrementorInStatementIfExpression(state, incrementor, incrementorStr) {
if (ts.TypeGuards.isExpression(incrementor)) {
if (!ts.TypeGuards.isCallExpression(incrementor) &&
!expressionModifiesVariable(incrementor) &&
!ts.TypeGuards.isVariableDeclarationList(incrementor)) {
incrementorStr = `local _ = ` + incrementorStr;
}
}
return incrementorStr;
}
exports.placeIncrementorInStatementIfExpression = placeIncrementorInStatementIfExpression;
//# sourceMappingURL=expression.js.map