/** * Domain definitions for deterministic scene logic. * * A domain is a finite set of geometry subjects extracted from a scene. * Domains are the ground over which quantifiers range. * * Invariant: every domain is enumerable and closed within a single * materialized GeometryWorld. No domain may silently default to an * empty set; empty domains must be reported explicitly. */ import type { ImhotepId, SubjectKind } from './types.js' // --------------------------------------------------------------------------- // Domain Descriptor // --------------------------------------------------------------------------- export interface DomainDescriptor { domainId: ImhotepId kind: DomainKind selector?: string parentVar?: string subjectKind?: SubjectKind } export type DomainKind = | 'elements' | 'descendants' | 'lineBoxes' | 'textRuns' | 'fragments' | 'frames' | 'custom' // --------------------------------------------------------------------------- // Domain Value (materialized) // --------------------------------------------------------------------------- export interface DomainValue { domainId: ImhotepId /** Stable numeric subject ids, stored as a flat array for fast iteration. */ subjectIds: Uint32Array /** Source selector or domain expression that produced this set. */ provenance: string /** If true, the domain is known to be complete for the scene. */ closed: boolean } // --------------------------------------------------------------------------- // Built-in Domain Functions // --------------------------------------------------------------------------- export interface DomainFunctions { /** Select elements matching a CSS selector. */ elements(selector: string): DomainDescriptor /** Select descendants of a bound parent variable matching a selector. */ descendants(parentVar: string, selector: string): DomainDescriptor /** Select line boxes for a given text node subject. */ lineBoxes(textNodeId: ImhotepId): DomainDescriptor /** Select text runs for a given text node subject. */ textRuns(textNodeId: ImhotepId): DomainDescriptor /** Select fragment boxes for a given subject. */ fragments(subjectId: ImhotepId): DomainDescriptor /** Select frames of a given kind. */ frames(frameKind: string): DomainDescriptor } // --------------------------------------------------------------------------- // Domain Enumeration Result // --------------------------------------------------------------------------- export interface DomainEnumeration { domainId: ImhotepId subjectIds: Uint32Array empty: boolean diagnostic?: DomainDiagnostic } export interface DomainDiagnostic { code: string message: string domainId: ImhotepId } // --------------------------------------------------------------------------- // Default Domain Registry Implementation // --------------------------------------------------------------------------- export class DomainRegistry { private registry = new Map() register(descriptor: DomainDescriptor): void { this.registry.set(descriptor.domainId, descriptor) } lookup(domainId: ImhotepId): DomainDescriptor | undefined { return this.registry.get(domainId) } list(): DomainDescriptor[] { return Array.from(this.registry.values()) } clear(): void { this.registry.clear() } } // Global default instance for backward compatibility. const globalDomainRegistry = new DomainRegistry() export function registerDomain(descriptor: DomainDescriptor): void { globalDomainRegistry.register(descriptor) } export function lookupDomain(domainId: ImhotepId): DomainDescriptor | undefined { return globalDomainRegistry.lookup(domainId) } export function listDomains(): DomainDescriptor[] { return globalDomainRegistry.list() } export function clearDomainRegistry(): void { globalDomainRegistry.clear() } // --------------------------------------------------------------------------- // Domain Factory // --------------------------------------------------------------------------- export function createElementsDomain( domainId: ImhotepId, selector: string, ): DomainDescriptor { return { domainId, kind: 'elements', selector, } } export function createDescendantsDomain( domainId: ImhotepId, parentVar: string, selector: string, ): DomainDescriptor { return { domainId, kind: 'descendants', parentVar, selector, } } export function createLineBoxesDomain( domainId: ImhotepId, textNodeId: ImhotepId, ): DomainDescriptor { return { domainId, kind: 'lineBoxes', selector: textNodeId, } } export function createTextRunsDomain( domainId: ImhotepId, textNodeId: ImhotepId, ): DomainDescriptor { return { domainId, kind: 'textRuns', selector: textNodeId, } } export function createFragmentsDomain( domainId: ImhotepId, subjectId: ImhotepId, ): DomainDescriptor { return { domainId, kind: 'fragments', selector: subjectId, } } export function createFramesDomain( domainId: ImhotepId, frameKind: string, ): DomainDescriptor { return { domainId, kind: 'frames', selector: frameKind, } } // --------------------------------------------------------------------------- // Domain Value Factory // --------------------------------------------------------------------------- export function createDomainValue( domainId: ImhotepId, subjectIds: Uint32Array, provenance: string, closed = true, ): DomainValue { return { domainId, subjectIds, provenance, closed, } }