gdp-wired 0.8.0 → 0.10.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 +30 -9
- package/dist/core/dsl.d.ts +117 -27
- package/dist/core/dsl.js +315 -36
- package/dist/core/gdp.d.ts +2 -2
- package/dist/core/gdp.js +2 -1
- package/dist/core/machine.d.ts +10 -0
- package/dist/lean-kernel/emit.d.ts +5 -0
- package/dist/lean-kernel/emit.js +134 -84
- package/dist/lean-kernel/library.js +5 -5
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -67,6 +67,10 @@ All of these are proven automatically, and each proof is also a Lean theorem:
|
|
|
67
67
|
- **Records and variants**: inputs, state, results, map cells and list items made of named fields, or one of several
|
|
68
68
|
cases each with fields of its own (a payment by card or in cash, a seat free, held or sold), every case covered
|
|
69
69
|
(`examples/datatypes.ts`).
|
|
70
|
+
- **Lists a request carries, and trees**: an invoice's lines, with folds over them (the total, the taxable part) and
|
|
71
|
+
lemmas about the folds proven by induction over the lines (`examples/invoices.ts`); a fold over a tree as a value (a
|
|
72
|
+
spend roll-up over an org chart, sign-offs over a document's sections), its laws proven by induction over the tree
|
|
73
|
+
(`examples/folds.ts`).
|
|
70
74
|
- **Pure functions and two-run laws**: laws about what a function returns, and laws comparing two calls, like "the
|
|
71
75
|
secret never changes the answer". `examples/jev-fabric/` ports a Bend project's policy core and proves all 59 laws its
|
|
72
76
|
Bend proofs state.
|
|
@@ -209,13 +213,28 @@ const soon = retry.law('the next try is at most 64 after the last request', ({ne
|
|
|
209
213
|
- **Records and variants**: `record({limit: nat, blocked: bool})` hands out an object of its fields' values;
|
|
210
214
|
`variant({card: {...}, cash: {...}})` a value with `is(case)` and `match({card: c => ..., cash: c => ...})`, the only
|
|
211
215
|
place a case's fields are read. `Pay.make({tag: 'card', amount, verified})` builds a case to write or to pass to
|
|
212
|
-
`when`, and `same(a, b)` compares two values of one kind part by part
|
|
213
|
-
|
|
216
|
+
`when`, and `same(a, b)` compares two values of one kind part by part; `optional(c, value)` is a value present where c
|
|
217
|
+
holds (a result that may be missing). At runtime a record is an object of its fields and a variant `{tag: 'card',
|
|
218
|
+
...fields}` (or the key given, `variant({...}, {tag: 'kind'})`); a field or case the kind doesn't declare is refused.
|
|
219
|
+
What a kind keeps true of the values a step writes (a case in range, a flag 0 or 1) is a law of its own, `r.kindLaws()`,
|
|
220
|
+
which proveRule, proveSteps and proveLeadsTo prove beside the laws they are given. Both are their fields'
|
|
214
221
|
variables underneath (`pay.card.amount`, and the case's index as `pay`), so the kernel, both runtimes and the Lean
|
|
215
222
|
twin see nothing new. Maps and lists of them: `.maps({Acct: record({...}).from({...})})` (`Acct.at(k)`,
|
|
216
223
|
`Acct.set(k, value)`, `Acct.each(k => value)`) and `.items({Queue: Job})` (`push`, `pop`, `set`, `insertAt`,
|
|
217
224
|
`removeAt`, `apply`, `has`, `within`, `increasing(by)`), one map per variable of the kind; `rule.decode` reads them back
|
|
218
|
-
as objects and arrays.
|
|
225
|
+
as objects and arrays.
|
|
226
|
+
- **Lists a request carries** (`.carriesList('Lines', Line, folds, lemmas)`): the items one carried map per variable of
|
|
227
|
+
the kind, the length `Lines.len`, each fold (`{total: {from: 0, step: (acc, line) => acc.plus(line.amount)}}`) a
|
|
228
|
+
carried map of its running values whose equations every request is assumed to meet (the encoding computes them from the
|
|
229
|
+
array, and a request that doesn't meet them isn't allowed), read as `Lines.fold.total`; `Lines.every`, `some`, `has`,
|
|
230
|
+
`increasing(by)`, `at(i)`. A lemma about the folds (`({taxed, total}) => taxed.atMost(total)`) is proven by induction
|
|
231
|
+
over the items when the rule is built, then assumed at every prefix (`examples/invoices.ts`).
|
|
232
|
+
- **Folds over trees** (`fold(name).params(...).inputs(...).leaf(env => ({...})).node((env, left, right) => ({...}))`,
|
|
233
|
+
`proveFold`): a tree as a value (`{leaf: inputs}` or `{node: inputs, left, right}`), each leaf's values from its inputs
|
|
234
|
+
and each node's from its own and its children's; a law about the values is proven by induction over the tree (the
|
|
235
|
+
kernel's leaf and node goals, Lean's `fold_sound`), `f.run(tree, params)` evaluates the terms proven and `f.crossCheck`
|
|
236
|
+
holds the builders to them (`examples/folds.ts`). A tree in a rule's state, and claims that need a lemma about the
|
|
237
|
+
tree's shape nobody stated, stay Lean's.
|
|
219
238
|
- **State of any kind**: `.state({open: bool.from(true), status: oneOf('new', 'done').from('new'), owner: str().from(''), note: maybe(nat).from(null)})`;
|
|
220
239
|
a step writes each kind's own values, `when(c, a, b)` chooses between any two values of a kind, and `rule.decode(state)`
|
|
221
240
|
reads them back as runtime values.
|
|
@@ -237,15 +256,17 @@ const soon = retry.law('the next try is at most 64 after the last request', ({ne
|
|
|
237
256
|
own), and the Lean export takes them as the hypothesis they are, proving them where the function has a Lean
|
|
238
257
|
definition. A function defined and proven in Lean is how a rule reaches past what the kernel decides: `examples/functions.ts`.
|
|
239
258
|
- **Recurrences and their lemmas** (`recur(name, {args, fns, zero, next}, lemmas, between)`): f(0, a..) = zero and
|
|
240
|
-
f(x + 1, a..) = next(x, f(x, a..), a..), the further arguments `args` (up to
|
|
241
|
-
the kernel's own or a read of a function in `fns` (`modBy(7)`, another recurrence). Each lemma is a law about every x
|
|
259
|
+
f(x + 1, a..) = next(x, f(x, a..), a..), the further arguments `args` (up to four) fixed along the recursion, each term
|
|
260
|
+
the kernel's own or a read of a function in `fns` (`modBy(7)`, another recurrence), the start's too. Each lemma is a law about every x
|
|
242
261
|
and f(x), proven when the function is made, all of them together by induction (the recurrence run as a machine, each
|
|
243
262
|
lemma a law of it, so one lemma may lean on another, and on the facts of the functions it reads); each law `between`
|
|
244
263
|
is about every x <= y and f(x), f(y) ("never shrinks"), proven by induction on y from x, with the lemmas. One that
|
|
245
264
|
isn't proven throws `Unproven` with the induction step it breaks at. The two equations, the lemmas and the laws
|
|
246
|
-
between are the function's facts. The runtimes compute f by the recurrence
|
|
247
|
-
|
|
248
|
-
|
|
265
|
+
between are the function's facts. The runtimes compute f by the recurrence, continuing from the last value computed at
|
|
266
|
+
the same further arguments (a rule that reads f at a growing count takes one step a request); the Lean export defines
|
|
267
|
+
`Recur.<name>` by it (a function of several arguments through an injective pairing, proven so in Lean) and checks the
|
|
268
|
+
kernel's own proof of every lemma and law between: the machine it was proven by, with its trees, and the run of it that
|
|
269
|
+
reaches x and f(x), so a lemma with a product (squares: f(x) = x·x) needs no tactic of Lean's (`examples/lemmas.ts`).
|
|
249
270
|
- **Liveness** (`rule.leadsTo(name, {from, to, rank, helpful})`, `proveLeadsTo`): whenever `from` holds, `to` holds later in
|
|
250
271
|
every run that takes each helpful request infinitely often; proven by a rank no step raises while waiting and each
|
|
251
272
|
helpful request lowers in its region. `rank` may return several terms (compared in order) and `helpful` may be a list
|
|
@@ -308,7 +329,7 @@ Lean, compiled natively, wins where the state stays small. Details in [`docs/com
|
|
|
308
329
|
| `core/` | Machines, the interpreter and JS compiler, the builders, composition (`compose.ts`), the linear solver and its checker, Houdini invariants, models, the first Lean export |
|
|
309
330
|
| `kernel/` | The trusted kernel and the untrusted prover, with soundness fuzz (`kernel.test.ts`, `history.test.ts`) |
|
|
310
331
|
| `lean-kernel/` | The kernel's Lean twin, its soundness proofs, and the exported trees |
|
|
311
|
-
| `examples/` | The builders at work: `domains/` (187 rules across 21 domains, each with laws and broken variants), `harness.ts` (the triple check), `readme.ts`, `budget.ts`, `gdp.ts` (gdp-ts's example, its checks proven), `datatypes.ts` (records and variants), `lemmas.ts` (recurrences and their lemmas), `composition.ts`, `sets.ts`, `quantifiers.ts`, `functions.ts`, `lists.ts`, `sizes.ts`, `liveness.ts`, `steps.ts` (laws over up to 16 steps), and `jev-fabric/` (a Bend project's 59 proven laws, ported) |
|
|
332
|
+
| `examples/` | The builders at work: `domains/` (187 rules across 21 domains, each with laws and broken variants), `harness.ts` (the triple check), `readme.ts`, `budget.ts`, `gdp.ts` (gdp-ts's example, its checks proven), `datatypes.ts` (records and variants), `lemmas.ts` (recurrences and their lemmas), `invoices.ts` (lists a request carries), `folds.ts` (folds over trees), `composition.ts`, `sets.ts`, `quantifiers.ts`, `functions.ts`, `lists.ts`, `sizes.ts`, `liveness.ts`, `steps.ts` (laws over up to 16 steps), and `jev-fabric/` (a Bend project's 59 proven laws, ported) |
|
|
312
333
|
| `docs/` | The comparison with Bend and Lean, and the full scope |
|
|
313
334
|
| `compare/` | The same three rules in gdp-wired, Bend and plain Lean, checked and measured |
|
|
314
335
|
| `research/` | Everything around the library ([`research/README.md`](research/README.md)): the GPU searches (`search/`, `hw/`, `modal-gpu/`), invariant and rank synthesis (`synth/`), relational laws and guard synthesis (`next/`), bit-vector laws (`sat/`), the enumeration and benchmarks (`enum/`, `gpu/`, `perf/`), the first Lean checker (`lean/`) and the first prototype, the audit path (`audit/`) |
|
package/dist/core/dsl.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type C, type E, type Law, type Recurrence, type Machine, type Request, type State } from './machine.js';
|
|
2
|
-
import { type Goal, type Liveness, type Loop, type StepLaw, type Tree } from '../kernel/kernel.js';
|
|
2
|
+
import { type Fold, type Goal, type Liveness, type Loop, type StepLaw, type Tree } from '../kernel/kernel.js';
|
|
3
3
|
export type TermLike = Term | number;
|
|
4
4
|
export declare const termOf: (t: TermLike) => E;
|
|
5
5
|
export declare class Term {
|
|
@@ -43,7 +43,7 @@ export declare function when<K extends string>(c: Cond, then: Choice<K>, otherwi
|
|
|
43
43
|
export declare function when(c: Cond, then: Str, otherwise: Str): Str;
|
|
44
44
|
export declare function when<V>(c: Cond, then: Maybe<V>, otherwise: Maybe<V>): Maybe<V>;
|
|
45
45
|
export declare function when(c: Cond, then: Cond, otherwise: Cond): Cond;
|
|
46
|
-
export declare function when<C extends Cases>(c: Cond, then: Variant<C>, otherwise: Variant<C>): Variant<C>;
|
|
46
|
+
export declare function when<C extends Cases, T extends string>(c: Cond, then: Variant<C, T>, otherwise: Variant<C, T>): Variant<C, T>;
|
|
47
47
|
export declare function when<T extends Record<string, unknown>>(c: Cond, then: T, otherwise: T): T;
|
|
48
48
|
export declare const choose: (c: Cond, then: Cond, otherwise: Cond) => Cond;
|
|
49
49
|
export declare function same(a: unknown, b: unknown): Cond;
|
|
@@ -65,6 +65,7 @@ export declare abstract class Kind<V> {
|
|
|
65
65
|
abstract assume(name: string): Cond[];
|
|
66
66
|
abstract build(name: string, get: (part: string) => Term): V;
|
|
67
67
|
value(name: string, at?: At): V;
|
|
68
|
+
invariant(_value: V): Cond[];
|
|
68
69
|
abstract encode(name: string, raw: Raw): Record<string, number>;
|
|
69
70
|
abstract random(name: string, rand: Rand, bound: number): Record<string, number>;
|
|
70
71
|
abstract store(name: string, value: unknown): Record<string, TermLike>;
|
|
@@ -152,6 +153,7 @@ export declare class Maybe<V> {
|
|
|
152
153
|
}): Term;
|
|
153
154
|
}
|
|
154
155
|
export declare const maybe: <V>(of: Kind<V>) => Kind<Maybe<V>>;
|
|
156
|
+
export declare const optional: <V>(c: Cond, value: V) => Maybe<V>;
|
|
155
157
|
type Fields = Record<string, Kind<unknown>>;
|
|
156
158
|
export declare const record: <const K extends Fields>(fields: K) => Kind<ValuesOf<K>>;
|
|
157
159
|
type Cases = Record<string, Fields>;
|
|
@@ -161,40 +163,41 @@ type CaseValues<C extends Cases> = {
|
|
|
161
163
|
type MatchCases<C extends Cases, T> = {
|
|
162
164
|
[k in keyof C]: (fields: ValuesOf<C[k]>) => T;
|
|
163
165
|
};
|
|
164
|
-
export declare class Variant<C extends Cases = Cases> {
|
|
166
|
+
export declare class Variant<C extends Cases = Cases, T extends string = 'tag'> {
|
|
165
167
|
readonly tag: Term;
|
|
166
168
|
readonly cases: CaseValues<C>;
|
|
167
|
-
readonly kind: VariantKind<C>;
|
|
168
|
-
constructor(tag: Term, cases: CaseValues<C>, kind: VariantKind<C>);
|
|
169
|
+
readonly kind: VariantKind<C, T>;
|
|
170
|
+
constructor(tag: Term, cases: CaseValues<C>, kind: VariantKind<C, T>);
|
|
169
171
|
is(k: keyof C & string): Cond;
|
|
170
172
|
match(cases: MatchCases<C, Cond>): Cond;
|
|
171
173
|
match(cases: MatchCases<C, TermLike>): Term;
|
|
172
174
|
match<T>(cases: MatchCases<C, T>): T;
|
|
173
175
|
}
|
|
174
|
-
export type VariantWrite<C extends Cases> = {
|
|
176
|
+
export type VariantWrite<C extends Cases, T extends string = 'tag'> = {
|
|
175
177
|
[k in keyof C]: {
|
|
176
|
-
[f in
|
|
178
|
+
[f in T | keyof C[k]]: f extends T ? k : C[k][f] extends Kind<infer V> ? Writes<V> : never;
|
|
177
179
|
};
|
|
178
180
|
}[keyof C];
|
|
179
|
-
export declare class VariantKind<C extends Cases> extends Kind<Variant<C>> {
|
|
181
|
+
export declare class VariantKind<C extends Cases, T extends string = 'tag'> extends Kind<Variant<C, T>> {
|
|
180
182
|
readonly cases: C;
|
|
183
|
+
readonly tagKey: T;
|
|
181
184
|
readonly names: (keyof C & string)[];
|
|
182
|
-
|
|
183
|
-
constructor(cases: C);
|
|
185
|
+
constructor(cases: C, tagKey: T);
|
|
184
186
|
index(k: string): number;
|
|
185
187
|
private payload;
|
|
186
188
|
private filled;
|
|
187
189
|
private at;
|
|
188
190
|
vars(name: string): string[];
|
|
189
191
|
assume(name: string): Cond[];
|
|
190
|
-
build(name: string, get: (part: string) => Term): Variant<C>;
|
|
191
|
-
|
|
192
|
+
build(name: string, get: (part: string) => Term): Variant<C, T>;
|
|
193
|
+
invariant(x: Variant<C, T>): Cond[];
|
|
194
|
+
make(write: VariantWrite<C, T>): Variant<C, T>;
|
|
192
195
|
store(name: string, value: unknown): Record<string, TermLike>;
|
|
193
196
|
decode(name: string, vars: Record<string, number>): {
|
|
194
|
-
|
|
197
|
+
[x: string]: (keyof C & string) | Raw;
|
|
195
198
|
};
|
|
196
199
|
empty(): {
|
|
197
|
-
|
|
200
|
+
[x: string]: (keyof C & string) | Raw;
|
|
198
201
|
};
|
|
199
202
|
encode(name: string, raw: Raw): {
|
|
200
203
|
[x: string]: number;
|
|
@@ -203,10 +206,13 @@ export declare class VariantKind<C extends Cases> extends Kind<Variant<C>> {
|
|
|
203
206
|
[x: string]: number;
|
|
204
207
|
};
|
|
205
208
|
sample(rand: Rand, bound: number): {
|
|
206
|
-
|
|
209
|
+
[x: string]: (keyof C & string) | Raw;
|
|
207
210
|
};
|
|
208
211
|
}
|
|
209
|
-
export declare
|
|
212
|
+
export declare function variant<const C extends Cases>(cases: C): VariantKind<C>;
|
|
213
|
+
export declare function variant<const C extends Cases, const T extends string>(cases: C, opts: {
|
|
214
|
+
tag: T;
|
|
215
|
+
}): VariantKind<C, T>;
|
|
210
216
|
export declare const intern: ((text: string) => number) & {
|
|
211
217
|
load(entries: [string, number][]): void;
|
|
212
218
|
};
|
|
@@ -304,6 +310,35 @@ export type ItemsOp = {
|
|
|
304
310
|
readonly parts: Record<string, ListOp>;
|
|
305
311
|
readonly len: TermLike;
|
|
306
312
|
};
|
|
313
|
+
export type ListFold<V> = {
|
|
314
|
+
from: number;
|
|
315
|
+
step: (acc: Term, item: V) => TermLike;
|
|
316
|
+
};
|
|
317
|
+
export type ListLemma = (acc: Record<string, Term>, i: Term) => Cond;
|
|
318
|
+
export declare class CarriedList<V, Fd extends string = never> {
|
|
319
|
+
readonly name: string;
|
|
320
|
+
readonly kind: Kind<V>;
|
|
321
|
+
readonly len: Term;
|
|
322
|
+
readonly folds: Record<Fd, ListFold<V>>;
|
|
323
|
+
private readonly map;
|
|
324
|
+
readonly lemmas: Record<string, ListLemma>;
|
|
325
|
+
readonly fold: Record<Fd, Term>;
|
|
326
|
+
constructor(name: string, kind: Kind<V>, len: Term, folds: Record<Fd, ListFold<V>>, map: (part: string) => MapRef, lemmas?: Record<string, ListLemma>);
|
|
327
|
+
at(i: TermLike): V;
|
|
328
|
+
after(fold: Fd, i: TermLike): Term;
|
|
329
|
+
every(f: (item: V, i: Term) => Cond): Cond;
|
|
330
|
+
some(f: (item: V, i: Term) => Cond): Cond;
|
|
331
|
+
has(x: V): Cond;
|
|
332
|
+
increasing(by: (item: V) => Term): Cond;
|
|
333
|
+
equations(): Cond[];
|
|
334
|
+
private running;
|
|
335
|
+
prove(): Verdict;
|
|
336
|
+
get maps(): string[];
|
|
337
|
+
encode(raw: Raw): {
|
|
338
|
+
maps: Record<string, Map<number, number>>;
|
|
339
|
+
len: number;
|
|
340
|
+
};
|
|
341
|
+
}
|
|
307
342
|
export declare class ItemsRef<V> {
|
|
308
343
|
readonly name: string;
|
|
309
344
|
readonly kind: Kind<V>;
|
|
@@ -326,7 +361,7 @@ export declare class ItemsRef<V> {
|
|
|
326
361
|
export type Forall = {
|
|
327
362
|
readonly forall: (key: Term, ...more: Term[]) => Cond;
|
|
328
363
|
};
|
|
329
|
-
export declare function forall(f: (key: Term, key2: Term, key3: Term, key4: Term) => Cond): Forall;
|
|
364
|
+
export declare function forall(f: (key: Term, key2: Term, key3: Term, key4: Term, key5: Term, key6: Term) => Cond): Forall;
|
|
330
365
|
export type Relation = {
|
|
331
366
|
readonly when: Cond;
|
|
332
367
|
readonly holds: Cond;
|
|
@@ -356,9 +391,7 @@ type RecurEnv<A extends string, U> = {
|
|
|
356
391
|
export type RecurDef<A extends string, U extends Record<string, FnDef>> = {
|
|
357
392
|
args?: readonly A[];
|
|
358
393
|
fns?: U;
|
|
359
|
-
zero: TermLike | ((env:
|
|
360
|
-
[a in A]: Term;
|
|
361
|
-
}) => TermLike);
|
|
394
|
+
zero: TermLike | ((env: RecurEnv<A, U>) => TermLike);
|
|
362
395
|
next: (x: Term, prev: Term, env: RecurEnv<A, U>) => TermLike;
|
|
363
396
|
};
|
|
364
397
|
export declare const recur: <const A extends string = never, U extends Record<string, FnDef> = {}>(name: string, def: RecurDef<A, U>, lemmas?: Record<string, (x: Term, fx: Term, env: RecurEnv<A, U>) => Cond>, between?: Record<string, (x: Term, fx: Term, y: Term, fy: Term, env: RecurEnv<A, U>) => Cond>) => FnDef & {
|
|
@@ -369,7 +402,7 @@ type ValuesOf<K extends Kinds> = {
|
|
|
369
402
|
[n in keyof K]: K[n] extends Kind<infer V> ? V : never;
|
|
370
403
|
};
|
|
371
404
|
type Obj = object;
|
|
372
|
-
type Writes<V> = V extends Decimal ? DecimalLike | string : V extends Int ? IntLike : V extends Cond ? Cond | boolean : V extends Choice<infer K> ? Choice<K> | K : V extends Maybe<infer W> ? Maybe<W> | Writes<W> | null : V extends Str ? Str | string : V extends Variant<infer C> ? Variant<C> | VariantWrite<C> : V extends Term ? TermLike : V extends Record<string, unknown> ? {
|
|
405
|
+
type Writes<V> = V extends Decimal ? DecimalLike | string : V extends Int ? IntLike : V extends Cond ? Cond | boolean : V extends Choice<infer K> ? Choice<K> | K : V extends Maybe<infer W> ? Maybe<W> | Writes<W> | null : V extends Str ? Str | string : V extends Variant<infer C, infer T> ? Variant<C, T> | VariantWrite<C, T> : V extends Term ? TermLike : V extends Record<string, unknown> ? {
|
|
373
406
|
[k in keyof V]: Writes<V[k]>;
|
|
374
407
|
} : TermLike;
|
|
375
408
|
type Update<S extends Obj, M extends Obj> = Partial<{
|
|
@@ -388,6 +421,7 @@ type Spec = {
|
|
|
388
421
|
items?: [string, Kind<unknown>][];
|
|
389
422
|
kinded?: [string, Kind<unknown>][];
|
|
390
423
|
carried?: string[];
|
|
424
|
+
lists2?: [string, Kind<unknown>, Record<string, ListFold<unknown>>, Record<string, ListLemma>][];
|
|
391
425
|
fns?: [string, FnDef][];
|
|
392
426
|
facts?: ((env: never) => Record<string, Cond | Forall>)[];
|
|
393
427
|
flags: ((env: never) => Record<string, Cond>)[];
|
|
@@ -440,6 +474,9 @@ export declare class Rule<P extends Obj = {}, I extends Obj = {}, S extends Obj
|
|
|
440
474
|
carries<const N extends string>(...names: N[]): Rule<P, I & {
|
|
441
475
|
[k in N]: MapRef;
|
|
442
476
|
}, S, M, F, R, Su, Q>;
|
|
477
|
+
carriesList<const N extends string, V, Fd extends string = never>(name: N, of: Kind<V>, folds?: Record<Fd, ListFold<V>>, lemmas?: Record<string, (acc: Record<Fd, Term>, i: Term) => Cond>): Rule<P, I & {
|
|
478
|
+
[k in N]: CarriedList<V, Fd>;
|
|
479
|
+
}, S, M, F, R, Su, Q>;
|
|
443
480
|
flags<T extends Record<string, Cond>>(f: (env: P & I & S & M & F & Su & Q) => T): Rule<P, I, S, M, F & {
|
|
444
481
|
[k in keyof T]: Cond;
|
|
445
482
|
}, R, Su, Q>;
|
|
@@ -458,6 +495,7 @@ export declare class Rule<P extends Obj = {}, I extends Obj = {}, S extends Obj
|
|
|
458
495
|
prune(order: keyof R & string, after: (p: P) => TermLike): Rule<P, I, S, M, F, R, Su, Q>;
|
|
459
496
|
law(name: string, f: (env: P & S & M & Su) => Cond | Forall): Law;
|
|
460
497
|
private lawOf;
|
|
498
|
+
kindLaws(): Law[];
|
|
461
499
|
stepLaw(name: string, then: (before: P & I & S & M & F & Su & Q, after: S & M & Su) => Cond | Forall, when?: (before: P & I & S & M & F & Su & Q) => Cond): StepLaw;
|
|
462
500
|
stepsLaw(name: string, k: number, then: (first: P & I & S & M & F & Su & Q, last: S & M & Su, requests: (I & Q)[]) => Cond | Forall, when?: (before: P & I & S & M & F & Su & Q, j: number) => Cond | undefined): StepLaw;
|
|
463
501
|
leadsTo(name: string, spec: {
|
|
@@ -511,7 +549,7 @@ export declare class Rule<P extends Obj = {}, I extends Obj = {}, S extends Obj
|
|
|
511
549
|
[k in keyof P]: Raw;
|
|
512
550
|
}): Record<string, number>;
|
|
513
551
|
encodeInput(values: {
|
|
514
|
-
[k in keyof I]: I[k] extends MapRef ? ReadonlySet<number> | readonly number[] | ReadonlyMap<number, number> : Raw;
|
|
552
|
+
[k in keyof I]: I[k] extends MapRef ? ReadonlySet<number> | readonly number[] | ReadonlyMap<number, number> : I[k] extends CarriedList<any, any> ? readonly Raw[] : Raw;
|
|
515
553
|
}): Request;
|
|
516
554
|
randomParams(rand: Rand, bound: number): Record<string, number>;
|
|
517
555
|
randomInput(rand: Rand, bound: number): Request;
|
|
@@ -552,18 +590,18 @@ export type Decision = {
|
|
|
552
590
|
then: C;
|
|
553
591
|
goal: Goal;
|
|
554
592
|
};
|
|
555
|
-
type ResultOf<V> = 0 extends 1 & V ? Term : [V] extends [Cond] ? Cond : [V] extends [Decimal] ? Decimal : [V] extends [Int] ? Int : [V] extends [Choice<infer K>] ? Choice<K> : [V] extends [Str] ? Str : [V] extends [Variant<infer C>] ? Variant<C> : [V] extends [Term | number] ? Term : [V] extends [Record<string, unknown>] ? {
|
|
593
|
+
type ResultOf<V> = 0 extends 1 & V ? Term : [V] extends [Cond] ? Cond : [V] extends [Decimal] ? Decimal : [V] extends [Int] ? Int : [V] extends [Choice<infer K>] ? Choice<K> : [V] extends [Str] ? Str : [V] extends [Variant<infer C, infer T>] ? Variant<C, T> : [V] extends [Maybe<infer W>] ? Maybe<ResultOf<W>> : [V] extends [Term | number] ? Term : [V] extends [Record<string, unknown>] ? {
|
|
556
594
|
[f in keyof V]: ResultOf<V[f]>;
|
|
557
595
|
} : Term;
|
|
558
596
|
type Result<T> = {
|
|
559
597
|
[k in keyof T]: ResultOf<T[k]>;
|
|
560
598
|
};
|
|
561
|
-
type ValueOf<V> = 0 extends 1 & V ? number : [V] extends [Cond] ? boolean : [V] extends [Choice<infer K>] ? K : [V] extends [Str] ? string : [V] extends [Variant<infer C>] ? CaseRaw<C> : [V] extends [Term | number | Int | Decimal] ? number : [V] extends [Record<string, unknown>] ? {
|
|
599
|
+
type ValueOf<V> = 0 extends 1 & V ? number : [V] extends [Cond] ? boolean : [V] extends [Choice<infer K>] ? K : [V] extends [Str] ? string : [V] extends [Variant<infer C, infer T>] ? CaseRaw<C, T> : [V] extends [Maybe<infer W>] ? ValueOf<W> | null : [V] extends [Term | number | Int | Decimal] ? number : [V] extends [Record<string, unknown>] ? {
|
|
562
600
|
[f in keyof V]: ValueOf<V[f]>;
|
|
563
601
|
} : number;
|
|
564
|
-
type CaseRaw<C extends Cases> = {
|
|
602
|
+
type CaseRaw<C extends Cases, T extends string = 'tag'> = {
|
|
565
603
|
[k in keyof C]: {
|
|
566
|
-
|
|
604
|
+
[t in T]: k;
|
|
567
605
|
} & {
|
|
568
606
|
[f in keyof C[k]]: C[k][f] extends Kind<infer V> ? ValueOf<V> : never;
|
|
569
607
|
};
|
|
@@ -571,7 +609,7 @@ type CaseRaw<C extends Cases> = {
|
|
|
571
609
|
type Value<T> = {
|
|
572
610
|
[k in keyof T]: ValueOf<T[k]>;
|
|
573
611
|
};
|
|
574
|
-
type Field = Term | Cond | Int | Decimal | Choice<string> | Str | Variant<any> | {
|
|
612
|
+
type Field = Term | Cond | Int | Decimal | Choice<string> | Str | Variant<any, any> | Maybe<any> | {
|
|
575
613
|
[f: string]: Field | number;
|
|
576
614
|
};
|
|
577
615
|
export declare class Fun<P extends Obj = {}, I extends Obj = {}, O extends Obj = {}> {
|
|
@@ -685,3 +723,55 @@ export declare function crossCheckDecision(d: Decision, opts?: {
|
|
|
685
723
|
failure?: string;
|
|
686
724
|
};
|
|
687
725
|
export declare const proveLoop: (l: LoopRule<Obj, Obj, Obj>, laws: Law[]) => Verdict;
|
|
726
|
+
export type TreeValue<I> = {
|
|
727
|
+
leaf: I;
|
|
728
|
+
} | {
|
|
729
|
+
node: I;
|
|
730
|
+
left: TreeValue<I>;
|
|
731
|
+
right: TreeValue<I>;
|
|
732
|
+
};
|
|
733
|
+
type FoldSpec = {
|
|
734
|
+
name: string;
|
|
735
|
+
params: [string, Kind<unknown>][];
|
|
736
|
+
inputs: [string, Kind<unknown>][];
|
|
737
|
+
pre: ((p: never) => Cond)[];
|
|
738
|
+
assume: ((env: never) => Cond)[];
|
|
739
|
+
leaf?: (env: never) => Record<string, TermLike>;
|
|
740
|
+
node?: (env: never, left: never, right: never) => Record<string, TermLike>;
|
|
741
|
+
};
|
|
742
|
+
export declare class FoldRule<P extends Obj = {}, I extends Obj = {}, S extends Obj = {}> {
|
|
743
|
+
private readonly spec;
|
|
744
|
+
constructor(spec: FoldSpec);
|
|
745
|
+
private with;
|
|
746
|
+
get name(): string;
|
|
747
|
+
params<K extends Kinds>(kinds: K): FoldRule<P & ValuesOf<K>, I, S>;
|
|
748
|
+
inputs<K extends Kinds>(kinds: K): FoldRule<P, I & ValuesOf<K>, S>;
|
|
749
|
+
pre(f: (p: P) => Cond): FoldRule<P, I, S>;
|
|
750
|
+
assume(f: (env: P & I) => Cond): FoldRule<P, I, S>;
|
|
751
|
+
leaf<T extends Record<string, TermLike>>(f: (env: P & I) => T): FoldRule<P, I, {
|
|
752
|
+
[k in keyof T]: Term;
|
|
753
|
+
}>;
|
|
754
|
+
node(f: (env: P & I, left: S, right: S) => {
|
|
755
|
+
[k in keyof S]: TermLike;
|
|
756
|
+
}): FoldRule<P, I, S>;
|
|
757
|
+
private env;
|
|
758
|
+
private names;
|
|
759
|
+
private side;
|
|
760
|
+
law(name: string, f: (env: P & S) => Cond): Law;
|
|
761
|
+
get fold(): Fold;
|
|
762
|
+
run(tree: TreeValue<{
|
|
763
|
+
[k in keyof I]: Raw;
|
|
764
|
+
}>, params?: {
|
|
765
|
+
[k in keyof P]?: Raw;
|
|
766
|
+
}): {
|
|
767
|
+
[k in keyof S]: number;
|
|
768
|
+
};
|
|
769
|
+
crossCheck(laws?: Law[], opts?: {
|
|
770
|
+
trials?: number;
|
|
771
|
+
depth?: number;
|
|
772
|
+
bound?: number;
|
|
773
|
+
rand?: Rand;
|
|
774
|
+
}): Agreement;
|
|
775
|
+
}
|
|
776
|
+
export declare const fold: (name: string) => FoldRule;
|
|
777
|
+
export declare const proveFold: (f: FoldRule<Obj, Obj, Obj>, laws: Law[]) => Verdict;
|