capdag 1.306.150 → 1.361.331

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/capdag.js CHANGED
@@ -1,12 +1,36 @@
1
1
  // Cap URN JavaScript Implementation
2
2
  // Follows the exact same rules as Rust, Go, and Objective-C implementations
3
-
4
- // Import TaggedUrn from the tagged-urn package
5
- const {
6
- TaggedUrn,
7
- valuesMatch: taggedUrnValuesMatch,
8
- scoreTagValue
9
- } = require('tagged-urn');
3
+ //
4
+ // Dispatch, acceptance, equivalence and specificity are decided by code
5
+ // generated from the proved model in ../formal (Lean) by lungo, in ./formal,
6
+ // not written here. It runs as WebAssembly, instantiated once when this module
7
+ // is first imported.
8
+
9
+ import { TaggedUrn } from 'tagged-urn';
10
+ import * as machineParser from './machine-parser.js';
11
+ import { load } from './formal/index.js';
12
+
13
+ const model = await load();
14
+
15
+ // Node's modules, for what works with the file system and with processes:
16
+ // cartridge discovery, installation records and directory hashes. They exist
17
+ // only under Node; elsewhere this module loads without them, and asking for
18
+ // them there is an error naming what needed them.
19
+ const node = (typeof process !== 'undefined' && process.versions && process.versions.node)
20
+ ? {
21
+ fs: await import('node:fs'),
22
+ path: await import('node:path'),
23
+ crypto: await import('node:crypto'),
24
+ childProcess: await import('node:child_process'),
25
+ }
26
+ : null;
27
+
28
+ function nodeModules(what) {
29
+ if (node === null) {
30
+ throw new Error(`capdag: ${what} needs Node's file system and processes, which this runtime does not have`);
31
+ }
32
+ return node;
33
+ }
10
34
 
11
35
  /**
12
36
  * Error types for Cap URN operations
@@ -83,7 +107,7 @@ function processDirectionTag(taggedUrn, tagName) {
83
107
  */
84
108
  function canonicalizeDirectionSpec(spec, tagName) {
85
109
  if (spec === 'media:' || spec === '*') {
86
- return spec;
110
+ return 'media:';
87
111
  }
88
112
 
89
113
  try {
@@ -106,7 +130,7 @@ function canonicalizeDirectionSpec(spec, tagName) {
106
130
  */
107
131
  function validatePreservedDirectionSpec(spec, tagName) {
108
132
  if (spec === 'media:' || spec === '*') {
109
- return spec;
133
+ return 'media:';
110
134
  }
111
135
 
112
136
  try {
@@ -195,6 +219,27 @@ function validateNonStructuralTags(tags) {
195
219
  }
196
220
  }
197
221
 
222
+ /**
223
+ * A tagged URN as capdag's model takes it. Each program generated for
224
+ * JavaScript runs in a WebAssembly instance of its own, so tagged-urn's model
225
+ * value of a URN cannot pass here: this program makes its own, from the same
226
+ * tags, with the same function of the same model.
227
+ */
228
+ function modelUrn(urn) {
229
+ const made = model.make(urn.prefix, urn.modelTags());
230
+ if (made === null) {
231
+ throw new Error(`capdag: the model refused ${urn.toString()}, whose keys are sorted`);
232
+ }
233
+ return made;
234
+ }
235
+
236
+ const MODEL_EFFECTS = Object.freeze({
237
+ declared: Object.freeze({ kind: 'declared' }),
238
+ none: Object.freeze({ kind: 'none' }),
239
+ patch: Object.freeze({ kind: 'patch' }),
240
+ '?': Object.freeze({ kind: 'unspecified' }),
241
+ });
242
+
198
243
  class CapUrn {
199
244
  // Per-axis weights for cap-URN specificity. Two orders of
200
245
  // magnitude separate each axis to keep them in distinct digit
@@ -224,6 +269,20 @@ class CapUrn {
224
269
  }
225
270
  validateNonStructuralTags(this.tags);
226
271
  this._validateAdmissible();
272
+ // The same cap on the proved model's side: its three URNs and its effect.
273
+ // Dispatch, acceptance, equivalence and specificity are asked of it. Made
274
+ // here, from the same fields, and the cap is frozen, so the two can never
275
+ // describe different caps; it is not enumerable, so it is not part of what
276
+ // a cap serializes or compares as.
277
+ const formal = {
278
+ input: modelUrn(MediaUrn.fromString(this.inSpec)._urn),
279
+ output: modelUrn(MediaUrn.fromString(this.outSpec)._urn),
280
+ other: modelUrn(new TaggedUrn('cap', this.tags)),
281
+ effect: MODEL_EFFECTS[this.effectValue],
282
+ };
283
+ Object.defineProperty(this, 'formal', { value: formal, enumerable: false });
284
+ Object.freeze(this.tags);
285
+ Object.freeze(this);
227
286
  }
228
287
 
229
288
  /**
@@ -604,51 +663,10 @@ class CapUrn {
604
663
  if (!request) {
605
664
  return true;
606
665
  }
607
-
608
- // Input direction: pattern accepts instance. `media:` on the pattern side is
609
- // the wildcard top and skips the check.
610
- if (this.inSpec !== 'media:' && this.inSpec !== '*') {
611
- const capIn = MediaUrn.fromString(this.inSpec);
612
- const requestIn = MediaUrn.fromString(request.inSpec);
613
- if (!capIn.accepts(requestIn)) {
614
- return false;
615
- }
616
- }
617
-
618
- // Output direction: candidate output must conform to requested output.
619
- // `media:` on the pattern side is wildcard top and skips the check.
620
- if (this.outSpec !== 'media:' && this.outSpec !== '*') {
621
- const capOut = MediaUrn.fromString(this.outSpec);
622
- const requestOut = MediaUrn.fromString(request.outSpec);
623
- if (!capOut.conformsTo(requestOut)) {
624
- return false;
625
- }
626
- }
627
-
628
- if (this.effectValue !== CapEffect.ANY && this.effectValue !== request.effectValue) {
629
- return false;
630
- }
631
-
632
- // Y-axis: every tag's per-key match runs through the six-form
633
- // truth table (taggedUrnValuesMatch). Walk the union of all keys
634
- // appearing on either side so missing-on-pattern and
635
- // missing-on-instance cells both get evaluated.
636
- const allKeys = new Set([
637
- ...Object.keys(this.tags),
638
- ...Object.keys(request.tags),
639
- ]);
640
- for (const key of allKeys) {
641
- const patt = Object.prototype.hasOwnProperty.call(this.tags, key)
642
- ? this.tags[key]
643
- : undefined;
644
- const inst = Object.prototype.hasOwnProperty.call(request.tags, key)
645
- ? request.tags[key]
646
- : undefined;
647
- if (!taggedUrnValuesMatch(inst, patt)) {
648
- return false;
649
- }
650
- }
651
- return true;
666
+ // Decided by the proved model (CapDAG.Exec.accepts). The cap-tag axis runs
667
+ // opposite to isDispatchable's: this is the pattern relation, dispatch is
668
+ // the routing one.
669
+ return model.accepts(this.formal, request.formal);
652
670
  }
653
671
 
654
672
  /**
@@ -689,16 +707,8 @@ class CapUrn {
689
707
  * @returns {number} The specificity score
690
708
  */
691
709
  specificity() {
692
- const inUrn = MediaUrn.fromString(this.inSpec);
693
- const outUrn = MediaUrn.fromString(this.outSpec);
694
-
695
- let yScore = 0;
696
- for (const value of Object.values(this.tags)) {
697
- yScore += scoreTagValue(value);
698
- }
699
- return CapUrn.WEIGHT_OUT * outUrn.specificity()
700
- + CapUrn.WEIGHT_IN * inUrn.specificity()
701
- + yScore;
710
+ // Computed by the proved model (CapDAG.Exec.specificity).
711
+ return Number(model.specificity(this.formal));
702
712
  }
703
713
 
704
714
  /**
@@ -781,7 +791,7 @@ class CapUrn {
781
791
  * @returns {boolean}
782
792
  */
783
793
  isComparable(other) {
784
- return this.accepts(other) || other.accepts(this);
794
+ return model.comparable(this.formal, other.formal);
785
795
  }
786
796
 
787
797
  /**
@@ -792,7 +802,7 @@ class CapUrn {
792
802
  * @returns {boolean}
793
803
  */
794
804
  isEquivalent(other) {
795
- return this.accepts(other) && other.accepts(this);
805
+ return model.equivalent(this.formal, other.formal);
796
806
  }
797
807
 
798
808
  /**
@@ -857,45 +867,13 @@ class CapUrn {
857
867
  * @returns {boolean}
858
868
  */
859
869
  isDispatchable(request) {
860
- return this._inputDispatchable(request)
861
- && this._outputDispatchable(request)
862
- && this._effectDispatchable(request)
863
- && this._capTagsDispatchable(request);
864
- }
865
-
866
- _inputDispatchable(request) {
867
- if (request.inSpec === 'media:') return true;
868
- if (this.inSpec === 'media:') return true;
869
- return MediaUrn.fromString(request.inSpec).conformsTo(MediaUrn.fromString(this.inSpec));
870
- }
871
-
872
- _outputDispatchable(request) {
873
- if (request.outSpec === 'media:') return true;
874
- if (this.outSpec === 'media:') return false;
875
- return MediaUrn.fromString(this.outSpec).conformsTo(MediaUrn.fromString(request.outSpec));
876
- }
877
-
878
- _effectDispatchable(request) {
879
- return request.effectValue === CapEffect.ANY || this.effectValue === request.effectValue;
880
- }
881
-
882
- _capTagsDispatchable(request) {
883
- const allKeys = new Set([
884
- ...Object.keys(this.tags),
885
- ...Object.keys(request.tags),
886
- ]);
887
- for (const key of allKeys) {
888
- const patt = Object.prototype.hasOwnProperty.call(request.tags, key)
889
- ? request.tags[key]
890
- : undefined;
891
- const inst = Object.prototype.hasOwnProperty.call(this.tags, key)
892
- ? this.tags[key]
893
- : undefined;
894
- if (!taggedUrnValuesMatch(inst, patt)) {
895
- return false;
896
- }
897
- }
898
- return true;
870
+ // Decided by the proved model (CapDAG.Exec.dispatch): every axis is a type.
871
+ // The request's input refines the candidate's, the candidate's output
872
+ // refines the request's, the effect matches unless the request says
873
+ // ?effect, and the candidate's cap-tags refine the request's. `media:` on
874
+ // a request's input is a type — "may send anything" — so only a candidate
875
+ // that accepts anything serves it, which is what makes dispatch compose.
876
+ return model.dispatch(this.formal, request.formal);
899
877
  }
900
878
 
901
879
  /**
@@ -6172,8 +6150,7 @@ class CartridgeJson {
6172
6150
  * @throws {CartridgeJsonError}
6173
6151
  */
6174
6152
  static readFromDir(versionDir, expectedSlug) {
6175
- const fs = require('fs');
6176
- const path = require('path');
6153
+ const { fs, path } = nodeModules('reading cartridge.json');
6177
6154
  const jsonPath = path.join(versionDir, 'cartridge.json');
6178
6155
 
6179
6156
  if (!fs.existsSync(jsonPath)) {
@@ -6255,7 +6232,7 @@ class CartridgeJson {
6255
6232
  * @returns {string}
6256
6233
  */
6257
6234
  resolveEntryPoint(versionDir) {
6258
- const path = require('path');
6235
+ const { path } = nodeModules('resolving an entry point');
6259
6236
  return path.join(versionDir, this.entry);
6260
6237
  }
6261
6238
  }
@@ -6272,9 +6249,7 @@ class CartridgeJson {
6272
6249
  * @returns {string} Lowercase hex SHA256.
6273
6250
  */
6274
6251
  function hashCartridgeDirectory(dir) {
6275
- const fs = require('fs');
6276
- const path = require('path');
6277
- const crypto = require('crypto');
6252
+ const { fs, path, crypto } = nodeModules('hashing a cartridge directory');
6278
6253
 
6279
6254
  const files = [];
6280
6255
  const collect = (current) => {
@@ -6577,7 +6552,7 @@ function encodeHelloFrame() {
6577
6552
  * @throws {Error} when the handshake/probe fails.
6578
6553
  */
6579
6554
  function probeCartridgeCapGroups(entryPath) {
6580
- const { spawn } = require('child_process');
6555
+ const { spawn } = nodeModules('probing a cartridge').childProcess;
6581
6556
  return new Promise((resolve, reject) => {
6582
6557
  let child;
6583
6558
  try {
@@ -6714,8 +6689,7 @@ function probeCartridgeCapGroups(entryPath) {
6714
6689
  * @returns {Promise<Array<DiscoveredCartridge>>}
6715
6690
  */
6716
6691
  async function discoverCartridges(cartridgesRoot, identity) {
6717
- const fs = require('fs');
6718
- const path = require('path');
6692
+ const { fs, path } = nodeModules('discovering cartridges');
6719
6693
  const discovered = [];
6720
6694
 
6721
6695
  let rootStat;
@@ -6755,8 +6729,7 @@ async function discoverCartridges(cartridgesRoot, identity) {
6755
6729
  * Mirrors capdag::cartridge_discovery::scan_channel_root.
6756
6730
  */
6757
6731
  async function scanChannelRoot(scanRoot, expectedSlug, identity, discovered) {
6758
- const fs = require('fs');
6759
- const path = require('path');
6732
+ const { fs, path } = nodeModules('discovering cartridges');
6760
6733
 
6761
6734
  let nameEntries;
6762
6735
  try {
@@ -7645,7 +7618,6 @@ class Machine {
7645
7618
  // ============================================================================
7646
7619
 
7647
7620
  // Load the Peggy-generated parser
7648
- const machineParser = require('./machine-parser.js');
7649
7621
 
7650
7622
  /**
7651
7623
  * Assign a media URN to a node, or check consistency if already assigned.
@@ -8026,22 +7998,13 @@ class MediaRegistryEntry {
8026
7998
  * implementations (capdag, capdag-js, capdag-py, capdag-go, capdag-objc)
8027
7999
  * use this same algorithm so a URN's key is identical across languages.
8028
8000
  *
8029
- * Runtime detection: `crypto.subtle` is available in browsers and
8030
- * modern Node (≥ 16, exposed via `globalThis.crypto`); CommonJS Node
8031
- * also has the synchronous `crypto` module. We prefer subtle for
8032
- * portability and fall back to the Node module when subtle is absent.
8001
+ * `crypto.subtle` is on `globalThis` in browsers and in every Node this
8002
+ * package supports.
8033
8003
  */
8034
8004
  async function sha256Hex(s) {
8035
8005
  const utf8 = new TextEncoder().encode(s);
8036
- if (typeof globalThis.crypto !== 'undefined' && globalThis.crypto.subtle) {
8037
- const buf = await globalThis.crypto.subtle.digest('SHA-256', utf8);
8038
- return Array.from(new Uint8Array(buf)).map(b => b.toString(16).padStart(2, '0')).join('');
8039
- }
8040
- // Node CommonJS fallback. require() may throw in strict ESM contexts;
8041
- // we let it propagate because every supported runtime has a crypto API.
8042
- // eslint-disable-next-line global-require
8043
- const nodeCrypto = require('crypto');
8044
- return nodeCrypto.createHash('sha256').update(utf8).digest('hex');
8006
+ const buf = await globalThis.crypto.subtle.digest('SHA-256', utf8);
8007
+ return Array.from(new Uint8Array(buf)).map(b => b.toString(16).padStart(2, '0')).join('');
8045
8008
  }
8046
8009
 
8047
8010
  /**
@@ -8445,12 +8408,7 @@ class Manifest {
8445
8408
  }
8446
8409
  }
8447
8410
 
8448
- // Unified configurable planner vocabulary (mirrors Rust plan_space.rs and the
8449
- // PlanMachines/DiscoverConvergentTargets proto surface).
8450
- const planner = require('./planner.js');
8451
-
8452
- // Export for CommonJS
8453
- module.exports = {
8411
+ export {
8454
8412
  // Registry trust vocabulary — one verdict per registry, shared by every
8455
8413
  // cartridge that claims provenance from it.
8456
8414
  RegistryVerdict,
@@ -8466,24 +8424,6 @@ module.exports = {
8466
8424
  registryVerdictRemedy,
8467
8425
  MANIFEST_SIG_FORMAT,
8468
8426
  RELEASE_KEY_CERT_FORMAT,
8469
- // Planner plan-space vocabulary
8470
- PlanStateError: planner.PlanStateError,
8471
- ConvergencePresence: planner.ConvergencePresence,
8472
- ConvergenceLocation: planner.ConvergenceLocation,
8473
- ConvergenceMechanism: planner.ConvergenceMechanism,
8474
- ConvergenceArity: planner.ConvergenceArity,
8475
- DivergencePresence: planner.DivergencePresence,
8476
- DivergenceLocation: planner.DivergenceLocation,
8477
- RankPolicy: planner.RankPolicy,
8478
- PlanMode: planner.PlanMode,
8479
- PlanRequest: planner.PlanRequest,
8480
- parsePlanApex: planner.parsePlanApex,
8481
- parsePlanProfile: planner.parsePlanProfile,
8482
- parsePlanCost: planner.parsePlanCost,
8483
- parsePlanCandidate: planner.parsePlanCandidate,
8484
- parsePlanCandidates: planner.parsePlanCandidates,
8485
- parseConvergentTarget: planner.parseConvergentTarget,
8486
- parseConvergentTargets: planner.parseConvergentTargets,
8487
8427
  ALIAS_TARGET_CAP,
8488
8428
  ALIAS_TARGET_MEDIA,
8489
8429
  tokenIsUrn,
@@ -8541,7 +8481,7 @@ module.exports = {
8541
8481
  MEDIA_OBJECT,
8542
8482
  // List types
8543
8483
  MEDIA_LIST,
8544
- MEDIA_TEXTABLE_LIST: MEDIA_STRING_LIST,
8484
+ MEDIA_STRING_LIST as MEDIA_TEXTABLE_LIST,
8545
8485
  MEDIA_STRING_LIST,
8546
8486
  MEDIA_INTEGER_LIST,
8547
8487
  MEDIA_NUMBER_LIST,
@@ -8705,3 +8645,25 @@ module.exports = {
8705
8645
  MediaRegistryEntry,
8706
8646
  FabricRegistryClient,
8707
8647
  };
8648
+
8649
+ // Unified configurable planner vocabulary (mirrors Rust plan_space.rs and the
8650
+ // PlanMachines/DiscoverConvergentTargets proto surface).
8651
+ export {
8652
+ PlanStateError,
8653
+ ConvergencePresence,
8654
+ ConvergenceLocation,
8655
+ ConvergenceMechanism,
8656
+ ConvergenceArity,
8657
+ DivergencePresence,
8658
+ DivergenceLocation,
8659
+ RankPolicy,
8660
+ PlanMode,
8661
+ PlanRequest,
8662
+ parsePlanApex,
8663
+ parsePlanProfile,
8664
+ parsePlanCost,
8665
+ parsePlanCandidate,
8666
+ parsePlanCandidates,
8667
+ parseConvergentTarget,
8668
+ parseConvergentTargets,
8669
+ } from './planner.js';
@@ -0,0 +1,74 @@
1
+ // Generated by lungo 1.78.3254 from Lean 4.34.1 for program capdagFormal. Do not edit.
2
+ import * as L from "lungo-ts";
3
+
4
+ /** Lean's CapDAG.Exec.WfCap. */
5
+ export interface WfCap {
6
+ readonly input: Wf;
7
+ readonly output: Wf;
8
+ readonly other: Wf;
9
+ readonly effect: Effect;
10
+ }
11
+ export function wfCapType(): L.Type<WfCap>;
12
+
13
+ /** Lean's CapDAG.Effect. */
14
+ export type Effect =
15
+ | { readonly kind: "unspecified" }
16
+ | { readonly kind: "declared" }
17
+ | { readonly kind: "none" }
18
+ | { readonly kind: "patch" }
19
+ ;
20
+ export function effectType(): L.Type<Effect>;
21
+
22
+ /** Lean's TaggedUrn.Constraint. */
23
+ export type Constraint =
24
+ | { readonly kind: "missing" }
25
+ | { readonly kind: "unconstrained" }
26
+ | { readonly kind: "optionalNot"; readonly value: string }
27
+ | { readonly kind: "present" }
28
+ | { readonly kind: "presentNot"; readonly value: string }
29
+ | { readonly kind: "exact"; readonly value: string }
30
+ | { readonly kind: "absent" }
31
+ ;
32
+ export function constraintType(): L.Type<Constraint>;
33
+
34
+ /** Lean's TaggedUrn.Exec.Wf, held by handle: only the program's functions make and read its values. */
35
+ export class Wf extends L.Opaque {
36
+ private constructor();
37
+ }
38
+ export function wfType(): L.Type<Wf>;
39
+
40
+ /** The layout fingerprint and descriptor of each type, by Lean name, for modules using them. */
41
+ export const leanTypes: {
42
+ readonly [lean: string]: { readonly fingerprint: string; readonly type: (...args: L.Type<any>[]) => L.Type<any> };
43
+ };
44
+
45
+ /** The Lean program capdagFormal. */
46
+ export class CapdagFormal {
47
+ private constructor();
48
+ /** Lean's CapDAG.Exec.accepts : CapDAG.Exec.WfCap → CapDAG.Exec.WfCap → Bool */
49
+ accepts(pattern: WfCap, request: WfCap): boolean;
50
+ /** Lean's CapDAG.Exec.comparable : CapDAG.Exec.WfCap → CapDAG.Exec.WfCap → Bool */
51
+ comparable(a: WfCap, b: WfCap): boolean;
52
+ /** Lean's CapDAG.Exec.dispatch : CapDAG.Exec.WfCap → CapDAG.Exec.WfCap → Bool */
53
+ dispatch(candidate: WfCap, request: WfCap): boolean;
54
+ /** Lean's CapDAG.Exec.effectOk : CapDAG.Effect → CapDAG.Effect → Bool */
55
+ effectOk(candidate: Effect, request: Effect): boolean;
56
+ /** Lean's CapDAG.Exec.equivalent : CapDAG.Exec.WfCap → CapDAG.Exec.WfCap → Bool */
57
+ equivalent(a: WfCap, b: WfCap): boolean;
58
+ /** Lean's CapDAG.Exec.rankingKey : CapDAG.Exec.WfCap → CapDAG.Exec.WfCap → Nat × Nat */
59
+ rankingKey(candidate: WfCap, request: WfCap): [bigint, bigint];
60
+ /** Lean's CapDAG.Exec.select : List CapDAG.Exec.WfCap → CapDAG.Exec.WfCap → Option CapDAG.Exec.WfCap */
61
+ select(candidates: Array<WfCap>, request: WfCap): L.Option<WfCap>;
62
+ /** Lean's CapDAG.Exec.specificity : CapDAG.Exec.WfCap → Nat */
63
+ specificity(c: WfCap): bigint;
64
+ /** Lean's TaggedUrn.Exec.make : String → List (String × TaggedUrn.Constraint) → Option TaggedUrn.Exec.Wf */
65
+ make(scheme: string, tags: Array<[string, Constraint]>): L.Option<Wf>;
66
+ }
67
+
68
+ export interface LoadOptions {
69
+ /** The program module (default: `program.wasm` next to this file). */
70
+ module?: WebAssembly.Module | BufferSource;
71
+ wasi?: L.Wasi;
72
+ }
73
+
74
+ export function load(options?: LoadOptions): Promise<CapdagFormal>;
@@ -0,0 +1,185 @@
1
+ // Generated by lungo 1.78.3254 from Lean 4.34.1 for program capdagFormal. Do not edit.
2
+ import * as L from "lungo-ts";
3
+
4
+ async function programModule() {
5
+ const url = new URL("./program.wasm", import.meta.url);
6
+ if (typeof process !== "undefined" && process.versions?.node) {
7
+ const { readFile } = await import("node:fs/promises");
8
+ return readFile(url);
9
+ }
10
+ const response = await fetch(url);
11
+ if (!response.ok) throw new Error(`cannot load ${url}: ${response.status}`);
12
+ return response.arrayBuffer();
13
+ }
14
+
15
+ /** Describes CapDAG.Exec.WfCap for polymorphic functions. */
16
+ export function wfCapType() {
17
+ return new L.Type(
18
+ L.inductiveExpr(0),
19
+ (w, v) => {
20
+ if (typeof v !== "object" || v === null) throw new L.MalformedError("not a CapDAG.Exec.WfCap");
21
+ w.u32(0);
22
+ wfType().encode(w, v.input);
23
+ wfType().encode(w, v.output);
24
+ wfType().encode(w, v.other);
25
+ effectType().encode(w, v.effect);
26
+ },
27
+ (r) => {
28
+ const c = r.u32();
29
+ if (c !== 0) throw new L.MalformedError(`constructor index ${c} of CapDAG.Exec.WfCap`);
30
+ return ({ input: wfType().decode(r), output: wfType().decode(r), other: wfType().decode(r), effect: effectType().decode(r) });
31
+ },
32
+ );
33
+ }
34
+
35
+ /** Describes CapDAG.Effect for polymorphic functions. */
36
+ export function effectType() {
37
+ return new L.Type(
38
+ L.inductiveExpr(1),
39
+ (w, v) => {
40
+ if (typeof v !== "object" || v === null) throw new L.MalformedError("not a CapDAG.Effect");
41
+ switch (v.kind) {
42
+ case "unspecified":
43
+ w.u32(0);
44
+ return;
45
+ case "declared":
46
+ w.u32(1);
47
+ return;
48
+ case "none":
49
+ w.u32(2);
50
+ return;
51
+ case "patch":
52
+ w.u32(3);
53
+ return;
54
+ default:
55
+ throw new L.MalformedError(`${String(v.kind)} is not a constructor of CapDAG.Effect`);
56
+ }
57
+ },
58
+ (r) => {
59
+ const c = r.u32();
60
+ switch (c) {
61
+ case 0: return ({ kind: "unspecified" });
62
+ case 1: return ({ kind: "declared" });
63
+ case 2: return ({ kind: "none" });
64
+ case 3: return ({ kind: "patch" });
65
+ default: throw new L.MalformedError(`constructor index ${c} of CapDAG.Effect`);
66
+ }
67
+ },
68
+ );
69
+ }
70
+
71
+ /** Describes TaggedUrn.Constraint for polymorphic functions. */
72
+ export function constraintType() {
73
+ return new L.Type(
74
+ L.inductiveExpr(2),
75
+ (w, v) => {
76
+ if (typeof v !== "object" || v === null) throw new L.MalformedError("not a TaggedUrn.Constraint");
77
+ switch (v.kind) {
78
+ case "missing":
79
+ w.u32(0);
80
+ return;
81
+ case "unconstrained":
82
+ w.u32(1);
83
+ return;
84
+ case "optionalNot":
85
+ w.u32(2);
86
+ L.STRING.encode(w, v.value);
87
+ return;
88
+ case "present":
89
+ w.u32(3);
90
+ return;
91
+ case "presentNot":
92
+ w.u32(4);
93
+ L.STRING.encode(w, v.value);
94
+ return;
95
+ case "exact":
96
+ w.u32(5);
97
+ L.STRING.encode(w, v.value);
98
+ return;
99
+ case "absent":
100
+ w.u32(6);
101
+ return;
102
+ default:
103
+ throw new L.MalformedError(`${String(v.kind)} is not a constructor of TaggedUrn.Constraint`);
104
+ }
105
+ },
106
+ (r) => {
107
+ const c = r.u32();
108
+ switch (c) {
109
+ case 0: return ({ kind: "missing" });
110
+ case 1: return ({ kind: "unconstrained" });
111
+ case 2: return ({ kind: "optionalNot", value: L.STRING.decode(r) });
112
+ case 3: return ({ kind: "present" });
113
+ case 4: return ({ kind: "presentNot", value: L.STRING.decode(r) });
114
+ case 5: return ({ kind: "exact", value: L.STRING.decode(r) });
115
+ case 6: return ({ kind: "absent" });
116
+ default: throw new L.MalformedError(`constructor index ${c} of TaggedUrn.Constraint`);
117
+ }
118
+ },
119
+ );
120
+ }
121
+
122
+ /** Lean's TaggedUrn.Exec.Wf, held by handle: only the program's functions make and read its values. */
123
+ export class Wf extends L.Opaque {}
124
+
125
+ /** Describes TaggedUrn.Exec.Wf for polymorphic functions. */
126
+ export function wfType() {
127
+ return new L.Type(
128
+ L.inductiveExpr(3),
129
+ (w, v) => {
130
+ if (!(v instanceof Wf)) throw new L.MalformedError("not a TaggedUrn.Exec.Wf");
131
+ L.OPAQUE.encode(w, v);
132
+ },
133
+ (r) => new Wf(r.program, r.u64()),
134
+ );
135
+ }
136
+
137
+ /** The layout fingerprint and descriptor of each type, by Lean name, for modules using them. */
138
+ export const leanTypes = Object.freeze({
139
+ "CapDAG.Exec.WfCap": Object.freeze({ fingerprint: "2b8d6466d218f4ae6bc98d95bba55d98f21cac4a49446ae170993773cefdb830", type: wfCapType }),
140
+ "CapDAG.Effect": Object.freeze({ fingerprint: "38c7bd3c0527cda156713cd441c9b6b92bd5df8a39108fa101449a789abcb477", type: effectType }),
141
+ "TaggedUrn.Constraint": Object.freeze({ fingerprint: "481fc09e23c6415a7c3f05887577ec940a6ecc84b005e63476c1060b59edcac7", type: constraintType }),
142
+ "TaggedUrn.Exec.Wf": Object.freeze({ fingerprint: "20e9f81ad195b2f4a481e7a5dcae2b3d0de6efe7b3dc720db0e2aa3b52527785", type: wfType }),
143
+ });
144
+
145
+ /** The Lean program capdagFormal. */
146
+ export class CapdagFormal {
147
+ #program;
148
+ constructor(program) {
149
+ this.#program = program;
150
+ }
151
+ accepts(pattern, request) {
152
+ return this.#program.invoke("capdagFormal__call_l_CapDAG_dExec_daccepts", [], [[wfCapType(), pattern], [wfCapType(), request]], L.value(L.BOOL));
153
+ }
154
+ comparable(a, b) {
155
+ return this.#program.invoke("capdagFormal__call_l_CapDAG_dExec_dcomparable", [], [[wfCapType(), a], [wfCapType(), b]], L.value(L.BOOL));
156
+ }
157
+ dispatch(candidate, request) {
158
+ return this.#program.invoke("capdagFormal__call_l_CapDAG_dExec_ddispatch", [], [[wfCapType(), candidate], [wfCapType(), request]], L.value(L.BOOL));
159
+ }
160
+ effectOk(candidate, request) {
161
+ return this.#program.invoke("capdagFormal__call_l_CapDAG_dExec_deffectOk", [], [[effectType(), candidate], [effectType(), request]], L.value(L.BOOL));
162
+ }
163
+ equivalent(a, b) {
164
+ return this.#program.invoke("capdagFormal__call_l_CapDAG_dExec_dequivalent", [], [[wfCapType(), a], [wfCapType(), b]], L.value(L.BOOL));
165
+ }
166
+ rankingKey(candidate, request) {
167
+ return this.#program.invoke("capdagFormal__call_l_CapDAG_dExec_drankingKey", [], [[wfCapType(), candidate], [wfCapType(), request]], L.value(L.pair(L.NAT, L.NAT)));
168
+ }
169
+ select(candidates, request) {
170
+ return this.#program.invoke("capdagFormal__call_l_CapDAG_dExec_dselect", [], [[L.list(wfCapType()), candidates], [wfCapType(), request]], L.value(L.option(wfCapType())));
171
+ }
172
+ specificity(c) {
173
+ return this.#program.invoke("capdagFormal__call_l_CapDAG_dExec_dspecificity", [], [[wfCapType(), c]], L.value(L.NAT));
174
+ }
175
+ make(scheme, tags) {
176
+ return this.#program.invoke("capdagFormal__call_l_TaggedUrn_dExec_dmake", [], [[L.STRING, scheme], [L.list(L.pair(L.STRING, constraintType())), tags]], L.value(L.option(wfType())));
177
+ }
178
+ }
179
+
180
+ /** Instantiates the program; `options.host` implements its externs. */
181
+ export async function load(options = {}) {
182
+ const program = await L.Program.load(options.module ?? (await programModule()), { wasi: options.wasi });
183
+ program.types("capdagFormal__types");
184
+ return new CapdagFormal(program);
185
+ }
Binary file