@mettascript/core 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1035 @@
1
+ type IntVal = number | bigint;
2
+ /** A bigint that fits the safe-integer range collapses to a number; everything else stays bigint. */
3
+ declare function canonInt(n: IntVal): IntVal;
4
+ declare function addInt(x: IntVal, y: IntVal): IntVal;
5
+ declare function subInt(x: IntVal, y: IntVal): IntVal;
6
+ declare function mulInt(x: IntVal, y: IntVal): IntVal;
7
+ /** Integer division truncating toward zero (matches the existing `Math.trunc(a/b)` semantics). */
8
+ declare function intDiv(x: IntVal, y: IntVal): IntVal;
9
+ declare function intMod(x: IntVal, y: IntVal): IntVal;
10
+ declare function intAbs(n: IntVal): IntVal;
11
+ declare function isZero(n: IntVal): boolean;
12
+ /** Coerce either representation to a double for the f64 math ops (precision loss is acceptable there). */
13
+ declare function toF64(n: IntVal): number;
14
+ /** Three-way compare of two integer values, exact (promotes to bigint when needed). Value-level
15
+ * analogue of `compareNumbers`, used by the deterministic-core compiler on unwrapped ints. */
16
+ declare function cmpIntVal(a: IntVal, b: IntVal): number;
17
+
18
+ /**
19
+ * The MeTTa term model. A discriminated union on `kind` (convention C1).
20
+ * Every variant declares ALL seven fields in the SAME order so V8 keeps one
21
+ * hidden class across atoms (monomorphic property access on the hot path).
22
+ * Unused fields are `undefined`, never absent, never deleted (C1).
23
+ */
24
+ type MetaType = "Symbol" | "Variable" | "Expression" | "Grounded";
25
+ interface SymAtom {
26
+ readonly kind: "sym";
27
+ readonly name: string;
28
+ readonly items: undefined;
29
+ readonly value: undefined;
30
+ readonly typ: undefined;
31
+ readonly exec: undefined;
32
+ readonly match: undefined;
33
+ readonly ground: true;
34
+ }
35
+ interface VarAtom {
36
+ readonly kind: "var";
37
+ readonly name: string;
38
+ readonly items: undefined;
39
+ readonly value: undefined;
40
+ readonly typ: undefined;
41
+ readonly exec: undefined;
42
+ readonly match: undefined;
43
+ readonly ground: false;
44
+ }
45
+ interface ExprAtom {
46
+ readonly kind: "expr";
47
+ readonly name: undefined;
48
+ readonly items: readonly Atom[];
49
+ readonly value: undefined;
50
+ readonly typ: undefined;
51
+ readonly exec: undefined;
52
+ readonly match: undefined;
53
+ /** True iff no variable occurs anywhere inside (a precomputed ground flag): lets `applySubst`,
54
+ * `atomVars`, and `occurs` short-circuit instantly on closed terms. Computed once at construction. */
55
+ readonly ground: boolean;
56
+ }
57
+ /** A grounded value (LeaTTa `Ground`). Numbers track int vs float so `3` and `3.0` stay distinct. */
58
+ type Ground = {
59
+ readonly g: "int";
60
+ readonly n: number | bigint;
61
+ } | {
62
+ readonly g: "float";
63
+ readonly n: number;
64
+ } | {
65
+ readonly g: "str";
66
+ readonly s: string;
67
+ } | {
68
+ readonly g: "bool";
69
+ readonly b: boolean;
70
+ } | {
71
+ readonly g: "unit";
72
+ } | {
73
+ readonly g: "error";
74
+ readonly msg: string;
75
+ } | {
76
+ readonly g: "ext";
77
+ readonly kind: string;
78
+ readonly id: string;
79
+ };
80
+ /** A grounded atom: a structured `Ground` value with a derived type atom, plus optional executor
81
+ * and custom matcher (used by DAS-style grounded atoms; core built-in ops dispatch by symbol). */
82
+ interface GndAtom {
83
+ readonly kind: "gnd";
84
+ readonly name: undefined;
85
+ readonly items: undefined;
86
+ readonly value: Ground;
87
+ readonly typ: Atom;
88
+ readonly exec: GroundedExec | undefined;
89
+ readonly match: GroundedMatch | undefined;
90
+ readonly ground: true;
91
+ }
92
+ type Atom = SymAtom | VarAtom | ExprAtom | GndAtom;
93
+ /** A grounded atom's executor: applied when the atom heads an expression `(<gnd> arg...)`. Receives
94
+ * the evaluated argument atoms and returns the result atoms, either directly or as a Promise. A
95
+ * Promise suspends the async runner (as a named async op does) and is refused by the sync runner;
96
+ * it never widens the atom record, since `exec` stays a single slot. May throw / reject for a
97
+ * runtime error. */
98
+ type GroundedExec = (args: readonly Atom[]) => readonly Atom[] | Promise<readonly Atom[]>;
99
+ type GroundedMatch = (other: Atom) => readonly unknown[];
100
+ declare function groundEq(a: Ground, b: Ground): boolean;
101
+ declare function canInternExprItems(items: readonly Atom[]): boolean;
102
+ /** Interned symbol atom: equal names share one object (reference equality, low allocation). */
103
+ declare function sym(name: string): SymAtom;
104
+ /** Variable atom. Not interned: freshening needs distinct identities. */
105
+ declare function variable(name: string): VarAtom;
106
+ declare function expr(items: readonly Atom[]): ExprAtom;
107
+ interface InternTable {
108
+ readonly buckets: Map<number, Atom | Atom[]>;
109
+ readonly variables: Map<string, VarAtom>;
110
+ readonly expressions: WeakSet<ExprAtom>;
111
+ readonly hasUnsafeGrounded: WeakMap<ExprAtom, boolean>;
112
+ }
113
+ declare function createInternTable(): InternTable;
114
+ declare function internAtom(table: InternTable | undefined, a: Atom): Atom;
115
+ declare function internExpr(table: InternTable | undefined, a: ExprAtom): ExprAtom;
116
+ declare function internBuiltExpr(table: InternTable | undefined, a: ExprAtom): ExprAtom;
117
+ /** The built-in type atom for a grounded value (LeaTTa `getTypes` on grounded). */
118
+ declare function groundType(v: Ground): Atom;
119
+ declare function gnd(value: Ground, typ?: Atom, exec?: GroundedExec, match?: GroundedMatch): GndAtom;
120
+ /** Grounded literal constructors. */
121
+ declare const gint: (n: IntVal) => GndAtom;
122
+ declare const gfloat: (n: number) => GndAtom;
123
+ declare const gstr: (s: string) => GndAtom;
124
+ declare const gbool: (b: boolean) => GndAtom;
125
+ declare const gunit: GndAtom;
126
+ declare function metaType(a: Atom): MetaType;
127
+ declare const mixHash: (h: number, x: number) => number;
128
+ declare const strHash: (s: string) => number;
129
+ /** A 32-bit structural hash: equal structures hash equal. O(1) amortised for a fresh atom whose subterms
130
+ * are already hashed. Collisions are possible, so callers verify a match with `atomEq`. */
131
+ declare function hashOf(a: Atom): number;
132
+ /** Total term size (LeaTTa `Atom.size`): leaves are 1, an expression is 1 + sum of parts. */
133
+ declare function atomSize(a: Atom): number;
134
+ /** All variable names occurring in an atom (LeaTTa `Atom.vars`), in first-seen order, deduped. */
135
+ declare function atomVars(a: Atom, out?: string[]): string[];
136
+ /** Collect an atom's variable names into `out`, deduping via the shared `seen` set (O(1) membership instead
137
+ * of a linear `out.includes`). Hot accumulation loops (scopeVars/frameVars) reuse one `seen` across many
138
+ * atoms so the whole walk stays linear; `atomVars` is the one-shot wrapper that seeds `seen` from `out`. */
139
+ declare function collectVars(a: Atom, out: string[], seen: Set<string>): void;
140
+ /** The empty expression `()` (LeaTTa `Atom.empty`), the success marker used by `assert*`. */
141
+ declare const emptyExpr: ExprAtom;
142
+ /** Is this atom an `(Error ...)` expression? */
143
+ declare function isErrorAtom(a: Atom): boolean;
144
+ declare const isExpr: (a: Atom) => a is ExprAtom;
145
+ declare const isVar: (a: Atom) => a is VarAtom;
146
+ declare const isSym: (a: Atom) => a is SymAtom;
147
+ declare const isGnd: (a: Atom) => a is GndAtom;
148
+ /** Structural equality. Interned symbols short-circuit to reference identity. */
149
+ declare function atomEq(a: Atom, b: Atom): boolean;
150
+
151
+ interface LogNode {
152
+ readonly atom: Atom;
153
+ readonly prev: AtomLog;
154
+ readonly size: number;
155
+ /** Count of non-ground atoms in this log; the index fast path is valid only when this is 0. */
156
+ readonly nonGround: number;
157
+ }
158
+ /** An atom log: `null` is empty; otherwise the most recently appended atom and the rest. */
159
+ type AtomLog = LogNode | null;
160
+
161
+ interface ValRel {
162
+ readonly tag: "val";
163
+ readonly x: string;
164
+ readonly a: Atom;
165
+ readonly y: undefined;
166
+ }
167
+ interface EqRel {
168
+ readonly tag: "eq";
169
+ readonly x: string;
170
+ readonly a: undefined;
171
+ readonly y: string;
172
+ }
173
+ type BindingRel = ValRel | EqRel;
174
+ type Bindings = readonly BindingRel[];
175
+ declare const emptyBindings: Bindings;
176
+ /** The atom bound to `$x` by a direct `val` relation, if any (eq aliases are not followed). */
177
+ declare function lookupVal(b: Bindings, x: string): Atom | undefined;
178
+ /** Remove direct value bindings for `x`; equality relations remain. */
179
+ declare function removeVal(b: Bindings, x: string): Bindings;
180
+ /** True if the binding set carries a variable loop: some variable is reachable from itself by following
181
+ * value bindings (`$x ← (.. $y ..)`, `$y ← (.. $x ..)`), so the set has no finite instantiation. Deep and
182
+ * transitive, mirroring Hyperon `Bindings::has_loops` (a DFS over variable→value edges) and CeTTa
183
+ * `bindings_atom_has_loop`. Every matcher call site drops a looping set (`if (!hasLoop(m))`), the same
184
+ * boundary at which Hyperon's `match_atoms` filters `!binding.has_loops()`, so a cyclic unification that a
185
+ * direct match admits (`matchAtomsWith` has no occurs check, faithfully — LeaTTa's occurs check lives only
186
+ * in reconcile) never reaches the evaluator.
187
+ *
188
+ * Was shallow, catching only the one-hop self relations `$x ← $x` / `$x = $x`, which let an indirect cycle
189
+ * like `$x ← (→ $x A)` through. That is a first-bind cycle (each variable bound once); the occurs check in
190
+ * `reconcile`/`addVarBinding` only fires on a SECOND bind of a variable, so it never sees such a cycle, and
191
+ * the fixpoint resolver then unrolled it to depth `size(b)` and overflowed the native stack — Nil
192
+ * Geisweiller's bfc-xp `obc` proof search at size ≥ 7. Deep detection is exactly the guard that makes
193
+ * resolution terminate (Alloy model MT1: a binding graph is loop-free iff every variable resolves to a
194
+ * finite normal form; a first-bind-only cycle is reachable, so the check must run here at the match
195
+ * boundary, not only on reconcile). A variable bound directly to itself (`$x ← $x`) is an identity, not a
196
+ * loop, matching Hyperon's short-circuit; it is caught above and treated as a loop only in that trivial
197
+ * self form to preserve the previous behaviour exactly.
198
+ *
199
+ * The DFS is iterative (an explicit stack, never native recursion) so detecting a loop can never itself
200
+ * overflow, and 3-colours each variable so it is visited once: O(vars + total value size), like Hyperon's
201
+ * bitset walk. `atomVars` is cached by object identity, so a DAG-shared value is scanned once. */
202
+ declare function hasLoop(b: Bindings): boolean;
203
+ /** `hasLoop` for a `merge` result whose base was already loop-free.
204
+ *
205
+ * `merge` builds every output by prepending relations onto its base: `addVarBinding` prepends a value
206
+ * relation only for a variable the current set leaves unbound (a bound variable either no-ops or goes
207
+ * through `reconcile`, whose own extensions bottom out in the same prepend-or-no-op steps), and
208
+ * `addVarEquality` prepends an equality. The base is therefore a reference-identical suffix of the
209
+ * result, no prepend can shadow a base variable's first value, and the base's first-value graph embeds
210
+ * unchanged in the result's. A cycle in the result must then pass through a prepended value binding,
211
+ * so running the colour DFS only from the prepended variables is answer-equivalent to the full scan.
212
+ * The self-relation quick checks run on the prepended prefix alone for the same reason. Anything that
213
+ * is not a reference-identical suffix extension falls back to the full `hasLoop`.
214
+ *
215
+ * Callers must pass the exact base the result was merged from, and that base must itself be loop-free;
216
+ * the equivalence fuzz in match.test.ts pins this predicate to `hasLoop` over merge outputs. */
217
+ declare function hasLoopFromBase(merged: Bindings, base: Bindings): boolean;
218
+ /** Bind `$x ← a`, dropping any previous value binding for `$x`. Raw: no consistency check. */
219
+ declare function addValRaw(b: Bindings, x: string, a: Atom): Bindings;
220
+ /** Prepend `$x ← a` when the caller has already proved `$x` has no direct value binding. */
221
+ declare function prependValRaw(b: Bindings, x: string, a: Atom): Bindings;
222
+ /** Add the alias `$x = $y` (a no-op when `x = y`). Raw: no consistency check. */
223
+ declare function addEqRaw(b: Bindings, x: string, y: string): Bindings;
224
+ /** Build a single value relation. The canonical `ValRel` constructor for callers outside this module. */
225
+ declare function makeValRel(x: string, a: Atom): ValRel;
226
+ /** Build a single variable-equality relation. */
227
+ declare function makeEqRel(x: string, y: string): EqRel;
228
+ /** Build a binding set from an explicit list of relations (newest-first). */
229
+ declare function fromRelations(rels: readonly BindingRel[]): Bindings;
230
+ /** Number of relations in the set. */
231
+ declare function size(b: Bindings): number;
232
+ /** Whether the set has no relations. */
233
+ declare function isEmpty(b: Bindings): boolean;
234
+ /** Every relation, newest-first (the order `merge` folds them in). */
235
+ declare function relations(b: Bindings): Iterable<BindingRel>;
236
+ /** Each current value binding as `[var, atom]`. */
237
+ declare function valEntries(b: Bindings): Iterable<readonly [string, Atom]>;
238
+ /** Whether any value binding satisfies `pred`. */
239
+ declare function someVal(b: Bindings, pred: (x: string, a: Atom) => boolean): boolean;
240
+ /** Whether the set carries any `eq` alias. */
241
+ declare function hasEq(b: Bindings): boolean;
242
+ /** Each `eq` alias relation, newest-first. */
243
+ declare function eqRelations(b: Bindings): Iterable<EqRel>;
244
+
245
+ type ReduceEffect = {
246
+ readonly kind: "addAtom";
247
+ readonly space: Atom;
248
+ readonly atom: Atom;
249
+ } | {
250
+ readonly kind: "removeAtom";
251
+ readonly space: Atom;
252
+ readonly atom: Atom;
253
+ } | {
254
+ readonly kind: "bindToken";
255
+ readonly name: string;
256
+ readonly atom: Atom;
257
+ };
258
+ type ReduceResult = {
259
+ readonly tag: "ok";
260
+ readonly results: readonly Atom[];
261
+ readonly effects?: readonly ReduceEffect[];
262
+ } | {
263
+ readonly tag: "runtimeError";
264
+ readonly msg: string;
265
+ } | {
266
+ readonly tag: "incorrectArgument";
267
+ readonly msg: string;
268
+ } | {
269
+ readonly tag: "noReduce";
270
+ };
271
+ type GroundFn = (args: readonly Atom[]) => ReduceResult;
272
+ type GroundingTable = Map<string, GroundFn>;
273
+ /** Return the type carried by a grounded operation, if it has one. */
274
+ declare function groundedOperationType(op: GroundFn): Atom | undefined;
275
+ /** Replace the line-output sink used by `println!`/`trace!` (returns the previous sink). */
276
+ declare function setOutputSink(fn: (line: string) => void): (line: string) => void;
277
+ /** Replace the raw (no-newline) sink used by `print!` (returns the previous sink). */
278
+ declare function setRawSink(fn: (text: string) => void): (text: string) => void;
279
+ /** Enable or disable host effects such as file IO and git imports for this process. */
280
+ declare function setHostEffectsEnabled(enabled: boolean): void;
281
+ /** Three-way compare: exact for two Ints (promoting to bigint as needed), f64 otherwise. */
282
+ declare function compareNumbers(a: Atom, b: Atom): number | undefined;
283
+ /** Names of the PeTTa-compat grounded ops. They yield to user `=` rules (PeTTa is rules-first, builtins as
284
+ * fallback), so a program that defines its own e.g. `sort`/`length` is not shadowed by the stdlib one. */
285
+ declare const pettaOpNames: ReadonlySet<string>;
286
+ /** True only for the unchanged built-in function registered under this name. */
287
+ declare function isTableSafeGroundedOp(name: string, fn: GroundFn): boolean;
288
+ /** The arithmetic / boolean / list-surgery / math grounding core every KB starts with. */
289
+ declare function baseTable(): GroundingTable;
290
+ /** The full standard-library grounding table (base + stdlib grounded ops + PeTTa-compat). Later entries do
291
+ * not override earlier ones (Map keeps the first), so Hyperon ops win any name shared with PeTTa-compat. */
292
+ declare function stdTable(): GroundingTable;
293
+ /** Dispatch `op` through the grounding table, or `noReduce` if unknown. */
294
+ declare function callGrounded(gt: GroundingTable, op: string, args: readonly Atom[]): ReduceResult;
295
+
296
+ /** Thrown by a compiled node when it meets a case it cannot handle faithfully (division by zero);
297
+ * the caller catches it (along with a native stack `RangeError`) and re-runs the call in the
298
+ * interpreter, which is sound because the compiled subset is side-effect-free. */
299
+ declare const BAIL: unique symbol;
300
+ declare class Tup {
301
+ readonly v: readonly IntVal[];
302
+ constructor(v: readonly IntVal[]);
303
+ }
304
+ type FrameVal = IntVal | Tup;
305
+ type Ty = "int" | "bool" | "sym" | `tuple${number}` | `symtuple${number}`;
306
+ /** A compiled pure function. `run` is filled after the whole dependency group is compiled, so mutual
307
+ * recursion resolves through the holder object. */
308
+ interface FunctionalHolder {
309
+ kind: "functional";
310
+ arity: number;
311
+ retType: Ty;
312
+ paramTypes: Ty[];
313
+ run: (vals: FrameVal[]) => FrameVal | boolean;
314
+ }
315
+ interface CompiledAtomResult {
316
+ readonly atom: Atom;
317
+ readonly bnd: Bindings;
318
+ }
319
+ interface CompiledRunResult {
320
+ readonly results: readonly CompiledAtomResult[];
321
+ readonly counterDelta: number;
322
+ readonly state?: St;
323
+ }
324
+ interface RewriteHolder {
325
+ kind: "rewrite";
326
+ arity: number;
327
+ retType: Ty;
328
+ paramTypes: Ty[];
329
+ ruleCount: number;
330
+ run: (partAtoms: readonly Atom[]) => CompiledRunResult | undefined;
331
+ }
332
+ interface SymbolicHolder {
333
+ kind: "symbolic";
334
+ arity: number;
335
+ clauseCount: number;
336
+ run: (partAtoms: readonly Atom[], counter: number) => CompiledRunResult | undefined;
337
+ }
338
+ interface CompiledImpureOps {
339
+ readonly addAtom: (env: MinEnv, st: St, space: Atom, atom: Atom) => St | undefined;
340
+ /** Solutions of a `(match space pattern template)` under the current world: the instantiated
341
+ * template plus that solution's bindings, in the interpreter's own candidate order, and the
342
+ * fresh-variable counter advance the interpreted match would have cost. Undefined = not a space. */
343
+ readonly matchSolutions?: (env: MinEnv, st: St, space: Atom, pattern: Atom, template: Atom) => {
344
+ readonly pairs: ReadonlyArray<readonly [Atom, Bindings]>;
345
+ readonly counterDelta: number;
346
+ } | undefined;
347
+ /** The add-if-absent idiom on a ground atom: exact-membership probe, then append when absent.
348
+ * Undefined when the fast probe is unsound for this space (non-ground facts, static facts of the
349
+ * same head, state handles), sending the caller back to the interpreter. */
350
+ readonly addIfAbsent?: (env: MinEnv, st: St, space: Atom, atom: Atom) => {
351
+ readonly added: boolean;
352
+ readonly state: St;
353
+ } | undefined;
354
+ }
355
+ type ImpEval = {
356
+ readonly value: Atom;
357
+ readonly st: St;
358
+ } | typeof BAIL;
359
+ type ImpEmit = (value: Atom, st: St) => St | typeof BAIL;
360
+ type ImpForEach = (slots: readonly Atom[], st: St, ops: CompiledImpureOps, discard: boolean | undefined, emit: ImpEmit) => St | typeof BAIL;
361
+ interface ImperativeHolder {
362
+ kind: "imperative";
363
+ arity: number;
364
+ clauseCount: number;
365
+ run: (partAtoms: readonly Atom[], st: St, ops: CompiledImpureOps, discard?: boolean) => ImpEval;
366
+ runForEach?: ImpForEach;
367
+ }
368
+ interface NondetHolder {
369
+ kind: "nondet";
370
+ arity: number;
371
+ clauseCount: number;
372
+ /** Prefer direct depth-first search when a later recursive call consumes a clause-local field
373
+ * produced by an earlier answer. Independent overlapping calls retain table-first evaluation. */
374
+ preferDirectForModed: boolean;
375
+ run: (env: MinEnv, partAtoms: readonly Atom[], st: St, ops: CompiledImpureOps, fuel?: number) => CompiledRunResult | undefined;
376
+ }
377
+ type CompiledHolder = FunctionalHolder | RewriteHolder | SymbolicHolder | ImperativeHolder | NondetHolder;
378
+ type CompiledFns = Map<string, CompiledHolder>;
379
+ type Skel = {
380
+ readonly t: 0;
381
+ readonly a: Atom;
382
+ } | {
383
+ readonly t: 1;
384
+ readonly i: number;
385
+ } | {
386
+ readonly t: 2;
387
+ readonly items: readonly Skel[];
388
+ readonly arith: string | undefined;
389
+ };
390
+ interface SkelGoal {
391
+ readonly pat: Skel;
392
+ /** Empty string when `match` is set: a space-match goal has no dispatched function. */
393
+ readonly fn: string;
394
+ readonly args: readonly Skel[];
395
+ /** A `(match space pattern template)` goal, served by the injected immutable matcher with the
396
+ * solutions bound back onto the cells. The JIT declines any group carrying one, so only the
397
+ * skeleton interpreter and the immutable engine ever see it. */
398
+ readonly match?: {
399
+ readonly space: Skel;
400
+ readonly pattern: Skel;
401
+ readonly template: Skel;
402
+ };
403
+ }
404
+ type SkelTail = {
405
+ readonly tag: "tpl";
406
+ readonly tpl: Skel;
407
+ } | {
408
+ readonly tag: "empty";
409
+ } | {
410
+ readonly tag: "call";
411
+ readonly fn: string;
412
+ readonly args: readonly Skel[];
413
+ } | {
414
+ readonly tag: "match";
415
+ readonly space: Skel;
416
+ readonly pattern: Skel;
417
+ readonly template: Skel;
418
+ };
419
+ type SkelBody = {
420
+ readonly tag: "seq";
421
+ readonly goals: readonly SkelGoal[];
422
+ readonly tail: SkelTail;
423
+ } | {
424
+ readonly tag: "if";
425
+ readonly op: string;
426
+ readonly x: Skel;
427
+ readonly y: Skel;
428
+ readonly then: SkelBody;
429
+ readonly els: SkelBody;
430
+ };
431
+ interface SkelClause {
432
+ /** Number of clause-variable slots (the dispatch frame's length). */
433
+ readonly n: number;
434
+ /** Head argument skeletons (the head symbol is implied by the dispatch table). */
435
+ readonly lhsArgs: readonly Skel[];
436
+ readonly body: SkelBody;
437
+ }
438
+ /** Compile one answer-dependent recursive search group for query-directed dispatch. Independent
439
+ * overlapping recursion stays on moded tabling and returns undefined, so the caller can use the full
440
+ * compiler when the query needs another compiled fragment. */
441
+ declare function compileDependentNondetGroup(env: MinEnv, root: string): CompiledFns | undefined;
442
+ /** Compile every compilable pure single-clause function in `env` to a memoised native closure.
443
+ * Phase 1 infers return types (fixpoint, optimistic over recursion). Phase 2 compiles bodies with
444
+ * those types and drops any that fail end-to-end (a call to an uncompilable function fails too). */
445
+ declare function compileEnv(env: MinEnv): CompiledFns;
446
+ /** Run a compiled function, returning an ordered result bag, or `undefined` to fall back to the interpreter
447
+ * when the call falls outside the proven subset. */
448
+ declare function runCompiled(env: MinEnv, op: string, partAtoms: readonly Atom[], st: St, ops?: CompiledImpureOps, discard?: boolean, fuel?: number): CompiledRunResult | undefined;
449
+ declare function runCompiledEffectCount(env: MinEnv, op: string, partAtoms: readonly Atom[], st: St, ops: CompiledImpureOps): {
450
+ readonly count: number;
451
+ readonly state: St;
452
+ } | undefined;
453
+
454
+ type TermId = number;
455
+ type FactId = number;
456
+ declare class Int32Chunks {
457
+ private readonly chunks;
458
+ private tail;
459
+ length: number;
460
+ push(value: number): number;
461
+ get(index: number): number;
462
+ }
463
+ declare function canCompactAtom(a: Atom): boolean;
464
+ declare class FlatAtomSpaceTable {
465
+ readonly termKind: Int32Chunks;
466
+ readonly termStart: Int32Chunks;
467
+ readonly termLen: Int32Chunks;
468
+ readonly termHash: Int32Chunks;
469
+ readonly termGround: Int32Chunks;
470
+ readonly termData: Int32Chunks;
471
+ readonly factRoot: Int32Chunks;
472
+ readonly factHeadSym: Int32Chunks;
473
+ private slots;
474
+ private slotCount;
475
+ private missSlot;
476
+ private missHash;
477
+ private readonly symByName;
478
+ private readonly intNumberGrounds;
479
+ private readonly floatGrounds;
480
+ private readonly groundByKey;
481
+ private readonly varByName;
482
+ private readonly termFacts;
483
+ private readonly nestedHeadFacts;
484
+ private readonly symbols;
485
+ private readonly grounds;
486
+ private readonly vars;
487
+ private readonly decoded;
488
+ private readonly termIdOf;
489
+ get factCount(): number;
490
+ insertFact(atom: Atom): FactId;
491
+ factsForTerm(term: TermId): readonly FactId[];
492
+ insertAtom(atom: Atom): TermId;
493
+ private insertAtomUncached;
494
+ lookupAtom(atom: Atom): TermId | undefined;
495
+ private lookupAtomUncached;
496
+ decodeTerm(term: TermId): Atom;
497
+ private decodeTermUncached;
498
+ isTermGround(term: TermId): boolean;
499
+ headSymOf(term: TermId): number;
500
+ lookupHeadSym(name: string): number | undefined;
501
+ factsForNestedPattern(pattern: Atom): readonly FactId[] | undefined;
502
+ private internSym;
503
+ private internGround;
504
+ private lookupGround;
505
+ private internNumericGround;
506
+ private internGroundByKey;
507
+ private internVar;
508
+ private internLeaf;
509
+ private lookupLeaf;
510
+ private internExpr;
511
+ private lookupExpr;
512
+ private pushTerm;
513
+ private recordMiss;
514
+ private growSlots;
515
+ }
516
+ declare class FlatAtomSpace {
517
+ private readonly table;
518
+ private readonly ranges;
519
+ private readonly dead;
520
+ readonly liveCount: number;
521
+ readonly nonGroundCount: number;
522
+ private arr;
523
+ private constructor();
524
+ static empty(): FlatAtomSpace;
525
+ static fromAtoms(atoms: readonly Atom[]): FlatAtomSpace | undefined;
526
+ get size(): number;
527
+ /** Append a batch as new visible facts. Returns undefined when some atom is not flat-storable (a
528
+ * grounded executor/matcher); the caller keeps such a batch on the plain log instead. */
529
+ appendAll(atoms: readonly Atom[]): FlatAtomSpace | undefined;
530
+ removeOne(atom: Atom): FlatAtomSpace;
531
+ exactCount(atom: Atom): number;
532
+ candidatesFor(patternHead: string | undefined, pattern?: Atom): Iterable<Atom>;
533
+ toArray(): Atom[];
534
+ /** Columnar mirror of the `&self` direct tally in eval.ts: over the visible facts the head filter
535
+ * admits (head symbol `patternHead` or no symbol head, same filter as `candidatesFor`), count the
536
+ * ones an all-distinct-variable pattern `(k $v..)` of `arity` items unifies with, without decoding
537
+ * any fact. `iterated` is the admitted total (it advances the candidate counter). */
538
+ countHeadArity(patternHead: string, arity: number): {
539
+ count: number;
540
+ iterated: number;
541
+ };
542
+ roundTrip(atom: Atom): Atom;
543
+ private decodeFact;
544
+ private visibleFactIds;
545
+ private factVisible;
546
+ }
547
+
548
+ interface RangeEntry {
549
+ readonly value: Atom;
550
+ readonly occurrence: number;
551
+ readonly atom: Atom;
552
+ }
553
+ interface ArityColumn {
554
+ readonly total: number;
555
+ readonly entries: readonly RangeEntry[];
556
+ }
557
+ interface SortedColumn {
558
+ readonly functor: string;
559
+ readonly argPosition: number;
560
+ readonly totalCandidates: number;
561
+ readonly arities: ReadonlyMap<number, ArityColumn>;
562
+ }
563
+
564
+ interface FactIdView {
565
+ readonly count: number;
566
+ ids(): Iterable<number>;
567
+ }
568
+ /** Compact storage for static symbol-headed expression facts.
569
+ *
570
+ * Fact ids are the source positions passed to `fromAtoms`. Head keys use the evaluator's `headKey`
571
+ * format for the supported fact shape: the symbol name at expression position 0.
572
+ */
573
+ declare class StaticCompactBase {
574
+ private readonly table;
575
+ private readonly headFacts;
576
+ readonly size: number;
577
+ private readonly columnCache;
578
+ private readonly factMemo;
579
+ private memoizeFactDecode;
580
+ private constructor();
581
+ /** Encode all atoms as facts 0..n-1. The batch is rejected if any fact is not compactable or is
582
+ * not a symbol-headed expression. */
583
+ static fromAtoms(atoms: readonly Atom[]): StaticCompactBase | undefined;
584
+ factAtom(id: number): Atom;
585
+ /** Switch `factAtom` to per-fact memoized decoding: repeated reads of a fact return the identical
586
+ * object. The evaluator wiring requires this (its evaluated-atoms and freshen caches key on object
587
+ * identity); the unmemoized default keeps the standalone store's steady heap flat. */
588
+ enableDecodeMemo(): void;
589
+ /** Structural membership without decoding: whether some stored fact equals `atom`. The interned term
590
+ * table gives each distinct term one id, so equality is an id lookup plus a per-term fact check. */
591
+ hasFact(atom: Atom): boolean;
592
+ /** Whether the functor stores two structurally identical facts. Interning makes duplicate facts share
593
+ * one root term id, so this is a Set scan over the bucket's root ids, never a decode. */
594
+ hasDuplicateFacts(headKey: string): boolean;
595
+ factsForHead(headKey: string): FactIdView;
596
+ equalRange(headKey: string, argPos: number, value: Atom): readonly number[];
597
+ bucketSize(headKey: string, argPos: number, value: Atom): number;
598
+ numericRange(headKey: string, argPos: number, low: Atom | undefined, high: Atom | undefined, incLow: boolean, incHigh: boolean): readonly number[] | undefined;
599
+ private column;
600
+ private buildColumn;
601
+ private buildNumericColumn;
602
+ private buildKeyColumn;
603
+ private argumentTerm;
604
+ private termValue;
605
+ private equalNumeric;
606
+ private countEqualNumeric;
607
+ private filteredNumericIds;
608
+ private equalKeyed;
609
+ private countEqualKeyed;
610
+ private keyBounds;
611
+ private decodeTermFresh;
612
+ }
613
+
614
+ declare class StaticAtomStore {
615
+ private readonly slots;
616
+ private ids;
617
+ private base;
618
+ private arr;
619
+ get length(): number;
620
+ /** The compact base, when a compaction sweep installed one. */
621
+ get compactBase(): StaticCompactBase | undefined;
622
+ push(atom: Atom): void;
623
+ get(index: number): Atom;
624
+ /** Install the compaction result: `factIds[slot]` is the base fact id for compacted slots and
625
+ * OBJECT_SLOT elsewhere. Compacted slots release their object references. */
626
+ adoptCompact(base: StaticCompactBase, factIds: Int32Array): void;
627
+ /** De-compaction for one functor: restore the given slots to plain object storage (the atoms are
628
+ * decoded through the memoized base, so identity stays stable for anything already handed out). */
629
+ restoreSlots(slots: Int32Array): void;
630
+ /** Membership by structural equality. Object slots compare directly; compacted facts resolve through
631
+ * the base's interned term table without decoding. */
632
+ hasAtom(atom: Atom): boolean;
633
+ /** `some` over the OBJECT slots only. Used by the custom-matcher scan: a compacted fact passed
634
+ * `canCompactAtom`, so it cannot contain a custom grounded matcher and never satisfies that scan. */
635
+ someObject(predicate: (atom: Atom) => boolean): boolean;
636
+ [Symbol.iterator](): Iterator<Atom>;
637
+ /** Materialize the full slot-order list (the `get-atoms` / variable-headed-pattern enumeration).
638
+ * Memoized until the store changes; callers must not mutate the result. */
639
+ toArray(): Atom[];
640
+ }
641
+
642
+ type TraceEvent = {
643
+ readonly kind: "reduce";
644
+ readonly atom: string;
645
+ } | {
646
+ readonly kind: "grounded";
647
+ readonly op: string;
648
+ } | {
649
+ readonly kind: "specialize";
650
+ readonly from: string;
651
+ readonly to: string;
652
+ } | {
653
+ readonly kind: "overflow";
654
+ readonly atom: string;
655
+ };
656
+ type TraceSink = (event: TraceEvent) => void;
657
+
658
+ declare const TAG_ARITY = 0;
659
+ declare const TAG_SYMBOL = 1;
660
+ declare const TAG_NEWVAR = 2;
661
+ declare const TAG_VARREF = 3;
662
+ /** Interns symbols and grounded values to dense integer ids, with a reverse map so a flat atom decodes
663
+ * back exactly. Symbols and grounds share the id space (a ground's id reconstructs the ground). */
664
+ declare class Interner {
665
+ private readonly byKey;
666
+ private readonly entries;
667
+ private add;
668
+ internSym(name: string): number;
669
+ internGround(value: Ground): number;
670
+ /** The id for a symbol/ground if already interned, else undefined (a pattern symbol absent from the
671
+ * KB can never match, so its lookup short-circuits). */
672
+ lookupSym(name: string): number | undefined;
673
+ lookupGround(value: Ground): number | undefined;
674
+ /** Reconstruct the atom for a leaf id. */
675
+ decodeLeaf(id: number): Atom;
676
+ get size(): number;
677
+ }
678
+ /** Encode an atom into the token array `out`, interning leaves. `varMap` assigns de Bruijn indices to
679
+ * variable names (shared across one atom so repeated variables become VARREF). */
680
+ declare function encodeInto(a: Atom, out: number[], it: Interner, varMap: Map<string, number>): void;
681
+ /** Encode a single atom to a token array. */
682
+ declare function encodeAtom(a: Atom, it: Interner): number[];
683
+ /** Decode the token at `pos`, returning the atom and the position after it. Variables are reconstructed
684
+ * with de Bruijn names `$0`, `$1`, … (so a decoded atom is alpha-equivalent to the original). */
685
+ declare function decodeAt(tokens: Int32Array | number[], pos: number, it: Interner): [Atom, number];
686
+ /** Decode a full token array to an atom. */
687
+ declare function decodeAtom(tokens: Int32Array | number[], it: Interner): Atom;
688
+ /** The number of tokens in the subterm starting at `pos`. */
689
+ declare function subtermLen(tokens: Int32Array | number[], pos: number): number;
690
+ /** Encode a query pattern using lookup (not interning): returns the tokens and the variable names in de
691
+ * Bruijn order, or `null` if a pattern symbol/ground is absent from the interner (fast fail; it can
692
+ * never match any stored fact). */
693
+ declare function encodePattern(a: Atom, it: Interner): {
694
+ tokens: number[];
695
+ varNames: string[];
696
+ } | null;
697
+ /** One-sided match of an encoded pattern against an encoded ground fact in a (possibly shared) token
698
+ * array. Returns the variable bindings (de Bruijn index -> the matched fact subterm's [start, end)
699
+ * token range), or `null` on mismatch. Pure integer work over the token array, so a worker can run it
700
+ * against a `SharedArrayBuffer`-backed `Int32Array` with no copying. */
701
+ declare function matchFlatAt(pat: ArrayLike<number>, fact: Int32Array | number[], factStart: number): Map<number, [number, number]> | null;
702
+ /** A flat, interned knowledge base: facts are appended as token runs into one array, indexed by head
703
+ * functor id, and matched against an encoded pattern by integer scan. */
704
+ declare class FlatKB {
705
+ readonly interner: Interner;
706
+ private readonly tokens;
707
+ private readonly byFunctor;
708
+ private readonly other;
709
+ private readonly offsets;
710
+ /** The token array (for packing into a SharedArrayBuffer). */
711
+ get tokenArray(): readonly number[];
712
+ /** Every fact's start offset, in insertion order (for sharding across workers). */
713
+ get factOffsets(): readonly number[];
714
+ /** Add a (typically ground) atom to the KB. */
715
+ add(a: Atom): void;
716
+ /** Candidate fact offsets for a pattern, using the functor index when the pattern head is a known
717
+ * symbol; otherwise every fact. */
718
+ private candidates;
719
+ /** Match `pattern` against the KB, returning a binding map (variable name -> matched atom) per match. */
720
+ match(pattern: Atom): Array<Map<string, Atom>>;
721
+ get size(): number;
722
+ }
723
+ declare const _internals: {
724
+ tok: (tag: number, payload?: number) => number;
725
+ tagOf: (tok: number) => number;
726
+ payloadOf: (tok: number) => number;
727
+ subtermLen: typeof subtermLen;
728
+ };
729
+
730
+ interface TableKey {
731
+ readonly tokens: readonly number[];
732
+ readonly generation: number;
733
+ }
734
+ interface VariantAtomKey {
735
+ readonly tokens: readonly number[];
736
+ readonly varNames: readonly string[];
737
+ readonly canonicalMap: Map<string, string>;
738
+ }
739
+ interface EncodedAtomKey extends TableKey, VariantAtomKey {
740
+ }
741
+ /** Encode an atom for variant lookup without printing it. Variables are canonicalized by first occurrence. */
742
+ declare function encodeVariantKey(a: Atom, interner: Interner): VariantAtomKey;
743
+ declare class TokenTrie<V> {
744
+ private readonly root;
745
+ get(tokens: readonly number[]): V | undefined;
746
+ set(tokens: readonly number[], value: V): void;
747
+ delete(tokens: readonly number[]): boolean;
748
+ clear(): void;
749
+ }
750
+ interface CompletedTableEntry {
751
+ readonly numCallVars: number;
752
+ readonly results: readonly Atom[];
753
+ readonly answerCount: number;
754
+ readonly approxCells: number;
755
+ }
756
+ interface ActiveTableEntry {
757
+ readonly tokens: readonly number[];
758
+ readonly numCallVars: number;
759
+ readonly results: readonly Atom[];
760
+ readonly answerCount: number;
761
+ readonly approxCells: number;
762
+ cyclic: boolean;
763
+ overBudget: boolean;
764
+ }
765
+ interface TableBudget {
766
+ readonly maxCompletedEntries: number;
767
+ readonly maxCompletedAnswers: number;
768
+ readonly maxApproxCells: number;
769
+ readonly maxEntryCells: number;
770
+ readonly maxInternerLeaves: number;
771
+ }
772
+ type TableKeyKind = "ground" | "ground-distinct" | "moded";
773
+ declare class TableSpace {
774
+ private readonly budget;
775
+ interner: Interner;
776
+ private generation;
777
+ private readonly completed;
778
+ private readonly active;
779
+ private readonly activeStack;
780
+ private head;
781
+ private tail;
782
+ private entries;
783
+ private answers;
784
+ private cells;
785
+ private activeCount;
786
+ private activeAnswers;
787
+ private activeCells;
788
+ constructor(budget?: TableBudget);
789
+ key(kind: TableKeyKind, call: Atom, runtimeVersion: number): EncodedAtomKey;
790
+ isCurrentKey(key: TableKey): boolean;
791
+ getCompleted(key: TableKey): CompletedTableEntry | undefined;
792
+ rememberCompleted(key: TableKey, numCallVars: number, results: readonly Atom[]): void;
793
+ beginActive(key: TableKey, numCallVars: number): ActiveTableEntry | null | undefined;
794
+ getActive(key: TableKey): ActiveTableEntry | undefined;
795
+ isTopActive(entry: ActiveTableEntry): boolean;
796
+ markCyclic(entry: ActiveTableEntry): void;
797
+ addActiveAnswers(entry: ActiveTableEntry, results: readonly Atom[]): number;
798
+ endActive(key: TableKey): void;
799
+ clear(): void;
800
+ private resetTables;
801
+ stats(): {
802
+ entries: number;
803
+ answers: number;
804
+ approxCells: number;
805
+ };
806
+ entryCellLimit(): number;
807
+ resourceBudget(): TableBudget;
808
+ private entryCost;
809
+ private touch;
810
+ private insertHead;
811
+ private unlink;
812
+ private remove;
813
+ private evict;
814
+ private makeRoomForActive;
815
+ private resetInternerAndTables;
816
+ private maybeResetInterner;
817
+ }
818
+
819
+ /** A grounded operation that runs asynchronously, for the async runner. */
820
+ type AsyncGroundFn = (args: readonly Atom[]) => Promise<ReduceResult>;
821
+ type HostImportFn = (space: Atom, file: Atom) => ReduceResult | Promise<ReduceResult>;
822
+ /** Thrown when synchronous evaluation reaches an async grounded operation. Use the async runner. */
823
+ declare class AsyncInSyncError extends Error {
824
+ constructor(op: string);
825
+ }
826
+ type Ret = "none" | "chain" | "function";
827
+ interface Frame {
828
+ readonly atom: Atom;
829
+ readonly ret: Ret;
830
+ readonly vars: readonly string[];
831
+ readonly fin: boolean;
832
+ }
833
+ interface StackCons {
834
+ readonly head: Frame;
835
+ readonly tail: Stack;
836
+ }
837
+ type Stack = StackCons | null;
838
+ interface Item {
839
+ readonly stack: Stack;
840
+ readonly bnd: Bindings;
841
+ }
842
+ interface MinEnv {
843
+ ruleIndex: Map<string, Array<[Atom, Atom]>>;
844
+ varRules: Array<[Atom, Atom]>;
845
+ varRulesVar: Array<[Atom, Atom]>;
846
+ sigs: Map<string, Atom[]>;
847
+ gt: GroundingTable;
848
+ /** Static `&self` atoms in insertion (occurrence) order. Slot-stable: the nested match index refers
849
+ * to slots by occurrence id and `get-atoms` order is observable, so the compaction sweep swaps a
850
+ * slot's storage without renumbering. */
851
+ atoms: StaticAtomStore;
852
+ types: Map<string, Atom[]>;
853
+ imports: Map<string, Atom[]>;
854
+ exprTypes: Array<[Atom, Atom]>;
855
+ /** Async grounded operations, dispatched by the async runner; empty for pure synchronous evaluation. */
856
+ agt: Map<string, AsyncGroundFn>;
857
+ /** Optional host-language import hook used by async `import!` for files outside the MeTTa import map. */
858
+ hostImport?: HostImportFn;
859
+ /** Optional opt-in execution trace sink. `undefined` when tracing is off, so emit sites cost one branch.
860
+ * Always present (as `undefined` when off) to keep the env object's shape monomorphic on the hot path. */
861
+ trace?: TraceSink | undefined;
862
+ /** Per-runner `with-mutex` locks (a Promise chain per key), so mutexes do not leak across runners. */
863
+ mutexes: Map<string, Promise<void>>;
864
+ /** Optional per-run hash-cons table for immutable terms. */
865
+ intern?: InternTable;
866
+ /** Ground expressions already observed to reduce to themselves for the current rule set. */
867
+ evaluatedAtoms: WeakSet<Atom>;
868
+ factIndex: Map<string, Atom[]>;
869
+ argIndex: Map<string, Atom[]>;
870
+ nonGroundAtPos: Map<string, Atom[]>;
871
+ /** Internal static nested-head index. Optional so existing structural `MinEnv` values stay compatible. */
872
+ nestedMatchIndex?: StaticNestedMatchIndex | undefined;
873
+ varHeadedFacts: Atom[];
874
+ /** Automatic tabling storage: structural variant keys over token tries and bounded completed entries.
875
+ * `undefined` when tabling is disabled. */
876
+ tableSpace?: TableSpace | undefined;
877
+ /** Positive only while an idempotent unique(collapse ...) consumer evaluates a proven-pure ground call. */
878
+ distinctGroundDepth?: number | undefined;
879
+ /** Functor names proven tabling-safe by `analyzePurity`; recomputed when equations change. */
880
+ pureFunctors?: Set<string>;
881
+ /** Functor names proven safe for MODED tabling by `analyzePurity(env, MODED_IMPURE_OPS)` — a superset of
882
+ * `pureFunctors` (only `empty`, which is genuinely pure, is treated more permissively); recomputed
883
+ * alongside it. */
884
+ modedPureFunctors?: Set<string>;
885
+ /** Pure functors whose rule SCC has branching recursion, so ground tabling is likely useful. */
886
+ tableWorth?: Set<string>;
887
+ /** Pure functors whose rule SCC has branching recursion under the moded purity rules. */
888
+ modedTableWorth?: Set<string>;
889
+ /** Set when equations changed and the purity/profitability analysis must be refreshed before evaluation. */
890
+ tablingDirty?: boolean | undefined;
891
+ /** Memo for `getTypes` of ground atoms: a ground atom's type is a pure function of the env's type tables,
892
+ * which only change via `addAtomToEnv` (where this is reset). Keyed by atom identity, so the recursion
893
+ * reuses the type of every shared subterm (a growing Peano/list term is the worst case otherwise). */
894
+ typeCache?: WeakMap<Atom, Atom[]> | undefined;
895
+ /** Optional parallel branch evaluator for `hyperpose` (set by a host worker pool). Given the formatted
896
+ * branch atoms and whether to stop at the first result, returns each branch's result atoms, or `null` for
897
+ * a branch that errored or (under firstOnly) lost the race. It re-evaluates each branch from the program's
898
+ * rules in a worker, so it is only used when a branch is pure and the space carries no runtime additions,
899
+ * so it is identical to evaluating in line. */
900
+ parEval?: (branchSrcs: string[], firstOnly: boolean) => (Atom[] | null)[];
901
+ /** Async host-worker equivalent, used by browser Web Workers and other non-blocking hosts. */
902
+ parEvalAsync?: (branchSrcs: string[], firstOnly: boolean) => Promise<(Atom[] | null)[]>;
903
+ /** Compiled pure deterministic functions (the int/bool functional core); undefined when disabled. */
904
+ compiled?: CompiledFns | undefined;
905
+ /** Set when an equation changed, so the compiler re-runs before the next query. */
906
+ compileDirty?: boolean | undefined;
907
+ /** False when `compiled` contains only query-directed dependent search groups. Undefined retains the
908
+ * historical meaning for structural environments whose map was produced by `compileEnv`. */
909
+ compiledComplete?: boolean | undefined;
910
+ /** Opt-in trail-based matching (`experimental.trail`): the conjunctive `match` enumerates on a WAM-style
911
+ * trail (zero per-solution allocation) instead of the immutable `Bindings`/`merge` threading. Off by
912
+ * default; byte-identical to the reference matcher (differential-gated), falling back to it per query for
913
+ * cases the trail cannot reproduce (custom grounded matchers). */
914
+ useTrail?: boolean;
915
+ /** Compact runtime `&self` atomspace. When on, runtime additions are stored as flat term ids and decoded
916
+ * only when a query or observable operation needs tree atoms. */
917
+ useFlatAtomspace?: boolean;
918
+ /** Anchored-acyclic conjunctive matching (`experimental.conjNested`, on by default): a `(, ...)` whose
919
+ * first goal is anchored by a ground argument and whose later goals are connected over a ground,
920
+ * duplicate-free candidate domain runs through the source-ordered binding-aware nested loop (matchConj),
921
+ * which probes the argument index per bound join variable instead of materializing every goal's full
922
+ * relation for matchConjJoin's WCO. Differential-gated to matchConjJoin: same solution multiset and
923
+ * multiplicity. Enumeration order can interleave differently when the anchor bucket is not grouped by
924
+ * the join variable (MeTTa leaves query order unspecified — the MOPS workspace is a multiset); on
925
+ * unique-entity-per-goal shapes the orders coincide, asserted by the differential suite.
926
+ * Cyclic, unanchored, non-ground-fact, or duplicate-fact conjunctions stay on matchConjJoin. */
927
+ useConjNested?: boolean;
928
+ /** Ordered numeric single-column range matching (`experimental.rangeIndex`, on by default): a single
929
+ * functor-headed all-variable pattern whose template is a pure nested `if` numeric range filter enumerates
930
+ * the sorted numeric column slice instead of scanning the whole functor bucket. The selected slice is
931
+ * restored to source order before yielding. */
932
+ useRangeIndex?: boolean;
933
+ /** Mark normal-form ground `match` results as already evaluated (`experimental.matchEvalMark`, on by
934
+ * default) so the first consumer visit takes the existing evaluatedAtoms short-circuit. */
935
+ useMatchEvalMark?: boolean;
936
+ /** Answer a public-entry bare `(match &self pat templ)` straight from its match plan
937
+ * (`experimental.directMatch`, on by default), skipping the generator driver, the worklist, and the
938
+ * per-result reduce probe those would run. Guarded to the exact cases where that machinery is a
939
+ * provable no-op; anything else declines to the general path. */
940
+ useDirectMatch?: boolean;
941
+ /** Lazily-computed set of head functors that have a duplicate ground fact. matchConjJoin's WCO trie dedups
942
+ * duplicate relation tuples, so it collapses a conjunction over duplicate facts to one solution; the nested
943
+ * loop preserves multiplicity. Only functors with no duplicate facts route to the nested loop, so the two
944
+ * paths stay byte-identical. Computed once (conjNested only) from factIndex and cached here. */
945
+ duplicateFactHeadsCache?: Set<string> | undefined;
946
+ /** Compact static fact storage (`experimental.staticCompact`, on by default for buildEnv loads): large
947
+ * all-ground flat-fact functors are swept into one shared StaticCompactBase; their slots, factIndex
948
+ * buckets, and argIndex postings release the object forest, and candidates decode on demand through the
949
+ * base's memoized decoder with sorted-column equality/range probes standing in for argIndex. */
950
+ staticBase?: StaticCompactBase;
951
+ /** Per-functor compaction metadata for `staticBase` (functors currently served by the compact base). */
952
+ compactHeads?: Map<string, CompactHeadMeta>;
953
+ /** Lazy ordered numeric column indexes for `experimental.rangeIndex`. Keyed by functor and argument
954
+ * position; a `null` cache entry records a column that is not safely numeric, so later declined queries do
955
+ * not rescan the fact bucket. */
956
+ numericRangeIndexCache?: Map<string, SortedColumn | null> | undefined;
957
+ }
958
+ interface StaticNestedMatchIndex {
959
+ /** Occurrence ids by functor, argument position, and nested expression head. */
960
+ readonly byHead: Map<string, number[]>;
961
+ /** Occurrence ids whose argument or argument head has a custom grounded matcher. */
962
+ readonly wildcardAtPos: Map<string, number[]>;
963
+ /** Root functors with a non-ground static fact. */
964
+ readonly nonGroundFactHeads: Set<string>;
965
+ }
966
+ /** Compaction metadata for one functor served by the shared StaticCompactBase. */
967
+ interface CompactHeadMeta {
968
+ /** Fact count (the whole bucket, every arity). */
969
+ readonly count: number;
970
+ /** The facts' env.atoms slots, ascending (bucket insertion order). */
971
+ readonly slots: Int32Array;
972
+ /** The uniform expression arity (item count), or -1 when the bucket mixes arities. */
973
+ readonly arity: number;
974
+ /** Fact count per expression arity (the all-distinct-variable tally reads these without decoding). */
975
+ readonly arityCounts: ReadonlyMap<number, number>;
976
+ /** Distinct leaf symbol names across all argument positions; with the functor itself, these decide
977
+ * whether a decoded fact is in normal form without decoding (isNormalForm on a flat ground fact
978
+ * reduces to isDefinedHead over the head and its symbol leaves). */
979
+ readonly leafSyms: readonly string[];
980
+ /** Whether the bucket stores two structurally identical facts (the conjNested routing guard). */
981
+ readonly hasDup: boolean;
982
+ }
983
+ declare function setStaticCompactThresholdForTests(n: number): number;
984
+ /** An empty environment for grounding table `gt`. Grow it with `addAtomToEnv`. */
985
+ declare function emptyEnv(gt: GroundingTable): MinEnv;
986
+ /** Register a sync grounded operation and invalidate analyses that may have classified its name. */
987
+ declare function registerGroundedOperation(env: MinEnv, name: string, op: GroundFn): void;
988
+ /** Register an async grounded operation and invalidate analyses that may have classified its name. */
989
+ declare function registerAsyncGroundedOperation(env: MinEnv, name: string, op: AsyncGroundFn): void;
990
+ declare function addAtomToEnv(env: MinEnv, x: Atom): void;
991
+ declare function buildEnv(atoms: Atom[], gt: GroundingTable, staticCompact?: boolean): MinEnv;
992
+ type NamedSpace = AtomLog;
993
+ interface World {
994
+ spaces: Map<string, NamedSpace>;
995
+ store: Map<number, Atom>;
996
+ tokens: Map<string, Atom>;
997
+ selfExtra: AtomLog;
998
+ flatSelfExtra: FlatAtomSpace | undefined;
999
+ selfRules: Map<string, Array<[Atom, Atom]>>;
1000
+ selfVarRules: ReadonlyArray<[Atom, Atom]>;
1001
+ selfRuleVersion: number;
1002
+ removedStatic: AtomLog;
1003
+ removedStaticHeads: ReadonlySet<string>;
1004
+ removedStaticVarRules: boolean;
1005
+ maxStackDepth: number;
1006
+ }
1007
+ interface St {
1008
+ counter: number;
1009
+ world: World;
1010
+ }
1011
+ declare const initSt: () => St;
1012
+ declare function freshenRule(counter: number, lhs: Atom, rhs: Atom): [Atom, Atom];
1013
+ declare function getTypes(env: MinEnv, a: Atom): Atom[];
1014
+ declare function checkApplication(env: MinEnv, w: World, op: string, args: readonly Atom[], opSig?: Atom[] | undefined): Atom | null;
1015
+ declare function mettaEval(env: MinEnv, fuel: number, st: St, bnd: Bindings, a: Atom): [Array<[Atom, Bindings]>, St];
1016
+ /** Async type-directed evaluation: awaits async grounded operations (`env.agt`). An optional `signal`
1017
+ * makes it cancellable (used by `race` to stop losing branches). */
1018
+ declare function mettaEvalAsync(env: MinEnv, fuel: number, st: St, bnd: Bindings, a: Atom, signal?: AbortSignal): Promise<[Array<[Atom, Bindings]>, St]>;
1019
+ /** Evaluate `atom` (i.e. interpret `(eval atom)`) under `env`, returning the result atoms. */
1020
+ declare function evalAtom(env: MinEnv, atom: Atom, st?: St, fuel?: number): [Atom[], St];
1021
+
1022
+ interface HostInterop {
1023
+ readonly name: string;
1024
+ readonly prelude?: string;
1025
+ readonly asyncOps?: ReadonlyMap<string, AsyncGroundFn>;
1026
+ readonly hostImport?: HostImportFn;
1027
+ dispose?(): Promise<void> | void;
1028
+ }
1029
+ type HostTextLoader = (path: string, from?: string) => Promise<string>;
1030
+ interface ComposeHostInteropsOptions {
1031
+ readonly allowDuplicateAsyncOps?: boolean;
1032
+ }
1033
+ declare function composeHostInterops(interops: readonly HostInterop[], options?: ComposeHostInteropsOptions): HostInterop;
1034
+
1035
+ export { type TableKey as $, type Atom as A, type Bindings as B, type CompiledFns as C, type ReduceResult as D, type EncodedAtomKey as E, FlatKB as F, type GndAtom as G, type HostImportFn as H, type InternTable as I, type Ret as J, type SkelBody as K, type SkelClause as L, type MinEnv as M, type SkelGoal as N, type SkelTail as O, type St as P, type Stack as Q, type ReduceEffect as R, type Skel as S, type TraceSink as T, type StackCons as U, type SymAtom as V, TAG_ARITY as W, TAG_NEWVAR as X, TAG_SYMBOL as Y, TAG_VARREF as Z, type TableBudget as _, type AsyncGroundFn as a, internBuiltExpr as a$, type TableKeyKind as a0, TableSpace as a1, TokenTrie as a2, type TraceEvent as a3, type ValRel as a4, type VarAtom as a5, type VariantAtomKey as a6, type World as a7, _internals as a8, addAtomToEnv as a9, encodeInto as aA, encodePattern as aB, encodeVariantKey as aC, eqRelations as aD, evalAtom as aE, expr as aF, freshenRule as aG, fromRelations as aH, gbool as aI, getTypes as aJ, gfloat as aK, gint as aL, gnd as aM, groundEq as aN, groundType as aO, groundedOperationType as aP, gstr as aQ, gunit as aR, hasEq as aS, hasLoop as aT, hasLoopFromBase as aU, hashOf as aV, initSt as aW, intAbs as aX, intDiv as aY, intMod as aZ, internAtom as a_, addEqRaw as aa, addInt as ab, addValRaw as ac, atomEq as ad, atomSize as ae, atomVars as af, baseTable as ag, buildEnv as ah, callGrounded as ai, canCompactAtom as aj, canInternExprItems as ak, canonInt as al, checkApplication as am, cmpIntVal as an, collectVars as ao, compareNumbers as ap, compileDependentNondetGroup as aq, compileEnv as ar, composeHostInterops as as, createInternTable as at, decodeAt as au, decodeAtom as av, emptyBindings as aw, emptyEnv as ax, emptyExpr as ay, encodeAtom as az, type ActiveTableEntry as b, internExpr as b0, isEmpty as b1, isErrorAtom as b2, isExpr as b3, isGnd as b4, isSym as b5, isTableSafeGroundedOp as b6, isVar as b7, isZero as b8, lookupVal as b9, toF64 as bA, valEntries as bB, variable as bC, makeEqRel as ba, makeValRel as bb, matchFlatAt as bc, metaType as bd, mettaEval as be, mettaEvalAsync as bf, mixHash as bg, mulInt as bh, pettaOpNames as bi, prependValRaw as bj, registerAsyncGroundedOperation as bk, registerGroundedOperation as bl, relations as bm, removeVal as bn, runCompiled as bo, runCompiledEffectCount as bp, setHostEffectsEnabled as bq, setOutputSink as br, setRawSink as bs, setStaticCompactThresholdForTests as bt, size as bu, someVal as bv, stdTable as bw, strHash as bx, subInt as by, sym as bz, AsyncInSyncError as c, BAIL as d, type BindingRel as e, type CompiledHolder as f, type CompiledImpureOps as g, type CompiledRunResult as h, type CompletedTableEntry as i, type ComposeHostInteropsOptions as j, type EqRel as k, type ExprAtom as l, FlatAtomSpace as m, FlatAtomSpaceTable as n, type Frame as o, type Ground as p, type GroundFn as q, type GroundedExec as r, type GroundedMatch as s, type GroundingTable as t, type HostInterop as u, type HostTextLoader as v, type IntVal as w, Interner as x, type Item as y, type MetaType as z };