UNPKG

js-moi-manifest

Version:

Module to encode and decode MOI Logic Engine input and output.

202 lines (173 loc) 7.16 kB
import { ErrorCode, ErrorUtils } from "js-moi-utils"; import type { LogicManifest } from "../types/manifest"; import { ContextStateMatrix } from "./context-state-matrix"; /** * This class represents a descriptor for elements in the logic manifest. */ export class ElementDescriptor { protected stateMatrix: ContextStateMatrix; protected elements: Map<number, LogicManifest.Element> = new Map(); protected callSites: Map<string, LogicManifest.CallSite> = new Map(); protected classDefs: Map<string, number> = new Map(); protected methodDefs: Map<string, LogicManifest.MethodDef> = new Map(); protected eventsDefs = new Map<string, LogicManifest.EventDef>(); constructor(elements: LogicManifest.Element[]) { this.stateMatrix = new ContextStateMatrix(elements); // Populate the maps for elements, call sites, class and method definitions. for (const element of elements) { this.elements.set(element.ptr, element); switch (element.kind) { case "class": const classData = element.data as LogicManifest.Class; this.classDefs.set("class." + classData.name, element.ptr); break; case "method": const methodData = element.data as LogicManifest.Method; const methodDef: LogicManifest.MethodDef = { ptr: element.ptr, class: methodData.class, }; this.methodDefs.set(methodData.name, methodDef); break; case "callable": const routineData = element.data as LogicManifest.Routine; const callsite: LogicManifest.CallSite = { ptr: element.ptr, kind: routineData.kind, }; this.callSites.set(routineData.name, callsite); break; case "event": const eventData = element.data as LogicManifest.Event; this.eventsDefs.set(eventData.name, { ptr: element.ptr, topics: eventData.topics }); break; default: break; } } } /** * Retrieves the state matrix associated with the ElementDescriptor. * * @returns {ContextStateMatrix} The state matrix. */ public getStateMatrix(): ContextStateMatrix { return this.stateMatrix; } /** * Retrieves the map of elements associated with the ElementDescriptor. * * @returns {Map<number, LogicManifest.Element>} The elements map. */ public getElements(): Map<number, LogicManifest.Element> { return this.elements; } /** * Retrieves the map of call sites associated with the ElementDescriptor. * * @returns {Map<string, CallSite>} The call sites map. */ public getCallsites(): Map<string, LogicManifest.CallSite> { return this.callSites; } /** * Retrieves the map of class definitions associated with the ElementDescriptor. * * @returns {Map<string, number>} The class definitions map. */ public getClassDefs(): Map<string, number> { return this.classDefs; } public getEvents(): Map<string, LogicManifest.EventDef> { return this.eventsDefs; } /** * Retrieves the map of method definitions associated with the ElementDescriptor. * * @returns {Map<string, MethodDef>} The method definitions map. */ public getMethodDefs(): Map<string, LogicManifest.MethodDef> { return this.methodDefs; } /** * Retrieves the methods of a class based on the given class name. * * @param {string} className - The name of the class. * @returns {Map<string, LogicManifest.Method>} The methods of the class. * @throws {Error} if the class name is invalid. */ public getClassMethods(className: string): Map<string, LogicManifest.Method> { const classPtr = this.classDefs.get(className); if (classPtr === undefined) { return ErrorUtils.throwError(`Invalid class name: ${className}`, ErrorCode.INVALID_ARGUMENT); } const classMethods: Map<string, LogicManifest.Method> = new Map(); this.methodDefs.forEach((method, methodName) => { if (method.class === className) { const element = this.elements.get(method.ptr); classMethods.set(methodName, element.data as LogicManifest.Method); } }); return classMethods; } /** * Retrieves the element from the logic manifest based on the given * routine name. * * @param {string} routineName - The name of the routine. * @returns {LogicManifest.Element} The routine element. * @throws {Error} if the routine name is invalid. */ public getRoutineElement(routineName: string): LogicManifest.Element { const callsite = this.callSites.get(routineName); if (!callsite) { return ErrorUtils.throwError(`Invalid routine name: ${routineName}`, ErrorCode.INVALID_ARGUMENT); } return this.elements.get(callsite.ptr); } /** * Retrieves the element from the logic manifest based on the given * class name. * * @returns {LogicManifest.Element} The class element. * @throws {Error} if the class name is invalid. */ public getClassElement(className: string): LogicManifest.Element { const ptr = this.classDefs.get(className); if (ptr === undefined) { return ErrorUtils.throwError(`Invalid routine name: ${className}`, ErrorCode.INVALID_ARGUMENT); } return this.elements.get(ptr); } /** * Retrieves the element from the logic manifest based on the given * method name. * * @param {string} methodName - The name of the method. * @returns {LogicManifest.Element} The method element. * @throws {Error} if the method name is invalid. */ public getMethodElement(methodName: string): LogicManifest.Element { const methodDef = this.methodDefs.get(methodName); if (!methodDef) { return ErrorUtils.throwError(`Invalid routine name: ${methodName}`, ErrorCode.INVALID_ARGUMENT); } return this.elements.get(methodDef.ptr); } /** * Retrieves the element from the logic manifest based on the given * event name. * * @param {string} eventName - The name of the event. * @returns {LogicManifest.Element<LogicManifest.Event>} The event element. * * @throws {Error} if the event name is invalid. */ public getEventElement(eventName: string) { const eventDef = this.eventsDefs.get(eventName); if (!eventDef) { return ErrorUtils.throwError(`Invalid event name: ${eventName}`, ErrorCode.INVALID_ARGUMENT); } return this.elements.get(eventDef.ptr) as LogicManifest.Element<LogicManifest.Event>; } }