v1.1.0: pooled runtime, 959 tests, production hardening (0 squash)
This commit is contained in:
@@ -0,0 +1,223 @@
|
||||
/**
|
||||
* 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<ImhotepId, DomainDescriptor>()
|
||||
|
||||
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,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user