@suss/resolution 0.29.0 → 0.31.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/dist/index.d.cts CHANGED
@@ -312,6 +312,62 @@ interface SpannedNode<N> {
312
312
  */
313
313
  declare function nodeOfKey<N extends SpannedNode<N>>(rootsByFile: ReadonlyMap<string, N>, key: string): N | null;
314
314
 
315
+ /**
316
+ * packWords.ts: the facts a pack states about its own library.
317
+ *
318
+ * Nothing in a source file says that `Account.find(id)` gives back one
319
+ * Account, or that entering `httpx.Client()` gives back the client it
320
+ * built. The library knows, the pack writes it down, and an adapter puts
321
+ * it in the store. Every adapter did that with a loop of its own, so
322
+ * each new word had to be written three times. `addPackWords` is the one
323
+ * loop; an adapter maps its own pack type onto `PackWords` and calls it.
324
+ *
325
+ * The field names match the fact vocabulary at the top of `index.ts`.
326
+ */
327
+
328
+ /** A method on a class reaching `base` gives back one of that class. */
329
+ interface GivesBackOne {
330
+ base: string;
331
+ method: string;
332
+ }
333
+ /** The same, for a library that takes the class at position `argument` instead of as the receiver. */
334
+ interface GivesBackOneOfArgument extends GivesBackOne {
335
+ argument: number;
336
+ }
337
+ /** The same again, for the bare function `module` exports under `name`. */
338
+ interface GivesBackOneOfImport {
339
+ module: string;
340
+ name: string;
341
+ argument: number;
342
+ }
343
+ /** Entering one of `module`'s `name` gives back that same object. */
344
+ interface EntersAsSelf {
345
+ module: string;
346
+ name: string;
347
+ }
348
+ /** Calling `callee` out of `module` gives back its argument at `argument`. */
349
+ interface UnwrapsByName {
350
+ callee: string;
351
+ argument: number;
352
+ module: string;
353
+ }
354
+ /** A field given a call of `module`'s `name` declares an association. */
355
+ interface AssociationConstructor {
356
+ module: string;
357
+ name: string;
358
+ }
359
+ /** What a run's packs say about their own libraries, in one language-neutral shape. */
360
+ interface PackWords {
361
+ givesBackOne?: ReadonlyArray<GivesBackOne>;
362
+ givesBackOneOfArgument?: ReadonlyArray<GivesBackOneOfArgument>;
363
+ givesBackOneOfImport?: ReadonlyArray<GivesBackOneOfImport>;
364
+ entersAsSelf?: ReadonlyArray<EntersAsSelf>;
365
+ unwrapsByName?: ReadonlyArray<UnwrapsByName>;
366
+ associationConstructor?: ReadonlyArray<AssociationConstructor>;
367
+ }
368
+ /** Put a run's pack declarations in the store, so the shared rules can read them. */
369
+ declare function addPackWords(db: Database, words: PackWords): void;
370
+
315
371
  /**
316
372
  * The rules an adapter evaluates, and how a question is put to them.
317
373
  *
@@ -334,11 +390,24 @@ declare const ASKING_RELATIONS: readonly string[];
334
390
  * reaches it. Built once per language and kept, because the rewrite
335
391
  * does not depend on the facts.
336
392
  *
393
+ * The questions asked under an allocation site are left out, which
394
+ * drops every rule behind them, so a caller that never mentions a
395
+ * context pays nothing for the second closure.
396
+ *
337
397
  * `SUSS_RESOLUTION_ON_DEMAND=0` runs the same rules unrestricted. Both
338
398
  * settings give the same answers; they differ in how much never gets
339
399
  * derived at all.
340
400
  */
341
401
  declare function resolutionProgram(languageRules?: readonly Rule[]): OnDemandRules;
402
+ /**
403
+ * The same rules with the three questions under an allocation site
404
+ * added, which is what `askResolutionUnder` evaluates.
405
+ *
406
+ * Running both programs over one database costs the context-free one
407
+ * its resume state, so a caller with many context-free questions and a
408
+ * few under a site is better off asking the context-free ones first.
409
+ */
410
+ declare function resolutionUnderProgram(languageRules?: readonly Rule[]): OnDemandRules;
342
411
  /**
343
412
  * What a caller takes back once it has read an answer: the question and
344
413
  * every relation derived under it. Empty when nothing is demand-driven,
@@ -357,6 +426,12 @@ declare function queryFacts(program: OnDemandRules): readonly string[];
357
426
  * question, which is how each adapter reads a project.
358
427
  */
359
428
  declare function askResolution(db: Database, keys: Iterable<string>, asking?: string, program?: OnDemandRules): void;
429
+ /**
430
+ * `askResolution` for a value read under one allocation site. Each pair
431
+ * is a question of its own, so asking about a value under two sites is
432
+ * two rows, and asking the same pair twice costs nothing.
433
+ */
434
+ declare function askResolutionUnder(db: Database, pairs: Iterable<readonly [string, string]>, program?: OnDemandRules): void;
360
435
 
361
436
  /**
362
437
  * The result shape a why session hands back, shared by every language
@@ -418,22 +493,58 @@ interface ExplainResolvedKeyOptions {
418
493
  declare function explainResolvedKey(options: ExplainResolvedKeyOptions): WhyExplained | null;
419
494
 
420
495
  /**
421
- * The single-answer policy shared by every question shaped `[key,
422
- * answer]`, such as `wantedIsWrittenAs` or `wantedSubjectWritten`. A
423
- * call is written as itself, so a call asked about directly always
424
- * matches its own key; that row is dropped before the count so one
425
- * other answer settles it instead of counting as two.
496
+ * What counts as an answer to a question shaped `[key, answer]`, such as
497
+ * `wantedIsWrittenAs` or `wantedSubjectWritten`. A call is written as
498
+ * itself, so a call asked about directly always matches its own key; that
499
+ * row is dropped before the count so one other answer settles it instead
500
+ * of counting as two.
426
501
  *
427
502
  * A placeholder write, `client = None` before a guard fills it in, is
428
503
  * set aside the same way when the key has any other answer. A key
429
504
  * written only as a placeholder keeps it.
505
+ *
506
+ * A caller that can only use one answer takes `singleAnswers`; one with
507
+ * something to say about a value written two ways takes `answersByKey`.
430
508
  */
431
509
 
432
- /** The one answer each key settles on, once a key's match against itself is dropped. */
510
+ /** Every answer each key has, in the order the rows arrive, with the two drops above applied. */
511
+ declare function answersByKey(rows: Iterable<Tuple>, placeholders?: ReadonlySet<string>): Map<string, string[]>;
512
+ /** The one answer each key settles on, for a caller that treats several as none. */
433
513
  declare function singleAnswers(rows: Iterable<Tuple>, placeholders?: ReadonlySet<string>): Map<string, string>;
434
514
  /** The keys an adapter marked `placeholderValue`, for passing to `singleAnswers`. */
435
515
  declare function placeholderValues(db: Database): ReadonlySet<string>;
436
516
 
517
+ /**
518
+ * Reading an answer that was asked for under one allocation site.
519
+ *
520
+ * The context-free readers take a key and get everything the rules
521
+ * settled it on. These take a key and a site, and get what the value is
522
+ * when the receiver behind it is the one that site made, so two clients
523
+ * of one class answer apart here and together context-free.
524
+ *
525
+ * Nothing is derived until `askResolutionUnder` has put the pair as a
526
+ * question, the same way the context-free readers need `askResolution`.
527
+ */
528
+
529
+ /** Every expression the value was written as under this site. */
530
+ declare function isWrittenAsUnder(db: Database, key: string, site: string): string[];
531
+ /** Every function or object the value comes down to under this site. */
532
+ declare function comesToUnder(db: Database, key: string, site: string): string[];
533
+ /** Every object the value refers to under this site, sites included. */
534
+ declare function objectOfUnder(db: Database, key: string, site: string): string[];
535
+ /**
536
+ * The single expression the value was written as under this site, under
537
+ * the policy the context-free reader applies: two answers are ambiguity,
538
+ * and ambiguity is nothing.
539
+ */
540
+ declare function writtenValueUnder(db: Database, key: string, site: string): string | null;
541
+ /**
542
+ * Every site a class was made at, once `askResolution` has asked
543
+ * `wantedSites` about it. These are the sites to put a value question
544
+ * under.
545
+ */
546
+ declare function allocationSitesOf(db: Database, cls: string): string[];
547
+
437
548
  /**
438
549
  * What a name written more than once comes down to.
439
550
  *
@@ -483,13 +594,29 @@ interface NameWrite {
483
594
  */
484
595
  declare function valueLeftByWrites(writes: readonly NameWrite[], ordered: boolean): string | null;
485
596
 
597
+ type Ask = (keys: readonly string[]) => void;
486
598
  /**
487
599
  * The single expression a value was written as, once the caller has
488
600
  * asked the rules about `key`. A call to a project function is asked
489
601
  * about as well, through `ask`, so the answer is what that function
490
602
  * returns rather than the call itself.
491
603
  */
492
- declare function writtenValueOf(db: Database, key: string, ask: (keys: readonly string[]) => void): string | null;
604
+ declare function writtenValueOf(db: Database, key: string, ask: Ask, relation?: string): string | null;
605
+ /**
606
+ * Every expression a value was written as. More than one is a value with
607
+ * more than one possible source, which a caller says something about at
608
+ * the site rather than reading as the same nothing as a chain that went
609
+ * nowhere.
610
+ */
611
+ declare function writtenValuesOf(db: Database, key: string, ask: Ask, relation?: string): string[];
612
+ /**
613
+ * The one expression each key was written as, for a caller with several
614
+ * keys at once. Keys the rules settled on nothing, or on more than one
615
+ * expression, are left out. One round of asking covers them all, which
616
+ * is what a caller gets here that a loop over `writtenValueOf` would
617
+ * not.
618
+ */
619
+ declare function writtenValuesByKey(db: Database, keys: readonly string[], ask: Ask, relation?: string): Map<string, string>;
493
620
 
494
621
  /** A step to the value x is written as. */
495
622
  declare const VALUE_STEP: _suss_datalog.Term;
@@ -501,23 +628,35 @@ declare const VALUE_STEP: _suss_datalog.Term;
501
628
  */
502
629
  declare const NAMESPACE_IMPORT_NAME = "*";
503
630
  declare const NAMESPACE_IMPORT: _suss_datalog.Term;
631
+ /**
632
+ * The label on the `comesFrom` rule for a member read off a whole-module
633
+ * import. `explain` tells that proof from the two import ones by it.
634
+ */
635
+ declare const NAMESPACE_MEMBER_RULE = "namespace member";
636
+ /**
637
+ * The label on the `contains` rule that walks a class's ancestry.
638
+ * `explain` says a name came from a base class when it fired.
639
+ */
640
+ declare const BASE_CLASS_RULE = "base class";
641
+ /** A step from an instance to the class it is one of. */
642
+ declare const INSTANCE_STEP: _suss_datalog.Term;
504
643
  /** A step to what running the call x is handed back. */
505
644
  declare const RESULT_STEP: _suss_datalog.Term;
645
+ /** The context a value read outside every allocation site is read under. */
646
+ declare const NO_CONTEXT_NAME = "none";
647
+ declare const NO_CONTEXT: _suss_datalog.Term;
506
648
  /**
507
- * The rules every language adapter shares. Concatenate a language's own
508
- * rules onto these before evaluating.
509
- *
510
- * Every construct states its hops once, as `stepsTo(x, y, kind)`, which
511
- * says x leads to y. A value step goes to the value x is written as, and a
512
- * result step runs the call x is and goes to what that call handed back.
513
- * `reaches` is the closure of those steps, and a walk counts as a result
514
- * walk once it has run a call anywhere along it.
649
+ * Rules with a `stepsTo` twin for each hop among them.
515
650
  *
516
- * Each question is that one closure with its own stopping condition, so
517
- * adding a construct is one step and every question gets it, and adding
518
- * a question is a stopping condition and no steps at all.
651
+ * `reaches` reads `stepsTo` and `reachesUnder` reads `hop`. A rule
652
+ * passing one through to the other would look tidier and costs far
653
+ * more: the demand for `stepsTo` is one of the largest relations a run
654
+ * derives, and every row of it would be copied into a demand for `hop`
655
+ * whether or not anybody asked about a context. A language that states
656
+ * a hop of its own passes it through here for the same reason.
519
657
  */
520
- declare const RESOLUTION_RULES: _suss_datalog.Rule[];
658
+ declare function alsoSteps(rules: readonly Rule[]): Rule[];
659
+ declare const RESOLUTION_RULES: Rule[];
521
660
  /**
522
661
  * The questions a caller asks, written as rules. Two facts say somebody
523
662
  * is asking: `wanted(x)` for what a value is, and `wantedOrigin(x)` for
@@ -535,8 +674,17 @@ declare const RESOLUTION_RULES: _suss_datalog.Rule[];
535
674
  * the value's function makes, so a caller that only wants to know what a
536
675
  * handler resolves to should not pay for that.
537
676
  */
538
- declare const RESOLUTION_QUESTIONS: _suss_datalog.Rule[];
677
+ declare const RESOLUTION_QUESTIONS: Rule[];
539
678
  /** The relations `RESOLUTION_QUESTIONS` answers into. */
540
679
  declare const ANSWER_RELATIONS: string[];
680
+ /**
681
+ * The three of those a caller asks under one allocation site.
682
+ *
683
+ * They are listed apart because leaving them out of what a program has
684
+ * to answer drops the whole second closure from it. A run that never
685
+ * mentions a context would otherwise carry a thousand rewritten rules
686
+ * it can never fire, and the engine reads every rule once a round.
687
+ */
688
+ declare const UNDER_ANSWER_RELATIONS: string[];
541
689
 
542
- export { ANSWER_RELATIONS, ASKING_RELATIONS, type CalleeOutcome, type CaseFiles, type ChainReads, type ContractCase, type ContractOptions, type DescribeAtom, type ExplainOptions, type ExplainResolvedKeyOptions, type ExplainStats, FACT_CONTRACT_CASES, type FactsOf, type MountEdge, type MountEdges, NAMESPACE_IMPORT, NAMESPACE_IMPORT_NAME, type NameReads, type NameWrite, type OrderedWrite, RESOLUTION_QUESTIONS, RESOLUTION_RULES, RESULT_STEP, type ReadNode, type ResolutionExplanation, type ResolutionStep, type SpannedNode, type StepContext, type StepPhrase, VALUE_STEP, type ValueLocation, type WhyExplained, agreedMountPrefix, askResolution, calleeOutcomeOf, calleeOutcomes, checkFactContract, couldBeSettled, explainResolutionProof, explainResolvedKey, joinMountedPath, mountPathsOf, nodeOfKey, placeholderValues, queryFacts, renderExplanation, resolutionProgram, singleAnswers, startsAtName, valueLeftByWrites, writesRunInOrder, writtenSourcesOf, writtenValueOf };
690
+ export { ANSWER_RELATIONS, ASKING_RELATIONS, type AssociationConstructor, BASE_CLASS_RULE, type CalleeOutcome, type CaseFiles, type ChainReads, type ContractCase, type ContractOptions, type DescribeAtom, type EntersAsSelf, type ExplainOptions, type ExplainResolvedKeyOptions, type ExplainStats, FACT_CONTRACT_CASES, type FactsOf, type GivesBackOne, type GivesBackOneOfArgument, type GivesBackOneOfImport, INSTANCE_STEP, type MountEdge, type MountEdges, NAMESPACE_IMPORT, NAMESPACE_IMPORT_NAME, NAMESPACE_MEMBER_RULE, NO_CONTEXT, NO_CONTEXT_NAME, type NameReads, type NameWrite, type OrderedWrite, type PackWords, RESOLUTION_QUESTIONS, RESOLUTION_RULES, RESULT_STEP, type ReadNode, type ResolutionExplanation, type ResolutionStep, type SpannedNode, type StepContext, type StepPhrase, UNDER_ANSWER_RELATIONS, type UnwrapsByName, VALUE_STEP, type ValueLocation, type WhyExplained, addPackWords, agreedMountPrefix, allocationSitesOf, alsoSteps, answersByKey, askResolution, askResolutionUnder, calleeOutcomeOf, calleeOutcomes, checkFactContract, comesToUnder, couldBeSettled, explainResolutionProof, explainResolvedKey, isWrittenAsUnder, joinMountedPath, mountPathsOf, nodeOfKey, objectOfUnder, placeholderValues, queryFacts, renderExplanation, resolutionProgram, resolutionUnderProgram, singleAnswers, startsAtName, valueLeftByWrites, writesRunInOrder, writtenSourcesOf, writtenValueOf, writtenValueUnder, writtenValuesByKey, writtenValuesOf };
package/dist/index.d.ts CHANGED
@@ -312,6 +312,62 @@ interface SpannedNode<N> {
312
312
  */
313
313
  declare function nodeOfKey<N extends SpannedNode<N>>(rootsByFile: ReadonlyMap<string, N>, key: string): N | null;
314
314
 
315
+ /**
316
+ * packWords.ts: the facts a pack states about its own library.
317
+ *
318
+ * Nothing in a source file says that `Account.find(id)` gives back one
319
+ * Account, or that entering `httpx.Client()` gives back the client it
320
+ * built. The library knows, the pack writes it down, and an adapter puts
321
+ * it in the store. Every adapter did that with a loop of its own, so
322
+ * each new word had to be written three times. `addPackWords` is the one
323
+ * loop; an adapter maps its own pack type onto `PackWords` and calls it.
324
+ *
325
+ * The field names match the fact vocabulary at the top of `index.ts`.
326
+ */
327
+
328
+ /** A method on a class reaching `base` gives back one of that class. */
329
+ interface GivesBackOne {
330
+ base: string;
331
+ method: string;
332
+ }
333
+ /** The same, for a library that takes the class at position `argument` instead of as the receiver. */
334
+ interface GivesBackOneOfArgument extends GivesBackOne {
335
+ argument: number;
336
+ }
337
+ /** The same again, for the bare function `module` exports under `name`. */
338
+ interface GivesBackOneOfImport {
339
+ module: string;
340
+ name: string;
341
+ argument: number;
342
+ }
343
+ /** Entering one of `module`'s `name` gives back that same object. */
344
+ interface EntersAsSelf {
345
+ module: string;
346
+ name: string;
347
+ }
348
+ /** Calling `callee` out of `module` gives back its argument at `argument`. */
349
+ interface UnwrapsByName {
350
+ callee: string;
351
+ argument: number;
352
+ module: string;
353
+ }
354
+ /** A field given a call of `module`'s `name` declares an association. */
355
+ interface AssociationConstructor {
356
+ module: string;
357
+ name: string;
358
+ }
359
+ /** What a run's packs say about their own libraries, in one language-neutral shape. */
360
+ interface PackWords {
361
+ givesBackOne?: ReadonlyArray<GivesBackOne>;
362
+ givesBackOneOfArgument?: ReadonlyArray<GivesBackOneOfArgument>;
363
+ givesBackOneOfImport?: ReadonlyArray<GivesBackOneOfImport>;
364
+ entersAsSelf?: ReadonlyArray<EntersAsSelf>;
365
+ unwrapsByName?: ReadonlyArray<UnwrapsByName>;
366
+ associationConstructor?: ReadonlyArray<AssociationConstructor>;
367
+ }
368
+ /** Put a run's pack declarations in the store, so the shared rules can read them. */
369
+ declare function addPackWords(db: Database, words: PackWords): void;
370
+
315
371
  /**
316
372
  * The rules an adapter evaluates, and how a question is put to them.
317
373
  *
@@ -334,11 +390,24 @@ declare const ASKING_RELATIONS: readonly string[];
334
390
  * reaches it. Built once per language and kept, because the rewrite
335
391
  * does not depend on the facts.
336
392
  *
393
+ * The questions asked under an allocation site are left out, which
394
+ * drops every rule behind them, so a caller that never mentions a
395
+ * context pays nothing for the second closure.
396
+ *
337
397
  * `SUSS_RESOLUTION_ON_DEMAND=0` runs the same rules unrestricted. Both
338
398
  * settings give the same answers; they differ in how much never gets
339
399
  * derived at all.
340
400
  */
341
401
  declare function resolutionProgram(languageRules?: readonly Rule[]): OnDemandRules;
402
+ /**
403
+ * The same rules with the three questions under an allocation site
404
+ * added, which is what `askResolutionUnder` evaluates.
405
+ *
406
+ * Running both programs over one database costs the context-free one
407
+ * its resume state, so a caller with many context-free questions and a
408
+ * few under a site is better off asking the context-free ones first.
409
+ */
410
+ declare function resolutionUnderProgram(languageRules?: readonly Rule[]): OnDemandRules;
342
411
  /**
343
412
  * What a caller takes back once it has read an answer: the question and
344
413
  * every relation derived under it. Empty when nothing is demand-driven,
@@ -357,6 +426,12 @@ declare function queryFacts(program: OnDemandRules): readonly string[];
357
426
  * question, which is how each adapter reads a project.
358
427
  */
359
428
  declare function askResolution(db: Database, keys: Iterable<string>, asking?: string, program?: OnDemandRules): void;
429
+ /**
430
+ * `askResolution` for a value read under one allocation site. Each pair
431
+ * is a question of its own, so asking about a value under two sites is
432
+ * two rows, and asking the same pair twice costs nothing.
433
+ */
434
+ declare function askResolutionUnder(db: Database, pairs: Iterable<readonly [string, string]>, program?: OnDemandRules): void;
360
435
 
361
436
  /**
362
437
  * The result shape a why session hands back, shared by every language
@@ -418,22 +493,58 @@ interface ExplainResolvedKeyOptions {
418
493
  declare function explainResolvedKey(options: ExplainResolvedKeyOptions): WhyExplained | null;
419
494
 
420
495
  /**
421
- * The single-answer policy shared by every question shaped `[key,
422
- * answer]`, such as `wantedIsWrittenAs` or `wantedSubjectWritten`. A
423
- * call is written as itself, so a call asked about directly always
424
- * matches its own key; that row is dropped before the count so one
425
- * other answer settles it instead of counting as two.
496
+ * What counts as an answer to a question shaped `[key, answer]`, such as
497
+ * `wantedIsWrittenAs` or `wantedSubjectWritten`. A call is written as
498
+ * itself, so a call asked about directly always matches its own key; that
499
+ * row is dropped before the count so one other answer settles it instead
500
+ * of counting as two.
426
501
  *
427
502
  * A placeholder write, `client = None` before a guard fills it in, is
428
503
  * set aside the same way when the key has any other answer. A key
429
504
  * written only as a placeholder keeps it.
505
+ *
506
+ * A caller that can only use one answer takes `singleAnswers`; one with
507
+ * something to say about a value written two ways takes `answersByKey`.
430
508
  */
431
509
 
432
- /** The one answer each key settles on, once a key's match against itself is dropped. */
510
+ /** Every answer each key has, in the order the rows arrive, with the two drops above applied. */
511
+ declare function answersByKey(rows: Iterable<Tuple>, placeholders?: ReadonlySet<string>): Map<string, string[]>;
512
+ /** The one answer each key settles on, for a caller that treats several as none. */
433
513
  declare function singleAnswers(rows: Iterable<Tuple>, placeholders?: ReadonlySet<string>): Map<string, string>;
434
514
  /** The keys an adapter marked `placeholderValue`, for passing to `singleAnswers`. */
435
515
  declare function placeholderValues(db: Database): ReadonlySet<string>;
436
516
 
517
+ /**
518
+ * Reading an answer that was asked for under one allocation site.
519
+ *
520
+ * The context-free readers take a key and get everything the rules
521
+ * settled it on. These take a key and a site, and get what the value is
522
+ * when the receiver behind it is the one that site made, so two clients
523
+ * of one class answer apart here and together context-free.
524
+ *
525
+ * Nothing is derived until `askResolutionUnder` has put the pair as a
526
+ * question, the same way the context-free readers need `askResolution`.
527
+ */
528
+
529
+ /** Every expression the value was written as under this site. */
530
+ declare function isWrittenAsUnder(db: Database, key: string, site: string): string[];
531
+ /** Every function or object the value comes down to under this site. */
532
+ declare function comesToUnder(db: Database, key: string, site: string): string[];
533
+ /** Every object the value refers to under this site, sites included. */
534
+ declare function objectOfUnder(db: Database, key: string, site: string): string[];
535
+ /**
536
+ * The single expression the value was written as under this site, under
537
+ * the policy the context-free reader applies: two answers are ambiguity,
538
+ * and ambiguity is nothing.
539
+ */
540
+ declare function writtenValueUnder(db: Database, key: string, site: string): string | null;
541
+ /**
542
+ * Every site a class was made at, once `askResolution` has asked
543
+ * `wantedSites` about it. These are the sites to put a value question
544
+ * under.
545
+ */
546
+ declare function allocationSitesOf(db: Database, cls: string): string[];
547
+
437
548
  /**
438
549
  * What a name written more than once comes down to.
439
550
  *
@@ -483,13 +594,29 @@ interface NameWrite {
483
594
  */
484
595
  declare function valueLeftByWrites(writes: readonly NameWrite[], ordered: boolean): string | null;
485
596
 
597
+ type Ask = (keys: readonly string[]) => void;
486
598
  /**
487
599
  * The single expression a value was written as, once the caller has
488
600
  * asked the rules about `key`. A call to a project function is asked
489
601
  * about as well, through `ask`, so the answer is what that function
490
602
  * returns rather than the call itself.
491
603
  */
492
- declare function writtenValueOf(db: Database, key: string, ask: (keys: readonly string[]) => void): string | null;
604
+ declare function writtenValueOf(db: Database, key: string, ask: Ask, relation?: string): string | null;
605
+ /**
606
+ * Every expression a value was written as. More than one is a value with
607
+ * more than one possible source, which a caller says something about at
608
+ * the site rather than reading as the same nothing as a chain that went
609
+ * nowhere.
610
+ */
611
+ declare function writtenValuesOf(db: Database, key: string, ask: Ask, relation?: string): string[];
612
+ /**
613
+ * The one expression each key was written as, for a caller with several
614
+ * keys at once. Keys the rules settled on nothing, or on more than one
615
+ * expression, are left out. One round of asking covers them all, which
616
+ * is what a caller gets here that a loop over `writtenValueOf` would
617
+ * not.
618
+ */
619
+ declare function writtenValuesByKey(db: Database, keys: readonly string[], ask: Ask, relation?: string): Map<string, string>;
493
620
 
494
621
  /** A step to the value x is written as. */
495
622
  declare const VALUE_STEP: _suss_datalog.Term;
@@ -501,23 +628,35 @@ declare const VALUE_STEP: _suss_datalog.Term;
501
628
  */
502
629
  declare const NAMESPACE_IMPORT_NAME = "*";
503
630
  declare const NAMESPACE_IMPORT: _suss_datalog.Term;
631
+ /**
632
+ * The label on the `comesFrom` rule for a member read off a whole-module
633
+ * import. `explain` tells that proof from the two import ones by it.
634
+ */
635
+ declare const NAMESPACE_MEMBER_RULE = "namespace member";
636
+ /**
637
+ * The label on the `contains` rule that walks a class's ancestry.
638
+ * `explain` says a name came from a base class when it fired.
639
+ */
640
+ declare const BASE_CLASS_RULE = "base class";
641
+ /** A step from an instance to the class it is one of. */
642
+ declare const INSTANCE_STEP: _suss_datalog.Term;
504
643
  /** A step to what running the call x is handed back. */
505
644
  declare const RESULT_STEP: _suss_datalog.Term;
645
+ /** The context a value read outside every allocation site is read under. */
646
+ declare const NO_CONTEXT_NAME = "none";
647
+ declare const NO_CONTEXT: _suss_datalog.Term;
506
648
  /**
507
- * The rules every language adapter shares. Concatenate a language's own
508
- * rules onto these before evaluating.
509
- *
510
- * Every construct states its hops once, as `stepsTo(x, y, kind)`, which
511
- * says x leads to y. A value step goes to the value x is written as, and a
512
- * result step runs the call x is and goes to what that call handed back.
513
- * `reaches` is the closure of those steps, and a walk counts as a result
514
- * walk once it has run a call anywhere along it.
649
+ * Rules with a `stepsTo` twin for each hop among them.
515
650
  *
516
- * Each question is that one closure with its own stopping condition, so
517
- * adding a construct is one step and every question gets it, and adding
518
- * a question is a stopping condition and no steps at all.
651
+ * `reaches` reads `stepsTo` and `reachesUnder` reads `hop`. A rule
652
+ * passing one through to the other would look tidier and costs far
653
+ * more: the demand for `stepsTo` is one of the largest relations a run
654
+ * derives, and every row of it would be copied into a demand for `hop`
655
+ * whether or not anybody asked about a context. A language that states
656
+ * a hop of its own passes it through here for the same reason.
519
657
  */
520
- declare const RESOLUTION_RULES: _suss_datalog.Rule[];
658
+ declare function alsoSteps(rules: readonly Rule[]): Rule[];
659
+ declare const RESOLUTION_RULES: Rule[];
521
660
  /**
522
661
  * The questions a caller asks, written as rules. Two facts say somebody
523
662
  * is asking: `wanted(x)` for what a value is, and `wantedOrigin(x)` for
@@ -535,8 +674,17 @@ declare const RESOLUTION_RULES: _suss_datalog.Rule[];
535
674
  * the value's function makes, so a caller that only wants to know what a
536
675
  * handler resolves to should not pay for that.
537
676
  */
538
- declare const RESOLUTION_QUESTIONS: _suss_datalog.Rule[];
677
+ declare const RESOLUTION_QUESTIONS: Rule[];
539
678
  /** The relations `RESOLUTION_QUESTIONS` answers into. */
540
679
  declare const ANSWER_RELATIONS: string[];
680
+ /**
681
+ * The three of those a caller asks under one allocation site.
682
+ *
683
+ * They are listed apart because leaving them out of what a program has
684
+ * to answer drops the whole second closure from it. A run that never
685
+ * mentions a context would otherwise carry a thousand rewritten rules
686
+ * it can never fire, and the engine reads every rule once a round.
687
+ */
688
+ declare const UNDER_ANSWER_RELATIONS: string[];
541
689
 
542
- export { ANSWER_RELATIONS, ASKING_RELATIONS, type CalleeOutcome, type CaseFiles, type ChainReads, type ContractCase, type ContractOptions, type DescribeAtom, type ExplainOptions, type ExplainResolvedKeyOptions, type ExplainStats, FACT_CONTRACT_CASES, type FactsOf, type MountEdge, type MountEdges, NAMESPACE_IMPORT, NAMESPACE_IMPORT_NAME, type NameReads, type NameWrite, type OrderedWrite, RESOLUTION_QUESTIONS, RESOLUTION_RULES, RESULT_STEP, type ReadNode, type ResolutionExplanation, type ResolutionStep, type SpannedNode, type StepContext, type StepPhrase, VALUE_STEP, type ValueLocation, type WhyExplained, agreedMountPrefix, askResolution, calleeOutcomeOf, calleeOutcomes, checkFactContract, couldBeSettled, explainResolutionProof, explainResolvedKey, joinMountedPath, mountPathsOf, nodeOfKey, placeholderValues, queryFacts, renderExplanation, resolutionProgram, singleAnswers, startsAtName, valueLeftByWrites, writesRunInOrder, writtenSourcesOf, writtenValueOf };
690
+ export { ANSWER_RELATIONS, ASKING_RELATIONS, type AssociationConstructor, BASE_CLASS_RULE, type CalleeOutcome, type CaseFiles, type ChainReads, type ContractCase, type ContractOptions, type DescribeAtom, type EntersAsSelf, type ExplainOptions, type ExplainResolvedKeyOptions, type ExplainStats, FACT_CONTRACT_CASES, type FactsOf, type GivesBackOne, type GivesBackOneOfArgument, type GivesBackOneOfImport, INSTANCE_STEP, type MountEdge, type MountEdges, NAMESPACE_IMPORT, NAMESPACE_IMPORT_NAME, NAMESPACE_MEMBER_RULE, NO_CONTEXT, NO_CONTEXT_NAME, type NameReads, type NameWrite, type OrderedWrite, type PackWords, RESOLUTION_QUESTIONS, RESOLUTION_RULES, RESULT_STEP, type ReadNode, type ResolutionExplanation, type ResolutionStep, type SpannedNode, type StepContext, type StepPhrase, UNDER_ANSWER_RELATIONS, type UnwrapsByName, VALUE_STEP, type ValueLocation, type WhyExplained, addPackWords, agreedMountPrefix, allocationSitesOf, alsoSteps, answersByKey, askResolution, askResolutionUnder, calleeOutcomeOf, calleeOutcomes, checkFactContract, comesToUnder, couldBeSettled, explainResolutionProof, explainResolvedKey, isWrittenAsUnder, joinMountedPath, mountPathsOf, nodeOfKey, objectOfUnder, placeholderValues, queryFacts, renderExplanation, resolutionProgram, resolutionUnderProgram, singleAnswers, startsAtName, valueLeftByWrites, writesRunInOrder, writtenSourcesOf, writtenValueOf, writtenValueUnder, writtenValuesByKey, writtenValuesOf };