@kipper/target-js
Version:
The JavaScript target for the Kipper compiler 🦊
340 lines • 18.6 kB
JavaScript
"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