UNPKG

@kipper/target-js

Version:

The JavaScript target for the Kipper compiler 🦊

664 lines • 39 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 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