UNPKG

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

160 lines 8.2 kB
"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 typeUtilities_1 = require("../typeUtilities"); const utility_1 = require("../utility"); function compileMapElement(state, element) { if (ts.TypeGuards.isArrayLiteralExpression(element)) { const [key, value] = _1.compileCallArguments(state, element.getElements().map(e => utility_1.skipNodesDownwards(e))); return `[${key}] = ${value};\n`; } else if (ts.TypeGuards.isCallExpression(element) && typeUtilities_1.isTupleType(element.getReturnType())) { const key = state.getNewId(); const value = state.getNewId(); state.pushPrecedingStatementToNewId(element, _1.compileExpression(state, element).slice(2, -2), `${key}, ${value}`); return `[${key}] = ${value};\n`; } else { const id = _1.getReadableExpressionName(state, element, _1.compileExpression(state, element)); return `[${id}[1]] = ${id}[2];\n`; } } function compileSetElement(state, element) { const [key] = _1.compileCallArguments(state, [element]); return `[${key}] = true;\n`; } const compileMapSetElement = new Map([ ["map", { compile: compileMapElement, addMethodName: "set" }], ["set", { compile: compileSetElement, addMethodName: "add" }], ]); function compileSetMapConstructorHelper(state, node, args, type, mode = "") { const preDeclaration = mode ? "setmetatable(" : ""; const postDeclaration = mode ? `, { __mode = "${mode}" })` : ""; const typeArgument = typeUtilities_1.getType(node).getTypeArguments()[0]; if (typeArgument.isNullable() || typeArgument.isUndefined()) { throw new CompilerError_1.CompilerError(`Cannot create a ${type} with a nullable index!`, node, CompilerError_1.CompilerErrorType.NullableIndexOnMapOrSet); } const firstParam = utility_1.skipNodesDownwards(args[0]); let exp = node; let parent = utility_1.skipNodesUpwards(node.getParent()); const { compile: compileElement, addMethodName: addMethodName } = compileMapSetElement.get(type); while (ts.TypeGuards.isPropertyAccessExpression(parent) && addMethodName === parent.getName()) { const grandparent = utility_1.skipNodesUpwards(parent.getParent()); if (ts.TypeGuards.isCallExpression(grandparent)) { exp = grandparent; parent = utility_1.skipNodesUpwards(grandparent.getParent()); } else { break; } } const pushCondition = ts.TypeGuards.isNewExpression(exp) ? () => true : (declaration) => declaration.isIdentifier; if (firstParam && (!ts.TypeGuards.isArrayLiteralExpression(firstParam) || firstParam.getChildrenOfKind(ts.SyntaxKind.SpreadElement).length > 0)) { state.usesTSLibrary = true; const id = state.pushToDeclarationOrNewId(exp, preDeclaration + `TS.${type}_new(${_1.compileCallArgumentsAndJoin(state, args)})` + postDeclaration, pushCondition); return id; } else { let id = ""; const lines = new Array(); let hasContext = false; if (firstParam) { for (let element of firstParam.getElements()) { element = utility_1.skipNodesDownwards(element); if (hasContext) { state.pushPrecedingStatements(exp, id + compileElement(state, element)); } else { state.enterPrecedingStatementContext(); const line = compileElement(state, element); const context = state.exitPrecedingStatementContext(); if (context.length > 0) { hasContext = true; id = state.pushToDeclarationOrNewId(exp, preDeclaration + "{}" + postDeclaration, declaration => declaration.isIdentifier); state.pushPrecedingStatements(exp, ...lines.map(current => state.indent + id + current), ...context, state.indent + id + line); } else { lines.push(line); } } } } if (!hasContext) { id = state.pushToDeclarationOrNewId(exp, lines.length === 0 ? preDeclaration + "{}" + postDeclaration : preDeclaration + lines.reduce((result, line) => result + state.indent + utility_1.joinIndentedLines([line], 1), "{\n") + state.indent + "}" + postDeclaration, pushCondition); } return id; } } const ARRAY_NIL_LIMIT = 200; function compileNewExpression(state, node) { const expNode = utility_1.skipNodesDownwards(node.getExpression()); const expressionType = typeUtilities_1.getType(expNode); const name = _1.compileExpression(state, expNode); const args = node.getFirstChildByKind(ts.SyntaxKind.OpenParenToken) ? node.getArguments().map(arg => utility_1.skipNodesDownwards(arg)) : []; if (_1.inheritsFromRoact(expressionType)) { throw new CompilerError_1.CompilerError(`Roact components cannot be created using new\n` + utility_1.suggest(`Proper usage: Roact.createElement(${name}), <${name}></${name}> or <${name}/>`), node, CompilerError_1.CompilerErrorType.RoactNoNewComponentAllowed); } if (typeUtilities_1.inheritsFrom(expressionType, "ArrayConstructor")) { if (args.length === 0) { return "{}"; } let result = `{`; if (args.length === 1) { const arg = args[0]; if (ts.TypeGuards.isNumericLiteral(arg) && arg.getText().match(/^\d+$/) && arg.getLiteralValue() <= ARRAY_NIL_LIMIT) { const literalValue = arg.getLiteralValue(); if (literalValue !== 0) { result += ", nil".repeat(literalValue).substring(1) + " "; } } else { throw new CompilerError_1.CompilerError("Invalid argument #1 passed into ArrayConstructor. Expected a simple integer fewer or equal to " + ARRAY_NIL_LIMIT + ".", node, CompilerError_1.CompilerErrorType.BadBuiltinConstructorCall); } } else if (args.length !== 0) { throw new CompilerError_1.CompilerError("Invalid arguments passed into ArrayConstructor!", node, CompilerError_1.CompilerErrorType.BadBuiltinConstructorCall); } return _1.appendDeclarationIfMissing(state, utility_1.skipNodesUpwards(node.getParent()), result + `}`); } if (typeUtilities_1.inheritsFrom(expressionType, "MapConstructor")) { return _1.appendDeclarationIfMissing(state, utility_1.skipNodesUpwards(node.getParent()), compileSetMapConstructorHelper(state, node, args, "map")); } if (typeUtilities_1.inheritsFrom(expressionType, "SetConstructor")) { return _1.appendDeclarationIfMissing(state, utility_1.skipNodesUpwards(node.getParent()), compileSetMapConstructorHelper(state, node, args, "set")); } if (typeUtilities_1.inheritsFrom(expressionType, "WeakMapConstructor")) { return _1.appendDeclarationIfMissing(state, utility_1.skipNodesUpwards(node.getParent()), compileSetMapConstructorHelper(state, node, args, "map", "k")); } if (typeUtilities_1.inheritsFrom(expressionType, "WeakSetConstructor")) { return _1.appendDeclarationIfMissing(state, utility_1.skipNodesUpwards(node.getParent()), compileSetMapConstructorHelper(state, node, args, "set", "k")); } return `${name}.new(${_1.compileCallArgumentsAndJoin(state, args)})`; } exports.compileNewExpression = compileNewExpression; //# sourceMappingURL=new.js.map