v1.1.0: pooled runtime, 959 tests, production hardening (0 squash)
This commit is contained in:
@@ -0,0 +1,232 @@
|
||||
/**
|
||||
* Flattened, data-oriented execution IR for first-order logic formulas.
|
||||
*
|
||||
* The hot-path representation stores formulas in parallel typed arrays
|
||||
* indexed by formulaId. No deep nesting exists at runtime; child
|
||||
* relationships are expressed through numeric offsets into the same
|
||||
* flat tables.
|
||||
*
|
||||
* Invariant: every formula referenced by a child pointer is stored in
|
||||
* the same LogicIr instance. The root formula always has id 0.
|
||||
*/
|
||||
|
||||
import type { ImhotepId, SourceOrigin } from './types.js'
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Formula Kinds (must fit in Uint8)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export const FORMULA_KIND_FORALL = 1
|
||||
export const FORMULA_KIND_EXISTS = 2
|
||||
export const FORMULA_KIND_AND = 3
|
||||
export const FORMULA_KIND_OR = 4
|
||||
export const FORMULA_KIND_NOT = 5
|
||||
export const FORMULA_KIND_IMPLIES = 6
|
||||
export const FORMULA_KIND_PREDICATE = 7
|
||||
|
||||
export type FormulaKind =
|
||||
| typeof FORMULA_KIND_FORALL
|
||||
| typeof FORMULA_KIND_EXISTS
|
||||
| typeof FORMULA_KIND_AND
|
||||
| typeof FORMULA_KIND_OR
|
||||
| typeof FORMULA_KIND_NOT
|
||||
| typeof FORMULA_KIND_IMPLIES
|
||||
| typeof FORMULA_KIND_PREDICATE
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Logic IR Tables
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export interface LogicIr {
|
||||
/** Total number of formulas in this IR. */
|
||||
formulaCount: number
|
||||
|
||||
// Formula classification (all Uint8Array)
|
||||
formulaKind: Uint8Array
|
||||
|
||||
// Child pointers (Uint32Array, 0xFFFFFFFF means "none")
|
||||
formulaLeft: Uint32Array
|
||||
formulaRight: Uint32Array
|
||||
|
||||
// Binding region (for quantifiers)
|
||||
// Each quantifier formula references a slice [bindingStart, bindingStart + bindingCount)
|
||||
// in the flat binding table below.
|
||||
bindingStart: Uint32Array
|
||||
bindingCount: Uint8Array
|
||||
|
||||
// Predicate call region (for atomic formulas)
|
||||
// Each predicate formula references a slice [argStart, argStart + argCount)
|
||||
predicateId: Uint32Array
|
||||
argStart: Uint32Array
|
||||
argCount: Uint8Array
|
||||
|
||||
// Origin and proof tracking (Uint32Array)
|
||||
originIndex: Uint32Array
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Flat Binding Table
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export interface BindingTable {
|
||||
/** Number of bindings. */
|
||||
count: number
|
||||
|
||||
// Variable names (string table index)
|
||||
variableNameId: Uint32Array
|
||||
|
||||
// Domain descriptor index
|
||||
domainId: Uint32Array
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Flat Argument Table (for predicate calls)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export interface ArgTable {
|
||||
/** Number of argument terms. */
|
||||
count: number
|
||||
|
||||
// Term kind: 1 = variable, 2 = accessor, 3 = literal number
|
||||
termKind: Uint8Array
|
||||
|
||||
// For variables: binding table index
|
||||
// For accessors: variable binding index
|
||||
// For literals: 0xFFFFFFFF (value stored in literalValue)
|
||||
termRef: Uint32Array
|
||||
|
||||
// For accessors: string table index of property name
|
||||
// For literals: the literal numeric value (reinterpreted as Uint32)
|
||||
termAux: Uint32Array
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Predicate Registry Index
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export interface PredicateIndexEntry {
|
||||
predicateId: number
|
||||
name: string
|
||||
arity: number
|
||||
domainSignature: number[]
|
||||
requiredFacts: string[]
|
||||
}
|
||||
|
||||
export interface PredicateIndex {
|
||||
entries: PredicateIndexEntry[]
|
||||
byName: Map<string, number>
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// String Table (shared across IR tables)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export interface IrStringTable {
|
||||
values: string[]
|
||||
byValue: Map<string, number>
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Evaluation Request
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export interface LogicEvaluationRequest {
|
||||
logicIr: LogicIr
|
||||
bindings: BindingTable
|
||||
args: ArgTable
|
||||
predicates: PredicateIndex
|
||||
strings: IrStringTable
|
||||
rootFormulaId: number
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Builder
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export interface LogicIrBuilder {
|
||||
addFormula(descriptor: LogicFormulaDescriptor): number
|
||||
addBinding(descriptor: LogicBindingDescriptor): number
|
||||
addArg(descriptor: LogicArgDescriptor): number
|
||||
build(): LogicIr
|
||||
}
|
||||
|
||||
export interface LogicFormulaDescriptor {
|
||||
kind: FormulaKind
|
||||
left?: number
|
||||
right?: number
|
||||
bindingStart?: number
|
||||
bindingCount?: number
|
||||
predicateId?: number
|
||||
argStart?: number
|
||||
argCount?: number
|
||||
originIndex?: number
|
||||
}
|
||||
|
||||
export interface LogicBindingDescriptor {
|
||||
variableNameId: number
|
||||
domainId: number
|
||||
}
|
||||
|
||||
export interface LogicArgDescriptor {
|
||||
termKind: number
|
||||
termRef: number
|
||||
termAux: number
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Helper: Create empty Logic IR
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export function createEmptyLogicIr(): LogicIr {
|
||||
return {
|
||||
formulaCount: 0,
|
||||
formulaKind: new Uint8Array(0),
|
||||
formulaLeft: new Uint32Array(0),
|
||||
formulaRight: new Uint32Array(0),
|
||||
bindingStart: new Uint32Array(0),
|
||||
bindingCount: new Uint8Array(0),
|
||||
predicateId: new Uint32Array(0),
|
||||
argStart: new Uint32Array(0),
|
||||
argCount: new Uint8Array(0),
|
||||
originIndex: new Uint32Array(0),
|
||||
}
|
||||
}
|
||||
|
||||
export function createEmptyBindingTable(): BindingTable {
|
||||
return {
|
||||
count: 0,
|
||||
variableNameId: new Uint32Array(0),
|
||||
domainId: new Uint32Array(0),
|
||||
}
|
||||
}
|
||||
|
||||
export function createEmptyArgTable(): ArgTable {
|
||||
return {
|
||||
count: 0,
|
||||
termKind: new Uint8Array(0),
|
||||
termRef: new Uint32Array(0),
|
||||
termAux: new Uint32Array(0),
|
||||
}
|
||||
}
|
||||
|
||||
export function createEmptyStringTable(): IrStringTable {
|
||||
return {
|
||||
values: [],
|
||||
byValue: new Map(),
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Helper: Intern a string into the string table
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export function internString(table: IrStringTable, value: string): number {
|
||||
const existing = table.byValue.get(value)
|
||||
if (existing !== undefined) {
|
||||
return existing
|
||||
}
|
||||
const id = table.values.length
|
||||
table.values.push(value)
|
||||
table.byValue.set(value, id)
|
||||
return id
|
||||
}
|
||||
Reference in New Issue
Block a user