@metta-ts/core 1.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.
- package/LICENSE +21 -0
- package/README.md +33 -0
- package/dist/index.d.ts +632 -0
- package/dist/index.js +4777 -0
- package/package.json +51 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,632 @@
|
|
|
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. May throw to signal a runtime error. */
|
|
95
|
+
type GroundedExec = (args: readonly Atom[]) => readonly Atom[];
|
|
96
|
+
type GroundedMatch = (other: Atom) => readonly unknown[];
|
|
97
|
+
/** Structural equality of grounded values (LeaTTa `Ground.BEq`). */
|
|
98
|
+
declare function groundEq(a: Ground, b: Ground): boolean;
|
|
99
|
+
/** Interned symbol atom: equal names share one object (reference equality, low allocation). */
|
|
100
|
+
declare function sym(name: string): SymAtom;
|
|
101
|
+
/** Variable atom. Not interned: freshening needs distinct identities. */
|
|
102
|
+
declare function variable(name: string): VarAtom;
|
|
103
|
+
declare function expr(items: readonly Atom[]): ExprAtom;
|
|
104
|
+
/** The built-in type atom for a grounded value (LeaTTa `getTypes` on grounded). */
|
|
105
|
+
declare function groundType(v: Ground): Atom;
|
|
106
|
+
declare function gnd(value: Ground, typ?: Atom, exec?: GroundedExec, match?: GroundedMatch): GndAtom;
|
|
107
|
+
/** Grounded literal constructors. */
|
|
108
|
+
declare const gint: (n: IntVal) => GndAtom;
|
|
109
|
+
declare const gfloat: (n: number) => GndAtom;
|
|
110
|
+
declare const gstr: (s: string) => GndAtom;
|
|
111
|
+
declare const gbool: (b: boolean) => GndAtom;
|
|
112
|
+
declare const gunit: GndAtom;
|
|
113
|
+
declare function metaType(a: Atom): MetaType;
|
|
114
|
+
/** A 32-bit structural hash: equal structures hash equal. O(1) amortised for a fresh atom whose subterms
|
|
115
|
+
* are already hashed. Collisions are possible, so callers verify a match with `atomEq`. */
|
|
116
|
+
declare function hashOf(a: Atom): number;
|
|
117
|
+
/** Total term size (LeaTTa `Atom.size`): leaves are 1, an expression is 1 + sum of parts. */
|
|
118
|
+
declare function atomSize(a: Atom): number;
|
|
119
|
+
/** All variable names occurring in an atom (LeaTTa `Atom.vars`), in first-seen order, deduped. */
|
|
120
|
+
declare function atomVars(a: Atom, out?: string[]): string[];
|
|
121
|
+
/** Collect an atom's variable names into `out`, deduping via the shared `seen` set (O(1) membership instead
|
|
122
|
+
* of a linear `out.includes`). Hot accumulation loops (scopeVars/frameVars) reuse one `seen` across many
|
|
123
|
+
* atoms so the whole walk stays linear; `atomVars` is the one-shot wrapper that seeds `seen` from `out`. */
|
|
124
|
+
declare function collectVars(a: Atom, out: string[], seen: Set<string>): void;
|
|
125
|
+
/** The empty expression `()` (LeaTTa `Atom.empty`), the success marker used by `assert*`. */
|
|
126
|
+
declare const emptyExpr: ExprAtom;
|
|
127
|
+
/** Is this atom an `(Error ...)` expression? */
|
|
128
|
+
declare function isErrorAtom(a: Atom): boolean;
|
|
129
|
+
declare const isExpr: (a: Atom) => a is ExprAtom;
|
|
130
|
+
declare const isVar: (a: Atom) => a is VarAtom;
|
|
131
|
+
declare const isSym: (a: Atom) => a is SymAtom;
|
|
132
|
+
declare const isGnd: (a: Atom) => a is GndAtom;
|
|
133
|
+
/** Structural equality. Interned symbols short-circuit to reference identity. */
|
|
134
|
+
declare function atomEq(a: Atom, b: Atom): boolean;
|
|
135
|
+
|
|
136
|
+
interface ValRel {
|
|
137
|
+
readonly tag: "val";
|
|
138
|
+
readonly x: string;
|
|
139
|
+
readonly a: Atom;
|
|
140
|
+
readonly y: undefined;
|
|
141
|
+
}
|
|
142
|
+
interface EqRel {
|
|
143
|
+
readonly tag: "eq";
|
|
144
|
+
readonly x: string;
|
|
145
|
+
readonly a: undefined;
|
|
146
|
+
readonly y: string;
|
|
147
|
+
}
|
|
148
|
+
type BindingRel = ValRel | EqRel;
|
|
149
|
+
type Bindings = readonly BindingRel[];
|
|
150
|
+
declare const emptyBindings: Bindings;
|
|
151
|
+
/** The atom bound to `$x` by a direct `val` relation, if any (eq aliases are not followed). */
|
|
152
|
+
declare function lookupVal(b: Bindings, x: string): Atom | undefined;
|
|
153
|
+
/** Remove direct value bindings for `x`; equality relations remain. */
|
|
154
|
+
declare function removeVal(b: Bindings, x: string): Bindings;
|
|
155
|
+
/** True if the set contains a trivial self-loop (`$x ← $x` or `$x = $x`). */
|
|
156
|
+
declare function hasLoop(b: Bindings): boolean;
|
|
157
|
+
/** Bind `$x ← a`, dropping any previous value binding for `$x`. Raw: no consistency check. */
|
|
158
|
+
declare function addValRaw(b: Bindings, x: string, a: Atom): Bindings;
|
|
159
|
+
/** Add the alias `$x = $y` (a no-op when `x = y`). Raw: no consistency check. */
|
|
160
|
+
declare function addEqRaw(b: Bindings, x: string, y: string): Bindings;
|
|
161
|
+
|
|
162
|
+
interface Leaf<V> {
|
|
163
|
+
readonly kind: "leaf";
|
|
164
|
+
readonly key: string;
|
|
165
|
+
readonly val: V;
|
|
166
|
+
}
|
|
167
|
+
interface Collision<V> {
|
|
168
|
+
readonly kind: "collision";
|
|
169
|
+
readonly entries: ReadonlyArray<Leaf<V>>;
|
|
170
|
+
}
|
|
171
|
+
type Branch<V> = ReadonlyArray<PNode<V>>;
|
|
172
|
+
type PNode<V> = Leaf<V> | Collision<V> | Branch<V> | null;
|
|
173
|
+
/** A persistent string -> V map. `null` is the empty map. */
|
|
174
|
+
type PMap<V> = Branch<V> | null;
|
|
175
|
+
|
|
176
|
+
/** Distinct ground atoms sharing one 32-bit hash, each with its multiplicity in the log. */
|
|
177
|
+
type Bucket = ReadonlyArray<{
|
|
178
|
+
readonly atom: Atom;
|
|
179
|
+
readonly count: number;
|
|
180
|
+
}>;
|
|
181
|
+
interface LogNode {
|
|
182
|
+
readonly atom: Atom;
|
|
183
|
+
readonly prev: AtomLog;
|
|
184
|
+
readonly size: number;
|
|
185
|
+
/** Exact-match index over the ground atoms in this log (and all earlier nodes). */
|
|
186
|
+
readonly groundIdx: PMap<Bucket>;
|
|
187
|
+
/** Count of non-ground atoms in this log; the index fast path is valid only when this is 0. */
|
|
188
|
+
readonly nonGround: number;
|
|
189
|
+
}
|
|
190
|
+
/** An atom log: `null` is empty; otherwise the most recently appended atom and the rest. */
|
|
191
|
+
type AtomLog = LogNode | null;
|
|
192
|
+
|
|
193
|
+
type ReduceResult = {
|
|
194
|
+
readonly tag: "ok";
|
|
195
|
+
readonly results: readonly Atom[];
|
|
196
|
+
} | {
|
|
197
|
+
readonly tag: "runtimeError";
|
|
198
|
+
readonly msg: string;
|
|
199
|
+
} | {
|
|
200
|
+
readonly tag: "incorrectArgument";
|
|
201
|
+
readonly msg: string;
|
|
202
|
+
} | {
|
|
203
|
+
readonly tag: "noReduce";
|
|
204
|
+
};
|
|
205
|
+
type GroundFn = (args: readonly Atom[]) => ReduceResult;
|
|
206
|
+
type GroundingTable = Map<string, GroundFn>;
|
|
207
|
+
/** Replace the line-output sink used by `println!`/`trace!` (returns the previous sink). */
|
|
208
|
+
declare function setOutputSink(fn: (line: string) => void): (line: string) => void;
|
|
209
|
+
/** Replace the raw (no-newline) sink used by `print!` (returns the previous sink). */
|
|
210
|
+
declare function setRawSink(fn: (text: string) => void): (text: string) => void;
|
|
211
|
+
/** Names of the PeTTa-compat grounded ops. They yield to user `=` rules (PeTTa is rules-first, builtins as
|
|
212
|
+
* fallback), so a program that defines its own e.g. `sort`/`length` is not shadowed by the stdlib one. */
|
|
213
|
+
declare const pettaOpNames: ReadonlySet<string>;
|
|
214
|
+
/** The arithmetic / boolean / list-surgery / math grounding core every KB starts with. */
|
|
215
|
+
declare function baseTable(): GroundingTable;
|
|
216
|
+
/** The full standard-library grounding table (base + stdlib grounded ops + PeTTa-compat). Later entries do
|
|
217
|
+
* not override earlier ones (Map keeps the first), so Hyperon ops win any name shared with PeTTa-compat. */
|
|
218
|
+
declare function stdTable(): GroundingTable;
|
|
219
|
+
/** Dispatch `op` through the grounding table, or `noReduce` if unknown. */
|
|
220
|
+
declare function callGrounded(gt: GroundingTable, op: string, args: readonly Atom[]): ReduceResult;
|
|
221
|
+
|
|
222
|
+
/** Thrown by a compiled node when it meets a case it cannot handle faithfully (division by zero);
|
|
223
|
+
* the caller catches it (along with a native stack `RangeError`) and re-runs the call in the
|
|
224
|
+
* interpreter, which is sound because the compiled subset is side-effect-free. */
|
|
225
|
+
declare const BAIL: unique symbol;
|
|
226
|
+
declare class Tup {
|
|
227
|
+
readonly v: readonly IntVal[];
|
|
228
|
+
constructor(v: readonly IntVal[]);
|
|
229
|
+
}
|
|
230
|
+
type FrameVal = IntVal | Tup;
|
|
231
|
+
type Ty = "int" | "bool" | `tuple${number}`;
|
|
232
|
+
/** A compiled function. `run` is filled after the whole dependency group is compiled, so mutual
|
|
233
|
+
* recursion resolves through the holder object. */
|
|
234
|
+
interface CompiledHolder {
|
|
235
|
+
arity: number;
|
|
236
|
+
retType: Ty;
|
|
237
|
+
paramTypes: Ty[];
|
|
238
|
+
run: (vals: FrameVal[]) => FrameVal | boolean;
|
|
239
|
+
}
|
|
240
|
+
type CompiledFns = Map<string, CompiledHolder>;
|
|
241
|
+
/** Compile every compilable pure single-clause function in `env` to a memoised native closure.
|
|
242
|
+
* Phase 1 infers return types (fixpoint, optimistic over recursion). Phase 2 compiles bodies with
|
|
243
|
+
* those types and drops any that fail end-to-end (a call to an uncompilable function fails too). */
|
|
244
|
+
declare function compileEnv(env: MinEnv): CompiledFns;
|
|
245
|
+
/** Run a compiled function for a ground-int call, returning the result atom, or `undefined` to fall
|
|
246
|
+
* back to the interpreter (not compiled, non-int args, or a runtime bail). */
|
|
247
|
+
declare function runCompiled(env: MinEnv, op: string, partAtoms: readonly Atom[]): Atom | undefined;
|
|
248
|
+
|
|
249
|
+
/** A grounded operation that runs asynchronously, for the async runner. */
|
|
250
|
+
type AsyncGroundFn = (args: readonly Atom[]) => Promise<ReduceResult>;
|
|
251
|
+
/** Thrown when synchronous evaluation reaches an async grounded operation. Use the async runner. */
|
|
252
|
+
declare class AsyncInSyncError extends Error {
|
|
253
|
+
constructor(op: string);
|
|
254
|
+
}
|
|
255
|
+
type Ret = "none" | "chain" | "function";
|
|
256
|
+
interface Frame {
|
|
257
|
+
readonly atom: Atom;
|
|
258
|
+
readonly ret: Ret;
|
|
259
|
+
readonly vars: readonly string[];
|
|
260
|
+
readonly fin: boolean;
|
|
261
|
+
}
|
|
262
|
+
interface StackCons {
|
|
263
|
+
readonly head: Frame;
|
|
264
|
+
readonly tail: Stack;
|
|
265
|
+
}
|
|
266
|
+
type Stack = StackCons | null;
|
|
267
|
+
interface Item {
|
|
268
|
+
readonly stack: Stack;
|
|
269
|
+
readonly bnd: Bindings;
|
|
270
|
+
}
|
|
271
|
+
interface MinEnv {
|
|
272
|
+
ruleIndex: Map<string, Array<[Atom, Atom]>>;
|
|
273
|
+
varRules: Array<[Atom, Atom]>;
|
|
274
|
+
sigs: Map<string, Atom[]>;
|
|
275
|
+
gt: GroundingTable;
|
|
276
|
+
atoms: Atom[];
|
|
277
|
+
types: Map<string, Atom[]>;
|
|
278
|
+
imports: Map<string, Atom[]>;
|
|
279
|
+
exprTypes: Array<[Atom, Atom]>;
|
|
280
|
+
/** Async grounded operations, dispatched by the async runner; empty for pure synchronous evaluation. */
|
|
281
|
+
agt: Map<string, AsyncGroundFn>;
|
|
282
|
+
/** Per-runner `with-mutex` locks (a Promise chain per key), so mutexes do not leak across runners. */
|
|
283
|
+
mutexes: Map<string, Promise<void>>;
|
|
284
|
+
factIndex: Map<string, Atom[]>;
|
|
285
|
+
argIndex: Map<string, Atom[]>;
|
|
286
|
+
nonGroundAtPos: Map<string, Atom[]>;
|
|
287
|
+
varHeadedFacts: Atom[];
|
|
288
|
+
/** Automatic-tabling memo: a ground pure call's printed form maps to its ordered result bag.
|
|
289
|
+
* `undefined` when tabling is disabled. */
|
|
290
|
+
table?: Map<string, Atom[]>;
|
|
291
|
+
/** Functor names proven tabling-safe by `analyzePurity`; recomputed when equations change. */
|
|
292
|
+
pureFunctors?: Set<string>;
|
|
293
|
+
/** Memo for `getTypes` of ground atoms: a ground atom's type is a pure function of the env's type tables,
|
|
294
|
+
* which only change via `addAtomToEnv` (where this is reset). Keyed by atom identity, so the recursion
|
|
295
|
+
* reuses the type of every shared subterm (a growing Peano/list term is the worst case otherwise). */
|
|
296
|
+
typeCache?: WeakMap<Atom, Atom[]> | undefined;
|
|
297
|
+
/** Optional parallel branch evaluator for `hyperpose` (set by the Node runner to a worker_threads pool;
|
|
298
|
+
* undefined in the browser). Given the formatted branch atoms and whether to stop at the first result,
|
|
299
|
+
* returns each branch's result atoms, or `null` for a branch that errored or (under firstOnly) lost the
|
|
300
|
+
* race. It re-evaluates each branch from the program's rules in a worker, so it is only used when a branch
|
|
301
|
+
* is pure and the space carries no runtime additions, so it is identical to evaluating in line. */
|
|
302
|
+
parEval?: (branchSrcs: string[], firstOnly: boolean) => (Atom[] | null)[];
|
|
303
|
+
/** Compiled pure deterministic functions (the int/bool functional core); undefined when disabled. */
|
|
304
|
+
compiled?: CompiledFns;
|
|
305
|
+
/** Set when an equation changed, so the compiler re-runs before the next query. */
|
|
306
|
+
compileDirty?: boolean;
|
|
307
|
+
/** Opt-in PeTTa-style auto-currying, enabled by `(import! &self curry)`. When set, a symbol-headed
|
|
308
|
+
* call applied to fewer arguments than the function's arity reduces to `(partial fn (args))` instead
|
|
309
|
+
* of staying irreducible. Off by default, so the Hyperon oracle baseline is unaffected. */
|
|
310
|
+
curry?: boolean;
|
|
311
|
+
}
|
|
312
|
+
/** An empty environment for grounding table `gt`. Grow it with `addAtomToEnv`. */
|
|
313
|
+
declare function emptyEnv(gt: GroundingTable): MinEnv;
|
|
314
|
+
/** Incorporate one atom into `env` (mutating): rule index, signatures, types, and the atom list.
|
|
315
|
+
* Lets a sequential runner extend the env per atom instead of rebuilding it each query; correctness
|
|
316
|
+
* gated by the 270/270 oracle. */
|
|
317
|
+
declare function addAtomToEnv(env: MinEnv, x: Atom): void;
|
|
318
|
+
declare function buildEnv(atoms: Atom[], gt: GroundingTable): MinEnv;
|
|
319
|
+
interface World {
|
|
320
|
+
spaces: Map<string, Atom[]>;
|
|
321
|
+
store: Map<number, Atom>;
|
|
322
|
+
tokens: Map<string, Atom>;
|
|
323
|
+
selfExtra: AtomLog;
|
|
324
|
+
selfRules: Map<string, Array<[Atom, Atom]>>;
|
|
325
|
+
selfVarRules: ReadonlyArray<[Atom, Atom]>;
|
|
326
|
+
maxStackDepth: number;
|
|
327
|
+
}
|
|
328
|
+
interface St {
|
|
329
|
+
counter: number;
|
|
330
|
+
world: World;
|
|
331
|
+
}
|
|
332
|
+
declare const initSt: () => St;
|
|
333
|
+
declare function freshenRule(counter: number, lhs: Atom, rhs: Atom): [Atom, Atom];
|
|
334
|
+
declare function getTypes(env: MinEnv, a: Atom): Atom[];
|
|
335
|
+
declare function mettaEval(env: MinEnv, fuel: number, st: St, bnd: Bindings, a: Atom): [Array<[Atom, Bindings]>, St];
|
|
336
|
+
/** Async type-directed evaluation: awaits async grounded operations (`env.agt`). An optional `signal`
|
|
337
|
+
* makes it cancellable (used by `race` to stop losing branches). */
|
|
338
|
+
declare function mettaEvalAsync(env: MinEnv, fuel: number, st: St, bnd: Bindings, a: Atom, signal?: AbortSignal): Promise<[Array<[Atom, Bindings]>, St]>;
|
|
339
|
+
/** Evaluate `atom` (i.e. interpret `(eval atom)`) under `env`, returning the result atoms. */
|
|
340
|
+
declare function evalAtom(env: MinEnv, atom: Atom, st?: St, fuel?: number): [Atom[], St];
|
|
341
|
+
|
|
342
|
+
/** Ops that read or write mutable state, do I/O, read types/spaces, or introduce nondeterminism.
|
|
343
|
+
* A functor whose body reaches any of these (directly or transitively) is not tabled in P1. */
|
|
344
|
+
declare const IMPURE_OPS: ReadonlySet<string>;
|
|
345
|
+
/** The set of functor names safe to table. Conservative: a variable-headed (`$x`-headed) equation can match
|
|
346
|
+
* anything, so its presence disables tabling entirely. (`varRules` also holds expression-headed equations,
|
|
347
|
+
* which match only their own constructor and are harmless here.) */
|
|
348
|
+
declare function analyzePurity(env: MinEnv): Set<string>;
|
|
349
|
+
/** The memo key for a ground call. The call has no variables, so its printed form is canonical. */
|
|
350
|
+
declare function tableKey(call: Atom): string;
|
|
351
|
+
/** A key is well-formed only if it contains no Float leaf (IEEE-754 breaks lawful equality, so a
|
|
352
|
+
* float-keyed table could merge or split keys differently from `match`). Mutable references never
|
|
353
|
+
* appear in a ground call, so the float check is the only one needed in P1. */
|
|
354
|
+
declare function keyWellFormed(a: Atom): boolean;
|
|
355
|
+
|
|
356
|
+
/** A relation: a set of tuples, each a binding of this relation's variables to values. */
|
|
357
|
+
interface Relation<V> {
|
|
358
|
+
readonly vars: readonly string[];
|
|
359
|
+
readonly tuples: ReadonlyArray<ReadonlyMap<string, V>>;
|
|
360
|
+
}
|
|
361
|
+
/** The worst-case-optimal join (generic join / leapfrog-triejoin family): all bindings of every variable
|
|
362
|
+
* satisfying all relations. Each relation is indexed once into a trie over its variables in the join
|
|
363
|
+
* order, so binding a variable intersects the relations' current trie levels by key lookup rather than
|
|
364
|
+
* rescanning every tuple. That avoids the naive generic join's repeated tuple scans. `key` maps a
|
|
365
|
+
* value to a comparable string; pass `varOrder` to fix the elimination order (first-seen otherwise). */
|
|
366
|
+
declare function wcoJoin<V>(rels: ReadonlyArray<Relation<V>>, key: (v: V) => string, varOrder?: readonly string[]): Array<Map<string, V>>;
|
|
367
|
+
|
|
368
|
+
/** A substitution: an association list of variable name to atom. */
|
|
369
|
+
type Subst = ReadonlyArray<readonly [string, Atom]>;
|
|
370
|
+
declare const emptySubst: Subst;
|
|
371
|
+
/** First value assigned to `x`, if any. */
|
|
372
|
+
declare function lookupSubst(s: Subst, x: string): Atom | undefined;
|
|
373
|
+
/** Drop every binding for `x`. */
|
|
374
|
+
declare function eraseSubst(s: Subst, x: string): Subst;
|
|
375
|
+
/** `(x,a) :: erase s x` (LeaTTa `Subst.extend`). */
|
|
376
|
+
declare function extendSubst(s: Subst, x: string, a: Atom): Subst;
|
|
377
|
+
/** Apply `s` to an atom: replace each variable by its assigned value (one pass; the substituted
|
|
378
|
+
* value is not itself re-substituted). */
|
|
379
|
+
declare function applySubst(s: Subst, a: Atom): Atom;
|
|
380
|
+
/** Occurs-check: does `$x` appear anywhere in the atom? */
|
|
381
|
+
declare function occurs(x: string, a: Atom): boolean;
|
|
382
|
+
|
|
383
|
+
/** Most-general unifier of two atoms, or null if they do not unify. */
|
|
384
|
+
declare function unifyTop(a: Atom, b: Atom): Subst | null;
|
|
385
|
+
/** Whether two atoms unify (the satisfiability check used by addVarBinding). */
|
|
386
|
+
declare function unifiable(a: Atom, b: Atom): boolean;
|
|
387
|
+
|
|
388
|
+
/** A custom matcher for grounded atoms; may be nondeterministic. */
|
|
389
|
+
type GroundMatcher = (left: Atom, right: Atom) => Bindings[];
|
|
390
|
+
/** Add `$x ← v` to `b` consistently. If `$x` is already bound to a different value, reconcile the old value
|
|
391
|
+
* against the new one (propagating the unification constraint), rejecting a cyclic result. Mirrors hyperon's
|
|
392
|
+
* `add_var_binding` with LeaTTa's occurs check. */
|
|
393
|
+
declare function addVarBinding(b: Bindings, x: string, v: Atom): Bindings[];
|
|
394
|
+
/** Add the alias `$x = $y` to `b` consistently. If both are already value-bound to different values,
|
|
395
|
+
* reconcile those values (mirrors hyperon's `add_var_equality`); otherwise record the equality. */
|
|
396
|
+
declare function addVarEquality(b: Bindings, x: string, y: string): Bindings[];
|
|
397
|
+
/** Combine two binding sets into all their consistent unions (LeaTTa `merge`). */
|
|
398
|
+
declare function merge(a: Bindings, b: Bindings): Bindings[];
|
|
399
|
+
/** Match atoms in the official left/right style (LeaTTa `matchAtomsWith`). `leftSuffix` (default empty)
|
|
400
|
+
* scopes the LEFT atom's variables: a left variable `$x` is treated as `$x<suffix>`, so a rule LHS can be
|
|
401
|
+
* matched without first cloning it with freshened variables. */
|
|
402
|
+
declare function matchAtomsWith(custom: GroundMatcher | undefined, l: Atom, r: Atom, leftSuffix?: string): Bindings[];
|
|
403
|
+
/** Match pattern `l` against `r` with the default matcher (no custom grounded matching). */
|
|
404
|
+
declare function matchAtoms(l: Atom, r: Atom): Bindings[];
|
|
405
|
+
/** Match a rule LHS `l` against `r`, scoping `l`'s variables with `suffix` (so the rule need not be cloned
|
|
406
|
+
* with freshened variables first). The resulting bindings key the rule variables as `name<suffix>`, exactly
|
|
407
|
+
* as upfront freshening would, so `instantiate(_, rhs, suffix)` resolves the matching RHS identically. */
|
|
408
|
+
declare function matchAtomsScoped(l: Atom, r: Atom, suffix: string): Bindings[];
|
|
409
|
+
|
|
410
|
+
/** A binding set viewed as a substitution: value bindings only; `eq` aliases are dropped. */
|
|
411
|
+
declare function bindingsToSubst(b: Bindings): Subst;
|
|
412
|
+
/** Apply a binding set to an atom: replace each variable by its value binding (eq aliases dropped), one
|
|
413
|
+
* pass. Walks `b` directly via `lookupVal` instead of first materializing a `Subst` array on every call.
|
|
414
|
+
* that conversion was pure allocation on the hot substitution path (instantiate dominated the emit
|
|
415
|
+
* profile). A new term is built only where a child changed; the empty binding and closed subterms
|
|
416
|
+
* short-circuit to sharing. */
|
|
417
|
+
declare function instantiate(b: Bindings, a: Atom, suffix?: string): Atom;
|
|
418
|
+
|
|
419
|
+
declare function alphaEq(a: Atom, b: Atom): boolean;
|
|
420
|
+
|
|
421
|
+
type TokenConstructor = (token: string) => Atom;
|
|
422
|
+
declare class Tokenizer {
|
|
423
|
+
private readonly entries;
|
|
424
|
+
/** Register a (regex, constructor). Order matters: the first matching pattern wins. */
|
|
425
|
+
register(re: RegExp, make: TokenConstructor): void;
|
|
426
|
+
/** A grounded atom for `token`, or undefined if no pattern matches (caller falls back to Symbol). */
|
|
427
|
+
tokenize(token: string): Atom | undefined;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
interface TopAtom {
|
|
431
|
+
readonly atom: Atom;
|
|
432
|
+
readonly bang: boolean;
|
|
433
|
+
}
|
|
434
|
+
declare function parse(src: string, tk: Tokenizer): Atom | undefined;
|
|
435
|
+
/** Parse a whole program into its sequence of top-level atoms. */
|
|
436
|
+
declare function parseAll(src: string, tk: Tokenizer): TopAtom[];
|
|
437
|
+
/** Print an atom back to MeTTa source (inverse of parse for normalized input). */
|
|
438
|
+
declare function format(a: Atom): string;
|
|
439
|
+
|
|
440
|
+
interface Space {
|
|
441
|
+
add(atom: Atom): void;
|
|
442
|
+
/** Remove the first structurally-equal atom; returns whether one was removed. */
|
|
443
|
+
remove(atom: Atom): boolean;
|
|
444
|
+
/** All binding sets under which `pattern` matches a stored atom. `freshen`, if given, is applied
|
|
445
|
+
* to each stored atom before matching (rule-variable freshening). */
|
|
446
|
+
query(pattern: Atom, freshen?: (a: Atom) => Atom): Bindings[];
|
|
447
|
+
atoms(): readonly Atom[];
|
|
448
|
+
}
|
|
449
|
+
/** Linear-scan in-memory space. Indexing is a future extension behind this same interface. */
|
|
450
|
+
declare class InMemorySpace implements Space {
|
|
451
|
+
private readonly store;
|
|
452
|
+
add(atom: Atom): void;
|
|
453
|
+
remove(atom: Atom): boolean;
|
|
454
|
+
query(pattern: Atom, freshen?: (a: Atom) => Atom): Bindings[];
|
|
455
|
+
atoms(): readonly Atom[];
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
/** The standard tokenizer: integer/float literals and the `True`/`False` grounded booleans. */
|
|
459
|
+
declare function standardTokenizer(): Tokenizer;
|
|
460
|
+
/** The prelude's atoms (parsed once and cached). */
|
|
461
|
+
declare function preludeAtoms(): Atom[];
|
|
462
|
+
interface QueryResult {
|
|
463
|
+
readonly query: Atom;
|
|
464
|
+
readonly results: Atom[];
|
|
465
|
+
}
|
|
466
|
+
declare const DEFAULT_FUEL = 100000;
|
|
467
|
+
interface RunOptions {
|
|
468
|
+
readonly tabling?: boolean;
|
|
469
|
+
readonly maxStackDepth?: number;
|
|
470
|
+
readonly parEvalImpl?: (rulesSrc: string, branchSrcs: string[], firstOnly: boolean) => (string[] | null)[];
|
|
471
|
+
}
|
|
472
|
+
/** Evaluate a parsed program sequentially. `imports` backs `import!` (pre-read by the caller). */
|
|
473
|
+
declare function evalSequential(atoms: readonly {
|
|
474
|
+
atom: Atom;
|
|
475
|
+
bang: boolean;
|
|
476
|
+
}[], fuel?: number, imports?: Map<string, Atom[]>, opts?: RunOptions): QueryResult[];
|
|
477
|
+
/** Parse and run a MeTTa source string sequentially. */
|
|
478
|
+
declare function runProgram(src: string, fuel?: number, imports?: Map<string, Atom[]>, opts?: RunOptions): QueryResult[];
|
|
479
|
+
/** Async sequential evaluation: like `runProgram`, but `!`-queries are awaited, so async grounded
|
|
480
|
+
* operations (registered in `asyncOps`) can perform I/O. Sync programs give identical results to
|
|
481
|
+
* `runProgram`; the async path only differs when an async op is actually reached. */
|
|
482
|
+
declare function runProgramAsync(src: string, asyncOps?: Map<string, AsyncGroundFn>, fuel?: number, imports?: Map<string, Atom[]>): Promise<QueryResult[]>;
|
|
483
|
+
/** Module names referenced by top-level `import!` statements (so a caller can pre-read them). */
|
|
484
|
+
declare function collectImports(src: string): string[];
|
|
485
|
+
/** An oracle assertion passes iff its query evaluates to exactly the unit atom `()`. */
|
|
486
|
+
declare function isOraclePass(r: QueryResult): boolean;
|
|
487
|
+
/** Run a test file and report pass/fail counts and the failing queries. */
|
|
488
|
+
declare function oracleReport(src: string, fuel?: number, imports?: Map<string, Atom[]>): {
|
|
489
|
+
total: number;
|
|
490
|
+
passed: number;
|
|
491
|
+
failures: string[];
|
|
492
|
+
};
|
|
493
|
+
|
|
494
|
+
/** The `concurrency` module: timing/concurrency extensions (transaction, and later par/race/mutex). */
|
|
495
|
+
declare const CONCURRENCY_MODULE_SRC = "\n (: transaction (-> Atom %Undefined%))\n";
|
|
496
|
+
/** The `curry` module: PeTTa-style partial application. Importing it sets the engine's curry flag (see
|
|
497
|
+
* the import! handler), so a symbol-headed call applied to fewer arguments than the function's arity
|
|
498
|
+
* reduces to `(partial fn (args))`. This module supplies the rules that *apply* such a closure (append
|
|
499
|
+
* the new arguments and re-evaluate the now-fuller call, which re-curries if still short), plus the
|
|
500
|
+
* same under-application handling for |-> lambdas, whose head is an expression and so is not reached by
|
|
501
|
+
* the symbol-headed hook. Off unless imported, so the Hyperon oracle baseline is untouched. */
|
|
502
|
+
declare const CURRY_MODULE_SRC = "\n (: partial (-> Atom Expression Atom))\n\n ; Apply a closure to further arguments: append them to the bound list, rebuild the call, evaluate it.\n ; append is forced through its own let (cons-atom would otherwise take it as a literal subexpression),\n ; and the rebuilt call is fully reduced with metta (eval is a single step), which re-curries if still\n ; under-applied.\n (= ((partial $f $bound) $a)\n (let $args (append $bound ($a))\n (let $call (cons-atom $f $args) (metta $call %Undefined% &self))))\n (= ((partial $f $bound) $a $b)\n (let $args (append $bound ($a $b))\n (let $call (cons-atom $f $args) (metta $call %Undefined% &self))))\n\n ; An under-applied |-> lambda (head is an expression, so the core hook does not see it) becomes a\n ; partial closure over the lambda value; applying it later rebuilds the full application.\n (= ((|-> ($p1 $p2) $body) $a1)\n (partial (|-> ($p1 $p2) $body) ($a1)))\n (= ((|-> ($p1 $p2 $p3) $body) $a1)\n (partial (|-> ($p1 $p2 $p3) $body) ($a1)))\n (= ((|-> ($p1 $p2 $p3) $body) $a1 $a2)\n (partial (|-> ($p1 $p2 $p3) $body) ($a1 $a2)))\n";
|
|
503
|
+
/** The built-in extension modules, by the name used in `(import! &self <name>)`. */
|
|
504
|
+
declare function builtinModules(): Map<string, Atom[]>;
|
|
505
|
+
/** A fresh imports map seeded with the built-in extension modules, optionally merged with caller
|
|
506
|
+
* imports. Built-ins are only applied when a program actually `(import! ...)`s them, so this never
|
|
507
|
+
* affects the Hyperon oracle baseline. Built-in module names are reserved: a caller-supplied module of
|
|
508
|
+
* the same name does NOT override the built-in (otherwise a disk file that happens to share a name, e.g.
|
|
509
|
+
* a corpus `curry.metta` that itself does `(import! &self curry)`, would shadow the built-in rules). */
|
|
510
|
+
declare function withBuiltinModules(extra?: Map<string, Atom[]>): Map<string, Atom[]>;
|
|
511
|
+
|
|
512
|
+
declare const STDLIB_SRC = "\n ; ---- Types of the grounded ops (math, bool, atom). Hyperon's grounded atoms carry their type\n ; intrinsically and `get-type` reads it; @metta-ts grounds these as host functions in builtins.ts,\n ; so the type signature is declared here to match. Values from hyperon-experimental math.rs/atom.rs\n ; (math ops are f64-valued, so e.g. pow-math/sqrt-math return Number; min-atom/max-atom take any\n ; expression, typed %Undefined% -> Number). The core arithmetic and comparison ops (+ - < == \u2026) are\n ; already declared in the prelude.\n (: pow-math (-> Number Number Number))\n (: sqrt-math (-> Number Number))\n (: abs-math (-> Number Number))\n (: log-math (-> Number Number Number))\n (: trunc-math (-> Number Number))\n (: ceil-math (-> Number Number))\n (: floor-math (-> Number Number))\n (: round-math (-> Number Number))\n (: sin-math (-> Number Number))\n (: asin-math (-> Number Number))\n (: cos-math (-> Number Number))\n (: acos-math (-> Number Number))\n (: tan-math (-> Number Number))\n (: atan-math (-> Number Number))\n (: isnan-math (-> Number Bool))\n (: isinf-math (-> Number Bool))\n (: min-atom (-> %Undefined% Number))\n (: max-atom (-> %Undefined% Number))\n (: and (-> Bool Bool Bool))\n (: or (-> Bool Bool Bool))\n (: not (-> Bool Bool))\n (: xor (-> Bool Bool Bool))\n\n ; sealed alpha-renames the variables of its second argument. That argument is Atom-typed so the\n ; body reaches sealed unevaluated (hyperon-experimental core.rs: (-> Expression Atom Atom)); without\n ; this the reduce loop would evaluate the body first, e.g. collapsing (== 1 $e) before renaming.\n (: sealed (-> Expression Atom Atom))\n\n ; ---- IO (host primitives grounded in builtins.ts) ----\n (: println! (-> %Undefined% (->)))\n (: print! (-> %Undefined% (->)))\n (: format-args (-> String Expression String))\n ; repr renders an atom's textual form. The argument is Atom-typed (not evaluated) so repr shows the\n ; atom as written; to repr a reduced form, evaluate it first (e.g. bind it with let).\n (: repr (-> Atom String))\n\n ; trace! prints its first argument and returns the (evaluated) second.\n (: trace! (-> %Undefined% %Undefined% %Undefined%))\n (= (trace! $msg $ret) (let $unit (println! $msg) $ret))\n\n ; include = import a module's contents into the current space.\n (: include (-> Atom %Undefined%))\n (= (include $module) (import! &self $module))\n\n ; ---- Error system ----\n (: ErrorType Type)\n (: ErrorDescription Type)\n (: IncorrectNumberOfArguments ErrorDescription)\n (: BadType (-> Type Type ErrorDescription))\n (: BadArgType (-> Number Type Type ErrorDescription))\n\n ; ---- Module system (minimal: @metta-ts resolves modules via import! into a space) ----\n (: module-space-no-deps (-> SpaceType SpaceType))\n (= (module-space-no-deps $s) $s)\n (: print-mods! (-> (->)))\n (= (print-mods!) ())\n (: git-module! (-> Atom (->)))\n (= (git-module! $url) (Error (git-module! $url) \"git-module! is not supported in @metta-ts\"))\n\n ; ---- Documentation system (ported from hyperon stdlib.metta) ----\n (: DocDescription Type)\n (: DocInformal Type)\n (: DocFormal Type)\n (: DocItem Type)\n (: DocKindFunction Type)\n (: DocKindAtom Type)\n (: DocType Type)\n (: DocParameters Type)\n (: DocParameter Type)\n (: DocParameterInformal Type)\n (: DocReturn Type)\n (: DocReturnInformal Type)\n (: @doc (-> Atom DocDescription DocParameters DocReturnInformal DocInformal))\n (: @desc (-> String DocDescription))\n (: @param (-> DocType DocDescription DocParameter))\n (: @return (-> DocType DocDescription DocReturn))\n (: @doc-formal (-> DocItem DocKindFunction DocType DocDescription DocParameters DocReturn DocFormal))\n (: @item (-> Atom DocItem))\n (: @kind (-> Atom DocKindFunction))\n (: @type (-> Type DocType))\n (: @params (-> Expression DocParameters))\n\n (= (get-doc-single-atom $space $atom)\n (let $type (get-type-space $space $atom)\n (if (is-function $type)\n (get-doc-function $space $atom $type)\n (get-doc-atom $space $atom) )))\n (= (get-doc-function $space $name $type)\n (unify $space (@doc $name $desc (@params $params) $ret)\n (let $type' (if (== $type %Undefined%) (undefined-doc-function-type $params) (cdr-atom $type))\n (let ($params' $ret') (get-doc-params $params $ret $type')\n (@doc-formal (@item $name) (@kind function) (@type $type) $desc (@params $params') $ret')))\n Empty ))\n (= (get-doc-atom $space $atom)\n (let $type (get-type-space $space $atom)\n (unify $space (@doc $atom $desc)\n (@doc-formal (@item $atom) (@kind atom) (@type $type) $desc)\n (unify $space (@doc $atom $desc' (@params $params) $ret)\n (get-doc-function $space $atom %Undefined%)\n Empty ))))\n (= (get-doc-params $params $ret $types)\n (let $head-type (car-atom $types)\n (let $tail-types (cdr-atom $types)\n (if (== () $params)\n (let (@return $ret-desc) $ret\n (() (@return (@type $head-type) (@desc $ret-desc))) )\n (let (@param $param-desc) (car-atom $params)\n (let $tail-params (cdr-atom $params)\n (let ($params' $result-ret) (get-doc-params $tail-params $ret $tail-types)\n (let $result-params (cons-atom (@param (@type $head-type) (@desc $param-desc)) $params')\n ($result-params $result-ret) ))))))))\n (= (undefined-doc-function-type $params)\n (if (== () $params) (%Undefined%)\n (let $params-tail (cdr-atom $params)\n (let $tail (undefined-doc-function-type $params-tail)\n (cons-atom %Undefined% $tail) ))))\n (= (help-param! $param)\n (let (@param (@type $type) (@desc $desc)) $param\n (println! (format-args \" {} {}\" ((type $type) $desc))) ))\n (: help-space! (-> SpaceType (->)))\n (= (help-space! $space)\n (let $_ (collapse\n (unify $space (@doc $name (@desc $desc) $params $ret)\n (let () (println! (format-args \"{} {}\" ($name $desc))) Empty)\n Empty )) ()))\n\n ; mod-space! loads a module into a fresh space and returns it.\n (: mod-space! (-> Atom SpaceType))\n (= (mod-space! $module) (let $s (new-space) (let $u (import! $s $module) $s)))\n";
|
|
513
|
+
/** The standard-library atoms (parsed once and cached). Always loaded by the runner. */
|
|
514
|
+
declare function stdlibAtoms(): Atom[];
|
|
515
|
+
|
|
516
|
+
declare const TAG_ARITY = 0;
|
|
517
|
+
declare const TAG_SYMBOL = 1;
|
|
518
|
+
declare const TAG_NEWVAR = 2;
|
|
519
|
+
declare const TAG_VARREF = 3;
|
|
520
|
+
/** Interns symbols and grounded values to dense integer ids, with a reverse map so a flat atom decodes
|
|
521
|
+
* back exactly. Symbols and grounds share the id space (a ground's id reconstructs the ground). */
|
|
522
|
+
declare class Interner {
|
|
523
|
+
private readonly byKey;
|
|
524
|
+
private readonly entries;
|
|
525
|
+
private add;
|
|
526
|
+
internSym(name: string): number;
|
|
527
|
+
internGround(value: Ground): number;
|
|
528
|
+
/** The id for a symbol/ground if already interned, else undefined (a pattern symbol absent from the
|
|
529
|
+
* KB can never match, so its lookup short-circuits). */
|
|
530
|
+
lookupSym(name: string): number | undefined;
|
|
531
|
+
lookupGround(value: Ground): number | undefined;
|
|
532
|
+
/** Reconstruct the atom for a leaf id. */
|
|
533
|
+
decodeLeaf(id: number): Atom;
|
|
534
|
+
get size(): number;
|
|
535
|
+
}
|
|
536
|
+
/** Encode an atom into the token array `out`, interning leaves. `varMap` assigns de Bruijn indices to
|
|
537
|
+
* variable names (shared across one atom so repeated variables become VARREF). */
|
|
538
|
+
declare function encodeInto(a: Atom, out: number[], it: Interner, varMap: Map<string, number>): void;
|
|
539
|
+
/** Encode a single atom to a token array. */
|
|
540
|
+
declare function encodeAtom(a: Atom, it: Interner): number[];
|
|
541
|
+
/** Decode the token at `pos`, returning the atom and the position after it. Variables are reconstructed
|
|
542
|
+
* with de Bruijn names `$0`, `$1`, … (so a decoded atom is alpha-equivalent to the original). */
|
|
543
|
+
declare function decodeAt(tokens: Int32Array | number[], pos: number, it: Interner): [Atom, number];
|
|
544
|
+
/** Decode a full token array to an atom. */
|
|
545
|
+
declare function decodeAtom(tokens: Int32Array | number[], it: Interner): Atom;
|
|
546
|
+
/** The number of tokens in the subterm starting at `pos`. */
|
|
547
|
+
declare function subtermLen(tokens: Int32Array | number[], pos: number): number;
|
|
548
|
+
/** Encode a query pattern using lookup (not interning): returns the tokens and the variable names in de
|
|
549
|
+
* Bruijn order, or `null` if a pattern symbol/ground is absent from the interner (fast fail; it can
|
|
550
|
+
* never match any stored fact). */
|
|
551
|
+
declare function encodePattern(a: Atom, it: Interner): {
|
|
552
|
+
tokens: number[];
|
|
553
|
+
varNames: string[];
|
|
554
|
+
} | null;
|
|
555
|
+
/** One-sided match of an encoded pattern against an encoded ground fact in a (possibly shared) token
|
|
556
|
+
* array. Returns the variable bindings (de Bruijn index -> the matched fact subterm's [start, end)
|
|
557
|
+
* token range), or `null` on mismatch. Pure integer work over the token array, so a worker can run it
|
|
558
|
+
* against a `SharedArrayBuffer`-backed `Int32Array` with no copying. */
|
|
559
|
+
declare function matchFlatAt(pat: ArrayLike<number>, fact: Int32Array | number[], factStart: number): Map<number, [number, number]> | null;
|
|
560
|
+
/** A flat, interned knowledge base: facts are appended as token runs into one array, indexed by head
|
|
561
|
+
* functor id, and matched against an encoded pattern by integer scan. */
|
|
562
|
+
declare class FlatKB {
|
|
563
|
+
readonly interner: Interner;
|
|
564
|
+
private readonly tokens;
|
|
565
|
+
private readonly byFunctor;
|
|
566
|
+
private readonly other;
|
|
567
|
+
private readonly offsets;
|
|
568
|
+
/** The token array (for packing into a SharedArrayBuffer). */
|
|
569
|
+
get tokenArray(): readonly number[];
|
|
570
|
+
/** Every fact's start offset, in insertion order (for sharding across workers). */
|
|
571
|
+
get factOffsets(): readonly number[];
|
|
572
|
+
/** Add a (typically ground) atom to the KB. */
|
|
573
|
+
add(a: Atom): void;
|
|
574
|
+
/** Candidate fact offsets for a pattern, using the functor index when the pattern head is a known
|
|
575
|
+
* symbol; otherwise every fact. */
|
|
576
|
+
private candidates;
|
|
577
|
+
/** Match `pattern` against the KB, returning a binding map (variable name -> matched atom) per match. */
|
|
578
|
+
match(pattern: Atom): Array<Map<string, Atom>>;
|
|
579
|
+
get size(): number;
|
|
580
|
+
}
|
|
581
|
+
declare const _internals: {
|
|
582
|
+
tok: (tag: number, payload?: number) => number;
|
|
583
|
+
tagOf: (tok: number) => number;
|
|
584
|
+
payloadOf: (tok: number) => number;
|
|
585
|
+
subtermLen: typeof subtermLen;
|
|
586
|
+
};
|
|
587
|
+
|
|
588
|
+
/** A frequent subpattern and its compression economics. */
|
|
589
|
+
interface HeavyPattern {
|
|
590
|
+
/** The repeated subpattern (decoded for inspection). */
|
|
591
|
+
readonly pattern: Atom;
|
|
592
|
+
/** How many times it occurs across the KB. */
|
|
593
|
+
readonly count: number;
|
|
594
|
+
/** Its size in tokens. */
|
|
595
|
+
readonly len: number;
|
|
596
|
+
/** Tokens saved by factoring it: `(count - 1) * len - count * refCost`. */
|
|
597
|
+
readonly gain: number;
|
|
598
|
+
}
|
|
599
|
+
/**
|
|
600
|
+
* The top-`k` heaviest repeated subpatterns in `kb`, by compression gain. `refCost` is the token cost of
|
|
601
|
+
* a reference to a factored definition (MORK starts at ~4–8). Only subpatterns occurring ≥2 times with
|
|
602
|
+
* positive gain are returned (single symbols never pay to factor). Brute-force and exact; the oracle
|
|
603
|
+
* for any future output-sensitive index.
|
|
604
|
+
*/
|
|
605
|
+
declare function williamTopK(kb: FlatKB, k: number, refCost?: number): HeavyPattern[];
|
|
606
|
+
|
|
607
|
+
declare class Trail {
|
|
608
|
+
private readonly binds;
|
|
609
|
+
private readonly trail;
|
|
610
|
+
/** A restore point: the current trail length. */
|
|
611
|
+
mark(): number;
|
|
612
|
+
/** Undo every binding made since `m`. */
|
|
613
|
+
undo(m: number): void;
|
|
614
|
+
/** Bind `$name` to `a` and record it on the trail. The caller guarantees `$name` is currently unbound. */
|
|
615
|
+
bind(name: string, a: Atom): void;
|
|
616
|
+
/** Follow variable bindings to the representative: a non-variable, or an unbound variable. */
|
|
617
|
+
deref(a: Atom): Atom;
|
|
618
|
+
/** Resolve `a` against the current bindings, one pass (the same discipline as the immutable
|
|
619
|
+
* `instantiate`/`applySubst`): a variable becomes its bound value as-is; the value's own variables are
|
|
620
|
+
* not re-resolved, and an expression's children are resolved. This matches the evaluator exactly,
|
|
621
|
+
* including that a cyclic binding (`$y = (.. $y ..)`, which `matchAtoms` produces and `hasLoop` does not
|
|
622
|
+
* reject) terminates instead of looping. A new term is built only where a child changed. */
|
|
623
|
+
resolve(a: Atom): Atom;
|
|
624
|
+
}
|
|
625
|
+
/** Unify two atoms against the trail, binding variables in place; returns whether they unify. On failure
|
|
626
|
+
* the trail may hold partial bindings, so callers undo to a mark. Mirrors the immutable matcher: a
|
|
627
|
+
* variable binds to the other side (no occurs check; `matchAtoms` admits cyclic bindings and the
|
|
628
|
+
* evaluator's one-pass `resolve` handles them, so adding one here would diverge), two symbols/grounded
|
|
629
|
+
* values must be equal, two expressions must have equal arity and unify pointwise. */
|
|
630
|
+
declare function unifyTrail(tr: Trail, l0: Atom, r0: Atom): boolean;
|
|
631
|
+
|
|
632
|
+
export { type AsyncGroundFn, AsyncInSyncError, type Atom, BAIL, type BindingRel, type Bindings, CONCURRENCY_MODULE_SRC, CURRY_MODULE_SRC, type CompiledFns, type CompiledHolder, DEFAULT_FUEL, type EqRel, type ExprAtom, FlatKB, type Frame, type GndAtom, type Ground, type GroundFn, type GroundMatcher, type GroundedExec, type GroundedMatch, type GroundingTable, type HeavyPattern, IMPURE_OPS, InMemorySpace, type IntVal, Interner, type Item, type MetaType, type MinEnv, type QueryResult, type ReduceResult, type Relation, type Ret, type RunOptions, STDLIB_SRC, type Space, type St, type Stack, type StackCons, type Subst, type SymAtom, TAG_ARITY, TAG_NEWVAR, TAG_SYMBOL, TAG_VARREF, type TokenConstructor, Tokenizer, type TopAtom, Trail, type ValRel, type VarAtom, type World, _internals, addAtomToEnv, addEqRaw, addInt, addValRaw, addVarBinding, addVarEquality, alphaEq, analyzePurity, applySubst, atomEq, atomSize, atomVars, baseTable, bindingsToSubst, buildEnv, builtinModules, callGrounded, canonInt, cmpIntVal, collectImports, collectVars, compileEnv, decodeAt, decodeAtom, emptyBindings, emptyEnv, emptyExpr, emptySubst, encodeAtom, encodeInto, encodePattern, eraseSubst, evalAtom, evalSequential, expr, extendSubst, format, freshenRule, gbool, getTypes, gfloat, gint, gnd, groundEq, groundType, gstr, gunit, hasLoop, hashOf, initSt, instantiate, intAbs, intDiv, intMod, isErrorAtom, isExpr, isGnd, isOraclePass, isSym, isVar, isZero, keyWellFormed, lookupSubst, lookupVal, matchAtoms, matchAtomsScoped, matchAtomsWith, matchFlatAt, merge, metaType, mettaEval, mettaEvalAsync, mulInt, occurs, oracleReport, parse, parseAll, pettaOpNames, preludeAtoms, removeVal, runCompiled, runProgram, runProgramAsync, setOutputSink, setRawSink, standardTokenizer, stdTable, stdlibAtoms, subInt, sym, tableKey, toF64, unifiable, unifyTop, unifyTrail, variable, wcoJoin, williamTopK, withBuiltinModules };
|