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
218 lines • 8.8 kB
JavaScript
;
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 typeUtilities_1 = require("../typeUtilities");
const utility_1 = require("../utility");
function shouldCompileAsSpreadableList(elements) {
const { length } = elements;
for (let i = 0; i < length; i++) {
if (ts.TypeGuards.isSpreadElement(elements[i])) {
return i + 1 !== length;
}
}
return false;
}
exports.shouldCompileAsSpreadableList = shouldCompileAsSpreadableList;
function compileSpreadableList(state, elements, compile = _1.compileExpression) {
// The logic here is equivalent to the compileList logic, although it looks a bit more complicated
let isInArray = false;
const parts = new Array();
const contexts = new Array();
const args = new Array();
let gIndex = 0;
let lastContextualIndex;
let lastContextualElement;
for (const element of elements) {
if (ts.TypeGuards.isSpreadElement(element)) {
state.enterPrecedingStatementContext();
const expStr = compileSpreadExpressionOrThrow(state, utility_1.skipNodesDownwards(element.getExpression()));
const context = state.exitPrecedingStatementContext();
if (context.length > 0) {
lastContextualIndex = gIndex;
lastContextualElement = element;
}
parts.push(expStr);
contexts.push(context);
args.push(element);
gIndex++;
isInArray = false;
}
else {
let last;
let lastContext;
let lastElement;
if (isInArray) {
last = parts[parts.length - 1];
lastContext = contexts[contexts.length - 1];
lastElement = args[args.length - 1];
}
else {
last = new Array();
lastContext = new Array();
lastElement = new Array();
parts.push(last);
contexts.push(lastContext);
args.push(lastElement);
}
state.enterPrecedingStatementContext();
const expStr = compile(state, element);
const context = state.exitPrecedingStatementContext();
if (context.length > 0) {
lastContextualIndex = gIndex;
lastContextualElement = element;
}
last.push(expStr);
lastContext.push(context);
lastElement.push(element);
gIndex++;
isInArray = true;
}
}
if (lastContextualIndex !== undefined) {
let gIter = 0;
for (let i = 0; i < contexts.length; i++) {
if (gIter === lastContextualIndex) {
if (typeof parts[i] === "string") {
state.pushPrecedingStatements(lastContextualElement, ...contexts[i]);
}
else {
contexts[i].forEach(context => state.pushPrecedingStatements(lastContextualElement, ...context));
}
break;
}
const part = parts[i];
if (typeof part === "string") {
const arg = args[i];
const context = contexts[i];
if (context.length > 0) {
state.pushPrecedingStatements(arg, ...context);
}
if (typeUtilities_1.shouldPushToPrecedingStatement(arg, part, context)) {
let nextContext;
// get nextContext
if (typeof parts[i + 1] === "string") {
nextContext = contexts[i + 1];
}
else {
const contextSet = contexts[i + 1];
nextContext = contextSet.reduce((a, x) => {
a.push(...x);
return a;
}, new Array());
nextContext.isPushed = false;
}
parts[i] = state.pushPrecedingStatementToReuseableId(arg, part, nextContext);
}
gIter++;
}
else {
const arg = args[i];
const context = contexts[i];
for (let j = 0; j < context.length; j++) {
const subContext = context[j];
const subExp = arg[j];
const subStr = part[j];
if (subContext.length > 0) {
state.pushPrecedingStatements(subExp, ...subContext);
}
if (typeUtilities_1.shouldPushToPrecedingStatement(subExp, subStr, subContext)) {
part[j] = state.pushPrecedingStatementToReuseableId(subExp, subStr, context[j + 1]);
}
if (++gIter === lastContextualIndex) {
state.pushPrecedingStatements(lastContextualElement, ...context[j + 1]);
break;
}
}
}
}
}
return parts;
}
exports.compileSpreadableList = compileSpreadableList;
function compileSpreadableListAndJoin(state, elements, shouldWrapInConcat = true, compile = _1.compileExpression) {
let params = compileSpreadableList(state, elements, compile)
.map(v => {
if (typeof v === "string") {
return v;
}
else {
return `{ ${v.join(", ")} }`;
}
})
.join(", ");
if (shouldWrapInConcat) {
state.usesTSLibrary = true;
params = `TS.array_concat(${params})`;
}
return params;
}
exports.compileSpreadableListAndJoin = compileSpreadableListAndJoin;
function compileSpreadExpression(state, expression) {
const expType = typeUtilities_1.getType(expression);
if (typeUtilities_1.isSetType(expType)) {
state.usesTSLibrary = true;
return `TS.set_values(${_1.compileExpression(state, expression)})`;
}
else if (typeUtilities_1.isMapType(expType)) {
state.usesTSLibrary = true;
return `TS.map_entries(${_1.compileExpression(state, expression)})`;
}
else if (typeUtilities_1.isArrayType(expType)) {
return _1.compileExpression(state, expression);
}
else if (typeUtilities_1.isStringType(expType)) {
if (ts.TypeGuards.isStringLiteral(expression)) {
const text = expression.getText();
const quote = text.slice(-1);
return "{" + text.replace(/\\?./g, a => `${quote}${a}${quote}, `).slice(4, -7) + " }";
}
else {
return `string.split(${_1.compileExpression(state, expression)}, "")`;
}
}
else if (typeUtilities_1.isIterableFunction(expType)) {
state.usesTSLibrary = true;
return `TS.iterableFunctionCache(${_1.compileExpression(state, expression)})`;
}
else if (typeUtilities_1.isIterableIterator(expType, expression)) {
state.usesTSLibrary = true;
return `TS.iterableCache(${_1.compileExpression(state, expression)})`;
}
else {
state.usesTSLibrary = true;
const arrName = _1.getReadableExpressionName(state, expression);
return `TS.iterableCache(${arrName}[TS.Symbol_iterator](${arrName}))`;
}
}
exports.compileSpreadExpression = compileSpreadExpression;
function compileSpreadExpressionOrThrow(state, expression) {
const result = compileSpreadExpression(state, expression);
if (result) {
return result;
}
else {
throw new CompilerError_1.CompilerError(`Unable to spread expression of type ${typeUtilities_1.getType(expression).getText()}`, expression, CompilerError_1.CompilerErrorType.BadSpreadType);
}
}
exports.compileSpreadExpressionOrThrow = compileSpreadExpressionOrThrow;
function compileSpreadElement(state, node) {
const expression = node.getExpression();
_1.checkNonAny(expression, true);
if (ts.TypeGuards.isCallExpression(expression) && typeUtilities_1.isTupleReturnTypeCall(expression)) {
return _1.compileCallExpression(state, expression, true);
}
else {
return `unpack(${compileSpreadExpressionOrThrow(state, expression)})`;
}
}
exports.compileSpreadElement = compileSpreadElement;
//# sourceMappingURL=spread.js.map