UNPKG

typescript-to-lua

Version:

A generic TypeScript to Lua transpiler. Write your code in TypeScript and publish Lua!

214 lines 9.29 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.transformBuiltinPropertyAccessExpression = transformBuiltinPropertyAccessExpression; exports.transformBuiltinCallExpression = transformBuiltinCallExpression; exports.transformBuiltinIdentifierExpression = transformBuiltinIdentifierExpression; exports.checkForLuaLibType = checkForLuaLibType; exports.tryGetStandardLibrarySymbolOfType = tryGetStandardLibrarySymbolOfType; const ts = require("typescript"); const lua = require("../../LuaAST"); const lua_ast_1 = require("../utils/lua-ast"); const lualib_1 = require("../utils/lualib"); const symbols_1 = require("../utils/symbols"); const typescript_1 = require("../utils/typescript"); const call_1 = require("../visitors/call"); const array_1 = require("./array"); const console_1 = require("./console"); const function_1 = require("./function"); const global_1 = require("./global"); const math_1 = require("./math"); const number_1 = require("./number"); const object_1 = require("./object"); const promise_1 = require("./promise"); const string_1 = require("./string"); const symbol_1 = require("./symbol"); const diagnostics_1 = require("../utils/diagnostics"); const CompilerOptions_1 = require("../../CompilerOptions"); const map_1 = require("./map"); function transformBuiltinPropertyAccessExpression(context, node) { const ownerType = context.checker.getTypeAtLocation(node.expression); if (ts.isIdentifier(node.expression) && (0, typescript_1.isStandardLibraryType)(context, ownerType, undefined)) { switch (ownerType.symbol.name) { case "NumberConstructor": return (0, number_1.transformNumberProperty)(context, node); case "Math": return (0, math_1.transformMathProperty)(context, node); case "SymbolConstructor": (0, lualib_1.importLuaLibFeature)(context, lualib_1.LuaLibFeature.Symbol); } } if ((0, typescript_1.isStringType)(context, ownerType)) { return (0, string_1.transformStringProperty)(context, node); } if ((0, typescript_1.isArrayType)(context, ownerType)) { return (0, array_1.transformArrayProperty)(context, node); } if ((0, typescript_1.isFunctionType)(ownerType)) { return (0, function_1.transformFunctionProperty)(context, node); } } function transformBuiltinCallExpression(context, node) { const expressionType = context.checker.getTypeAtLocation(node.expression); if (ts.isIdentifier(node.expression) && (0, typescript_1.isStandardLibraryType)(context, expressionType, undefined)) { checkForLuaLibType(context, expressionType); const result = (0, global_1.tryTransformBuiltinGlobalCall)(context, node, expressionType); if (result) return result; } const calledMethod = ts.getOriginalNode((0, call_1.getCalledExpression)(node)); if (ts.isPropertyAccessExpression(calledMethod)) { const globalResult = tryTransformBuiltinGlobalMethodCall(context, node, calledMethod); if (globalResult) return globalResult; const prototypeResult = tryTransformBuiltinPropertyCall(context, node, calledMethod); if (prototypeResult) return prototypeResult; // object prototype call may work even without resolved signature/type (which the other builtin calls use) // e.g. (foo as any).toString() // prototype methods take precedence (e.g. number.toString(2)) const objectResult = (0, object_1.tryTransformObjectPrototypeCall)(context, node, calledMethod); if (objectResult) return objectResult; } } function tryTransformBuiltinGlobalMethodCall(context, node, calledMethod) { const ownerType = context.checker.getTypeAtLocation(calledMethod.expression); const ownerSymbol = tryGetStandardLibrarySymbolOfType(context, ownerType); if (!ownerSymbol || ownerSymbol.parent) return; let result; switch (ownerSymbol.name) { case "ArrayConstructor": result = (0, array_1.transformArrayConstructorCall)(context, node, calledMethod); break; case "Console": result = (0, console_1.transformConsoleCall)(context, node, calledMethod); break; case "MapConstructor": result = (0, map_1.transformMapConstructorCall)(context, node, calledMethod); break; case "Math": result = (0, math_1.transformMathCall)(context, node, calledMethod); break; case "StringConstructor": result = (0, string_1.transformStringConstructorMethodCall)(context, node, calledMethod); break; case "ObjectConstructor": result = (0, object_1.transformObjectConstructorCall)(context, node, calledMethod); break; case "SymbolConstructor": result = (0, symbol_1.transformSymbolConstructorCall)(context, node, calledMethod); break; case "NumberConstructor": result = (0, number_1.transformNumberConstructorCall)(context, node, calledMethod); break; case "PromiseConstructor": result = (0, promise_1.transformPromiseConstructorCall)(context, node, calledMethod); break; } if (result && calledMethod.questionDotToken) { // e.g. console?.log() context.diagnostics.push((0, diagnostics_1.unsupportedBuiltinOptionalCall)(calledMethod)); } return result; } function tryTransformBuiltinPropertyCall(context, node, calledMethod) { const functionType = context.checker.getTypeAtLocation(node.expression); const callSymbol = tryGetStandardLibrarySymbolOfType(context, functionType); if (!callSymbol) return; const ownerSymbol = callSymbol.parent; if (!ownerSymbol || ownerSymbol.parent) return; switch (ownerSymbol.name) { case "String": return (0, string_1.transformStringPrototypeCall)(context, node, calledMethod); case "Number": return (0, number_1.transformNumberPrototypeCall)(context, node, calledMethod); case "Array": case "ReadonlyArray": return (0, array_1.transformArrayPrototypeCall)(context, node, calledMethod); case "Function": case "CallableFunction": case "NewableFunction": return (0, function_1.transformFunctionPrototypeCall)(context, node, calledMethod); } } function transformBuiltinIdentifierExpression(context, node, symbol) { switch (node.text) { case "NaN": return (0, lua_ast_1.createNaN)(node); case "Infinity": if (context.luaTarget === CompilerOptions_1.LuaTarget.Lua50) { const one = lua.createNumericLiteral(1); const zero = lua.createNumericLiteral(0); return lua.createBinaryExpression(one, zero, lua.SyntaxKind.DivisionOperator); } else { const math = lua.createIdentifier("math"); const huge = lua.createStringLiteral("huge"); return lua.createTableIndexExpression(math, huge, node); } case "globalThis": return lua.createIdentifier("_G", node, (0, symbols_1.getIdentifierSymbolId)(context, node, symbol), "globalThis"); } } const builtinErrorTypeNames = new Set([ "Error", "ErrorConstructor", "RangeError", "RangeErrorConstructor", "ReferenceError", "ReferenceErrorConstructor", "SyntaxError", "SyntaxErrorConstructor", "TypeError", "TypeErrorConstructor", "URIError", "URIErrorConstructor", ]); function checkForLuaLibType(context, type) { const symbol = type.symbol; if (!symbol || symbol.parent) return; const name = symbol.name; switch (name) { case "Map": case "MapConstructor": (0, lualib_1.importLuaLibFeature)(context, lualib_1.LuaLibFeature.Map); return; case "Set": case "SetConstructor": (0, lualib_1.importLuaLibFeature)(context, lualib_1.LuaLibFeature.Set); return; case "WeakMap": case "WeakMapConstructor": (0, lualib_1.importLuaLibFeature)(context, lualib_1.LuaLibFeature.WeakMap); return; case "WeakSet": case "WeakSetConstructor": (0, lualib_1.importLuaLibFeature)(context, lualib_1.LuaLibFeature.WeakSet); return; case "Promise": case "PromiseConstructor": (0, lualib_1.importLuaLibFeature)(context, lualib_1.LuaLibFeature.Promise); return; } if (builtinErrorTypeNames.has(name)) { (0, lualib_1.importLuaLibFeature)(context, lualib_1.LuaLibFeature.Error); } } function tryGetStandardLibrarySymbolOfType(context, type) { if (type.isUnionOrIntersection()) { for (const subType of type.types) { const symbol = tryGetStandardLibrarySymbolOfType(context, subType); if (symbol) return symbol; } } else if ((0, typescript_1.isStandardLibraryType)(context, type, undefined)) { return type.symbol; } return undefined; } //# sourceMappingURL=index.js.map