gdp-wired 0.14.2 → 0.15.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/README.md +26 -13
- package/dist/core/discover.d.ts +27 -0
- package/dist/core/discover.js +491 -0
- package/dist/core/dsl.d.ts +18 -0
- package/dist/core/dsl.js +33 -3
- package/dist/core/infer.d.ts +29 -0
- package/dist/core/infer.js +573 -0
- package/dist/kernel/kernel.d.ts +5 -1
- package/dist/kernel/kernel.js +44 -12
- package/dist/kernel/prove.d.ts +8 -0
- package/dist/kernel/prove.js +152 -15
- package/dist/lean-kernel/emit.d.ts +2 -1
- package/dist/lean-kernel/emit.js +37 -23
- package/dist/lean-kernel/library.js +1 -1
- package/package.json +10 -2
package/dist/core/dsl.js
CHANGED
|
@@ -1416,8 +1416,12 @@ export const recur = (name, def, lemmas = {}, between = {}) => {
|
|
|
1416
1416
|
proofs.between = { machine: r.machine, laws };
|
|
1417
1417
|
verdict = { proven: true, checked: verdict.checked && v.checked };
|
|
1418
1418
|
}
|
|
1419
|
-
|
|
1419
|
+
const out = { ...base, verdict, facts: facts(true) };
|
|
1420
|
+
recurDefs.set(out, { name, def: def, lemmas: lemmas, between: between });
|
|
1421
|
+
return out;
|
|
1420
1422
|
};
|
|
1423
|
+
const recurDefs = new WeakMap();
|
|
1424
|
+
export const recurOf = (d) => recurDefs.get(d);
|
|
1421
1425
|
const distinctNames = (what, names) => { if (new Set(names).size !== names.length)
|
|
1422
1426
|
throw new Error(`${what}: a name given twice`); };
|
|
1423
1427
|
// A recurrence as JavaScript: a function of its arguments, the functions it reads inlined (each called on its arguments,
|
|
@@ -1527,6 +1531,21 @@ export class Rule {
|
|
|
1527
1531
|
}
|
|
1528
1532
|
with(more) { return new Rule({ ...this.spec, ...more }); }
|
|
1529
1533
|
get name() { return this.spec.name; }
|
|
1534
|
+
// For core/discover.ts: the functions and carried lists the rule reads, and the same rule with functions made again
|
|
1535
|
+
// and lemmas added to its lists' folds (each proven here, as carriesList proves its own).
|
|
1536
|
+
get parts() {
|
|
1537
|
+
return { params: this.spec.params, fns: this.spec.fns ?? [], lists: this.spec.lists2 ?? [] };
|
|
1538
|
+
}
|
|
1539
|
+
withParts(fns, listLemmas = {}) {
|
|
1540
|
+
const lists = (this.spec.lists2 ?? []).map(([n, k, fs, ls]) => [n, k, fs, { ...ls, ...(listLemmas[n] ?? {}) }]);
|
|
1541
|
+
for (const [n, k, fs, ls] of lists)
|
|
1542
|
+
if (listLemmas[n]) {
|
|
1543
|
+
const v2 = new CarriedList(n, k, v(`${n}_len`), fs, part => new MapRef(part, 0), ls, undefined, this.spec.params).prove();
|
|
1544
|
+
if (!(v2.proven && v2.checked))
|
|
1545
|
+
throw new Unproven(`${n}'s fold lemmas`, v2);
|
|
1546
|
+
}
|
|
1547
|
+
return this.with({ fns: (this.spec.fns ?? []).map(([n, d]) => [n, fns[n] ?? d]), lists2: lists });
|
|
1548
|
+
}
|
|
1530
1549
|
params(kinds) { return this.with({ params: [...this.spec.params, ...Object.entries(kinds)] }); }
|
|
1531
1550
|
inputs(kinds) { return this.with({ inputs: [...this.spec.inputs, ...Object.entries(kinds)] }); }
|
|
1532
1551
|
// Each variable starts at a natural or at a term over the params, or is declared by a kind and starts where `from`
|
|
@@ -1758,6 +1777,8 @@ export class Rule {
|
|
|
1758
1777
|
// A decision: whenever the params and the request meet `given`, `then` holds. Decisions don't read the state; the
|
|
1759
1778
|
// functions' facts are assumed at the arguments the decision reads them at, and a carried list's equations (each
|
|
1760
1779
|
// fold's start, its step and its lemmas) at the list's end, the key before it and every key the decision reads it at.
|
|
1780
|
+
// A condition about every key (`everyKey`, `subsetOf`, ...) in `given` or `then` makes the decision a step law of
|
|
1781
|
+
// this rule (its conditions as flags, the step left as it is): the flags' quantifiers are what the kernel closes.
|
|
1761
1782
|
decide(name, given, then) {
|
|
1762
1783
|
const env = this.env({ flags: false, state: false, queries: false });
|
|
1763
1784
|
const g = given(env), hyps = [...this.kindAssumptions(), ...this.spec.pre.map(f => f(env).c), ...this.spec.assume.map(f => f(env).c), ...(Array.isArray(g) ? g : [g]).map(c => c.c)];
|
|
@@ -1766,7 +1787,14 @@ export class Rule {
|
|
|
1766
1787
|
const listed = lists.flatMap(l => l.equationsAt(uniqueTerms([l.len, l.len.minus(1), ...keysRead([...hyps, t], l.maps)])).map(c => c.c));
|
|
1767
1788
|
const goal = { name, hyps: [...listed, ...hyps, { op: 'not', x: t }] };
|
|
1768
1789
|
const facts = this.spec.fns?.length || this.spec.facts?.length ? factsFor(this.machine, goal) : [];
|
|
1769
|
-
|
|
1790
|
+
const d = { name, rule: this, given: hyps, then: t, goal: { name, hyps: [...facts, ...goal.hyps] } };
|
|
1791
|
+
if ([...(Array.isArray(g) ? g : [g]).map(c => c.c), t].some(quantifiedIn)) {
|
|
1792
|
+
const conds = (e) => { const own = given(e); return { given$: all(...(Array.isArray(own) ? own : [own])), then$: then(e) }; };
|
|
1793
|
+
const r = (this.spec.step ? this : this.step(() => ({}))).flags(conds);
|
|
1794
|
+
const flag = (f) => (env) => env[f];
|
|
1795
|
+
d.steps = { rule: r, law: r.stepLaw(name, flag('then$'), flag('given$')) };
|
|
1796
|
+
}
|
|
1797
|
+
return withSource(d, { decision: { given: given, then: then, own: Array.isArray(g) ? g.length : 1 } });
|
|
1770
1798
|
}
|
|
1771
1799
|
// A decision about two requests under the same params (noninterference, say: requests that differ only in a secret
|
|
1772
1800
|
// are decided alike). `given` and `then` read both; the second request's inputs are named b.<input> in a witness.
|
|
@@ -2249,6 +2277,8 @@ const expandParts = (updates) => {
|
|
|
2249
2277
|
};
|
|
2250
2278
|
const encode = (kinds, values) => Object.assign({}, ...kinds.map(([n, k]) => k.encode(n, values[n])));
|
|
2251
2279
|
export const rule = (name) => new Rule({ name, params: [], inputs: [], state: [], maps: [], flags: [], pre: [], assume: [], sums: [], queries: [] });
|
|
2280
|
+
const quantifiedE = (e) => e.op === 'if' ? quantifiedIn(e.c) || quantifiedE(e.then) || quantifiedE(e.else) : 'a' in e && typeof e.a === 'object' ? quantifiedE(e.a) || ('b' in e && typeof e.b === 'object' && quantifiedE(e.b)) : false;
|
|
2281
|
+
const quantifiedIn = (c) => c.op === 'all' || (c.op === 'not' ? quantifiedIn(c.x) : c.op === 'and' || c.op === 'or' ? c.xs.some(quantifiedIn) : c.op === 'flag' ? false : quantifiedE(c.a) || quantifiedE(c.b));
|
|
2252
2282
|
// The kind a result field is kept in.
|
|
2253
2283
|
const kindOf = (t) => (t instanceof Cond ? bool : t instanceof Int ? int : t instanceof Decimal ? decimal(t.places) : t instanceof Choice ? oneOf(...t.values) : t instanceof Str ? str({ like: t.patterns })
|
|
2254
2284
|
: t instanceof Variant ? t.kind : t instanceof Maybe ? maybe(kindOf(t.inner)) : isRecord(t) ? record(Object.fromEntries(Object.entries(t).map(([f, x]) => [f, kindOf(x)]))) : nat);
|
|
@@ -2487,7 +2517,7 @@ export function proveLeadsTo(r, laws, l) {
|
|
|
2487
2517
|
const out = proveLiveness(r.machine, withKinds(r, laws), l);
|
|
2488
2518
|
return { proven: out.proven, checked: out.checked, ...(out.failed ? { goal: out.failed.goal, stuck: out.failed.stuck, ...(out.failed.witness ? { witness: out.failed.witness } : {}), ...(out.failed.why ? { why: out.failed.why } : {}) } : {}) };
|
|
2489
2519
|
}
|
|
2490
|
-
export const proveDecision = (d) => goalsVerdict([d.goal]);
|
|
2520
|
+
export const proveDecision = (d) => (d.steps ? proveSteps(d.steps.rule, [], [d.steps.law]) : goalsVerdict([d.goal]));
|
|
2491
2521
|
const seeded = (seed) => { let x = seed; return k => { x = (x * 1103515245 + 12345) % 2 ** 31; return Math.floor(x / 2 ** 31 * k); }; };
|
|
2492
2522
|
// A decision's callbacks against its condition, on random params and requests: `given` and `then` each run with every
|
|
2493
2523
|
// value known, against what the interpreter evaluates of the decision built from them.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { type Law, type Machine, type State } from './machine.js';
|
|
2
|
+
import { type StepLaw, type Verdict, proveRule } from './dsl.js';
|
|
3
|
+
type AnyRule = Parameters<typeof proveRule>[0];
|
|
4
|
+
export type InferOptions = {
|
|
5
|
+
ms?: number;
|
|
6
|
+
runsMs?: number;
|
|
7
|
+
seen?: State[];
|
|
8
|
+
constants?: number[];
|
|
9
|
+
maxCandidates?: number;
|
|
10
|
+
first?: Verdict;
|
|
11
|
+
progress?: (phase: string, info: Record<string, number | string>) => void;
|
|
12
|
+
};
|
|
13
|
+
export type Found = {
|
|
14
|
+
law: Law;
|
|
15
|
+
text: string;
|
|
16
|
+
source?: string;
|
|
17
|
+
};
|
|
18
|
+
export type Inferred = Verdict & {
|
|
19
|
+
found: Found[];
|
|
20
|
+
stats: {
|
|
21
|
+
samples: number;
|
|
22
|
+
candidates: number;
|
|
23
|
+
alive: number;
|
|
24
|
+
proofs: number;
|
|
25
|
+
ms: number;
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
export declare function inferLaws(target: AnyRule | Machine, laws: Law[], stepLaws?: StepLaw[], opts?: InferOptions): Inferred;
|
|
29
|
+
export {};
|