@suss/resolution 0.28.0 → 0.30.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.cjs +155 -0
- package/dist/index.d.cts +9 -1
- package/dist/index.d.ts +9 -1
- package/dist/index.js +154 -0
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -34,6 +34,7 @@ __export(index_exports, {
|
|
|
34
34
|
calleeOutcomeOf: () => calleeOutcomeOf,
|
|
35
35
|
calleeOutcomes: () => calleeOutcomes,
|
|
36
36
|
checkFactContract: () => checkFactContract,
|
|
37
|
+
couldBeSettled: () => couldBeSettled,
|
|
37
38
|
explainResolutionProof: () => explainResolutionProof,
|
|
38
39
|
explainResolvedKey: () => explainResolvedKey,
|
|
39
40
|
joinMountedPath: () => joinMountedPath,
|
|
@@ -152,6 +153,9 @@ function askAboutSources(db, keys, program) {
|
|
|
152
153
|
wave = next;
|
|
153
154
|
}
|
|
154
155
|
}
|
|
156
|
+
function couldBeSettled(db, key) {
|
|
157
|
+
return db.has("func", [key]) || db.has("objectValue", [key]) || sourcesOf(db, key).length > 0;
|
|
158
|
+
}
|
|
155
159
|
function sourcesOf(db, key) {
|
|
156
160
|
const base = db.lookup("readsProperty", 0, key)[0];
|
|
157
161
|
if (base !== void 0) {
|
|
@@ -584,6 +588,38 @@ var DEFAULT_PHRASES = {
|
|
|
584
588
|
]
|
|
585
589
|
};
|
|
586
590
|
},
|
|
591
|
+
"declared finder": ({ tuple, premises, describe }) => {
|
|
592
|
+
const method = String(premises[1].tuple[2]);
|
|
593
|
+
const base = String(premises[4].tuple[0]);
|
|
594
|
+
return {
|
|
595
|
+
reason: `${describe(tuple[0])} calls ${method} on ${describe(tuple[1])}, which gives back one of it`,
|
|
596
|
+
assumptions: [
|
|
597
|
+
`a pack declares that ${method} on a class extending ${base} gives back one of that class`
|
|
598
|
+
]
|
|
599
|
+
};
|
|
600
|
+
},
|
|
601
|
+
"declared argument finder": ({ tuple, premises, describe }) => {
|
|
602
|
+
const method = String(premises[1].tuple[2]);
|
|
603
|
+
const position = String(premises[2].tuple[1]);
|
|
604
|
+
const base = String(premises[3].tuple[0]);
|
|
605
|
+
return {
|
|
606
|
+
reason: `${describe(tuple[0])} calls ${method} with ${describe(tuple[1])} at argument ${position}, which gives back one of it`,
|
|
607
|
+
assumptions: [
|
|
608
|
+
`a pack declares that ${method} with a class extending ${base} at argument ${position} gives back one of that class`
|
|
609
|
+
]
|
|
610
|
+
};
|
|
611
|
+
},
|
|
612
|
+
"declared import finder": ({ tuple, premises, describe }) => {
|
|
613
|
+
const module2 = String(premises[1].tuple[1]);
|
|
614
|
+
const name = String(premises[1].tuple[2]);
|
|
615
|
+
const position = String(premises[2].tuple[2]);
|
|
616
|
+
return {
|
|
617
|
+
reason: `${describe(tuple[0])} calls ${name} from ${module2} with ${describe(tuple[1])} at argument ${position}, which gives back one of it`,
|
|
618
|
+
assumptions: [
|
|
619
|
+
`a pack declares that ${name} from ${module2} gives back one of the class at argument ${position}`
|
|
620
|
+
]
|
|
621
|
+
};
|
|
622
|
+
},
|
|
587
623
|
"call result": ({ tuple, premises, describe, inline }) => {
|
|
588
624
|
const invokes = premises[0];
|
|
589
625
|
const invoked = invokes.tuple[1];
|
|
@@ -1070,6 +1106,57 @@ var RESOLUTION_RULES = [
|
|
|
1070
1106
|
],
|
|
1071
1107
|
"class instance"
|
|
1072
1108
|
),
|
|
1109
|
+
// A finder the library declares, keyed on the base a pack named so a
|
|
1110
|
+
// project class with a method of the same name on another hierarchy is
|
|
1111
|
+
// left alone. The DESIGN says what a chain of them composes into.
|
|
1112
|
+
(0, import_datalog4.rule)(
|
|
1113
|
+
"stepsTo",
|
|
1114
|
+
[(0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("cls"), VALUE_STEP],
|
|
1115
|
+
[
|
|
1116
|
+
(0, import_datalog4.lit)("call", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("c")),
|
|
1117
|
+
(0, import_datalog4.lit)("readsProperty", (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("o"), (0, import_datalog4.variable)("m")),
|
|
1118
|
+
(0, import_datalog4.lit)("objectOf", (0, import_datalog4.variable)("o"), (0, import_datalog4.variable)("cls")),
|
|
1119
|
+
(0, import_datalog4.lit)("objectValue", (0, import_datalog4.variable)("cls")),
|
|
1120
|
+
// Before `libraryBase`, so the demand rewrite asks it with the base
|
|
1121
|
+
// bound and walks an ancestry only for a method a pack declared.
|
|
1122
|
+
(0, import_datalog4.lit)("givesBackOne", (0, import_datalog4.variable)("n"), (0, import_datalog4.variable)("m")),
|
|
1123
|
+
(0, import_datalog4.lit)("libraryBase", (0, import_datalog4.variable)("cls"), (0, import_datalog4.variable)("n"))
|
|
1124
|
+
],
|
|
1125
|
+
"declared finder"
|
|
1126
|
+
),
|
|
1127
|
+
// The same word, for a library that takes the class as an argument
|
|
1128
|
+
// instead of as the receiver. The argument having to reach the base a
|
|
1129
|
+
// pack named is what keeps an unrelated `get` out.
|
|
1130
|
+
(0, import_datalog4.rule)(
|
|
1131
|
+
"stepsTo",
|
|
1132
|
+
[(0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("cls"), VALUE_STEP],
|
|
1133
|
+
[
|
|
1134
|
+
(0, import_datalog4.lit)("call", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("c")),
|
|
1135
|
+
(0, import_datalog4.lit)("readsProperty", (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("o"), (0, import_datalog4.variable)("m")),
|
|
1136
|
+
(0, import_datalog4.lit)("callArg", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("k"), (0, import_datalog4.variable)("a")),
|
|
1137
|
+
// Before `libraryBase`, so the demand rewrite asks it with the base
|
|
1138
|
+
// bound and walks an ancestry only for a method a pack declared.
|
|
1139
|
+
(0, import_datalog4.lit)("givesBackOneOfArgument", (0, import_datalog4.variable)("n"), (0, import_datalog4.variable)("m"), (0, import_datalog4.variable)("k")),
|
|
1140
|
+
(0, import_datalog4.lit)("objectOf", (0, import_datalog4.variable)("a"), (0, import_datalog4.variable)("cls")),
|
|
1141
|
+
(0, import_datalog4.lit)("libraryBase", (0, import_datalog4.variable)("cls"), (0, import_datalog4.variable)("n"))
|
|
1142
|
+
],
|
|
1143
|
+
"declared argument finder"
|
|
1144
|
+
),
|
|
1145
|
+
// The same again for a function called on its own rather than read off
|
|
1146
|
+
// anything, keyed on the module it was imported from so a project
|
|
1147
|
+
// function spelled the same way is not mistaken for it.
|
|
1148
|
+
(0, import_datalog4.rule)(
|
|
1149
|
+
"stepsTo",
|
|
1150
|
+
[(0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("cls"), VALUE_STEP],
|
|
1151
|
+
[
|
|
1152
|
+
(0, import_datalog4.lit)("call", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("c")),
|
|
1153
|
+
(0, import_datalog4.lit)("comesFrom", (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("mod"), (0, import_datalog4.variable)("n")),
|
|
1154
|
+
(0, import_datalog4.lit)("givesBackOneOfImport", (0, import_datalog4.variable)("mod"), (0, import_datalog4.variable)("n"), (0, import_datalog4.variable)("k")),
|
|
1155
|
+
(0, import_datalog4.lit)("callArg", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("k"), (0, import_datalog4.variable)("a")),
|
|
1156
|
+
(0, import_datalog4.lit)("objectOf", (0, import_datalog4.variable)("a"), (0, import_datalog4.variable)("cls"))
|
|
1157
|
+
],
|
|
1158
|
+
"declared import finder"
|
|
1159
|
+
),
|
|
1073
1160
|
// Wrapper transparency, derived: calling a factory that returns a
|
|
1074
1161
|
// function which calls its parameter k steps to argument k.
|
|
1075
1162
|
(0, import_datalog4.rule)(
|
|
@@ -1343,6 +1430,54 @@ var RESOLUTION_RULES = [
|
|
|
1343
1430
|
(0, import_datalog4.lit)("contains", (0, import_datalog4.variable)("baseCls"), (0, import_datalog4.variable)("n"), (0, import_datalog4.variable)("held"))
|
|
1344
1431
|
]
|
|
1345
1432
|
),
|
|
1433
|
+
// An association is read off an instance as a property, and stating
|
|
1434
|
+
// it as `contains` is what puts it on the ancestry rule, so a concern
|
|
1435
|
+
// or a base class can be the one that declares it.
|
|
1436
|
+
(0, import_datalog4.rule)(
|
|
1437
|
+
"contains",
|
|
1438
|
+
[(0, import_datalog4.variable)("cls"), (0, import_datalog4.variable)("n"), (0, import_datalog4.variable)("t")],
|
|
1439
|
+
[(0, import_datalog4.lit)("declaresAssociation", (0, import_datalog4.variable)("cls"), (0, import_datalog4.variable)("n"), (0, import_datalog4.variable)("t"))],
|
|
1440
|
+
"declared association"
|
|
1441
|
+
),
|
|
1442
|
+
// The same, for a language that buries the declaration in an ordinary
|
|
1443
|
+
// assignment. Keying on the module the callable came from is what
|
|
1444
|
+
// keeps a project function spelled the same way out.
|
|
1445
|
+
(0, import_datalog4.rule)(
|
|
1446
|
+
"contains",
|
|
1447
|
+
[(0, import_datalog4.variable)("cls"), (0, import_datalog4.variable)("n"), (0, import_datalog4.variable)("t")],
|
|
1448
|
+
[
|
|
1449
|
+
(0, import_datalog4.lit)("fieldCall", (0, import_datalog4.variable)("cls"), (0, import_datalog4.variable)("n"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("t")),
|
|
1450
|
+
(0, import_datalog4.lit)("comesFrom", (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("m"), (0, import_datalog4.variable)("name")),
|
|
1451
|
+
(0, import_datalog4.lit)("associationConstructor", (0, import_datalog4.variable)("m"), (0, import_datalog4.variable)("name"))
|
|
1452
|
+
],
|
|
1453
|
+
"constructed association"
|
|
1454
|
+
),
|
|
1455
|
+
// The library base a class's ancestry arrives at, however many of a
|
|
1456
|
+
// project's own classes sit in between. A base the run declares has a
|
|
1457
|
+
// node to keep walking from; one it does not has only a name.
|
|
1458
|
+
(0, import_datalog4.rule)("libraryBase", [(0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("n")], [(0, import_datalog4.lit)("extendsNamed", (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("n"))]),
|
|
1459
|
+
(0, import_datalog4.rule)(
|
|
1460
|
+
"libraryBase",
|
|
1461
|
+
[(0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("n")],
|
|
1462
|
+
[
|
|
1463
|
+
(0, import_datalog4.lit)("extends", (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("x")),
|
|
1464
|
+
(0, import_datalog4.lit)("comesTo", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("b")),
|
|
1465
|
+
(0, import_datalog4.lit)("libraryBase", (0, import_datalog4.variable)("b"), (0, import_datalog4.variable)("n"))
|
|
1466
|
+
]
|
|
1467
|
+
),
|
|
1468
|
+
// A base a library hands back from a call rather than exporting as a
|
|
1469
|
+
// class, SQLAlchemy's `Base = declarative_base()`. The walk stops at
|
|
1470
|
+
// the call, so the function it called is the name to match on.
|
|
1471
|
+
(0, import_datalog4.rule)(
|
|
1472
|
+
"libraryBase",
|
|
1473
|
+
[(0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("n")],
|
|
1474
|
+
[
|
|
1475
|
+
(0, import_datalog4.lit)("extends", (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("x")),
|
|
1476
|
+
(0, import_datalog4.lit)("isWrittenAs", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("r")),
|
|
1477
|
+
(0, import_datalog4.lit)("call", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("cc")),
|
|
1478
|
+
(0, import_datalog4.lit)("comesFrom", (0, import_datalog4.variable)("cc"), (0, import_datalog4.variable)("m"), (0, import_datalog4.variable)("n"))
|
|
1479
|
+
]
|
|
1480
|
+
),
|
|
1346
1481
|
// Which function a factory returns, and which of its parameters that
|
|
1347
1482
|
// function calls: together they are what makes it a wrapper.
|
|
1348
1483
|
(0, import_datalog4.rule)(
|
|
@@ -1691,6 +1826,25 @@ var RESOLUTION_QUESTIONS = [
|
|
|
1691
1826
|
[(0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("n")],
|
|
1692
1827
|
[(0, import_datalog4.lit)("ancestryChain", (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("b")), (0, import_datalog4.lit)("extendsNamed", (0, import_datalog4.variable)("b"), (0, import_datalog4.variable)("n"))]
|
|
1693
1828
|
),
|
|
1829
|
+
// Each method the same chain declares, so a caller that settled a
|
|
1830
|
+
// receiver on a class can tell a method the project writes itself
|
|
1831
|
+
// from one only the library provides.
|
|
1832
|
+
(0, import_datalog4.rule)(
|
|
1833
|
+
"wantedDeclaredName",
|
|
1834
|
+
[(0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("n")],
|
|
1835
|
+
[
|
|
1836
|
+
(0, import_datalog4.lit)("ancestryChain", (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("b")),
|
|
1837
|
+
(0, import_datalog4.lit)("holdsProperty", (0, import_datalog4.variable)("b"), (0, import_datalog4.variable)("n"), (0, import_datalog4.variable)("held"))
|
|
1838
|
+
]
|
|
1839
|
+
),
|
|
1840
|
+
// A method the class gets under a name the source computes rather than
|
|
1841
|
+
// writes out. The adapter settles the name against the same facts and
|
|
1842
|
+
// says so, and the chain reports it beside the ones written out.
|
|
1843
|
+
(0, import_datalog4.rule)(
|
|
1844
|
+
"wantedDeclaredName",
|
|
1845
|
+
[(0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("n")],
|
|
1846
|
+
[(0, import_datalog4.lit)("ancestryChain", (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("b")), (0, import_datalog4.lit)("declaresName", (0, import_datalog4.variable)("b"), (0, import_datalog4.variable)("n"))]
|
|
1847
|
+
),
|
|
1694
1848
|
(0, import_datalog4.rule)("anchorChain", [(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("x")], [(0, import_datalog4.lit)("wantedAnchor", (0, import_datalog4.variable)("x"))]),
|
|
1695
1849
|
(0, import_datalog4.rule)(
|
|
1696
1850
|
"anchorChain",
|
|
@@ -1754,6 +1908,7 @@ var ANSWER_RELATIONS = [
|
|
|
1754
1908
|
calleeOutcomeOf,
|
|
1755
1909
|
calleeOutcomes,
|
|
1756
1910
|
checkFactContract,
|
|
1911
|
+
couldBeSettled,
|
|
1757
1912
|
explainResolutionProof,
|
|
1758
1913
|
explainResolvedKey,
|
|
1759
1914
|
joinMountedPath,
|
package/dist/index.d.cts
CHANGED
|
@@ -58,6 +58,14 @@ type CalleeOutcome =
|
|
|
58
58
|
declare function calleeOutcomes(db: Database, keys: readonly string[], program?: OnDemandRules): Map<string, CalleeOutcome>;
|
|
59
59
|
/** What one callee is, for a caller with a single key in hand. */
|
|
60
60
|
declare function calleeOutcomeOf(db: Database, key: string, program?: OnDemandRules): CalleeOutcome;
|
|
61
|
+
/**
|
|
62
|
+
* Whether this run says anything at all about the key: it is a value
|
|
63
|
+
* itself, or something built it. A key that fails this settles on
|
|
64
|
+
* nothing, and asking anyway adds a `wanted` fact that every later
|
|
65
|
+
* question has to derive over, so a caller with a batch of keys and a
|
|
66
|
+
* cheap question about each one puts this in front of the batch.
|
|
67
|
+
*/
|
|
68
|
+
declare function couldBeSettled(db: Database, key: string): boolean;
|
|
61
69
|
declare function writtenSourcesOf(db: Database, key: string): string[];
|
|
62
70
|
|
|
63
71
|
/** The tuples of one relation, as strings, which is all a case compares. */
|
|
@@ -531,4 +539,4 @@ declare const RESOLUTION_QUESTIONS: _suss_datalog.Rule[];
|
|
|
531
539
|
/** The relations `RESOLUTION_QUESTIONS` answers into. */
|
|
532
540
|
declare const ANSWER_RELATIONS: string[];
|
|
533
541
|
|
|
534
|
-
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, explainResolutionProof, explainResolvedKey, joinMountedPath, mountPathsOf, nodeOfKey, placeholderValues, queryFacts, renderExplanation, resolutionProgram, singleAnswers, startsAtName, valueLeftByWrites, writesRunInOrder, writtenSourcesOf, writtenValueOf };
|
|
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 };
|
package/dist/index.d.ts
CHANGED
|
@@ -58,6 +58,14 @@ type CalleeOutcome =
|
|
|
58
58
|
declare function calleeOutcomes(db: Database, keys: readonly string[], program?: OnDemandRules): Map<string, CalleeOutcome>;
|
|
59
59
|
/** What one callee is, for a caller with a single key in hand. */
|
|
60
60
|
declare function calleeOutcomeOf(db: Database, key: string, program?: OnDemandRules): CalleeOutcome;
|
|
61
|
+
/**
|
|
62
|
+
* Whether this run says anything at all about the key: it is a value
|
|
63
|
+
* itself, or something built it. A key that fails this settles on
|
|
64
|
+
* nothing, and asking anyway adds a `wanted` fact that every later
|
|
65
|
+
* question has to derive over, so a caller with a batch of keys and a
|
|
66
|
+
* cheap question about each one puts this in front of the batch.
|
|
67
|
+
*/
|
|
68
|
+
declare function couldBeSettled(db: Database, key: string): boolean;
|
|
61
69
|
declare function writtenSourcesOf(db: Database, key: string): string[];
|
|
62
70
|
|
|
63
71
|
/** The tuples of one relation, as strings, which is all a case compares. */
|
|
@@ -531,4 +539,4 @@ declare const RESOLUTION_QUESTIONS: _suss_datalog.Rule[];
|
|
|
531
539
|
/** The relations `RESOLUTION_QUESTIONS` answers into. */
|
|
532
540
|
declare const ANSWER_RELATIONS: string[];
|
|
533
541
|
|
|
534
|
-
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, explainResolutionProof, explainResolvedKey, joinMountedPath, mountPathsOf, nodeOfKey, placeholderValues, queryFacts, renderExplanation, resolutionProgram, singleAnswers, startsAtName, valueLeftByWrites, writesRunInOrder, writtenSourcesOf, writtenValueOf };
|
|
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 };
|
package/dist/index.js
CHANGED
|
@@ -98,6 +98,9 @@ function askAboutSources(db, keys, program) {
|
|
|
98
98
|
wave = next;
|
|
99
99
|
}
|
|
100
100
|
}
|
|
101
|
+
function couldBeSettled(db, key) {
|
|
102
|
+
return db.has("func", [key]) || db.has("objectValue", [key]) || sourcesOf(db, key).length > 0;
|
|
103
|
+
}
|
|
101
104
|
function sourcesOf(db, key) {
|
|
102
105
|
const base = db.lookup("readsProperty", 0, key)[0];
|
|
103
106
|
if (base !== void 0) {
|
|
@@ -530,6 +533,38 @@ var DEFAULT_PHRASES = {
|
|
|
530
533
|
]
|
|
531
534
|
};
|
|
532
535
|
},
|
|
536
|
+
"declared finder": ({ tuple, premises, describe }) => {
|
|
537
|
+
const method = String(premises[1].tuple[2]);
|
|
538
|
+
const base = String(premises[4].tuple[0]);
|
|
539
|
+
return {
|
|
540
|
+
reason: `${describe(tuple[0])} calls ${method} on ${describe(tuple[1])}, which gives back one of it`,
|
|
541
|
+
assumptions: [
|
|
542
|
+
`a pack declares that ${method} on a class extending ${base} gives back one of that class`
|
|
543
|
+
]
|
|
544
|
+
};
|
|
545
|
+
},
|
|
546
|
+
"declared argument finder": ({ tuple, premises, describe }) => {
|
|
547
|
+
const method = String(premises[1].tuple[2]);
|
|
548
|
+
const position = String(premises[2].tuple[1]);
|
|
549
|
+
const base = String(premises[3].tuple[0]);
|
|
550
|
+
return {
|
|
551
|
+
reason: `${describe(tuple[0])} calls ${method} with ${describe(tuple[1])} at argument ${position}, which gives back one of it`,
|
|
552
|
+
assumptions: [
|
|
553
|
+
`a pack declares that ${method} with a class extending ${base} at argument ${position} gives back one of that class`
|
|
554
|
+
]
|
|
555
|
+
};
|
|
556
|
+
},
|
|
557
|
+
"declared import finder": ({ tuple, premises, describe }) => {
|
|
558
|
+
const module = String(premises[1].tuple[1]);
|
|
559
|
+
const name = String(premises[1].tuple[2]);
|
|
560
|
+
const position = String(premises[2].tuple[2]);
|
|
561
|
+
return {
|
|
562
|
+
reason: `${describe(tuple[0])} calls ${name} from ${module} with ${describe(tuple[1])} at argument ${position}, which gives back one of it`,
|
|
563
|
+
assumptions: [
|
|
564
|
+
`a pack declares that ${name} from ${module} gives back one of the class at argument ${position}`
|
|
565
|
+
]
|
|
566
|
+
};
|
|
567
|
+
},
|
|
533
568
|
"call result": ({ tuple, premises, describe, inline }) => {
|
|
534
569
|
const invokes = premises[0];
|
|
535
570
|
const invoked = invokes.tuple[1];
|
|
@@ -1016,6 +1051,57 @@ var RESOLUTION_RULES = [
|
|
|
1016
1051
|
],
|
|
1017
1052
|
"class instance"
|
|
1018
1053
|
),
|
|
1054
|
+
// A finder the library declares, keyed on the base a pack named so a
|
|
1055
|
+
// project class with a method of the same name on another hierarchy is
|
|
1056
|
+
// left alone. The DESIGN says what a chain of them composes into.
|
|
1057
|
+
rule(
|
|
1058
|
+
"stepsTo",
|
|
1059
|
+
[v("r"), v("cls"), VALUE_STEP],
|
|
1060
|
+
[
|
|
1061
|
+
lit("call", v("r"), v("c")),
|
|
1062
|
+
lit("readsProperty", v("c"), v("o"), v("m")),
|
|
1063
|
+
lit("objectOf", v("o"), v("cls")),
|
|
1064
|
+
lit("objectValue", v("cls")),
|
|
1065
|
+
// Before `libraryBase`, so the demand rewrite asks it with the base
|
|
1066
|
+
// bound and walks an ancestry only for a method a pack declared.
|
|
1067
|
+
lit("givesBackOne", v("n"), v("m")),
|
|
1068
|
+
lit("libraryBase", v("cls"), v("n"))
|
|
1069
|
+
],
|
|
1070
|
+
"declared finder"
|
|
1071
|
+
),
|
|
1072
|
+
// The same word, for a library that takes the class as an argument
|
|
1073
|
+
// instead of as the receiver. The argument having to reach the base a
|
|
1074
|
+
// pack named is what keeps an unrelated `get` out.
|
|
1075
|
+
rule(
|
|
1076
|
+
"stepsTo",
|
|
1077
|
+
[v("r"), v("cls"), VALUE_STEP],
|
|
1078
|
+
[
|
|
1079
|
+
lit("call", v("r"), v("c")),
|
|
1080
|
+
lit("readsProperty", v("c"), v("o"), v("m")),
|
|
1081
|
+
lit("callArg", v("r"), v("k"), v("a")),
|
|
1082
|
+
// Before `libraryBase`, so the demand rewrite asks it with the base
|
|
1083
|
+
// bound and walks an ancestry only for a method a pack declared.
|
|
1084
|
+
lit("givesBackOneOfArgument", v("n"), v("m"), v("k")),
|
|
1085
|
+
lit("objectOf", v("a"), v("cls")),
|
|
1086
|
+
lit("libraryBase", v("cls"), v("n"))
|
|
1087
|
+
],
|
|
1088
|
+
"declared argument finder"
|
|
1089
|
+
),
|
|
1090
|
+
// The same again for a function called on its own rather than read off
|
|
1091
|
+
// anything, keyed on the module it was imported from so a project
|
|
1092
|
+
// function spelled the same way is not mistaken for it.
|
|
1093
|
+
rule(
|
|
1094
|
+
"stepsTo",
|
|
1095
|
+
[v("r"), v("cls"), VALUE_STEP],
|
|
1096
|
+
[
|
|
1097
|
+
lit("call", v("r"), v("c")),
|
|
1098
|
+
lit("comesFrom", v("c"), v("mod"), v("n")),
|
|
1099
|
+
lit("givesBackOneOfImport", v("mod"), v("n"), v("k")),
|
|
1100
|
+
lit("callArg", v("r"), v("k"), v("a")),
|
|
1101
|
+
lit("objectOf", v("a"), v("cls"))
|
|
1102
|
+
],
|
|
1103
|
+
"declared import finder"
|
|
1104
|
+
),
|
|
1019
1105
|
// Wrapper transparency, derived: calling a factory that returns a
|
|
1020
1106
|
// function which calls its parameter k steps to argument k.
|
|
1021
1107
|
rule(
|
|
@@ -1289,6 +1375,54 @@ var RESOLUTION_RULES = [
|
|
|
1289
1375
|
lit("contains", v("baseCls"), v("n"), v("held"))
|
|
1290
1376
|
]
|
|
1291
1377
|
),
|
|
1378
|
+
// An association is read off an instance as a property, and stating
|
|
1379
|
+
// it as `contains` is what puts it on the ancestry rule, so a concern
|
|
1380
|
+
// or a base class can be the one that declares it.
|
|
1381
|
+
rule(
|
|
1382
|
+
"contains",
|
|
1383
|
+
[v("cls"), v("n"), v("t")],
|
|
1384
|
+
[lit("declaresAssociation", v("cls"), v("n"), v("t"))],
|
|
1385
|
+
"declared association"
|
|
1386
|
+
),
|
|
1387
|
+
// The same, for a language that buries the declaration in an ordinary
|
|
1388
|
+
// assignment. Keying on the module the callable came from is what
|
|
1389
|
+
// keeps a project function spelled the same way out.
|
|
1390
|
+
rule(
|
|
1391
|
+
"contains",
|
|
1392
|
+
[v("cls"), v("n"), v("t")],
|
|
1393
|
+
[
|
|
1394
|
+
lit("fieldCall", v("cls"), v("n"), v("c"), v("t")),
|
|
1395
|
+
lit("comesFrom", v("c"), v("m"), v("name")),
|
|
1396
|
+
lit("associationConstructor", v("m"), v("name"))
|
|
1397
|
+
],
|
|
1398
|
+
"constructed association"
|
|
1399
|
+
),
|
|
1400
|
+
// The library base a class's ancestry arrives at, however many of a
|
|
1401
|
+
// project's own classes sit in between. A base the run declares has a
|
|
1402
|
+
// node to keep walking from; one it does not has only a name.
|
|
1403
|
+
rule("libraryBase", [v("c"), v("n")], [lit("extendsNamed", v("c"), v("n"))]),
|
|
1404
|
+
rule(
|
|
1405
|
+
"libraryBase",
|
|
1406
|
+
[v("c"), v("n")],
|
|
1407
|
+
[
|
|
1408
|
+
lit("extends", v("c"), v("x")),
|
|
1409
|
+
lit("comesTo", v("x"), v("b")),
|
|
1410
|
+
lit("libraryBase", v("b"), v("n"))
|
|
1411
|
+
]
|
|
1412
|
+
),
|
|
1413
|
+
// A base a library hands back from a call rather than exporting as a
|
|
1414
|
+
// class, SQLAlchemy's `Base = declarative_base()`. The walk stops at
|
|
1415
|
+
// the call, so the function it called is the name to match on.
|
|
1416
|
+
rule(
|
|
1417
|
+
"libraryBase",
|
|
1418
|
+
[v("c"), v("n")],
|
|
1419
|
+
[
|
|
1420
|
+
lit("extends", v("c"), v("x")),
|
|
1421
|
+
lit("isWrittenAs", v("x"), v("r")),
|
|
1422
|
+
lit("call", v("r"), v("cc")),
|
|
1423
|
+
lit("comesFrom", v("cc"), v("m"), v("n"))
|
|
1424
|
+
]
|
|
1425
|
+
),
|
|
1292
1426
|
// Which function a factory returns, and which of its parameters that
|
|
1293
1427
|
// function calls: together they are what makes it a wrapper.
|
|
1294
1428
|
rule(
|
|
@@ -1637,6 +1771,25 @@ var RESOLUTION_QUESTIONS = [
|
|
|
1637
1771
|
[v("c"), v("n")],
|
|
1638
1772
|
[lit("ancestryChain", v("c"), v("b")), lit("extendsNamed", v("b"), v("n"))]
|
|
1639
1773
|
),
|
|
1774
|
+
// Each method the same chain declares, so a caller that settled a
|
|
1775
|
+
// receiver on a class can tell a method the project writes itself
|
|
1776
|
+
// from one only the library provides.
|
|
1777
|
+
rule(
|
|
1778
|
+
"wantedDeclaredName",
|
|
1779
|
+
[v("c"), v("n")],
|
|
1780
|
+
[
|
|
1781
|
+
lit("ancestryChain", v("c"), v("b")),
|
|
1782
|
+
lit("holdsProperty", v("b"), v("n"), v("held"))
|
|
1783
|
+
]
|
|
1784
|
+
),
|
|
1785
|
+
// A method the class gets under a name the source computes rather than
|
|
1786
|
+
// writes out. The adapter settles the name against the same facts and
|
|
1787
|
+
// says so, and the chain reports it beside the ones written out.
|
|
1788
|
+
rule(
|
|
1789
|
+
"wantedDeclaredName",
|
|
1790
|
+
[v("c"), v("n")],
|
|
1791
|
+
[lit("ancestryChain", v("c"), v("b")), lit("declaresName", v("b"), v("n"))]
|
|
1792
|
+
),
|
|
1640
1793
|
rule("anchorChain", [v("x"), v("x")], [lit("wantedAnchor", v("x"))]),
|
|
1641
1794
|
rule(
|
|
1642
1795
|
"anchorChain",
|
|
@@ -1699,6 +1852,7 @@ export {
|
|
|
1699
1852
|
calleeOutcomeOf,
|
|
1700
1853
|
calleeOutcomes,
|
|
1701
1854
|
checkFactContract,
|
|
1855
|
+
couldBeSettled,
|
|
1702
1856
|
explainResolutionProof,
|
|
1703
1857
|
explainResolvedKey,
|
|
1704
1858
|
joinMountedPath,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@suss/resolution",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.30.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "The rules suss uses to follow a name in TypeScript, Python or Ruby to the function it comes down to.",
|
|
6
6
|
"keywords": [
|
|
@@ -56,6 +56,6 @@
|
|
|
56
56
|
"access": "public"
|
|
57
57
|
},
|
|
58
58
|
"dependencies": {
|
|
59
|
-
"@suss/datalog": "0.
|
|
59
|
+
"@suss/datalog": "0.30.0"
|
|
60
60
|
}
|
|
61
61
|
}
|