@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.cjs +949 -70
- package/dist/index.d.cts +169 -21
- package/dist/index.d.ts +169 -21
- package/dist/index.js +936 -70
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
// src/program.ts
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
clearRelations,
|
|
4
|
+
deriveOnDemand,
|
|
5
|
+
evaluate,
|
|
6
|
+
tupleKey
|
|
7
|
+
} from "@suss/datalog";
|
|
3
8
|
var ASKING_RELATIONS = [
|
|
4
9
|
"wanted",
|
|
10
|
+
"wantedUnder",
|
|
11
|
+
"wantedSites",
|
|
5
12
|
"wantedOrigin",
|
|
6
13
|
"wantedCallOrigin",
|
|
7
14
|
"wantedExportsOf",
|
|
@@ -11,8 +18,12 @@ var ASKING_RELATIONS = [
|
|
|
11
18
|
];
|
|
12
19
|
var NO_LANGUAGE_RULES = [];
|
|
13
20
|
var programs = /* @__PURE__ */ new WeakMap();
|
|
14
|
-
|
|
15
|
-
|
|
21
|
+
var underPrograms = /* @__PURE__ */ new WeakMap();
|
|
22
|
+
var contextFreeAnswers = () => ANSWER_RELATIONS.filter(
|
|
23
|
+
(relation) => !UNDER_ANSWER_RELATIONS.includes(relation)
|
|
24
|
+
);
|
|
25
|
+
function builtProgram(languageRules, cache, complete) {
|
|
26
|
+
const built = cache.get(languageRules);
|
|
16
27
|
if (built !== void 0) {
|
|
17
28
|
return built;
|
|
18
29
|
}
|
|
@@ -21,10 +32,16 @@ function resolutionProgram(languageRules = NO_LANGUAGE_RULES) {
|
|
|
21
32
|
...languageRules,
|
|
22
33
|
...RESOLUTION_QUESTIONS
|
|
23
34
|
];
|
|
24
|
-
const program = process.env.SUSS_RESOLUTION_ON_DEMAND === "0" ? { rules, demandDriven: [], demands: [] } : deriveOnDemand(rules,
|
|
25
|
-
|
|
35
|
+
const program = process.env.SUSS_RESOLUTION_ON_DEMAND === "0" ? { rules, demandDriven: [], demands: [] } : deriveOnDemand(rules, complete);
|
|
36
|
+
cache.set(languageRules, program);
|
|
26
37
|
return program;
|
|
27
38
|
}
|
|
39
|
+
function resolutionProgram(languageRules = NO_LANGUAGE_RULES) {
|
|
40
|
+
return builtProgram(languageRules, programs, contextFreeAnswers());
|
|
41
|
+
}
|
|
42
|
+
function resolutionUnderProgram(languageRules = NO_LANGUAGE_RULES) {
|
|
43
|
+
return builtProgram(languageRules, underPrograms, ANSWER_RELATIONS);
|
|
44
|
+
}
|
|
28
45
|
function queryFacts(program) {
|
|
29
46
|
if (program.demandDriven.length === 0) {
|
|
30
47
|
return [];
|
|
@@ -61,6 +78,29 @@ function askResolution(db, keys, asking = "wanted", program = resolutionProgram(
|
|
|
61
78
|
clearRelations(db, program.rules, forget);
|
|
62
79
|
}
|
|
63
80
|
}
|
|
81
|
+
var askedUnderByDb = /* @__PURE__ */ new WeakMap();
|
|
82
|
+
function askResolutionUnder(db, pairs, program = resolutionUnderProgram()) {
|
|
83
|
+
let asked = askedUnderByDb.get(db);
|
|
84
|
+
if (asked === void 0) {
|
|
85
|
+
asked = /* @__PURE__ */ new Set();
|
|
86
|
+
askedUnderByDb.set(db, asked);
|
|
87
|
+
}
|
|
88
|
+
const fresh = [...pairs].filter(
|
|
89
|
+
([key, site]) => !asked.has(tupleKey([key, site]))
|
|
90
|
+
);
|
|
91
|
+
if (fresh.length === 0) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
for (const [key, site] of fresh) {
|
|
95
|
+
asked.add(tupleKey([key, site]));
|
|
96
|
+
db.add("wantedUnder", [key, site]);
|
|
97
|
+
}
|
|
98
|
+
evaluate(db, program.rules);
|
|
99
|
+
const forget = queryFacts(program);
|
|
100
|
+
if (forget.length > 0) {
|
|
101
|
+
clearRelations(db, program.rules, forget);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
64
104
|
|
|
65
105
|
// src/callee.ts
|
|
66
106
|
var UNDECLARED = { kind: "undeclared" };
|
|
@@ -489,6 +529,12 @@ var DEFAULT_PHRASES = {
|
|
|
489
529
|
"last write": ({ tuple, describe }) => ({
|
|
490
530
|
reason: `${describe(tuple[0])} is written more than once, and the last write leaves it as ${describe(tuple[1])}`
|
|
491
531
|
}),
|
|
532
|
+
"one of several writes": ({ tuple, describe }) => ({
|
|
533
|
+
reason: `${describe(tuple[0])} is written more than once, and one of those writes makes it ${describe(tuple[1])}`,
|
|
534
|
+
assumptions: [
|
|
535
|
+
`nothing says which write to ${describe(tuple[0])} ran last, so every write it has is a possible value`
|
|
536
|
+
]
|
|
537
|
+
}),
|
|
492
538
|
fallback: ({ tuple, describe }) => ({
|
|
493
539
|
reason: `${describe(tuple[0])} is a fallback expression, and ${describe(tuple[1])} is the branch that resolves`
|
|
494
540
|
}),
|
|
@@ -505,7 +551,7 @@ var DEFAULT_PHRASES = {
|
|
|
505
551
|
"property read": ({ tuple, premises, describe }) => {
|
|
506
552
|
const [, object, name] = premises[0].tuple;
|
|
507
553
|
const contains = premises[2];
|
|
508
|
-
const inherited = contains.kind === "derived" && contains.
|
|
554
|
+
const inherited = contains.kind === "derived" && ruleLabel(contains.rule) === BASE_CLASS_RULE;
|
|
509
555
|
return {
|
|
510
556
|
reason: `${describe(tuple[0])} reads ${String(name)} off ${describe(object)}, which contains ${describe(tuple[1])}`,
|
|
511
557
|
notes: inherited ? [`${String(name)} comes from a base class`] : []
|
|
@@ -584,7 +630,8 @@ var CHAIN_RELATIONS = /* @__PURE__ */ new Set([
|
|
|
584
630
|
"isWrittenAs",
|
|
585
631
|
"comesFrom",
|
|
586
632
|
"reaches",
|
|
587
|
-
"stepsTo"
|
|
633
|
+
"stepsTo",
|
|
634
|
+
"hop"
|
|
588
635
|
]);
|
|
589
636
|
function inlineChain(proof, state) {
|
|
590
637
|
const explained = explainResolutionProof(proof, {
|
|
@@ -640,6 +687,17 @@ function importStep(proof, state) {
|
|
|
640
687
|
assumptions: []
|
|
641
688
|
};
|
|
642
689
|
}
|
|
690
|
+
function namespaceMemberStep(proof, state) {
|
|
691
|
+
const [x, module, name] = proof.tuple;
|
|
692
|
+
return {
|
|
693
|
+
from: x,
|
|
694
|
+
to: module,
|
|
695
|
+
rule: NAMESPACE_MEMBER_RULE,
|
|
696
|
+
reason: `${state.describe(x)} reads ${String(name)} off ${state.describe(module)}, which is imported whole`,
|
|
697
|
+
notes: [],
|
|
698
|
+
assumptions: []
|
|
699
|
+
};
|
|
700
|
+
}
|
|
643
701
|
var flattenInto = (proof, state) => {
|
|
644
702
|
if (proof.kind === "truncated") {
|
|
645
703
|
state.truncated = true;
|
|
@@ -649,7 +707,7 @@ var flattenInto = (proof, state) => {
|
|
|
649
707
|
return;
|
|
650
708
|
}
|
|
651
709
|
const relation = proof.relation;
|
|
652
|
-
if (relation === "stepsTo") {
|
|
710
|
+
if (relation === "stepsTo" || relation === "hop") {
|
|
653
711
|
state.steps.push(stepFrom(proof, state));
|
|
654
712
|
return;
|
|
655
713
|
}
|
|
@@ -660,6 +718,10 @@ var flattenInto = (proof, state) => {
|
|
|
660
718
|
return;
|
|
661
719
|
}
|
|
662
720
|
if (relation === "comesFrom") {
|
|
721
|
+
if (ruleLabel(proof.rule) === NAMESPACE_MEMBER_RULE) {
|
|
722
|
+
state.steps.push(namespaceMemberStep(proof, state));
|
|
723
|
+
return;
|
|
724
|
+
}
|
|
663
725
|
if (proof.premises.length === 2) {
|
|
664
726
|
flattenInto(proof.premises[0], state);
|
|
665
727
|
state.steps.push(importStep(proof.premises[1], state));
|
|
@@ -836,6 +898,37 @@ function nodeOfKey(rootsByFile, key) {
|
|
|
836
898
|
return null;
|
|
837
899
|
}
|
|
838
900
|
|
|
901
|
+
// src/packWords.ts
|
|
902
|
+
function addPackWords(db, words) {
|
|
903
|
+
for (const word of words.givesBackOne ?? []) {
|
|
904
|
+
db.add("givesBackOne", [word.base, word.method]);
|
|
905
|
+
}
|
|
906
|
+
for (const word of words.givesBackOneOfArgument ?? []) {
|
|
907
|
+
db.add("givesBackOneOfArgument", [
|
|
908
|
+
word.base,
|
|
909
|
+
word.method,
|
|
910
|
+
String(word.argument)
|
|
911
|
+
]);
|
|
912
|
+
}
|
|
913
|
+
for (const word of words.givesBackOneOfImport ?? []) {
|
|
914
|
+
db.add("givesBackOneOfImport", [
|
|
915
|
+
word.module,
|
|
916
|
+
word.name,
|
|
917
|
+
String(word.argument)
|
|
918
|
+
]);
|
|
919
|
+
}
|
|
920
|
+
for (const word of words.entersAsSelf ?? []) {
|
|
921
|
+
db.add("entersAsSelf", [word.module, word.name]);
|
|
922
|
+
}
|
|
923
|
+
for (const word of words.unwrapsByName ?? []) {
|
|
924
|
+
db.add("unwrapsByName", [word.callee, String(word.argument)]);
|
|
925
|
+
db.add("wrapperModule", [word.callee, word.module]);
|
|
926
|
+
}
|
|
927
|
+
for (const word of words.associationConstructor ?? []) {
|
|
928
|
+
db.add("associationConstructor", [word.module, word.name]);
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
|
|
839
932
|
// src/session.ts
|
|
840
933
|
import { Database, evaluate as evaluate2, proofOf, witnesses } from "@suss/datalog";
|
|
841
934
|
function explainResolvedKey(options) {
|
|
@@ -891,7 +984,7 @@ function explainResolvedKey(options) {
|
|
|
891
984
|
|
|
892
985
|
// src/singleAnswer.ts
|
|
893
986
|
var NO_PLACEHOLDERS = /* @__PURE__ */ new Set();
|
|
894
|
-
function
|
|
987
|
+
function answersByKey(rows, placeholders = NO_PLACEHOLDERS) {
|
|
895
988
|
const candidates = /* @__PURE__ */ new Map();
|
|
896
989
|
for (const row of rows) {
|
|
897
990
|
const key = String(row[0]);
|
|
@@ -903,9 +996,15 @@ function singleAnswers(rows, placeholders = NO_PLACEHOLDERS) {
|
|
|
903
996
|
set.add(answer);
|
|
904
997
|
candidates.set(key, set);
|
|
905
998
|
}
|
|
906
|
-
const
|
|
999
|
+
const answers = /* @__PURE__ */ new Map();
|
|
907
1000
|
for (const [key, set] of candidates) {
|
|
908
|
-
|
|
1001
|
+
answers.set(key, withoutPlaceholders(set, placeholders));
|
|
1002
|
+
}
|
|
1003
|
+
return answers;
|
|
1004
|
+
}
|
|
1005
|
+
function singleAnswers(rows, placeholders = NO_PLACEHOLDERS) {
|
|
1006
|
+
const settled = /* @__PURE__ */ new Map();
|
|
1007
|
+
for (const [key, answers] of answersByKey(rows, placeholders)) {
|
|
909
1008
|
if (answers.length === 1) {
|
|
910
1009
|
settled.set(key, answers[0]);
|
|
911
1010
|
}
|
|
@@ -923,6 +1022,28 @@ function withoutPlaceholders(answers, placeholders) {
|
|
|
923
1022
|
return kept;
|
|
924
1023
|
}
|
|
925
1024
|
|
|
1025
|
+
// src/underContext.ts
|
|
1026
|
+
function answersUnder(db, relation, key, site) {
|
|
1027
|
+
return db.lookup(relation, 0, key).filter((row) => String(row[1]) === site).map((row) => String(row[2]));
|
|
1028
|
+
}
|
|
1029
|
+
function isWrittenAsUnder(db, key, site) {
|
|
1030
|
+
return answersUnder(db, "wantedIsWrittenAsUnder", key, site);
|
|
1031
|
+
}
|
|
1032
|
+
function comesToUnder(db, key, site) {
|
|
1033
|
+
return answersUnder(db, "wantedComesToUnder", key, site);
|
|
1034
|
+
}
|
|
1035
|
+
function objectOfUnder(db, key, site) {
|
|
1036
|
+
return answersUnder(db, "wantedObjectOfUnder", key, site);
|
|
1037
|
+
}
|
|
1038
|
+
function writtenValueUnder(db, key, site) {
|
|
1039
|
+
const rows = isWrittenAsUnder(db, key, site).map((answer) => [key, answer]);
|
|
1040
|
+
const answers = answersByKey(rows, placeholderValues(db)).get(key) ?? [];
|
|
1041
|
+
return answers.length === 1 ? answers[0] : null;
|
|
1042
|
+
}
|
|
1043
|
+
function allocationSitesOf(db, cls) {
|
|
1044
|
+
return db.lookup("wantedAllocatedAt", 0, cls).map((row) => String(row[1]));
|
|
1045
|
+
}
|
|
1046
|
+
|
|
926
1047
|
// src/writes.ts
|
|
927
1048
|
function valueLeftByWrites(writes, ordered) {
|
|
928
1049
|
const deciding = writes.filter((write) => !write.narrowsName);
|
|
@@ -953,23 +1074,58 @@ function sharedConstruction(writes) {
|
|
|
953
1074
|
}
|
|
954
1075
|
|
|
955
1076
|
// src/writtenValue.ts
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
const
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
1077
|
+
var WRITTEN_AS = "wantedIsWrittenAs";
|
|
1078
|
+
function writtenValueOf(db, key, ask, relation = WRITTEN_AS) {
|
|
1079
|
+
const answers = settledByKey(db, [key], ask, relation).get(key) ?? [];
|
|
1080
|
+
return answers.length === 1 ? answers[0] : null;
|
|
1081
|
+
}
|
|
1082
|
+
function writtenValuesOf(db, key, ask, relation = WRITTEN_AS) {
|
|
1083
|
+
const settled = settledByKey(db, [key], ask, relation).get(key) ?? [];
|
|
1084
|
+
return settled.length > 0 ? settled : writesLeft(db, key);
|
|
1085
|
+
}
|
|
1086
|
+
function writtenValuesByKey(db, keys, ask, relation = WRITTEN_AS) {
|
|
1087
|
+
const one = /* @__PURE__ */ new Map();
|
|
1088
|
+
for (const [key, answers] of settledByKey(db, keys, ask, relation)) {
|
|
1089
|
+
if (answers.length === 1) {
|
|
1090
|
+
one.set(key, answers[0]);
|
|
1091
|
+
}
|
|
963
1092
|
}
|
|
964
|
-
|
|
965
|
-
|
|
1093
|
+
return one;
|
|
1094
|
+
}
|
|
1095
|
+
function settledByKey(db, keys, ask, relation) {
|
|
1096
|
+
const placeholders = placeholderValues(db);
|
|
1097
|
+
const byKey = answersByKey(db.facts(relation), placeholders);
|
|
1098
|
+
const direct = new Map(keys.map((key) => [key, byKey.get(key) ?? []]));
|
|
1099
|
+
const calls = new Set(db.facts("call").map((row) => String(row[0])));
|
|
1100
|
+
const throughCalls = [...direct.values()].flat().filter((answer) => calls.has(answer));
|
|
1101
|
+
if (throughCalls.length === 0) {
|
|
966
1102
|
return direct;
|
|
967
1103
|
}
|
|
968
|
-
ask(
|
|
969
|
-
const deeper = singleAnswers(db.facts(
|
|
970
|
-
|
|
1104
|
+
ask(throughCalls);
|
|
1105
|
+
const deeper = singleAnswers(db.facts(relation), placeholders);
|
|
1106
|
+
return new Map(
|
|
1107
|
+
[...direct].map(([key, answers]) => [
|
|
1108
|
+
key,
|
|
1109
|
+
collapseCalls(answers, calls, deeper)
|
|
1110
|
+
])
|
|
971
1111
|
);
|
|
972
|
-
|
|
1112
|
+
}
|
|
1113
|
+
function collapseCalls(direct, calls, deeper) {
|
|
1114
|
+
return [
|
|
1115
|
+
...new Set(
|
|
1116
|
+
direct.map(
|
|
1117
|
+
(answer) => calls.has(answer) ? deeper.get(answer) ?? answer : answer
|
|
1118
|
+
)
|
|
1119
|
+
)
|
|
1120
|
+
];
|
|
1121
|
+
}
|
|
1122
|
+
function writesLeft(db, key) {
|
|
1123
|
+
const unstated = db.facts("writesUnstated").some((row) => String(row[0]) === key);
|
|
1124
|
+
if (unstated) {
|
|
1125
|
+
return [];
|
|
1126
|
+
}
|
|
1127
|
+
const candidates = answersByKey(db.facts("mayHold"), placeholderValues(db)).get(key) ?? [];
|
|
1128
|
+
return candidates.length > 1 ? candidates : [];
|
|
973
1129
|
}
|
|
974
1130
|
|
|
975
1131
|
// src/index.ts
|
|
@@ -977,38 +1133,61 @@ import { constant, lit, rule, variable as v } from "@suss/datalog";
|
|
|
977
1133
|
var VALUE_STEP = constant("value");
|
|
978
1134
|
var NAMESPACE_IMPORT_NAME = "*";
|
|
979
1135
|
var NAMESPACE_IMPORT = constant(NAMESPACE_IMPORT_NAME);
|
|
1136
|
+
var NAMESPACE_MEMBER_RULE = "namespace member";
|
|
1137
|
+
var BASE_CLASS_RULE = "base class";
|
|
1138
|
+
var INSTANCE_STEP = constant("instance");
|
|
980
1139
|
var RESULT_STEP = constant("result");
|
|
981
|
-
var
|
|
1140
|
+
var NO_CONTEXT_NAME = "none";
|
|
1141
|
+
var NO_CONTEXT = constant(NO_CONTEXT_NAME);
|
|
1142
|
+
var STEP_LATTICE = [
|
|
1143
|
+
{ soFar: VALUE_STEP, next: v("kind"), took: v("kind") },
|
|
1144
|
+
{ soFar: INSTANCE_STEP, next: VALUE_STEP, took: INSTANCE_STEP },
|
|
1145
|
+
{ soFar: INSTANCE_STEP, next: INSTANCE_STEP, took: INSTANCE_STEP },
|
|
1146
|
+
{ soFar: INSTANCE_STEP, next: RESULT_STEP, took: RESULT_STEP },
|
|
1147
|
+
{ soFar: RESULT_STEP, next: VALUE_STEP, took: RESULT_STEP },
|
|
1148
|
+
{ soFar: RESULT_STEP, next: INSTANCE_STEP, took: RESULT_STEP },
|
|
1149
|
+
{ soFar: RESULT_STEP, next: RESULT_STEP, took: RESULT_STEP }
|
|
1150
|
+
];
|
|
1151
|
+
var STATED_RULES = [
|
|
982
1152
|
// Aliasing: const x = y, or an identifier referencing a declaration.
|
|
983
1153
|
// A language with a hop of its own, like JavaScript's `.bind`, states
|
|
984
1154
|
// it as a step too, or every question but `comesTo` misses it.
|
|
985
1155
|
rule(
|
|
986
|
-
"
|
|
1156
|
+
"hop",
|
|
987
1157
|
[v("x"), v("y"), VALUE_STEP],
|
|
988
1158
|
[lit("binds", v("x"), v("y"))],
|
|
989
1159
|
"alias"
|
|
990
1160
|
),
|
|
991
1161
|
// A name written more than once has the value the last write left
|
|
992
|
-
// there. The adapter works out which write that is and stays quiet
|
|
993
|
-
// when control flow decides
|
|
1162
|
+
// there. The adapter works out which write that is, and stays quiet
|
|
1163
|
+
// when control flow decides; the rule below takes that name instead.
|
|
994
1164
|
rule(
|
|
995
|
-
"
|
|
1165
|
+
"hop",
|
|
996
1166
|
[v("x"), v("y"), VALUE_STEP],
|
|
997
1167
|
[lit("endsHolding", v("x"), v("y"))],
|
|
998
1168
|
"last write"
|
|
999
1169
|
),
|
|
1170
|
+
// A name whose writes nothing orders leads to each of them, so a
|
|
1171
|
+
// caller that can use several values gets them all and one that needs
|
|
1172
|
+
// a single value gets none. A write stating no value stops every step.
|
|
1173
|
+
rule(
|
|
1174
|
+
"hop",
|
|
1175
|
+
[v("x"), v("y"), VALUE_STEP],
|
|
1176
|
+
[lit("mayHold", v("x"), v("y")), lit("writesAllStated", v("x"))],
|
|
1177
|
+
"one of several writes"
|
|
1178
|
+
),
|
|
1000
1179
|
// A fallback says the value is one of its branches, so each branch is
|
|
1001
1180
|
// a step. A branch that resolves to nothing makes no claim, and two
|
|
1002
1181
|
// branches resolving to different things fail the single-answer policy.
|
|
1003
1182
|
rule(
|
|
1004
|
-
"
|
|
1183
|
+
"hop",
|
|
1005
1184
|
[v("x"), v("b"), VALUE_STEP],
|
|
1006
1185
|
[lit("fallbackBranch", v("x"), v("b"))],
|
|
1007
1186
|
"fallback"
|
|
1008
1187
|
),
|
|
1009
1188
|
// An import steps to what the module exports under that name.
|
|
1010
1189
|
rule(
|
|
1011
|
-
"
|
|
1190
|
+
"hop",
|
|
1012
1191
|
[v("x"), v("value"), VALUE_STEP],
|
|
1013
1192
|
[
|
|
1014
1193
|
lit("imports", v("x"), v("m"), v("n")),
|
|
@@ -1042,8 +1221,8 @@ var RESOLUTION_RULES = [
|
|
|
1042
1221
|
// a method read off the result is the one the class declares. The
|
|
1043
1222
|
// caveat below is about a factory function, and a class is not one.
|
|
1044
1223
|
rule(
|
|
1045
|
-
"
|
|
1046
|
-
[v("r"), v("cls"),
|
|
1224
|
+
"hop",
|
|
1225
|
+
[v("r"), v("cls"), INSTANCE_STEP],
|
|
1047
1226
|
[
|
|
1048
1227
|
lit("call", v("r"), v("c")),
|
|
1049
1228
|
lit("comesTo", v("c"), v("cls")),
|
|
@@ -1051,12 +1230,21 @@ var RESOLUTION_RULES = [
|
|
|
1051
1230
|
],
|
|
1052
1231
|
"class instance"
|
|
1053
1232
|
),
|
|
1233
|
+
// The receiver a method is called on. Being one of a class is the
|
|
1234
|
+
// same hop a construction takes, so a method read off `self` finds
|
|
1235
|
+
// what the class declares.
|
|
1236
|
+
rule(
|
|
1237
|
+
"hop",
|
|
1238
|
+
[v("x"), v("cls"), INSTANCE_STEP],
|
|
1239
|
+
[lit("instanceOf", v("x"), v("cls"))],
|
|
1240
|
+
"receiver instance"
|
|
1241
|
+
),
|
|
1054
1242
|
// A finder the library declares, keyed on the base a pack named so a
|
|
1055
1243
|
// project class with a method of the same name on another hierarchy is
|
|
1056
1244
|
// left alone. The DESIGN says what a chain of them composes into.
|
|
1057
1245
|
rule(
|
|
1058
|
-
"
|
|
1059
|
-
[v("r"), v("cls"),
|
|
1246
|
+
"hop",
|
|
1247
|
+
[v("r"), v("cls"), INSTANCE_STEP],
|
|
1060
1248
|
[
|
|
1061
1249
|
lit("call", v("r"), v("c")),
|
|
1062
1250
|
lit("readsProperty", v("c"), v("o"), v("m")),
|
|
@@ -1073,8 +1261,8 @@ var RESOLUTION_RULES = [
|
|
|
1073
1261
|
// instead of as the receiver. The argument having to reach the base a
|
|
1074
1262
|
// pack named is what keeps an unrelated `get` out.
|
|
1075
1263
|
rule(
|
|
1076
|
-
"
|
|
1077
|
-
[v("r"), v("cls"),
|
|
1264
|
+
"hop",
|
|
1265
|
+
[v("r"), v("cls"), INSTANCE_STEP],
|
|
1078
1266
|
[
|
|
1079
1267
|
lit("call", v("r"), v("c")),
|
|
1080
1268
|
lit("readsProperty", v("c"), v("o"), v("m")),
|
|
@@ -1091,8 +1279,8 @@ var RESOLUTION_RULES = [
|
|
|
1091
1279
|
// anything, keyed on the module it was imported from so a project
|
|
1092
1280
|
// function spelled the same way is not mistaken for it.
|
|
1093
1281
|
rule(
|
|
1094
|
-
"
|
|
1095
|
-
[v("r"), v("cls"),
|
|
1282
|
+
"hop",
|
|
1283
|
+
[v("r"), v("cls"), INSTANCE_STEP],
|
|
1096
1284
|
[
|
|
1097
1285
|
lit("call", v("r"), v("c")),
|
|
1098
1286
|
lit("comesFrom", v("c"), v("mod"), v("n")),
|
|
@@ -1102,10 +1290,24 @@ var RESOLUTION_RULES = [
|
|
|
1102
1290
|
],
|
|
1103
1291
|
"declared import finder"
|
|
1104
1292
|
),
|
|
1293
|
+
// A block opened over a library's own constructor. The pack says
|
|
1294
|
+
// entering one gives back the object it built, so the name the block
|
|
1295
|
+
// opens is that call.
|
|
1296
|
+
rule(
|
|
1297
|
+
"hop",
|
|
1298
|
+
[v("y"), v("r"), VALUE_STEP],
|
|
1299
|
+
[
|
|
1300
|
+
lit("entersAs", v("y"), v("r")),
|
|
1301
|
+
lit("call", v("r"), v("c")),
|
|
1302
|
+
lit("comesFrom", v("c"), v("mod"), v("n")),
|
|
1303
|
+
lit("entersAsSelf", v("mod"), v("n"))
|
|
1304
|
+
],
|
|
1305
|
+
"context manager returns self"
|
|
1306
|
+
),
|
|
1105
1307
|
// Wrapper transparency, derived: calling a factory that returns a
|
|
1106
1308
|
// function which calls its parameter k steps to argument k.
|
|
1107
1309
|
rule(
|
|
1108
|
-
"
|
|
1310
|
+
"hop",
|
|
1109
1311
|
[v("r"), v("a"), VALUE_STEP],
|
|
1110
1312
|
[
|
|
1111
1313
|
lit("call", v("r"), v("c")),
|
|
@@ -1119,7 +1321,7 @@ var RESOLUTION_RULES = [
|
|
|
1119
1321
|
// argument k. The callee has to come from the library the pack said,
|
|
1120
1322
|
// so a local object spelled the same way is not mistaken for it.
|
|
1121
1323
|
rule(
|
|
1122
|
-
"
|
|
1324
|
+
"hop",
|
|
1123
1325
|
[v("r"), v("a"), VALUE_STEP],
|
|
1124
1326
|
[
|
|
1125
1327
|
lit("calleeName", v("r"), v("n")),
|
|
@@ -1133,44 +1335,441 @@ var RESOLUTION_RULES = [
|
|
|
1133
1335
|
// The one step that runs a function forwards: a call steps to what
|
|
1134
1336
|
// the function it invokes returns.
|
|
1135
1337
|
rule(
|
|
1136
|
-
"
|
|
1338
|
+
"hop",
|
|
1137
1339
|
[v("r"), v("ret"), RESULT_STEP],
|
|
1138
1340
|
[lit("invokes", v("r"), v("f")), lit("returnsValue", v("f"), v("ret"))],
|
|
1139
1341
|
"call result"
|
|
1140
1342
|
),
|
|
1141
|
-
//
|
|
1142
|
-
//
|
|
1143
|
-
//
|
|
1343
|
+
// What a function says it gives back when its body never states a
|
|
1344
|
+
// value. The adapter stays quiet about the annotation whenever the
|
|
1345
|
+
// body does state one, so the two never answer the same question.
|
|
1346
|
+
rule(
|
|
1347
|
+
"hop",
|
|
1348
|
+
[v("r"), v("cls"), RESULT_STEP],
|
|
1349
|
+
[
|
|
1350
|
+
lit("invokes", v("r"), v("f")),
|
|
1351
|
+
lit("returnsClass", v("f"), v("x")),
|
|
1352
|
+
lit("comesTo", v("x"), v("cls")),
|
|
1353
|
+
lit("objectValue", v("cls"))
|
|
1354
|
+
],
|
|
1355
|
+
"declared return type"
|
|
1356
|
+
),
|
|
1357
|
+
// Where a walk gets to, under the strongest step it took: value, then
|
|
1358
|
+
// instance, then result. The walk so far comes first, so demand stays
|
|
1359
|
+
// on the value asked about; the README says what the other order cost.
|
|
1144
1360
|
rule(
|
|
1145
1361
|
"reaches",
|
|
1146
1362
|
[v("x"), v("z"), v("kind")],
|
|
1147
1363
|
[lit("stepsTo", v("x"), v("z"), v("kind"))]
|
|
1148
1364
|
),
|
|
1365
|
+
// A rule per pair rather than one leaving the next step's kind free. A
|
|
1366
|
+
// free kind is a second question about the same relation, and a
|
|
1367
|
+
// demand-driven run then derives both to answer either.
|
|
1368
|
+
...STEP_LATTICE.map(
|
|
1369
|
+
({ soFar, next, took }) => rule(
|
|
1370
|
+
"reaches",
|
|
1371
|
+
[v("x"), v("z"), took],
|
|
1372
|
+
[
|
|
1373
|
+
lit("reaches", v("x"), v("y"), soFar),
|
|
1374
|
+
lit("stepsTo", v("y"), v("z"), next)
|
|
1375
|
+
]
|
|
1376
|
+
)
|
|
1377
|
+
),
|
|
1378
|
+
// A context is an allocation site, or nothing at all for a value read
|
|
1379
|
+
// outside every site. Both are stated, so a rule that starts a walk
|
|
1380
|
+
// binds its context from a premise rather than from a negation.
|
|
1381
|
+
rule("context", [NO_CONTEXT], [], "no context"),
|
|
1382
|
+
rule(
|
|
1383
|
+
"context",
|
|
1384
|
+
[v("site")],
|
|
1385
|
+
[lit("allocates", v("site"), v("cls"))],
|
|
1386
|
+
"site context"
|
|
1387
|
+
),
|
|
1388
|
+
// The same closure, with the context the walk started under and the
|
|
1389
|
+
// context it arrived under. It takes `hop`, because an argument and a
|
|
1390
|
+
// property read have their own rules below.
|
|
1391
|
+
rule(
|
|
1392
|
+
"reachesUnder",
|
|
1393
|
+
[v("x"), v("c"), v("z"), v("c"), v("kind")],
|
|
1394
|
+
[lit("context", v("c")), lit("hop", v("x"), v("z"), v("kind"))],
|
|
1395
|
+
"under one hop"
|
|
1396
|
+
),
|
|
1397
|
+
...STEP_LATTICE.map(
|
|
1398
|
+
({ soFar, next, took }) => rule(
|
|
1399
|
+
"reachesUnder",
|
|
1400
|
+
[v("x"), v("c"), v("z"), v("c2"), took],
|
|
1401
|
+
[
|
|
1402
|
+
lit("reachesUnder", v("x"), v("c"), v("y"), v("c2"), soFar),
|
|
1403
|
+
lit("hop", v("y"), v("z"), next)
|
|
1404
|
+
]
|
|
1405
|
+
)
|
|
1406
|
+
),
|
|
1407
|
+
// The receiver read under a site is that site. The ordinary hop from a
|
|
1408
|
+
// receiver to its class stays in `hop`, so `self` under any context
|
|
1409
|
+
// still comes to the class a single-answer reader wants.
|
|
1149
1410
|
rule(
|
|
1150
|
-
"
|
|
1151
|
-
[v("x"), v("
|
|
1411
|
+
"reachesUnder",
|
|
1412
|
+
[v("x"), v("c"), v("c"), v("c"), VALUE_STEP],
|
|
1413
|
+
[lit("instanceOf", v("x"), v("cls")), lit("allocates", v("c"), v("cls"))],
|
|
1414
|
+
"receiver is the site"
|
|
1415
|
+
),
|
|
1416
|
+
rule(
|
|
1417
|
+
"reachesUnder",
|
|
1418
|
+
[v("x"), v("c"), v("c2"), v("c2"), v("kind")],
|
|
1152
1419
|
[
|
|
1153
|
-
lit("
|
|
1154
|
-
lit("
|
|
1420
|
+
lit("reachesUnder", v("x"), v("c"), v("y"), v("c2"), v("kind")),
|
|
1421
|
+
lit("instanceOf", v("y"), v("cls")),
|
|
1422
|
+
lit("allocates", v("c2"), v("cls"))
|
|
1423
|
+
],
|
|
1424
|
+
"reached receiver is the site"
|
|
1425
|
+
),
|
|
1426
|
+
// The object an expression refers to under a context. A site is an
|
|
1427
|
+
// answer here, unlike `objectOf`, and the class an instance is one of
|
|
1428
|
+
// is an answer only under no context.
|
|
1429
|
+
rule(
|
|
1430
|
+
"objectOfUnder",
|
|
1431
|
+
[v("site"), v("c"), v("site")],
|
|
1432
|
+
[lit("context", v("c")), lit("allocates", v("site"), v("cls"))],
|
|
1433
|
+
"site is its own object"
|
|
1434
|
+
),
|
|
1435
|
+
rule(
|
|
1436
|
+
"objectOfUnder",
|
|
1437
|
+
[v("o"), v("c"), v("site")],
|
|
1438
|
+
[
|
|
1439
|
+
lit("reachesUnder", v("o"), v("c"), v("site"), v("c2"), VALUE_STEP),
|
|
1440
|
+
lit("allocates", v("site"), v("cls"))
|
|
1441
|
+
],
|
|
1442
|
+
"name of a site"
|
|
1443
|
+
),
|
|
1444
|
+
rule(
|
|
1445
|
+
"objectOfUnder",
|
|
1446
|
+
[v("o"), v("c"), v("obj")],
|
|
1447
|
+
[
|
|
1448
|
+
lit("reachesUnder", v("o"), v("c"), v("obj"), v("c2"), VALUE_STEP),
|
|
1449
|
+
lit("objectValue", v("obj"))
|
|
1450
|
+
],
|
|
1451
|
+
"written object under a context"
|
|
1452
|
+
),
|
|
1453
|
+
rule(
|
|
1454
|
+
"objectOfUnder",
|
|
1455
|
+
[v("o"), v("c"), v("obj")],
|
|
1456
|
+
[
|
|
1457
|
+
lit("reachesUnder", v("o"), v("c"), v("obj"), v("c2"), RESULT_STEP),
|
|
1458
|
+
lit("objectValue", v("obj"))
|
|
1459
|
+
],
|
|
1460
|
+
"returned object under a context"
|
|
1461
|
+
),
|
|
1462
|
+
rule(
|
|
1463
|
+
"objectOfUnder",
|
|
1464
|
+
[v("o"), NO_CONTEXT, v("cls")],
|
|
1465
|
+
[
|
|
1466
|
+
lit(
|
|
1467
|
+
"reachesUnder",
|
|
1468
|
+
v("o"),
|
|
1469
|
+
NO_CONTEXT,
|
|
1470
|
+
v("cls"),
|
|
1471
|
+
NO_CONTEXT,
|
|
1472
|
+
INSTANCE_STEP
|
|
1473
|
+
),
|
|
1474
|
+
lit("objectValue", v("cls"))
|
|
1475
|
+
],
|
|
1476
|
+
"class reached with no context"
|
|
1477
|
+
),
|
|
1478
|
+
rule(
|
|
1479
|
+
"objectOfUnder",
|
|
1480
|
+
[v("o"), NO_CONTEXT, v("cls")],
|
|
1481
|
+
[lit("instanceOf", v("o"), v("cls"))],
|
|
1482
|
+
"receiver class with no context"
|
|
1483
|
+
),
|
|
1484
|
+
rule(
|
|
1485
|
+
"objectOfUnder",
|
|
1486
|
+
[v("o"), v("c"), v("o")],
|
|
1487
|
+
[lit("context", v("c")), lit("objectValue", v("o"))],
|
|
1488
|
+
"object under a context is itself"
|
|
1489
|
+
),
|
|
1490
|
+
// A property read goes on under the site the object was made at, so a
|
|
1491
|
+
// field read off two constructions gives each one its own value. A
|
|
1492
|
+
// class or a literal object keeps the context the walk was already in.
|
|
1493
|
+
rule(
|
|
1494
|
+
"reachesUnder",
|
|
1495
|
+
[v("x"), v("c"), v("held"), v("site"), VALUE_STEP],
|
|
1496
|
+
[
|
|
1497
|
+
lit("context", v("c")),
|
|
1498
|
+
lit("readsProperty", v("x"), v("o"), v("n")),
|
|
1499
|
+
lit("objectOfUnder", v("o"), v("c"), v("site")),
|
|
1500
|
+
lit("allocates", v("site"), v("cls")),
|
|
1501
|
+
lit("contains", v("site"), v("n"), v("held"))
|
|
1502
|
+
],
|
|
1503
|
+
"property read at a site"
|
|
1504
|
+
),
|
|
1505
|
+
rule(
|
|
1506
|
+
"reachesUnder",
|
|
1507
|
+
[v("x"), v("c"), v("held"), v("c"), VALUE_STEP],
|
|
1508
|
+
[
|
|
1509
|
+
lit("context", v("c")),
|
|
1510
|
+
lit("readsProperty", v("x"), v("o"), v("n")),
|
|
1511
|
+
lit("objectOfUnder", v("o"), v("c"), v("obj")),
|
|
1512
|
+
lit("objectValue", v("obj")),
|
|
1513
|
+
lit("contains", v("obj"), v("n"), v("held"))
|
|
1514
|
+
],
|
|
1515
|
+
"property read off an object"
|
|
1516
|
+
),
|
|
1517
|
+
rule(
|
|
1518
|
+
"reachesUnder",
|
|
1519
|
+
[v("x"), v("c"), v("held"), v("site"), v("kind")],
|
|
1520
|
+
[
|
|
1521
|
+
lit("reachesUnder", v("x"), v("c"), v("y"), v("c2"), v("kind")),
|
|
1522
|
+
lit("readsProperty", v("y"), v("o"), v("n")),
|
|
1523
|
+
lit("objectOfUnder", v("o"), v("c2"), v("site")),
|
|
1524
|
+
lit("allocates", v("site"), v("cls")),
|
|
1525
|
+
lit("contains", v("site"), v("n"), v("held"))
|
|
1526
|
+
],
|
|
1527
|
+
"reached property read at a site"
|
|
1528
|
+
),
|
|
1529
|
+
rule(
|
|
1530
|
+
"reachesUnder",
|
|
1531
|
+
[v("x"), v("c"), v("held"), v("c2"), v("kind")],
|
|
1532
|
+
[
|
|
1533
|
+
lit("reachesUnder", v("x"), v("c"), v("y"), v("c2"), v("kind")),
|
|
1534
|
+
lit("readsProperty", v("y"), v("o"), v("n")),
|
|
1535
|
+
lit("objectOfUnder", v("o"), v("c2"), v("obj")),
|
|
1536
|
+
lit("objectValue", v("obj")),
|
|
1537
|
+
lit("contains", v("obj"), v("n"), v("held"))
|
|
1538
|
+
],
|
|
1539
|
+
"reached property read off an object"
|
|
1540
|
+
),
|
|
1541
|
+
// A parameter goes on at the argument, under the context its caller
|
|
1542
|
+
// was read in, and only from the calls that run the function under the
|
|
1543
|
+
// context the walk is in. This is the one hop that changes context.
|
|
1544
|
+
rule(
|
|
1545
|
+
"reachesUnder",
|
|
1546
|
+
[v("p"), v("c"), v("a"), v("c3"), VALUE_STEP],
|
|
1547
|
+
[
|
|
1548
|
+
lit("context", v("c")),
|
|
1549
|
+
lit("paramOf", v("f"), v("i"), v("p")),
|
|
1550
|
+
lit("entersUnder", v("r"), v("f"), v("c"), v("c3")),
|
|
1551
|
+
lit("callArg", v("r"), v("i"), v("a"))
|
|
1552
|
+
],
|
|
1553
|
+
"argument under a context"
|
|
1554
|
+
),
|
|
1555
|
+
rule(
|
|
1556
|
+
"reachesUnder",
|
|
1557
|
+
[v("p"), v("c"), v("a"), v("c3"), VALUE_STEP],
|
|
1558
|
+
[
|
|
1559
|
+
lit("context", v("c")),
|
|
1560
|
+
lit("paramNamed", v("f"), v("n"), v("p")),
|
|
1561
|
+
lit("entersUnder", v("r"), v("f"), v("c"), v("c3")),
|
|
1562
|
+
lit("callKeywordArg", v("r"), v("n"), v("a"))
|
|
1563
|
+
],
|
|
1564
|
+
"keyword argument under a context"
|
|
1565
|
+
),
|
|
1566
|
+
rule(
|
|
1567
|
+
"reachesUnder",
|
|
1568
|
+
[v("x"), v("c"), v("a"), v("c3"), v("kind")],
|
|
1569
|
+
[
|
|
1570
|
+
lit("reachesUnder", v("x"), v("c"), v("p"), v("c2"), v("kind")),
|
|
1571
|
+
lit("paramOf", v("f"), v("i"), v("p")),
|
|
1572
|
+
lit("entersUnder", v("r"), v("f"), v("c2"), v("c3")),
|
|
1573
|
+
lit("callArg", v("r"), v("i"), v("a"))
|
|
1574
|
+
],
|
|
1575
|
+
"reached argument under a context"
|
|
1576
|
+
),
|
|
1577
|
+
rule(
|
|
1578
|
+
"reachesUnder",
|
|
1579
|
+
[v("x"), v("c"), v("a"), v("c3"), v("kind")],
|
|
1580
|
+
[
|
|
1581
|
+
lit("reachesUnder", v("x"), v("c"), v("p"), v("c2"), v("kind")),
|
|
1582
|
+
lit("paramNamed", v("f"), v("n"), v("p")),
|
|
1583
|
+
lit("entersUnder", v("r"), v("f"), v("c2"), v("c3")),
|
|
1584
|
+
lit("callKeywordArg", v("r"), v("n"), v("a"))
|
|
1585
|
+
],
|
|
1586
|
+
"reached keyword argument under a context"
|
|
1587
|
+
),
|
|
1588
|
+
// Which call runs which function under which context. A construction
|
|
1589
|
+
// runs its constructor under the site it makes, a method call runs
|
|
1590
|
+
// under the site its receiver is, and anything else under no context.
|
|
1591
|
+
rule(
|
|
1592
|
+
"entersUnder",
|
|
1593
|
+
[v("site"), v("ctor"), v("site"), v("caller")],
|
|
1594
|
+
[
|
|
1595
|
+
lit("allocates", v("site"), v("cls")),
|
|
1596
|
+
lit("runsConstructor", v("cls"), v("ctor")),
|
|
1597
|
+
lit("callUnder", v("site"), v("caller"))
|
|
1598
|
+
],
|
|
1599
|
+
"construction enters its constructor"
|
|
1600
|
+
),
|
|
1601
|
+
rule(
|
|
1602
|
+
"entersUnder",
|
|
1603
|
+
[v("r"), v("f"), v("site"), v("caller")],
|
|
1604
|
+
[
|
|
1605
|
+
lit("call", v("r"), v("cal")),
|
|
1606
|
+
lit("readsProperty", v("cal"), v("o"), v("m")),
|
|
1607
|
+
lit("objectOfUnder", v("o"), v("caller"), v("site")),
|
|
1608
|
+
lit("allocates", v("site"), v("cls")),
|
|
1609
|
+
lit("contains", v("site"), v("m"), v("f")),
|
|
1610
|
+
lit("callUnder", v("r"), v("caller"))
|
|
1611
|
+
],
|
|
1612
|
+
"method call enters under its receiver"
|
|
1613
|
+
),
|
|
1614
|
+
// A call written as a name runs with whatever receiver the body
|
|
1615
|
+
// around it has, so a plain function called from a method keeps the
|
|
1616
|
+
// site rather than taking every caller of it.
|
|
1617
|
+
rule(
|
|
1618
|
+
"entersUnder",
|
|
1619
|
+
[v("r"), v("f"), v("c"), v("c")],
|
|
1620
|
+
[
|
|
1621
|
+
lit("context", v("c")),
|
|
1622
|
+
lit("callsNamed", v("r"), v("f")),
|
|
1623
|
+
lit("callUnder", v("r"), v("c"))
|
|
1624
|
+
],
|
|
1625
|
+
"named call enters under the site it is made in"
|
|
1626
|
+
),
|
|
1627
|
+
rule(
|
|
1628
|
+
"entersUnder",
|
|
1629
|
+
[v("r"), v("f"), NO_CONTEXT, v("caller")],
|
|
1630
|
+
[
|
|
1631
|
+
lit("callsFunction", v("r"), v("f")),
|
|
1632
|
+
lit("callUnder", v("r"), v("caller"))
|
|
1633
|
+
],
|
|
1634
|
+
"call enters with no context"
|
|
1635
|
+
),
|
|
1636
|
+
// The constructor a construction runs, the ancestry included, so a
|
|
1637
|
+
// subclass that declares none still fills in what it inherits.
|
|
1638
|
+
rule(
|
|
1639
|
+
"runsConstructor",
|
|
1640
|
+
[v("cls"), v("f")],
|
|
1641
|
+
[lit("initializes", v("cls"), v("f"))]
|
|
1642
|
+
),
|
|
1643
|
+
rule(
|
|
1644
|
+
"runsConstructor",
|
|
1645
|
+
[v("cls"), v("f")],
|
|
1646
|
+
[
|
|
1647
|
+
lit("extends", v("cls"), v("b")),
|
|
1648
|
+
lit("comesTo", v("b"), v("base")),
|
|
1649
|
+
lit("runsConstructor", v("base"), v("f"))
|
|
1155
1650
|
]
|
|
1156
1651
|
),
|
|
1157
|
-
//
|
|
1158
|
-
//
|
|
1159
|
-
// demand-driven run then derives both to answer either.
|
|
1652
|
+
// Which body a call is written in. One adapter states the call it
|
|
1653
|
+
// found and another states the callee, so both spellings are read.
|
|
1160
1654
|
rule(
|
|
1161
|
-
"
|
|
1162
|
-
[v("
|
|
1655
|
+
"callInBody",
|
|
1656
|
+
[v("f"), v("r")],
|
|
1657
|
+
[lit("bodyCallsDeep", v("f"), v("r")), lit("call", v("r"), v("c"))]
|
|
1658
|
+
),
|
|
1659
|
+
rule(
|
|
1660
|
+
"callInBody",
|
|
1661
|
+
[v("f"), v("r")],
|
|
1662
|
+
[lit("bodyCallsDeep", v("f"), v("c")), lit("call", v("r"), v("c"))]
|
|
1663
|
+
),
|
|
1664
|
+
// The context a call is made under: every site of the class whose
|
|
1665
|
+
// method or constructor it is written in, and no context for a call
|
|
1666
|
+
// outside every method body.
|
|
1667
|
+
rule(
|
|
1668
|
+
"callUnder",
|
|
1669
|
+
[v("r"), v("site")],
|
|
1670
|
+
[
|
|
1671
|
+
lit("callInBody", v("f"), v("r")),
|
|
1672
|
+
lit("holdsProperty", v("cls"), v("m"), v("f")),
|
|
1673
|
+
lit("allocates", v("site"), v("cls"))
|
|
1674
|
+
],
|
|
1675
|
+
"call in a method"
|
|
1676
|
+
),
|
|
1677
|
+
rule(
|
|
1678
|
+
"callUnder",
|
|
1679
|
+
[v("r"), v("site")],
|
|
1680
|
+
[
|
|
1681
|
+
lit("callInBody", v("f"), v("r")),
|
|
1682
|
+
lit("initializes", v("cls"), v("f")),
|
|
1683
|
+
lit("allocates", v("site"), v("cls"))
|
|
1684
|
+
],
|
|
1685
|
+
"call in a constructor"
|
|
1686
|
+
),
|
|
1687
|
+
// A plain function entered under a site makes its own calls under
|
|
1688
|
+
// that site, so a chain of plain functions off one method keeps it.
|
|
1689
|
+
rule(
|
|
1690
|
+
"callUnder",
|
|
1691
|
+
[v("r"), v("c")],
|
|
1692
|
+
[
|
|
1693
|
+
lit("callOutsideMethod", v("r")),
|
|
1694
|
+
lit("callInBody", v("f"), v("r")),
|
|
1695
|
+
lit("entersUnder", v("into"), v("f"), v("c"), v("c4"))
|
|
1696
|
+
],
|
|
1697
|
+
"call in a function entered under a site"
|
|
1698
|
+
),
|
|
1699
|
+
rule(
|
|
1700
|
+
"callUnder",
|
|
1701
|
+
[v("r"), NO_CONTEXT],
|
|
1702
|
+
[lit("callOutsideMethod", v("r"))],
|
|
1703
|
+
"call outside every method"
|
|
1704
|
+
),
|
|
1705
|
+
// The two questions a caller puts under a context, stopping where
|
|
1706
|
+
// `isWrittenAs` and `comesTo` stop, whatever context the walk ended in.
|
|
1707
|
+
rule(
|
|
1708
|
+
"isWrittenAsUnder",
|
|
1709
|
+
[v("x"), v("c"), v("x")],
|
|
1710
|
+
[lit("context", v("c")), lit("writtenValue", v("x"))]
|
|
1711
|
+
),
|
|
1712
|
+
rule(
|
|
1713
|
+
"isWrittenAsUnder",
|
|
1714
|
+
[v("x"), v("c"), v("x")],
|
|
1715
|
+
[lit("context", v("c")), lit("objectValue", v("x"))]
|
|
1716
|
+
),
|
|
1717
|
+
rule(
|
|
1718
|
+
"isWrittenAsUnder",
|
|
1719
|
+
[v("x"), v("c"), v("z")],
|
|
1163
1720
|
[
|
|
1164
|
-
lit("
|
|
1165
|
-
lit("
|
|
1721
|
+
lit("reachesUnder", v("x"), v("c"), v("z"), v("c2"), VALUE_STEP),
|
|
1722
|
+
lit("writtenValue", v("z"))
|
|
1166
1723
|
]
|
|
1167
1724
|
),
|
|
1168
1725
|
rule(
|
|
1169
|
-
"
|
|
1170
|
-
[v("x"), v("
|
|
1726
|
+
"isWrittenAsUnder",
|
|
1727
|
+
[v("x"), v("c"), v("z")],
|
|
1171
1728
|
[
|
|
1172
|
-
lit("
|
|
1173
|
-
lit("
|
|
1729
|
+
lit("reachesUnder", v("x"), v("c"), v("z"), v("c2"), VALUE_STEP),
|
|
1730
|
+
lit("objectValue", v("z"))
|
|
1731
|
+
]
|
|
1732
|
+
),
|
|
1733
|
+
rule(
|
|
1734
|
+
"comesToUnder",
|
|
1735
|
+
[v("x"), v("c"), v("x")],
|
|
1736
|
+
[lit("context", v("c")), lit("func", v("x"))]
|
|
1737
|
+
),
|
|
1738
|
+
rule(
|
|
1739
|
+
"comesToUnder",
|
|
1740
|
+
[v("x"), v("c"), v("x")],
|
|
1741
|
+
[lit("context", v("c")), lit("objectValue", v("x"))]
|
|
1742
|
+
),
|
|
1743
|
+
rule(
|
|
1744
|
+
"comesToUnder",
|
|
1745
|
+
[v("x"), v("c"), v("z")],
|
|
1746
|
+
[
|
|
1747
|
+
lit("reachesUnder", v("x"), v("c"), v("z"), v("c2"), VALUE_STEP),
|
|
1748
|
+
lit("func", v("z"))
|
|
1749
|
+
]
|
|
1750
|
+
),
|
|
1751
|
+
rule(
|
|
1752
|
+
"comesToUnder",
|
|
1753
|
+
[v("x"), v("c"), v("z")],
|
|
1754
|
+
[
|
|
1755
|
+
lit("reachesUnder", v("x"), v("c"), v("z"), v("c2"), VALUE_STEP),
|
|
1756
|
+
lit("objectValue", v("z"))
|
|
1757
|
+
]
|
|
1758
|
+
),
|
|
1759
|
+
rule(
|
|
1760
|
+
"comesToUnder",
|
|
1761
|
+
[v("x"), v("c"), v("z")],
|
|
1762
|
+
[
|
|
1763
|
+
lit("reachesUnder", v("x"), v("c"), v("z"), v("c2"), INSTANCE_STEP),
|
|
1764
|
+
lit("func", v("z"))
|
|
1765
|
+
]
|
|
1766
|
+
),
|
|
1767
|
+
rule(
|
|
1768
|
+
"comesToUnder",
|
|
1769
|
+
[v("x"), v("c"), v("z")],
|
|
1770
|
+
[
|
|
1771
|
+
lit("reachesUnder", v("x"), v("c"), v("z"), v("c2"), INSTANCE_STEP),
|
|
1772
|
+
lit("objectValue", v("z"))
|
|
1174
1773
|
]
|
|
1175
1774
|
),
|
|
1176
1775
|
// What a value comes down to: the walk that never ran a call, stopped
|
|
@@ -1188,6 +1787,18 @@ var RESOLUTION_RULES = [
|
|
|
1188
1787
|
[v("x"), v("z")],
|
|
1189
1788
|
[lit("reaches", v("x"), v("z"), VALUE_STEP), lit("objectValue", v("z"))]
|
|
1190
1789
|
),
|
|
1790
|
+
// An instance walk stops the same way, so a method read off
|
|
1791
|
+
// `new App()` still finds what the class declares.
|
|
1792
|
+
rule(
|
|
1793
|
+
"comesTo",
|
|
1794
|
+
[v("x"), v("z")],
|
|
1795
|
+
[lit("reaches", v("x"), v("z"), INSTANCE_STEP), lit("func", v("z"))]
|
|
1796
|
+
),
|
|
1797
|
+
rule(
|
|
1798
|
+
"comesTo",
|
|
1799
|
+
[v("x"), v("z")],
|
|
1800
|
+
[lit("reaches", v("x"), v("z"), INSTANCE_STEP), lit("objectValue", v("z"))]
|
|
1801
|
+
),
|
|
1191
1802
|
// The same stopping condition, for the walk that ran a call. A call
|
|
1192
1803
|
// gets no `comesTo` answer on purpose: coming back with what a
|
|
1193
1804
|
// factory returned would fight the unwrapping answer.
|
|
@@ -1228,6 +1839,13 @@ var RESOLUTION_RULES = [
|
|
|
1228
1839
|
lit("isWrittenAs", v("ret"), v("z"))
|
|
1229
1840
|
]
|
|
1230
1841
|
),
|
|
1842
|
+
// Which expression running f hands back, whether f returns it, writes
|
|
1843
|
+
// it into a name first, or ends on it as a shorthand body.
|
|
1844
|
+
rule(
|
|
1845
|
+
"returnsCall",
|
|
1846
|
+
[v("f"), v("c")],
|
|
1847
|
+
[lit("returnsValue", v("f"), v("v")), lit("isWrittenAs", v("v"), v("c"))]
|
|
1848
|
+
),
|
|
1231
1849
|
// What one call site put in a parameter, told apart from what the
|
|
1232
1850
|
// other callers passed.
|
|
1233
1851
|
rule(
|
|
@@ -1325,18 +1943,34 @@ var RESOLUTION_RULES = [
|
|
|
1325
1943
|
[v("x"), v("obj")],
|
|
1326
1944
|
[lit("givesBack", v("x"), v("obj")), lit("objectValue", v("obj"))]
|
|
1327
1945
|
),
|
|
1946
|
+
// A construction is the object it made, and so is any name for it.
|
|
1947
|
+
// The class stays an answer too, so an instance whose site is not in
|
|
1948
|
+
// the run still reads what the class stores.
|
|
1949
|
+
rule(
|
|
1950
|
+
"objectOf",
|
|
1951
|
+
[v("site"), v("site")],
|
|
1952
|
+
[lit("allocates", v("site"), v("c"))]
|
|
1953
|
+
),
|
|
1954
|
+
rule(
|
|
1955
|
+
"objectOf",
|
|
1956
|
+
[v("o"), v("site")],
|
|
1957
|
+
[
|
|
1958
|
+
lit("reaches", v("o"), v("site"), VALUE_STEP),
|
|
1959
|
+
lit("allocates", v("site"), v("c"))
|
|
1960
|
+
]
|
|
1961
|
+
),
|
|
1328
1962
|
// Which calls a function, found by the name the call is written as
|
|
1329
1963
|
// rather than by resolving every callee in the project. A caller knows
|
|
1330
1964
|
// the function and wants its call sites, so both of these start from
|
|
1331
1965
|
// the function. Starting from `call` instead asks what every call in
|
|
1332
1966
|
// the project imports, which was 72% of everything derived.
|
|
1333
1967
|
rule(
|
|
1334
|
-
"
|
|
1968
|
+
"callsNamed",
|
|
1335
1969
|
[v("r"), v("f")],
|
|
1336
1970
|
[lit("binds", v("c"), v("f")), lit("call", v("r"), v("c"))]
|
|
1337
1971
|
),
|
|
1338
1972
|
rule(
|
|
1339
|
-
"
|
|
1973
|
+
"callsNamed",
|
|
1340
1974
|
[v("r"), v("f")],
|
|
1341
1975
|
[
|
|
1342
1976
|
lit("moduleExport", v("m"), v("n"), v("f")),
|
|
@@ -1347,7 +1981,7 @@ var RESOLUTION_RULES = [
|
|
|
1347
1981
|
// The same, for a language whose adapter writes the import down as a
|
|
1348
1982
|
// declaration and the call's callee as the name referring to it.
|
|
1349
1983
|
rule(
|
|
1350
|
-
"
|
|
1984
|
+
"callsNamed",
|
|
1351
1985
|
[v("r"), v("f")],
|
|
1352
1986
|
[
|
|
1353
1987
|
lit("moduleExport", v("m"), v("n"), v("f")),
|
|
@@ -1356,6 +1990,36 @@ var RESOLUTION_RULES = [
|
|
|
1356
1990
|
lit("call", v("r"), v("c"))
|
|
1357
1991
|
]
|
|
1358
1992
|
),
|
|
1993
|
+
// `const f = (x) => ...` declares the name and puts the parameters on
|
|
1994
|
+
// the arrow, so everything above arrives at the declaration and
|
|
1995
|
+
// `paramOf` is about the arrow. One binds hop joins the two.
|
|
1996
|
+
rule(
|
|
1997
|
+
"callsNamed",
|
|
1998
|
+
[v("r"), v("f")],
|
|
1999
|
+
[lit("binds", v("g"), v("f")), lit("callsNamed", v("r"), v("g"))]
|
|
2000
|
+
),
|
|
2001
|
+
// Every one of those, and the binds hop again over the whole
|
|
2002
|
+
// relation, so a property holding a name for a function is reached
|
|
2003
|
+
// the way it was before the two were told apart.
|
|
2004
|
+
rule("callsFunction", [v("r"), v("f")], [lit("callsNamed", v("r"), v("f"))]),
|
|
2005
|
+
rule(
|
|
2006
|
+
"callsFunction",
|
|
2007
|
+
[v("r"), v("f")],
|
|
2008
|
+
[lit("binds", v("g"), v("f")), lit("callsFunction", v("r"), v("g"))]
|
|
2009
|
+
),
|
|
2010
|
+
// A function written on an object, called off it: `client.get(o)`.
|
|
2011
|
+
// Every rule above joins on a name the callee binds to, and a read of
|
|
2012
|
+
// a property binds to nothing.
|
|
2013
|
+
rule(
|
|
2014
|
+
"callsFunction",
|
|
2015
|
+
[v("r"), v("f")],
|
|
2016
|
+
[
|
|
2017
|
+
lit("holdsProperty", v("obj"), v("n"), v("f")),
|
|
2018
|
+
lit("readsProperty", v("c"), v("o"), v("n")),
|
|
2019
|
+
lit("objectOf", v("o"), v("obj")),
|
|
2020
|
+
lit("call", v("r"), v("c"))
|
|
2021
|
+
]
|
|
2022
|
+
),
|
|
1359
2023
|
// What an object contains, its base class included, so a method the base
|
|
1360
2024
|
// declares is found on a subclass that never overrode it. A method both
|
|
1361
2025
|
// declare gives two, and the caller decides. This is its own relation
|
|
@@ -1373,7 +2037,93 @@ var RESOLUTION_RULES = [
|
|
|
1373
2037
|
lit("extends", v("cls"), v("base")),
|
|
1374
2038
|
lit("comesTo", v("base"), v("baseCls")),
|
|
1375
2039
|
lit("contains", v("baseCls"), v("n"), v("held"))
|
|
1376
|
-
]
|
|
2040
|
+
],
|
|
2041
|
+
BASE_CLASS_RULE
|
|
2042
|
+
),
|
|
2043
|
+
// An association is read off an instance as a property, and stating
|
|
2044
|
+
// it as `contains` is what puts it on the ancestry rule, so a concern
|
|
2045
|
+
// or a base class can be the one that declares it.
|
|
2046
|
+
rule(
|
|
2047
|
+
"contains",
|
|
2048
|
+
[v("cls"), v("n"), v("t")],
|
|
2049
|
+
[lit("declaresAssociation", v("cls"), v("n"), v("t"))],
|
|
2050
|
+
"declared association"
|
|
2051
|
+
),
|
|
2052
|
+
// The same, for a language that buries the declaration in an ordinary
|
|
2053
|
+
// assignment. Keying on the module the callable came from is what
|
|
2054
|
+
// keeps a project function spelled the same way out.
|
|
2055
|
+
rule(
|
|
2056
|
+
"contains",
|
|
2057
|
+
[v("cls"), v("n"), v("t")],
|
|
2058
|
+
[
|
|
2059
|
+
lit("fieldCall", v("cls"), v("n"), v("c"), v("t")),
|
|
2060
|
+
lit("comesFrom", v("c"), v("m"), v("name")),
|
|
2061
|
+
lit("associationConstructor", v("m"), v("name"))
|
|
2062
|
+
],
|
|
2063
|
+
"constructed association"
|
|
2064
|
+
),
|
|
2065
|
+
// What the constructor put on the receiver. The class is the object
|
|
2066
|
+
// for an instance whose own site is not in the run.
|
|
2067
|
+
rule(
|
|
2068
|
+
"contains",
|
|
2069
|
+
[v("cls"), v("n"), v("held")],
|
|
2070
|
+
[
|
|
2071
|
+
lit("initializes", v("cls"), v("f")),
|
|
2072
|
+
lit("storesProperty", v("f"), v("n"), v("held"))
|
|
2073
|
+
],
|
|
2074
|
+
"constructor store"
|
|
2075
|
+
),
|
|
2076
|
+
// What any other method of the class put there. Two methods writing
|
|
2077
|
+
// one name give two rows, since nothing here orders them.
|
|
2078
|
+
rule(
|
|
2079
|
+
"contains",
|
|
2080
|
+
[v("cls"), v("n"), v("held")],
|
|
2081
|
+
[
|
|
2082
|
+
lit("holdsProperty", v("cls"), v("m"), v("f")),
|
|
2083
|
+
lit("storesProperty", v("f"), v("n"), v("held"))
|
|
2084
|
+
],
|
|
2085
|
+
"method store"
|
|
2086
|
+
),
|
|
2087
|
+
// A write through a name rather than through the receiver,
|
|
2088
|
+
// `client.timeout = 5`, which lands on whatever that name refers to.
|
|
2089
|
+
rule(
|
|
2090
|
+
"contains",
|
|
2091
|
+
[v("obj"), v("n"), v("held")],
|
|
2092
|
+
[
|
|
2093
|
+
lit("storesProperty", v("r"), v("n"), v("held")),
|
|
2094
|
+
lit("objectOf", v("r"), v("obj"))
|
|
2095
|
+
],
|
|
2096
|
+
"named receiver store"
|
|
2097
|
+
),
|
|
2098
|
+
// A call written with a class's own name, which is how most languages
|
|
2099
|
+
// spell a construction. A language that spells one some other way
|
|
2100
|
+
// states its own rule for this, the way Ruby does for `Const.new`.
|
|
2101
|
+
rule(
|
|
2102
|
+
"constructsNamed",
|
|
2103
|
+
[v("r"), v("cls")],
|
|
2104
|
+
[lit("objectValue", v("cls")), lit("callsNamed", v("r"), v("cls"))]
|
|
2105
|
+
),
|
|
2106
|
+
// Each construction is an object of its own containing what its
|
|
2107
|
+
// class stores, so two sites are two objects.
|
|
2108
|
+
rule(
|
|
2109
|
+
"contains",
|
|
2110
|
+
[v("site"), v("n"), v("held")],
|
|
2111
|
+
[
|
|
2112
|
+
lit("allocates", v("site"), v("cls")),
|
|
2113
|
+
lit("contains", v("cls"), v("n"), v("held"))
|
|
2114
|
+
],
|
|
2115
|
+
"allocated instance"
|
|
2116
|
+
),
|
|
2117
|
+
// A call that makes one of a class. Every finder a pack declared is
|
|
2118
|
+
// one too, so `User.find(1)` is a site the same way `User.new` is.
|
|
2119
|
+
rule(
|
|
2120
|
+
"allocates",
|
|
2121
|
+
[v("site"), v("cls")],
|
|
2122
|
+
[
|
|
2123
|
+
lit("call", v("site"), v("c")),
|
|
2124
|
+
lit("stepsTo", v("site"), v("cls"), INSTANCE_STEP)
|
|
2125
|
+
],
|
|
2126
|
+
"allocation site"
|
|
1377
2127
|
),
|
|
1378
2128
|
// The library base a class's ancestry arrives at, however many of a
|
|
1379
2129
|
// project's own classes sit in between. A base the run declares has a
|
|
@@ -1464,8 +2214,8 @@ var RESOLUTION_RULES = [
|
|
|
1464
2214
|
]
|
|
1465
2215
|
),
|
|
1466
2216
|
// Where a name comes from, when what it refers to lives outside the
|
|
1467
|
-
// source being read. A walk ends at
|
|
1468
|
-
//
|
|
2217
|
+
// source being read. A walk ends at what the source writes out, so it
|
|
2218
|
+
// never reaches a library's own function; these rules do.
|
|
1469
2219
|
rule(
|
|
1470
2220
|
"comesFrom",
|
|
1471
2221
|
[v("x"), v("m"), v("n")],
|
|
@@ -1479,6 +2229,28 @@ var RESOLUTION_RULES = [
|
|
|
1479
2229
|
lit("imports", v("y"), v("m"), v("n"))
|
|
1480
2230
|
]
|
|
1481
2231
|
),
|
|
2232
|
+
// A member read off a whole-module import: the member's own name is
|
|
2233
|
+
// what the module exports, so `fastapi.APIRouter` comes from
|
|
2234
|
+
// fastapi's `APIRouter`. Directly, or through a name for the module.
|
|
2235
|
+
rule(
|
|
2236
|
+
"comesFrom",
|
|
2237
|
+
[v("x"), v("m"), v("n")],
|
|
2238
|
+
[
|
|
2239
|
+
lit("readsProperty", v("x"), v("ns"), v("n")),
|
|
2240
|
+
lit("imports", v("ns"), v("m"), NAMESPACE_IMPORT)
|
|
2241
|
+
],
|
|
2242
|
+
NAMESPACE_MEMBER_RULE
|
|
2243
|
+
),
|
|
2244
|
+
rule(
|
|
2245
|
+
"comesFrom",
|
|
2246
|
+
[v("x"), v("m"), v("n")],
|
|
2247
|
+
[
|
|
2248
|
+
lit("readsProperty", v("x"), v("o"), v("n")),
|
|
2249
|
+
lit("reaches", v("o"), v("ns"), VALUE_STEP),
|
|
2250
|
+
lit("imports", v("ns"), v("m"), NAMESPACE_IMPORT)
|
|
2251
|
+
],
|
|
2252
|
+
NAMESPACE_MEMBER_RULE
|
|
2253
|
+
),
|
|
1482
2254
|
// Calling f ends up calling the name n that module m exports, one
|
|
1483
2255
|
// hop through f's own body or deeper through a wrapper of a wrapper.
|
|
1484
2256
|
// Several results is normal: a composed decorator applies them all.
|
|
@@ -1508,6 +2280,13 @@ var RESOLUTION_RULES = [
|
|
|
1508
2280
|
[lit("comesTo", v("x"), v("z")), lit("func", v("z"))]
|
|
1509
2281
|
)
|
|
1510
2282
|
];
|
|
2283
|
+
function alsoSteps(rules) {
|
|
2284
|
+
return [
|
|
2285
|
+
...rules,
|
|
2286
|
+
...rules.filter((r) => r.head.relation === "hop").map((r) => ({ ...r, head: { ...r.head, relation: "stepsTo" } }))
|
|
2287
|
+
];
|
|
2288
|
+
}
|
|
2289
|
+
var RESOLUTION_RULES = alsoSteps(STATED_RULES);
|
|
1511
2290
|
var RESOLUTION_QUESTIONS = [
|
|
1512
2291
|
rule(
|
|
1513
2292
|
"wantedResolves",
|
|
@@ -1530,12 +2309,55 @@ var RESOLUTION_QUESTIONS = [
|
|
|
1530
2309
|
[lit("wanted", v("x")), lit("isWrittenAs", v("x"), v("z"))]
|
|
1531
2310
|
),
|
|
1532
2311
|
// A call is given no `comesTo`, so this is the only way to ask what
|
|
1533
|
-
// object one arrives at, and
|
|
1534
|
-
//
|
|
2312
|
+
// object one arrives at, and a demand-driven run derives `objectOf`
|
|
2313
|
+
// nowhere without it. An allocation site is not one of the answers.
|
|
1535
2314
|
rule(
|
|
1536
2315
|
"wantedObjectOf",
|
|
1537
2316
|
[v("x"), v("z")],
|
|
1538
|
-
[
|
|
2317
|
+
[
|
|
2318
|
+
lit("wanted", v("x")),
|
|
2319
|
+
lit("objectOf", v("x"), v("z")),
|
|
2320
|
+
lit("objectValue", v("z"))
|
|
2321
|
+
]
|
|
2322
|
+
),
|
|
2323
|
+
// The same three questions under one allocation site, keyed by the
|
|
2324
|
+
// value and the site both. An allocation site is an answer here,
|
|
2325
|
+
// unlike `wantedObjectOf`, since a site is what a context is.
|
|
2326
|
+
rule(
|
|
2327
|
+
"wantedIsWrittenAsUnder",
|
|
2328
|
+
[v("x"), v("c"), v("z")],
|
|
2329
|
+
[
|
|
2330
|
+
lit("wantedUnder", v("x"), v("c")),
|
|
2331
|
+
lit("isWrittenAsUnder", v("x"), v("c"), v("z"))
|
|
2332
|
+
]
|
|
2333
|
+
),
|
|
2334
|
+
// Where a class was made, for a caller about to ask a value question
|
|
2335
|
+
// under each. Going through `constructsNamed` keeps the demand on the
|
|
2336
|
+
// calls written with the class's name rather than on every call.
|
|
2337
|
+
rule(
|
|
2338
|
+
"wantedAllocatedAt",
|
|
2339
|
+
[v("cls"), v("site")],
|
|
2340
|
+
[
|
|
2341
|
+
lit("wantedSites", v("cls")),
|
|
2342
|
+
lit("constructsNamed", v("site"), v("cls")),
|
|
2343
|
+
lit("allocates", v("site"), v("cls"))
|
|
2344
|
+
]
|
|
2345
|
+
),
|
|
2346
|
+
rule(
|
|
2347
|
+
"wantedComesToUnder",
|
|
2348
|
+
[v("x"), v("c"), v("z")],
|
|
2349
|
+
[
|
|
2350
|
+
lit("wantedUnder", v("x"), v("c")),
|
|
2351
|
+
lit("comesToUnder", v("x"), v("c"), v("z"))
|
|
2352
|
+
]
|
|
2353
|
+
),
|
|
2354
|
+
rule(
|
|
2355
|
+
"wantedObjectOfUnder",
|
|
2356
|
+
[v("x"), v("c"), v("z")],
|
|
2357
|
+
[
|
|
2358
|
+
lit("wantedUnder", v("x"), v("c")),
|
|
2359
|
+
lit("objectOfUnder", v("x"), v("c"), v("z"))
|
|
2360
|
+
]
|
|
1539
2361
|
),
|
|
1540
2362
|
// The same for the function a call returns: `app.use(requireCaller(config))`
|
|
1541
2363
|
// registers what the factory gives back, and `resolves` on the call
|
|
@@ -1552,6 +2374,19 @@ var RESOLUTION_QUESTIONS = [
|
|
|
1552
2374
|
[v("p"), v("r"), v("z")],
|
|
1553
2375
|
[lit("wanted", v("p")), lit("paramAt", v("r"), v("p"), v("z"))]
|
|
1554
2376
|
),
|
|
2377
|
+
// The argument as the caller wrote it. A parameter given a GraphQL
|
|
2378
|
+
// document has no `paramAt` answer, since that settles through
|
|
2379
|
+
// `comesTo`, which stops at a function or an object.
|
|
2380
|
+
rule(
|
|
2381
|
+
"wantedPassesArgument",
|
|
2382
|
+
[v("p"), v("r"), v("a")],
|
|
2383
|
+
[lit("wanted", v("p")), lit("passesArgument", v("r"), v("p"), v("a"))]
|
|
2384
|
+
),
|
|
2385
|
+
rule(
|
|
2386
|
+
"wantedReturnsCall",
|
|
2387
|
+
[v("f"), v("c")],
|
|
2388
|
+
[lit("wanted", v("f")), lit("returnsCall", v("f"), v("c"))]
|
|
2389
|
+
),
|
|
1555
2390
|
rule(
|
|
1556
2391
|
"wantedComesFrom",
|
|
1557
2392
|
[v("x"), v("m"), v("n")],
|
|
@@ -1760,6 +2595,14 @@ var RESOLUTION_QUESTIONS = [
|
|
|
1760
2595
|
lit("holdsProperty", v("b"), v("n"), v("held"))
|
|
1761
2596
|
]
|
|
1762
2597
|
),
|
|
2598
|
+
// A method the class gets under a name the source computes rather than
|
|
2599
|
+
// writes out. The adapter settles the name against the same facts and
|
|
2600
|
+
// says so, and the chain reports it beside the ones written out.
|
|
2601
|
+
rule(
|
|
2602
|
+
"wantedDeclaredName",
|
|
2603
|
+
[v("c"), v("n")],
|
|
2604
|
+
[lit("ancestryChain", v("c"), v("b")), lit("declaresName", v("b"), v("n"))]
|
|
2605
|
+
),
|
|
1763
2606
|
rule("anchorChain", [v("x"), v("x")], [lit("wantedAnchor", v("x"))]),
|
|
1764
2607
|
rule(
|
|
1765
2608
|
"anchorChain",
|
|
@@ -1807,35 +2650,58 @@ var RESOLUTION_QUESTIONS = [
|
|
|
1807
2650
|
var ANSWER_RELATIONS = [
|
|
1808
2651
|
...new Set(RESOLUTION_QUESTIONS.map((r) => r.head.relation))
|
|
1809
2652
|
];
|
|
2653
|
+
var UNDER_ANSWER_RELATIONS = [
|
|
2654
|
+
"wantedIsWrittenAsUnder",
|
|
2655
|
+
"wantedComesToUnder",
|
|
2656
|
+
"wantedObjectOfUnder"
|
|
2657
|
+
];
|
|
1810
2658
|
export {
|
|
1811
2659
|
ANSWER_RELATIONS,
|
|
1812
2660
|
ASKING_RELATIONS,
|
|
2661
|
+
BASE_CLASS_RULE,
|
|
1813
2662
|
FACT_CONTRACT_CASES,
|
|
2663
|
+
INSTANCE_STEP,
|
|
1814
2664
|
NAMESPACE_IMPORT,
|
|
1815
2665
|
NAMESPACE_IMPORT_NAME,
|
|
2666
|
+
NAMESPACE_MEMBER_RULE,
|
|
2667
|
+
NO_CONTEXT,
|
|
2668
|
+
NO_CONTEXT_NAME,
|
|
1816
2669
|
RESOLUTION_QUESTIONS,
|
|
1817
2670
|
RESOLUTION_RULES,
|
|
1818
2671
|
RESULT_STEP,
|
|
2672
|
+
UNDER_ANSWER_RELATIONS,
|
|
1819
2673
|
VALUE_STEP,
|
|
2674
|
+
addPackWords,
|
|
1820
2675
|
agreedMountPrefix,
|
|
2676
|
+
allocationSitesOf,
|
|
2677
|
+
alsoSteps,
|
|
2678
|
+
answersByKey,
|
|
1821
2679
|
askResolution,
|
|
2680
|
+
askResolutionUnder,
|
|
1822
2681
|
calleeOutcomeOf,
|
|
1823
2682
|
calleeOutcomes,
|
|
1824
2683
|
checkFactContract,
|
|
2684
|
+
comesToUnder,
|
|
1825
2685
|
couldBeSettled,
|
|
1826
2686
|
explainResolutionProof,
|
|
1827
2687
|
explainResolvedKey,
|
|
2688
|
+
isWrittenAsUnder,
|
|
1828
2689
|
joinMountedPath,
|
|
1829
2690
|
mountPathsOf,
|
|
1830
2691
|
nodeOfKey,
|
|
2692
|
+
objectOfUnder,
|
|
1831
2693
|
placeholderValues,
|
|
1832
2694
|
queryFacts,
|
|
1833
2695
|
renderExplanation,
|
|
1834
2696
|
resolutionProgram,
|
|
2697
|
+
resolutionUnderProgram,
|
|
1835
2698
|
singleAnswers,
|
|
1836
2699
|
startsAtName,
|
|
1837
2700
|
valueLeftByWrites,
|
|
1838
2701
|
writesRunInOrder,
|
|
1839
2702
|
writtenSourcesOf,
|
|
1840
|
-
writtenValueOf
|
|
2703
|
+
writtenValueOf,
|
|
2704
|
+
writtenValueUnder,
|
|
2705
|
+
writtenValuesByKey,
|
|
2706
|
+
writtenValuesOf
|
|
1841
2707
|
};
|