@kipper/target-js
Version:
The JavaScript target for the Kipper compiler 🦊
664 lines • 39 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 tools_1 = require("./tools");
const index_1 = require("./index");
const runtime_types_1 = require("./runtime-types");
function removeBrackets(lines) {
return lines.slice(1, lines.length - 1);
}
class JavaScriptTargetCodeGenerator extends core_1.KipperTargetCodeGenerator {
constructor() {
super(...arguments);
this.setUp = (programCtx, requirements) => tslib_1.__awaiter(this, void 0, void 0, function* () {
const inlinedRequirements = requirements.map((req) => req.join("")).join(", ");
return [
[`/* Generated from '${programCtx.fileName}' by the Kipper Compiler v${index_1.version} */`],
['"use strict"', ";"],
["// @ts-ignore"],
[
'var __globalScope = typeof __globalScope !== "undefined" ? __globalScope : typeof' +
' globalThis !== "undefined" ?' +
" globalThis : typeof" +
' window !== "undefined" ?' +
' window : typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : {}',
";",
],
["// @ts-ignore"],
[
"var __createKipper = () => {" +
" if (__globalScope.__kipper || __kipper) { return undefined; }" +
" class KipperError extends Error { constructor(msg) { super(msg); this.name='KipError'; }};" +
" class KipperNotImplementedError extends KipperError { " +
" constructor(msg) { super(msg); this.name = 'KipNotImplementedError'; } " +
" }" +
" class KipperType {" +
" constructor(name, fields, methods, baseType = null) " +
" { this.name = name; this.fields = fields; this.methods = methods; this.baseType = baseType; }" +
" isCompatibleWith(obj) { return this.name === obj.name; }" +
" };" +
" class KipperGenericType extends KipperType {" +
" constructor(name, fields, methods, genericArgs, baseType = null) " +
" { super(name, fields, methods, baseType); this.genericArgs = genericArgs; }" +
" isCompatibleWith(obj) { return this.name === obj.name; }" +
" changeGenericTypeArguments(genericArgs) { return new KipperGenericType(this.name, this.fields, this.methods, genericArgs, this.baseType) }" +
" };" +
" const __type_any = new KipperType('any', undefined, undefined);" +
" const __type_null = new KipperType('null', undefined, undefined);" +
" const __type_undefined = new KipperType('undefined', undefined, undefined);" +
" const __type_str = new KipperType('str', undefined, undefined);" +
" const __type_num = new KipperType('num', undefined, undefined);" +
" const __type_bool = new KipperType('bool', undefined, undefined);" +
" const __type_obj = new KipperType('obj', [], []);" +
" const __type_Array = new KipperGenericType('Array', undefined, undefined, {T: __type_any});" +
" const __type_Func = new KipperGenericType('Func', undefined, undefined, {T: [], R: __type_any});" +
" return {" +
" KipperError: KipperError," +
" TypeError: (class KipperTypeError extends KipperError { constructor(msg) { super(msg); this.name = 'KipTypeError'; } })," +
" IndexError: (class KipperIndexError extends KipperError { constructor(msg) { super(msg); this.name = 'KipIndexError'; } })," +
" NotImplementedError: KipperNotImplementedError," +
" Property: class KipperProperty { constructor(name, type) { this.name = name; this.type = type; } }," +
" MethodParameter: class MethodParameter { constructor(name, type) { this.name = name; this.type = type; } }," +
" Method: class KipperMethod { constructor(name, returnType, parameters) { this.name = name; this.returnType = returnType; this.parameters = parameters; } }," +
" Type: KipperType," +
" builtIn: {" +
" any: __type_any," +
" null: __type_null," +
" undefined: __type_undefined," +
" str: __type_str," +
" num: __type_num," +
" bool: __type_bool," +
" obj: __type_obj," +
" Array: __type_Array," +
" Func: __type_Func," +
" }," +
" assignTypeMeta: (value, typeMeta) => Object.assign(value, { __kipType: typeMeta })," +
" typeOf: (value) => {" +
" const prim = typeof value;" +
" switch (prim) {" +
" case 'undefined': return __kipper.builtIn.undefined;" +
" case 'string': return __kipper.builtIn.str;" +
" case 'number': return __kipper.builtIn.num;" +
" case 'boolean': return __kipper.builtIn.bool;" +
" case 'function': {" +
" return '__kipType' in value ? value.__kipType : __kipper.builtIn.Func;" +
" }" +
" case 'symbol':" +
" case 'bigint':" +
" case 'object': {" +
" if (value === null) return __kipper.builtIn.null;" +
" if (Array.isArray(value)) {" +
" return '__kipType' in value ? value.__kipType : __kipper.builtIn.Array;" +
" }" +
" const prot = Object.getPrototypeOf(value);" +
" if (prot && prot.constructor !== Object) {" +
" return prot.constructor;" +
" }" +
" return __kipper.builtIn.obj;" +
" }" +
" }" +
" }," +
" matches: (value, pattern) => {" +
" const primTypes = [ 'str', 'num', 'bool', 'null', 'undefined' ];" +
" const genTypes = [ 'Array', 'Func' ];" +
" if (pattern.fields && Array.isArray(pattern.fields)) {" +
" for (const field of pattern.fields) {" +
" const fieldName = field.name;" +
" const fieldType = field.type;" +
" const nameIsInType = fieldName in value;" +
" if (!nameIsInType) {" +
" return false;" +
" }" +
" const fieldValue = value[fieldName];" +
" const isSameType = __kipper.typeOf(fieldValue) === field.type;" +
" if (primTypes.includes(field.type.name) && !isSameType) {" +
" return false;" +
" }" +
" if (genTypes.includes(fieldType.name)) {" +
" throw new KipperNotImplementedError(\"Matches does not yet support the 'Array' and 'Func' types\");" +
" }" +
" if (!primTypes.includes(fieldType.name)) {" +
" if (!__kipper.matches(fieldValue, fieldType)) {" +
" return false;" +
" }" +
" }" +
" }" +
" }" +
" if (pattern.methods && Array.isArray(pattern.methods)) {" +
" for (const field of pattern.methods) {" +
" const fieldName = field.name;" +
" const fieldReturnType = field.returnType;" +
" const parameters = field.parameters;" +
" const nameIsInType = fieldName in value;" +
" if (!nameIsInType) {" +
" return false;" +
" }" +
" const fieldValue = value[fieldName];" +
" const isSameType = fieldReturnType === fieldValue.__kipType.genericArgs.R;" +
" if (!isSameType) {" +
" return false;" +
" }" +
" const methodParameters = fieldValue.__kipType.genericArgs.T;" +
" if (parameters.length !== methodParameters.length) {" +
" return false;" +
" }" +
" let count = 0;" +
" for (let param of parameters) {" +
" if (param.type.name !== methodParameters[count].name) {" +
" return false;" +
" }" +
" count++;" +
" }" +
" }" +
" }" +
" return true;" +
" }," +
inlinedRequirements +
" };" +
"};",
],
["var __kipper = __globalScope.__kipper = (__globalScope.__kipper || __createKipper());"],
];
});
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_1.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_1.CompoundStatement;
let secondBranchIsElseIf = semanticData.elseBranch instanceof core_1.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.doWhileLoopIterationStatement = (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_1.CompoundStatement;
return [
["do", " ", isCompound ? "{" : ""],
...(isCompound ? (0, tools_1.removeBraces)(statement) : (0, tools_1.indentLines)(statement)),
[isCompound ? "} " : "", "while", " ", "(", ...condition, ")"],
];
});
this.whileLoopIterationStatement = (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_1.CompoundStatement;
return [
["while", " ", "(", ...condition, ")", " ", isCompound ? "{" : ""],
...(isCompound ? (0, tools_1.removeBraces)(statement) : (0, tools_1.indentLines)(statement)),
[isCompound ? "}" : ""],
];
});
this.forLoopIterationStatement = (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_1.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* () {
const semanticData = node.getSemanticData();
return [[`${semanticData.identifier}`]];
});
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.interfaceDeclaration = (node) => tslib_1.__awaiter(this, void 0, void 0, function* () {
const runtimeInterfaceType = yield runtime_types_1.RuntimeTypesGenerator.generateInterfaceRuntimeType(node);
return [...runtimeInterfaceType];
});
this.interfacePropertyDeclaration = (node) => tslib_1.__awaiter(this, void 0, void 0, function* () {
return [];
});
this.interfaceMethodDeclaration = (node) => tslib_1.__awaiter(this, void 0, void 0, function* () {
return [];
});
this.classDeclaration = (node) => tslib_1.__awaiter(this, void 0, void 0, function* () {
const semanticData = node.getSemanticData();
const identifier = semanticData.identifier;
const classMembers = semanticData.classMembers;
const constructor = semanticData.constructorDeclaration;
const translatedMembers = yield Promise.all(classMembers.map((member) => tslib_1.__awaiter(this, void 0, void 0, function* () {
return yield member.translateCtxAndChildren();
})));
const translatedConstructor = constructor ? yield constructor.translateCtxAndChildren() : [];
return [
["class", " ", identifier, " ", "{"],
...(0, tools_1.indentLines)(translatedMembers.flat()),
...(0, tools_1.indentLines)(translatedConstructor),
["}"],
];
});
this.newInstantiationExpression = (node) => tslib_1.__awaiter(this, void 0, void 0, function* () {
const semanticData = node.getSemanticData();
const identifier = semanticData.class.getSemanticData().rawType.identifier;
const args = semanticData.args;
const translatedArgs = args.map((arg) => tslib_1.__awaiter(this, void 0, void 0, function* () {
return yield arg.translateCtxAndChildren();
}));
const finishedArgs = yield Promise.all(translatedArgs);
return ["new", " ", identifier, "(", ...finishedArgs.join(", "), ")"];
});
this.classPropertyDeclaration = (node) => tslib_1.__awaiter(this, void 0, void 0, function* () {
const semanticData = node.getSemanticData();
const identifier = semanticData.identifier;
return [`${identifier};`];
});
this.classMethodDeclaration = (node) => tslib_1.__awaiter(this, void 0, void 0, function* () {
const semanticData = node.getSemanticData();
const identifier = semanticData.identifier;
const params = semanticData.params;
const body = semanticData.functionBody;
const concatParams = () => tslib_1.__awaiter(this, void 0, void 0, function* () {
const translatedParams = yield Promise.all(params.map((param) => tslib_1.__awaiter(this, void 0, void 0, function* () {
return yield param.translateCtxAndChildren();
})));
return translatedParams.join(", ");
});
return [[identifier, `(`, yield concatParams(), `)`], ...(yield body.translateCtxAndChildren())];
});
this.classConstructorDeclaration = (node) => tslib_1.__awaiter(this, void 0, void 0, function* () {
const semanticData = node.getSemanticData();
const params = semanticData.params;
const body = semanticData.functionBody;
let processedParams = (yield Promise.all(params.map((param) => tslib_1.__awaiter(this, void 0, void 0, function* () {
return yield param.translateCtxAndChildren();
}))))
.map((param) => [...param.flat(), ", "])
.flat();
processedParams.pop();
return [["constructor", "(", ...processedParams, ")"], ...(yield body.translateCtxAndChildren())];
});
this.numberPrimaryExpression = (node) => tslib_1.__awaiter(this, void 0, void 0, function* () {
const semanticData = node.getSemanticData();
return [
semanticData.value,
];
});
this.arrayPrimaryExpression = (node) => tslib_1.__awaiter(this, void 0, void 0, function* () {
const values = node.getSemanticData().value;
const valueType = node.getTypeSemanticData().valueType;
const valueTypeIdentifier = index_1.TargetJS.getRuntimeType(valueType);
const translatedValues = yield Promise.all(values.map((value, i) => tslib_1.__awaiter(this, void 0, void 0, function* () {
const exp = yield value.translateCtxAndChildren();
return [...exp, i + 1 === values.length ? "" : ", "];
})));
return [
index_1.TargetJS.getBuiltInIdentifier("assignTypeMeta"),
"(",
"[",
...translatedValues.flat(),
"]",
",",
index_1.TargetJS.getBuiltInIdentifier("builtIn.Array.changeGenericTypeArguments"),
"(",
`{T: ${valueTypeIdentifier}}`,
")",
")",
];
});
this.objectPrimaryExpression = (node) => tslib_1.__awaiter(this, void 0, void 0, function* () {
const semanticData = node.getSemanticData();
const keyValuePairs = semanticData.keyValuePairs;
const translatedKeyValuePairs = yield Promise.all(keyValuePairs.map((pair) => tslib_1.__awaiter(this, void 0, void 0, function* () {
return [...(yield pair.translateCtxAndChildren()), ",", "\n"];
})));
return ["{", "\n", ...(0, tools_1.indentLines)(translatedKeyValuePairs).flat(), "}"];
});
this.objectProperty = (node) => tslib_1.__awaiter(this, void 0, void 0, function* () {
const expression = node.getSemanticData().value;
const identifier = node.getSemanticData().identifier;
const translatedExpression = (yield expression.translateCtxAndChildren()).join("");
return [identifier, ": ", translatedExpression];
});
this.identifierPrimaryExpression = (node) => tslib_1.__awaiter(this, void 0, void 0, function* () {
const refTarget = node.getSemanticData().ref;
let identifier = refTarget.isBuiltIn
? index_1.TargetJS.getBuiltInIdentifier(refTarget.builtInStructure)
: refTarget.identifier;
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 [object[0] + "." + semanticData.propertyIndexOrKeyOrSlice];
case "bracket": {
const keyOrIndex = yield semanticData.propertyIndexOrKeyOrSlice.translateCtxAndChildren();
if (node.parent instanceof core_1.AssignmentExpression) {
return [...object, "[", ...keyOrIndex, "]"];
}
else {
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* () {
const atoms = [];
for (const atom of node.getSemanticData().atoms) {
if (typeof atom === "string") {
atoms.push(atom);
}
else {
atoms.push("${", ...(yield atom.translateCtxAndChildren()), "}");
}
}
return ["`", ...atoms, "`"];
});
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().funcOrExp;
const exp = func instanceof core_1.Expression ? yield func.translateCtxAndChildren() : undefined;
const identifier = func instanceof core_1.ScopeDeclaration
? func.isBuiltIn
? index_1.TargetJS.getBuiltInIdentifier(func.builtInStructure)
: func.identifier
: undefined;
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 ? [identifier] : exp), "(", ...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_1.getConversionFunctionIdentifier)(originalType.identifier, destType.identifier));
return [func, "(", ...exp, ")"];
}
});
this.multiplicativeExpression = (node) => tslib_1.__awaiter(this, void 0, void 0, function* () {
const semanticData = node.getSemanticData();
const stringRepeatFunction = index_1.TargetJS.getBuiltInIdentifier("repeatString");
const exp1 = yield semanticData.leftOp.translateCtxAndChildren();
const exp2 = yield semanticData.rightOp.translateCtxAndChildren();
if (semanticData.leftOp.getTypeSemanticData().evaluatedType === core_1.BuiltInTypes.str) {
return [stringRepeatFunction, "(", ...exp1, ", ", ...exp2, ")"];
}
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.bitwiseOrExpression = (node) => tslib_1.__awaiter(this, void 0, void 0, function* () {
return yield this.translateOperatorExpressionWithOperands(node);
});
this.bitwiseAndExpression = (node) => tslib_1.__awaiter(this, void 0, void 0, function* () {
return yield this.translateOperatorExpressionWithOperands(node);
});
this.bitwiseXorExpression = (node) => tslib_1.__awaiter(this, void 0, void 0, function* () {
return yield this.translateOperatorExpressionWithOperands(node);
});
this.bitwiseShiftExpression = (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* () {
const semanticData = node.getSemanticData();
const condition = yield semanticData.condition.translateCtxAndChildren();
const trueBranch = yield semanticData.trueBranch.translateCtxAndChildren();
const falseBranch = yield semanticData.falseBranch.translateCtxAndChildren();
return [...condition, " ? ", ...trueBranch, " : ", ...falseBranch];
});
this.assignmentExpression = (node) => tslib_1.__awaiter(this, void 0, void 0, function* () {
const semanticData = node.getSemanticData();
const toAssign = yield semanticData.toAssign.translateCtxAndChildren();
const assignExp = yield semanticData.value.translateCtxAndChildren();
return [...toAssign, " ", semanticData.operator, " ", ...assignExp];
});
this.lambdaPrimaryExpression = (node) => tslib_1.__awaiter(this, void 0, void 0, function* () {
const semanticData = node.getSemanticData();
const params = semanticData.params;
const body = semanticData.functionBody;
const funcType = node.getTypeSemanticData().evaluatedType;
const translatedParams = (yield Promise.all(params.map((param) => tslib_1.__awaiter(this, void 0, void 0, function* () {
return yield param.translateCtxAndChildren();
}))))
.map((param) => [...param.flat(), ", "])
.flat();
translatedParams.pop();
const translatedBody = body instanceof core_1.Expression
? yield body.translateCtxAndChildren()
: (yield body.translateCtxAndChildren()).map((line) => [...line, "\n"]).flat();
const paramTypes = funcType.paramTypes.map((type) => index_1.TargetJS.getRuntimeType(type.getCompilableType()));
const returnType = index_1.TargetJS.getRuntimeType(funcType.returnType.getCompilableType());
return [
index_1.TargetJS.getBuiltInIdentifier("assignTypeMeta"),
"(",
"(",
...translatedParams,
") => ",
...(body instanceof core_1.CompoundStatement ? translatedBody.slice() : translatedBody),
",",
index_1.TargetJS.getBuiltInIdentifier("builtIn.Func.changeGenericTypeArguments"),
"(",
`{T: [${paramTypes.join(",")}], R: ${returnType}}`,
")",
")",
];
});
this.typeofExpression = (node) => tslib_1.__awaiter(this, void 0, void 0, function* () {
const semanticData = node.getSemanticData();
const operand = yield semanticData.operand.translateCtxAndChildren();
return [index_1.TargetJS.getBuiltInIdentifier("typeOf"), "(", ...operand, ")"];
});
this.matchesExpression = (node) => tslib_1.__awaiter(this, void 0, void 0, function* () {
const semanticData = node.getSemanticData();
const pattern = semanticData.pattern.getTypeSemanticData();
const translatedExpression = yield semanticData.expression.translateCtxAndChildren();
return [
index_1.TargetJS.getBuiltInIdentifier("matches"),
"(",
...translatedExpression,
", ",
`${index_1.TargetJS.internalInterfacePrefix}_${pattern.storedType.identifier}`,
")",
];
});
this.instanceOfExpression = (node) => tslib_1.__awaiter(this, void 0, void 0, function* () {
const semanticData = node.getSemanticData();
const typeData = node.getTypeSemanticData();
const operand = yield semanticData.operand.translateCtxAndChildren();
const classType = index_1.TargetJS.getRuntimeType(typeData.classType);
return [...operand, " ", "instanceof", " ", classType];
});
}
}
exports.JavaScriptTargetCodeGenerator = JavaScriptTargetCodeGenerator;
//# sourceMappingURL=code-generator.js.map