UNPKG

@kipper/target-js

Version:

The JavaScript target for the Kipper compiler 🦊

340 lines • 18.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.JavaScriptTargetCodeGenerator = void 0; const tslib_1 = require("tslib"); const core_1 = require("@kipper/core"); const core_2 = require("@kipper/core"); const tools_1 = require("./tools"); const index_1 = require("./index"); function removeBrackets(lines) { return lines.slice(1, lines.length - 1); } class JavaScriptTargetCodeGenerator extends core_2.KipperTargetCodeGenerator { constructor() { super(...arguments); this.setUp = (programCtx) => tslib_1.__awaiter(this, void 0, void 0, function* () { return [ [`/* Generated from '${programCtx.fileName}' by the Kipper Compiler v${index_1.version} */`], ['"use strict"', ";"], ["// @ts-ignore"], [ 'var __kipperGlobalScope = typeof __kipperGlobalScope !== "undefined" ? __kipperGlobalScope : typeof' + ' globalThis !== "undefined" ?' + " globalThis : typeof" + ' window !== "undefined" ?' + ' window : typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : {}', ";", ], ["// @ts-ignore"], ["var __kipper = __kipperGlobalScope.__kipper = __kipperGlobalScope.__kipper || __kipper || {}", ";"], [ '__kipper.TypeError = __kipper.TypeError || (class KipperTypeError extends TypeError { constructor(msg) { super(msg); this.name="TypeError"; }})', ";", ], [ '__kipper.IndexError = __kipper.IndexError || (class KipperIndexError extends Error { constructor(msg) { super(msg); this.name="IndexError"; }})', ";", ], ]; }); this.wrapUp = (programCtx) => tslib_1.__awaiter(this, void 0, void 0, function* () { return []; }); this.compoundStatement = (node) => tslib_1.__awaiter(this, void 0, void 0, function* () { let blockItem = []; for (let child of node.children) { const childCode = yield child.translateCtxAndChildren(); blockItem = blockItem.concat(childCode); } return [["{"], ...(0, tools_1.indentLines)(blockItem), ["}"]]; }); this.ifStatement = (node) => tslib_1.__awaiter(this, void 0, void 0, function* () { const semanticData = node.getSemanticData(); let condition = yield semanticData.condition.translateCtxAndChildren(); let statement = yield semanticData.ifBranch.translateCtxAndChildren(); if (semanticData.ifBranch instanceof core_2.CompoundStatement) { statement = removeBrackets(statement); } else { statement = (0, tools_1.indentLines)(statement); } let baseCode = [ ["if", " ", "(", ...condition, ")", " ", "{"], ...statement, ["}", " "], ]; if (!semanticData.elseBranch) { return baseCode; } let secondBranchIsCompoundStatement = semanticData.elseBranch instanceof core_2.CompoundStatement; let secondBranchIsElseIf = semanticData.elseBranch instanceof core_2.IfStatement; let secondBranchIsElse = !secondBranchIsElseIf; let secondCondition = null; let secondBranch = null; if (semanticData.elseBranch) { secondBranch = yield semanticData.elseBranch.translateCtxAndChildren(); if (secondBranchIsElseIf) { secondCondition = ["else", " ", ...secondBranch[0]]; secondBranch = secondBranch.slice(1, secondBranch.length); } else { secondCondition = ["else"]; } if (secondBranchIsCompoundStatement) { secondBranch = removeBrackets(secondBranch); } else if (secondBranchIsElse) { secondBranch = (0, tools_1.indentLines)(secondBranch); } } return [ ...baseCode.slice(0, baseCode.length - 1), ["}", " ", ...(secondCondition !== null && secondCondition !== void 0 ? secondCondition : []), ...(secondBranchIsCompoundStatement ? [" ", "{"] : [])], ...(secondBranch !== null && secondBranch !== void 0 ? secondBranch : []), ...(secondBranchIsCompoundStatement ? [["}", " "]] : []), ]; }); this.switchStatement = (node) => tslib_1.__awaiter(this, void 0, void 0, function* () { return []; }); this.expressionStatement = (node) => tslib_1.__awaiter(this, void 0, void 0, function* () { let exprCode = []; for (let child of node.children) { const childCode = yield child.translateCtxAndChildren(); exprCode.push(childCode.concat(";")); } return exprCode; }); this.doWhileLoopStatement = (node) => tslib_1.__awaiter(this, void 0, void 0, function* () { return []; }); this.whileLoopStatement = (node) => tslib_1.__awaiter(this, void 0, void 0, function* () { const semanticData = node.getSemanticData(); const condition = yield semanticData.loopCondition.translateCtxAndChildren(); const statement = yield semanticData.loopBody.translateCtxAndChildren(); const isCompound = semanticData.loopBody instanceof core_2.CompoundStatement; return [ ["while", " ", "(", ...condition, ")", " ", isCompound ? "{" : ""], ...(isCompound ? (0, tools_1.removeBraces)(statement) : (0, tools_1.indentLines)(statement)), [isCompound ? "}" : ""], ]; }); this.forLoopStatement = (node) => tslib_1.__awaiter(this, void 0, void 0, function* () { const semanticData = node.getSemanticData(); let forDeclaration = semanticData.forDeclaration ? yield semanticData.forDeclaration.translateCtxAndChildren() : []; const condition = semanticData.loopCondition ? yield semanticData.loopCondition.translateCtxAndChildren() : []; const forIterationExp = semanticData.forIterationExp ? yield semanticData.forIterationExp.translateCtxAndChildren() : []; let isCompound = semanticData.loopBody instanceof core_2.CompoundStatement; let loopBody = yield semanticData.loopBody.translateCtxAndChildren(); if (isCompound) { loopBody = removeBrackets(loopBody); } else { loopBody = (0, tools_1.indentLines)(loopBody); } forDeclaration = ((semanticData.forDeclaration instanceof core_1.VariableDeclaration ? forDeclaration[0] : [...forDeclaration, ";"])); return [ [ "for", " ", "(", ...forDeclaration, " ", ...condition, ";", " ", ...forIterationExp, ")", " ", ...(isCompound ? ["{"] : []), ], ...loopBody, isCompound ? ["}"] : [], ]; }); this.jumpStatement = (node) => tslib_1.__awaiter(this, void 0, void 0, function* () { const semanticData = node.getSemanticData(); return [semanticData.jmpType === "break" ? ["break", ";"] : ["continue", ";"]]; }); this.returnStatement = (node) => tslib_1.__awaiter(this, void 0, void 0, function* () { var _a; const semanticData = node.getSemanticData(); const returnValue = yield ((_a = semanticData.returnValue) === null || _a === void 0 ? void 0 : _a.translateCtxAndChildren()); return [["return", ...(returnValue ? [" ", ...returnValue] : []), ";"]]; }); this.parameterDeclaration = (node) => tslib_1.__awaiter(this, void 0, void 0, function* () { return []; }); this.functionDeclaration = (node) => tslib_1.__awaiter(this, void 0, void 0, function* () { const semanticData = node.getSemanticData(); const signature = (0, tools_1.getJSFunctionSignature)(node); const functionBody = yield semanticData.functionBody.translateCtxAndChildren(); return [[(0, tools_1.createJSFunctionSignature)(signature)], ...functionBody]; }); this.variableDeclaration = (node) => tslib_1.__awaiter(this, void 0, void 0, function* () { const semanticData = node.getSemanticData(); const storage = semanticData.storageType === "const" ? "const" : "let"; const assign = semanticData.value ? yield semanticData.value.translateCtxAndChildren() : []; return [[storage, " ", semanticData.identifier, ...(assign.length > 0 ? [" ", "=", " ", ...assign] : []), ";"]]; }); this.numberPrimaryExpression = (node) => tslib_1.__awaiter(this, void 0, void 0, function* () { const semanticData = node.getSemanticData(); return [ semanticData.value, ]; }); this.arrayLiteralExpression = (node) => tslib_1.__awaiter(this, void 0, void 0, function* () { return []; }); this.identifierPrimaryExpression = (node) => tslib_1.__awaiter(this, void 0, void 0, function* () { const semanticData = node.getSemanticData(); let identifier = semanticData.identifier; if (!(semanticData.ref.refTarget instanceof core_2.ScopeDeclaration)) { identifier = index_1.TargetJS.getBuiltInIdentifier(semanticData.ref.refTarget); } return [identifier]; }); this.memberAccessExpression = (node) => tslib_1.__awaiter(this, void 0, void 0, function* () { const semanticData = node.getSemanticData(); const object = yield semanticData.objectLike.translateCtxAndChildren(); switch (semanticData.accessType) { case "dot": return []; case "bracket": { const keyOrIndex = yield semanticData.propertyIndexOrKeyOrSlice.translateCtxAndChildren(); const sliceIdentifier = index_1.TargetJS.getBuiltInIdentifier("index"); return [sliceIdentifier, "(", ...object, ", ", ...keyOrIndex, ")"]; } case "slice": { const slice = semanticData.propertyIndexOrKeyOrSlice; const start = slice.start ? yield slice.start.translateCtxAndChildren() : "undefined"; const end = slice.end ? yield slice.end.translateCtxAndChildren() : "undefined"; const sliceIdentifier = index_1.TargetJS.getBuiltInIdentifier("slice"); return [sliceIdentifier, "(", ...object, ", ", ...start, ", ", ...end, ")"]; } } }); this.identifierTypeSpecifierExpression = (node) => tslib_1.__awaiter(this, void 0, void 0, function* () { return []; }); this.genericTypeSpecifierExpression = (node) => tslib_1.__awaiter(this, void 0, void 0, function* () { return []; }); this.typeofTypeSpecifierExpression = (node) => tslib_1.__awaiter(this, void 0, void 0, function* () { return []; }); this.stringPrimaryExpression = (node) => tslib_1.__awaiter(this, void 0, void 0, function* () { const semanticData = node.getSemanticData(); return [`${semanticData.quotationMarks}${semanticData.value}${semanticData.quotationMarks}`]; }); this.fStringPrimaryExpression = (node) => tslib_1.__awaiter(this, void 0, void 0, function* () { return []; }); this.boolPrimaryExpression = (node) => tslib_1.__awaiter(this, void 0, void 0, function* () { return [node.getSemanticData().value]; }); this.tangledPrimaryExpression = (node) => tslib_1.__awaiter(this, void 0, void 0, function* () { return ["(", ...(yield node.children[0].translateCtxAndChildren()), ")"]; }); this.voidOrNullOrUndefinedPrimaryExpression = (node) => tslib_1.__awaiter(this, void 0, void 0, function* () { const constantIdentifier = node.getSemanticData().constantIdentifier; return [constantIdentifier === "void" ? "void(0)" : constantIdentifier]; }); this.incrementOrDecrementPostfixExpression = (node) => tslib_1.__awaiter(this, void 0, void 0, function* () { const semanticData = node.getSemanticData(); const operandCode = yield semanticData.operand.translateCtxAndChildren(); return [...operandCode, semanticData.operator]; }); this.functionCallExpression = (node) => tslib_1.__awaiter(this, void 0, void 0, function* () { const semanticData = node.getSemanticData(); const func = node.getTypeSemanticData().func; const identifier = func instanceof core_2.ScopeFunctionDeclaration ? func.identifier : index_1.TargetJS.getBuiltInIdentifier(func.identifier); let args = []; for (const i of semanticData.args) { const arg = yield i.translateCtxAndChildren(); args = args.concat(arg.concat(", ")); } args = args.slice(0, -1); return [identifier, "(", ...args, ")"]; }); this.incrementOrDecrementUnaryExpression = (node) => tslib_1.__awaiter(this, void 0, void 0, function* () { const semanticData = node.getSemanticData(); const operandCode = yield semanticData.operand.translateCtxAndChildren(); return [semanticData.operator, ...operandCode]; }); this.operatorModifiedUnaryExpression = (node) => tslib_1.__awaiter(this, void 0, void 0, function* () { const semanticData = node.getSemanticData(); const operator = semanticData.operator; const operand = semanticData.operand; return [operator].concat(yield operand.translateCtxAndChildren()); }); this.castOrConvertExpression = (node) => tslib_1.__awaiter(this, void 0, void 0, function* () { const semanticData = node.getSemanticData(); const typeData = node.getTypeSemanticData(); const exp = yield semanticData.exp.translateCtxAndChildren(); const originalType = semanticData.exp.getTypeSemanticData().evaluatedType.getCompilableType(); const destType = typeData.castType.getCompilableType(); if (originalType === destType) { return exp; } else { const func = index_1.TargetJS.getBuiltInIdentifier((0, core_2.getConversionFunctionIdentifier)(originalType, destType)); return [func, "(", ...exp, ")"]; } }); this.multiplicativeExpression = (node) => tslib_1.__awaiter(this, void 0, void 0, function* () { const semanticData = node.getSemanticData(); const exp1 = yield semanticData.leftOp.translateCtxAndChildren(); const exp2 = yield semanticData.rightOp.translateCtxAndChildren(); return [...exp1, " ", semanticData.operator, " ", ...exp2]; }); this.additiveExpression = (node) => tslib_1.__awaiter(this, void 0, void 0, function* () { const semanticData = node.getSemanticData(); const exp1 = yield semanticData.leftOp.translateCtxAndChildren(); const exp2 = yield semanticData.rightOp.translateCtxAndChildren(); return [...exp1, " ", semanticData.operator, " ", ...exp2]; }); this.translateOperatorExpressionWithOperands = (node) => tslib_1.__awaiter(this, void 0, void 0, function* () { const semanticData = node.getSemanticData(); const exp1 = yield semanticData.leftOp.translateCtxAndChildren(); const exp2 = yield semanticData.rightOp.translateCtxAndChildren(); let operator = semanticData.operator; if (operator === "==" || operator === "!=") { operator = semanticData.operator + "="; } return [...exp1, " ", operator, " ", ...exp2]; }); this.relationalExpression = (node) => tslib_1.__awaiter(this, void 0, void 0, function* () { return yield this.translateOperatorExpressionWithOperands(node); }); this.equalityExpression = (node) => tslib_1.__awaiter(this, void 0, void 0, function* () { return yield this.translateOperatorExpressionWithOperands(node); }); this.logicalAndExpression = (node) => tslib_1.__awaiter(this, void 0, void 0, function* () { return yield this.translateOperatorExpressionWithOperands(node); }); this.logicalOrExpression = (node) => tslib_1.__awaiter(this, void 0, void 0, function* () { return yield this.translateOperatorExpressionWithOperands(node); }); this.conditionalExpression = (node) => tslib_1.__awaiter(this, void 0, void 0, function* () { return []; }); this.assignmentExpression = (node) => tslib_1.__awaiter(this, void 0, void 0, function* () { const semanticData = node.getSemanticData(); let identifier = semanticData.identifier; if (!(semanticData.assignTarget.refTarget instanceof core_2.ScopeDeclaration)) { identifier = index_1.TargetJS.getBuiltInIdentifier(identifier); } const assignExp = yield semanticData.value.translateCtxAndChildren(); return [identifier, " ", semanticData.operator, " ", ...assignExp]; }); } } exports.JavaScriptTargetCodeGenerator = JavaScriptTargetCodeGenerator; //# sourceMappingURL=code-generator.js.map