@suss/resolution 0.30.0 → 0.31.1
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 +997 -70
- package/dist/index.d.cts +216 -21
- package/dist/index.d.ts +216 -21
- package/dist/index.js +985 -70
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -22,34 +22,55 @@ var index_exports = {};
|
|
|
22
22
|
__export(index_exports, {
|
|
23
23
|
ANSWER_RELATIONS: () => ANSWER_RELATIONS,
|
|
24
24
|
ASKING_RELATIONS: () => ASKING_RELATIONS,
|
|
25
|
+
BASE_CLASS_RULE: () => BASE_CLASS_RULE,
|
|
25
26
|
FACT_CONTRACT_CASES: () => FACT_CONTRACT_CASES,
|
|
27
|
+
INSTANCE_STEP: () => INSTANCE_STEP,
|
|
26
28
|
NAMESPACE_IMPORT: () => NAMESPACE_IMPORT,
|
|
27
29
|
NAMESPACE_IMPORT_NAME: () => NAMESPACE_IMPORT_NAME,
|
|
30
|
+
NAMESPACE_MEMBER_RULE: () => NAMESPACE_MEMBER_RULE,
|
|
31
|
+
NO_CONTEXT: () => NO_CONTEXT,
|
|
32
|
+
NO_CONTEXT_NAME: () => NO_CONTEXT_NAME,
|
|
28
33
|
RESOLUTION_QUESTIONS: () => RESOLUTION_QUESTIONS,
|
|
29
34
|
RESOLUTION_RULES: () => RESOLUTION_RULES,
|
|
30
35
|
RESULT_STEP: () => RESULT_STEP,
|
|
36
|
+
UNDER_ANSWER_RELATIONS: () => UNDER_ANSWER_RELATIONS,
|
|
37
|
+
UNDER_QUESTION_ROW_BUDGET: () => UNDER_QUESTION_ROW_BUDGET,
|
|
38
|
+
UNDER_RUN_ROW_BUDGET: () => UNDER_RUN_ROW_BUDGET,
|
|
31
39
|
VALUE_STEP: () => VALUE_STEP,
|
|
40
|
+
addPackWords: () => addPackWords,
|
|
32
41
|
agreedMountPrefix: () => agreedMountPrefix,
|
|
42
|
+
allocationSitesOf: () => allocationSitesOf,
|
|
43
|
+
alsoSteps: () => alsoSteps,
|
|
44
|
+
answersByKey: () => answersByKey,
|
|
33
45
|
askResolution: () => askResolution,
|
|
46
|
+
askResolutionUnder: () => askResolutionUnder,
|
|
34
47
|
calleeOutcomeOf: () => calleeOutcomeOf,
|
|
35
48
|
calleeOutcomes: () => calleeOutcomes,
|
|
36
49
|
checkFactContract: () => checkFactContract,
|
|
50
|
+
comesToUnder: () => comesToUnder,
|
|
37
51
|
couldBeSettled: () => couldBeSettled,
|
|
38
52
|
explainResolutionProof: () => explainResolutionProof,
|
|
39
53
|
explainResolvedKey: () => explainResolvedKey,
|
|
54
|
+
isWrittenAsUnder: () => isWrittenAsUnder,
|
|
40
55
|
joinMountedPath: () => joinMountedPath,
|
|
41
56
|
mountPathsOf: () => mountPathsOf,
|
|
42
57
|
nodeOfKey: () => nodeOfKey,
|
|
58
|
+
objectOfUnder: () => objectOfUnder,
|
|
43
59
|
placeholderValues: () => placeholderValues,
|
|
44
60
|
queryFacts: () => queryFacts,
|
|
45
61
|
renderExplanation: () => renderExplanation,
|
|
46
62
|
resolutionProgram: () => resolutionProgram,
|
|
63
|
+
resolutionUnderProgram: () => resolutionUnderProgram,
|
|
47
64
|
singleAnswers: () => singleAnswers,
|
|
48
65
|
startsAtName: () => startsAtName,
|
|
66
|
+
underQuestionSpend: () => underQuestionSpend,
|
|
49
67
|
valueLeftByWrites: () => valueLeftByWrites,
|
|
50
68
|
writesRunInOrder: () => writesRunInOrder,
|
|
51
69
|
writtenSourcesOf: () => writtenSourcesOf,
|
|
52
|
-
writtenValueOf: () => writtenValueOf
|
|
70
|
+
writtenValueOf: () => writtenValueOf,
|
|
71
|
+
writtenValueUnder: () => writtenValueUnder,
|
|
72
|
+
writtenValuesByKey: () => writtenValuesByKey,
|
|
73
|
+
writtenValuesOf: () => writtenValuesOf
|
|
53
74
|
});
|
|
54
75
|
module.exports = __toCommonJS(index_exports);
|
|
55
76
|
|
|
@@ -57,6 +78,8 @@ module.exports = __toCommonJS(index_exports);
|
|
|
57
78
|
var import_datalog = require("@suss/datalog");
|
|
58
79
|
var ASKING_RELATIONS = [
|
|
59
80
|
"wanted",
|
|
81
|
+
"wantedUnder",
|
|
82
|
+
"wantedSites",
|
|
60
83
|
"wantedOrigin",
|
|
61
84
|
"wantedCallOrigin",
|
|
62
85
|
"wantedExportsOf",
|
|
@@ -66,8 +89,12 @@ var ASKING_RELATIONS = [
|
|
|
66
89
|
];
|
|
67
90
|
var NO_LANGUAGE_RULES = [];
|
|
68
91
|
var programs = /* @__PURE__ */ new WeakMap();
|
|
69
|
-
|
|
70
|
-
|
|
92
|
+
var underPrograms = /* @__PURE__ */ new WeakMap();
|
|
93
|
+
var contextFreeAnswers = () => ANSWER_RELATIONS.filter(
|
|
94
|
+
(relation) => !UNDER_ANSWER_RELATIONS.includes(relation)
|
|
95
|
+
);
|
|
96
|
+
function builtProgram(languageRules, cache, complete) {
|
|
97
|
+
const built = cache.get(languageRules);
|
|
71
98
|
if (built !== void 0) {
|
|
72
99
|
return built;
|
|
73
100
|
}
|
|
@@ -76,10 +103,16 @@ function resolutionProgram(languageRules = NO_LANGUAGE_RULES) {
|
|
|
76
103
|
...languageRules,
|
|
77
104
|
...RESOLUTION_QUESTIONS
|
|
78
105
|
];
|
|
79
|
-
const program = process.env.SUSS_RESOLUTION_ON_DEMAND === "0" ? { rules, demandDriven: [], demands: [] } : (0, import_datalog.deriveOnDemand)(rules,
|
|
80
|
-
|
|
106
|
+
const program = process.env.SUSS_RESOLUTION_ON_DEMAND === "0" ? { rules, demandDriven: [], demands: [] } : (0, import_datalog.deriveOnDemand)(rules, complete);
|
|
107
|
+
cache.set(languageRules, program);
|
|
81
108
|
return program;
|
|
82
109
|
}
|
|
110
|
+
function resolutionProgram(languageRules = NO_LANGUAGE_RULES) {
|
|
111
|
+
return builtProgram(languageRules, programs, contextFreeAnswers());
|
|
112
|
+
}
|
|
113
|
+
function resolutionUnderProgram(languageRules = NO_LANGUAGE_RULES) {
|
|
114
|
+
return builtProgram(languageRules, underPrograms, ANSWER_RELATIONS);
|
|
115
|
+
}
|
|
83
116
|
function queryFacts(program) {
|
|
84
117
|
if (program.demandDriven.length === 0) {
|
|
85
118
|
return [];
|
|
@@ -116,6 +149,75 @@ function askResolution(db, keys, asking = "wanted", program = resolutionProgram(
|
|
|
116
149
|
(0, import_datalog.clearRelations)(db, program.rules, forget);
|
|
117
150
|
}
|
|
118
151
|
}
|
|
152
|
+
var askedUnderByDb = /* @__PURE__ */ new WeakMap();
|
|
153
|
+
var UNDER_QUESTION_ROW_BUDGET = 2e7;
|
|
154
|
+
var UNDER_RUN_ROW_BUDGET = 4e7;
|
|
155
|
+
var spentUnderByDb = /* @__PURE__ */ new WeakMap();
|
|
156
|
+
function spendOf(db) {
|
|
157
|
+
let spend = spentUnderByDb.get(db);
|
|
158
|
+
if (spend === void 0) {
|
|
159
|
+
spend = { rows: 0, asked: 0, abandoned: 0, skipped: 0 };
|
|
160
|
+
spentUnderByDb.set(db, spend);
|
|
161
|
+
}
|
|
162
|
+
return spend;
|
|
163
|
+
}
|
|
164
|
+
function underQuestionSpend(db) {
|
|
165
|
+
return { ...spendOf(db) };
|
|
166
|
+
}
|
|
167
|
+
function askResolutionUnder(db, pairs, program = resolutionUnderProgram(), questionBudget = UNDER_QUESTION_ROW_BUDGET, runBudget = UNDER_RUN_ROW_BUDGET) {
|
|
168
|
+
let asked = askedUnderByDb.get(db);
|
|
169
|
+
if (asked === void 0) {
|
|
170
|
+
asked = /* @__PURE__ */ new Set();
|
|
171
|
+
askedUnderByDb.set(db, asked);
|
|
172
|
+
}
|
|
173
|
+
const fresh = [...pairs].filter(
|
|
174
|
+
([key, site]) => !asked.has((0, import_datalog.tupleKey)([key, site]))
|
|
175
|
+
);
|
|
176
|
+
if (fresh.length === 0) {
|
|
177
|
+
return "answered";
|
|
178
|
+
}
|
|
179
|
+
const spend = spendOf(db);
|
|
180
|
+
for (const [key, site] of fresh) {
|
|
181
|
+
asked.add((0, import_datalog.tupleKey)([key, site]));
|
|
182
|
+
}
|
|
183
|
+
spend.asked += 1;
|
|
184
|
+
if (spend.rows >= runBudget) {
|
|
185
|
+
spend.skipped += 1;
|
|
186
|
+
(0, import_datalog.chargeQuestion)("skipped");
|
|
187
|
+
return "abandoned";
|
|
188
|
+
}
|
|
189
|
+
for (const [key, site] of fresh) {
|
|
190
|
+
db.add("wantedUnder", [key, site]);
|
|
191
|
+
}
|
|
192
|
+
const forget = queryFacts(program);
|
|
193
|
+
const clearDerived = () => {
|
|
194
|
+
if (forget.length > 0) {
|
|
195
|
+
(0, import_datalog.clearRelations)(db, program.rules, forget);
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
const budget = (0, import_datalog.rowBudget)(questionBudget);
|
|
199
|
+
try {
|
|
200
|
+
(0, import_datalog.evaluate)(db, program.rules, void 0, budget);
|
|
201
|
+
} catch (error) {
|
|
202
|
+
if (!(error instanceof import_datalog.BudgetExhausted)) {
|
|
203
|
+
throw error;
|
|
204
|
+
}
|
|
205
|
+
spend.rows += error.examined;
|
|
206
|
+
spend.abandoned += 1;
|
|
207
|
+
(0, import_datalog.chargeQuestion)("abandoned");
|
|
208
|
+
db.retract("wantedUnder", fresh);
|
|
209
|
+
clearDerived();
|
|
210
|
+
(0, import_datalog.chargeAbandoned)(
|
|
211
|
+
fresh.map(([key, site]) => `${key} under ${site}`).join(", "),
|
|
212
|
+
error.examined
|
|
213
|
+
);
|
|
214
|
+
return "abandoned";
|
|
215
|
+
}
|
|
216
|
+
spend.rows += budget.examined;
|
|
217
|
+
(0, import_datalog.chargeQuestion)();
|
|
218
|
+
clearDerived();
|
|
219
|
+
return "answered";
|
|
220
|
+
}
|
|
119
221
|
|
|
120
222
|
// src/callee.ts
|
|
121
223
|
var UNDECLARED = { kind: "undeclared" };
|
|
@@ -544,6 +646,12 @@ var DEFAULT_PHRASES = {
|
|
|
544
646
|
"last write": ({ tuple, describe }) => ({
|
|
545
647
|
reason: `${describe(tuple[0])} is written more than once, and the last write leaves it as ${describe(tuple[1])}`
|
|
546
648
|
}),
|
|
649
|
+
"one of several writes": ({ tuple, describe }) => ({
|
|
650
|
+
reason: `${describe(tuple[0])} is written more than once, and one of those writes makes it ${describe(tuple[1])}`,
|
|
651
|
+
assumptions: [
|
|
652
|
+
`nothing says which write to ${describe(tuple[0])} ran last, so every write it has is a possible value`
|
|
653
|
+
]
|
|
654
|
+
}),
|
|
547
655
|
fallback: ({ tuple, describe }) => ({
|
|
548
656
|
reason: `${describe(tuple[0])} is a fallback expression, and ${describe(tuple[1])} is the branch that resolves`
|
|
549
657
|
}),
|
|
@@ -560,7 +668,7 @@ var DEFAULT_PHRASES = {
|
|
|
560
668
|
"property read": ({ tuple, premises, describe }) => {
|
|
561
669
|
const [, object, name] = premises[0].tuple;
|
|
562
670
|
const contains = premises[2];
|
|
563
|
-
const inherited = contains.kind === "derived" && contains.
|
|
671
|
+
const inherited = contains.kind === "derived" && (0, import_datalog2.ruleLabel)(contains.rule) === BASE_CLASS_RULE;
|
|
564
672
|
return {
|
|
565
673
|
reason: `${describe(tuple[0])} reads ${String(name)} off ${describe(object)}, which contains ${describe(tuple[1])}`,
|
|
566
674
|
notes: inherited ? [`${String(name)} comes from a base class`] : []
|
|
@@ -639,7 +747,8 @@ var CHAIN_RELATIONS = /* @__PURE__ */ new Set([
|
|
|
639
747
|
"isWrittenAs",
|
|
640
748
|
"comesFrom",
|
|
641
749
|
"reaches",
|
|
642
|
-
"stepsTo"
|
|
750
|
+
"stepsTo",
|
|
751
|
+
"hop"
|
|
643
752
|
]);
|
|
644
753
|
function inlineChain(proof, state) {
|
|
645
754
|
const explained = explainResolutionProof(proof, {
|
|
@@ -695,6 +804,17 @@ function importStep(proof, state) {
|
|
|
695
804
|
assumptions: []
|
|
696
805
|
};
|
|
697
806
|
}
|
|
807
|
+
function namespaceMemberStep(proof, state) {
|
|
808
|
+
const [x, module2, name] = proof.tuple;
|
|
809
|
+
return {
|
|
810
|
+
from: x,
|
|
811
|
+
to: module2,
|
|
812
|
+
rule: NAMESPACE_MEMBER_RULE,
|
|
813
|
+
reason: `${state.describe(x)} reads ${String(name)} off ${state.describe(module2)}, which is imported whole`,
|
|
814
|
+
notes: [],
|
|
815
|
+
assumptions: []
|
|
816
|
+
};
|
|
817
|
+
}
|
|
698
818
|
var flattenInto = (proof, state) => {
|
|
699
819
|
if (proof.kind === "truncated") {
|
|
700
820
|
state.truncated = true;
|
|
@@ -704,7 +824,7 @@ var flattenInto = (proof, state) => {
|
|
|
704
824
|
return;
|
|
705
825
|
}
|
|
706
826
|
const relation = proof.relation;
|
|
707
|
-
if (relation === "stepsTo") {
|
|
827
|
+
if (relation === "stepsTo" || relation === "hop") {
|
|
708
828
|
state.steps.push(stepFrom(proof, state));
|
|
709
829
|
return;
|
|
710
830
|
}
|
|
@@ -715,6 +835,10 @@ var flattenInto = (proof, state) => {
|
|
|
715
835
|
return;
|
|
716
836
|
}
|
|
717
837
|
if (relation === "comesFrom") {
|
|
838
|
+
if ((0, import_datalog2.ruleLabel)(proof.rule) === NAMESPACE_MEMBER_RULE) {
|
|
839
|
+
state.steps.push(namespaceMemberStep(proof, state));
|
|
840
|
+
return;
|
|
841
|
+
}
|
|
718
842
|
if (proof.premises.length === 2) {
|
|
719
843
|
flattenInto(proof.premises[0], state);
|
|
720
844
|
state.steps.push(importStep(proof.premises[1], state));
|
|
@@ -891,6 +1015,37 @@ function nodeOfKey(rootsByFile, key) {
|
|
|
891
1015
|
return null;
|
|
892
1016
|
}
|
|
893
1017
|
|
|
1018
|
+
// src/packWords.ts
|
|
1019
|
+
function addPackWords(db, words) {
|
|
1020
|
+
for (const word of words.givesBackOne ?? []) {
|
|
1021
|
+
db.add("givesBackOne", [word.base, word.method]);
|
|
1022
|
+
}
|
|
1023
|
+
for (const word of words.givesBackOneOfArgument ?? []) {
|
|
1024
|
+
db.add("givesBackOneOfArgument", [
|
|
1025
|
+
word.base,
|
|
1026
|
+
word.method,
|
|
1027
|
+
String(word.argument)
|
|
1028
|
+
]);
|
|
1029
|
+
}
|
|
1030
|
+
for (const word of words.givesBackOneOfImport ?? []) {
|
|
1031
|
+
db.add("givesBackOneOfImport", [
|
|
1032
|
+
word.module,
|
|
1033
|
+
word.name,
|
|
1034
|
+
String(word.argument)
|
|
1035
|
+
]);
|
|
1036
|
+
}
|
|
1037
|
+
for (const word of words.entersAsSelf ?? []) {
|
|
1038
|
+
db.add("entersAsSelf", [word.module, word.name]);
|
|
1039
|
+
}
|
|
1040
|
+
for (const word of words.unwrapsByName ?? []) {
|
|
1041
|
+
db.add("unwrapsByName", [word.callee, String(word.argument)]);
|
|
1042
|
+
db.add("wrapperModule", [word.callee, word.module]);
|
|
1043
|
+
}
|
|
1044
|
+
for (const word of words.associationConstructor ?? []) {
|
|
1045
|
+
db.add("associationConstructor", [word.module, word.name]);
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
|
|
894
1049
|
// src/session.ts
|
|
895
1050
|
var import_datalog3 = require("@suss/datalog");
|
|
896
1051
|
function explainResolvedKey(options) {
|
|
@@ -946,7 +1101,7 @@ function explainResolvedKey(options) {
|
|
|
946
1101
|
|
|
947
1102
|
// src/singleAnswer.ts
|
|
948
1103
|
var NO_PLACEHOLDERS = /* @__PURE__ */ new Set();
|
|
949
|
-
function
|
|
1104
|
+
function answersByKey(rows, placeholders = NO_PLACEHOLDERS) {
|
|
950
1105
|
const candidates = /* @__PURE__ */ new Map();
|
|
951
1106
|
for (const row of rows) {
|
|
952
1107
|
const key = String(row[0]);
|
|
@@ -958,9 +1113,15 @@ function singleAnswers(rows, placeholders = NO_PLACEHOLDERS) {
|
|
|
958
1113
|
set.add(answer);
|
|
959
1114
|
candidates.set(key, set);
|
|
960
1115
|
}
|
|
961
|
-
const
|
|
1116
|
+
const answers = /* @__PURE__ */ new Map();
|
|
962
1117
|
for (const [key, set] of candidates) {
|
|
963
|
-
|
|
1118
|
+
answers.set(key, withoutPlaceholders(set, placeholders));
|
|
1119
|
+
}
|
|
1120
|
+
return answers;
|
|
1121
|
+
}
|
|
1122
|
+
function singleAnswers(rows, placeholders = NO_PLACEHOLDERS) {
|
|
1123
|
+
const settled = /* @__PURE__ */ new Map();
|
|
1124
|
+
for (const [key, answers] of answersByKey(rows, placeholders)) {
|
|
964
1125
|
if (answers.length === 1) {
|
|
965
1126
|
settled.set(key, answers[0]);
|
|
966
1127
|
}
|
|
@@ -978,6 +1139,28 @@ function withoutPlaceholders(answers, placeholders) {
|
|
|
978
1139
|
return kept;
|
|
979
1140
|
}
|
|
980
1141
|
|
|
1142
|
+
// src/underContext.ts
|
|
1143
|
+
function answersUnder(db, relation, key, site) {
|
|
1144
|
+
return db.lookup(relation, 0, key).filter((row) => String(row[1]) === site).map((row) => String(row[2]));
|
|
1145
|
+
}
|
|
1146
|
+
function isWrittenAsUnder(db, key, site) {
|
|
1147
|
+
return answersUnder(db, "wantedIsWrittenAsUnder", key, site);
|
|
1148
|
+
}
|
|
1149
|
+
function comesToUnder(db, key, site) {
|
|
1150
|
+
return answersUnder(db, "wantedComesToUnder", key, site);
|
|
1151
|
+
}
|
|
1152
|
+
function objectOfUnder(db, key, site) {
|
|
1153
|
+
return answersUnder(db, "wantedObjectOfUnder", key, site);
|
|
1154
|
+
}
|
|
1155
|
+
function writtenValueUnder(db, key, site) {
|
|
1156
|
+
const rows = isWrittenAsUnder(db, key, site).map((answer) => [key, answer]);
|
|
1157
|
+
const answers = answersByKey(rows, placeholderValues(db)).get(key) ?? [];
|
|
1158
|
+
return answers.length === 1 ? answers[0] : null;
|
|
1159
|
+
}
|
|
1160
|
+
function allocationSitesOf(db, cls) {
|
|
1161
|
+
return db.lookup("wantedAllocatedAt", 0, cls).map((row) => String(row[1]));
|
|
1162
|
+
}
|
|
1163
|
+
|
|
981
1164
|
// src/writes.ts
|
|
982
1165
|
function valueLeftByWrites(writes, ordered) {
|
|
983
1166
|
const deciding = writes.filter((write) => !write.narrowsName);
|
|
@@ -1008,23 +1191,58 @@ function sharedConstruction(writes) {
|
|
|
1008
1191
|
}
|
|
1009
1192
|
|
|
1010
1193
|
// src/writtenValue.ts
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
const
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1194
|
+
var WRITTEN_AS = "wantedIsWrittenAs";
|
|
1195
|
+
function writtenValueOf(db, key, ask, relation = WRITTEN_AS) {
|
|
1196
|
+
const answers = settledByKey(db, [key], ask, relation).get(key) ?? [];
|
|
1197
|
+
return answers.length === 1 ? answers[0] : null;
|
|
1198
|
+
}
|
|
1199
|
+
function writtenValuesOf(db, key, ask, relation = WRITTEN_AS) {
|
|
1200
|
+
const settled = settledByKey(db, [key], ask, relation).get(key) ?? [];
|
|
1201
|
+
return settled.length > 0 ? settled : writesLeft(db, key);
|
|
1202
|
+
}
|
|
1203
|
+
function writtenValuesByKey(db, keys, ask, relation = WRITTEN_AS) {
|
|
1204
|
+
const one = /* @__PURE__ */ new Map();
|
|
1205
|
+
for (const [key, answers] of settledByKey(db, keys, ask, relation)) {
|
|
1206
|
+
if (answers.length === 1) {
|
|
1207
|
+
one.set(key, answers[0]);
|
|
1208
|
+
}
|
|
1018
1209
|
}
|
|
1019
|
-
|
|
1020
|
-
|
|
1210
|
+
return one;
|
|
1211
|
+
}
|
|
1212
|
+
function settledByKey(db, keys, ask, relation) {
|
|
1213
|
+
const placeholders = placeholderValues(db);
|
|
1214
|
+
const byKey = answersByKey(db.facts(relation), placeholders);
|
|
1215
|
+
const direct = new Map(keys.map((key) => [key, byKey.get(key) ?? []]));
|
|
1216
|
+
const calls = new Set(db.facts("call").map((row) => String(row[0])));
|
|
1217
|
+
const throughCalls = [...direct.values()].flat().filter((answer) => calls.has(answer));
|
|
1218
|
+
if (throughCalls.length === 0) {
|
|
1021
1219
|
return direct;
|
|
1022
1220
|
}
|
|
1023
|
-
ask(
|
|
1024
|
-
const deeper = singleAnswers(db.facts(
|
|
1025
|
-
|
|
1221
|
+
ask(throughCalls);
|
|
1222
|
+
const deeper = singleAnswers(db.facts(relation), placeholders);
|
|
1223
|
+
return new Map(
|
|
1224
|
+
[...direct].map(([key, answers]) => [
|
|
1225
|
+
key,
|
|
1226
|
+
collapseCalls(answers, calls, deeper)
|
|
1227
|
+
])
|
|
1026
1228
|
);
|
|
1027
|
-
|
|
1229
|
+
}
|
|
1230
|
+
function collapseCalls(direct, calls, deeper) {
|
|
1231
|
+
return [
|
|
1232
|
+
...new Set(
|
|
1233
|
+
direct.map(
|
|
1234
|
+
(answer) => calls.has(answer) ? deeper.get(answer) ?? answer : answer
|
|
1235
|
+
)
|
|
1236
|
+
)
|
|
1237
|
+
];
|
|
1238
|
+
}
|
|
1239
|
+
function writesLeft(db, key) {
|
|
1240
|
+
const unstated = db.facts("writesUnstated").some((row) => String(row[0]) === key);
|
|
1241
|
+
if (unstated) {
|
|
1242
|
+
return [];
|
|
1243
|
+
}
|
|
1244
|
+
const candidates = answersByKey(db.facts("mayHold"), placeholderValues(db)).get(key) ?? [];
|
|
1245
|
+
return candidates.length > 1 ? candidates : [];
|
|
1028
1246
|
}
|
|
1029
1247
|
|
|
1030
1248
|
// src/index.ts
|
|
@@ -1032,38 +1250,61 @@ var import_datalog4 = require("@suss/datalog");
|
|
|
1032
1250
|
var VALUE_STEP = (0, import_datalog4.constant)("value");
|
|
1033
1251
|
var NAMESPACE_IMPORT_NAME = "*";
|
|
1034
1252
|
var NAMESPACE_IMPORT = (0, import_datalog4.constant)(NAMESPACE_IMPORT_NAME);
|
|
1253
|
+
var NAMESPACE_MEMBER_RULE = "namespace member";
|
|
1254
|
+
var BASE_CLASS_RULE = "base class";
|
|
1255
|
+
var INSTANCE_STEP = (0, import_datalog4.constant)("instance");
|
|
1035
1256
|
var RESULT_STEP = (0, import_datalog4.constant)("result");
|
|
1036
|
-
var
|
|
1257
|
+
var NO_CONTEXT_NAME = "none";
|
|
1258
|
+
var NO_CONTEXT = (0, import_datalog4.constant)(NO_CONTEXT_NAME);
|
|
1259
|
+
var STEP_LATTICE = [
|
|
1260
|
+
{ soFar: VALUE_STEP, next: (0, import_datalog4.variable)("kind"), took: (0, import_datalog4.variable)("kind") },
|
|
1261
|
+
{ soFar: INSTANCE_STEP, next: VALUE_STEP, took: INSTANCE_STEP },
|
|
1262
|
+
{ soFar: INSTANCE_STEP, next: INSTANCE_STEP, took: INSTANCE_STEP },
|
|
1263
|
+
{ soFar: INSTANCE_STEP, next: RESULT_STEP, took: RESULT_STEP },
|
|
1264
|
+
{ soFar: RESULT_STEP, next: VALUE_STEP, took: RESULT_STEP },
|
|
1265
|
+
{ soFar: RESULT_STEP, next: INSTANCE_STEP, took: RESULT_STEP },
|
|
1266
|
+
{ soFar: RESULT_STEP, next: RESULT_STEP, took: RESULT_STEP }
|
|
1267
|
+
];
|
|
1268
|
+
var STATED_RULES = [
|
|
1037
1269
|
// Aliasing: const x = y, or an identifier referencing a declaration.
|
|
1038
1270
|
// A language with a hop of its own, like JavaScript's `.bind`, states
|
|
1039
1271
|
// it as a step too, or every question but `comesTo` misses it.
|
|
1040
1272
|
(0, import_datalog4.rule)(
|
|
1041
|
-
"
|
|
1273
|
+
"hop",
|
|
1042
1274
|
[(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("y"), VALUE_STEP],
|
|
1043
1275
|
[(0, import_datalog4.lit)("binds", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("y"))],
|
|
1044
1276
|
"alias"
|
|
1045
1277
|
),
|
|
1046
1278
|
// A name written more than once has the value the last write left
|
|
1047
|
-
// there. The adapter works out which write that is and stays quiet
|
|
1048
|
-
// when control flow decides
|
|
1279
|
+
// there. The adapter works out which write that is, and stays quiet
|
|
1280
|
+
// when control flow decides; the rule below takes that name instead.
|
|
1049
1281
|
(0, import_datalog4.rule)(
|
|
1050
|
-
"
|
|
1282
|
+
"hop",
|
|
1051
1283
|
[(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("y"), VALUE_STEP],
|
|
1052
1284
|
[(0, import_datalog4.lit)("endsHolding", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("y"))],
|
|
1053
1285
|
"last write"
|
|
1054
1286
|
),
|
|
1287
|
+
// A name whose writes nothing orders leads to each of them, so a
|
|
1288
|
+
// caller that can use several values gets them all and one that needs
|
|
1289
|
+
// a single value gets none. A write stating no value stops every step.
|
|
1290
|
+
(0, import_datalog4.rule)(
|
|
1291
|
+
"hop",
|
|
1292
|
+
[(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("y"), VALUE_STEP],
|
|
1293
|
+
[(0, import_datalog4.lit)("mayHold", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("y")), (0, import_datalog4.lit)("writesAllStated", (0, import_datalog4.variable)("x"))],
|
|
1294
|
+
"one of several writes"
|
|
1295
|
+
),
|
|
1055
1296
|
// A fallback says the value is one of its branches, so each branch is
|
|
1056
1297
|
// a step. A branch that resolves to nothing makes no claim, and two
|
|
1057
1298
|
// branches resolving to different things fail the single-answer policy.
|
|
1058
1299
|
(0, import_datalog4.rule)(
|
|
1059
|
-
"
|
|
1300
|
+
"hop",
|
|
1060
1301
|
[(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("b"), VALUE_STEP],
|
|
1061
1302
|
[(0, import_datalog4.lit)("fallbackBranch", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("b"))],
|
|
1062
1303
|
"fallback"
|
|
1063
1304
|
),
|
|
1064
1305
|
// An import steps to what the module exports under that name.
|
|
1065
1306
|
(0, import_datalog4.rule)(
|
|
1066
|
-
"
|
|
1307
|
+
"hop",
|
|
1067
1308
|
[(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("value"), VALUE_STEP],
|
|
1068
1309
|
[
|
|
1069
1310
|
(0, import_datalog4.lit)("imports", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("m"), (0, import_datalog4.variable)("n")),
|
|
@@ -1097,8 +1338,8 @@ var RESOLUTION_RULES = [
|
|
|
1097
1338
|
// a method read off the result is the one the class declares. The
|
|
1098
1339
|
// caveat below is about a factory function, and a class is not one.
|
|
1099
1340
|
(0, import_datalog4.rule)(
|
|
1100
|
-
"
|
|
1101
|
-
[(0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("cls"),
|
|
1341
|
+
"hop",
|
|
1342
|
+
[(0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("cls"), INSTANCE_STEP],
|
|
1102
1343
|
[
|
|
1103
1344
|
(0, import_datalog4.lit)("call", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("c")),
|
|
1104
1345
|
(0, import_datalog4.lit)("comesTo", (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("cls")),
|
|
@@ -1106,12 +1347,21 @@ var RESOLUTION_RULES = [
|
|
|
1106
1347
|
],
|
|
1107
1348
|
"class instance"
|
|
1108
1349
|
),
|
|
1350
|
+
// The receiver a method is called on. Being one of a class is the
|
|
1351
|
+
// same hop a construction takes, so a method read off `self` finds
|
|
1352
|
+
// what the class declares.
|
|
1353
|
+
(0, import_datalog4.rule)(
|
|
1354
|
+
"hop",
|
|
1355
|
+
[(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("cls"), INSTANCE_STEP],
|
|
1356
|
+
[(0, import_datalog4.lit)("instanceOf", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("cls"))],
|
|
1357
|
+
"receiver instance"
|
|
1358
|
+
),
|
|
1109
1359
|
// A finder the library declares, keyed on the base a pack named so a
|
|
1110
1360
|
// project class with a method of the same name on another hierarchy is
|
|
1111
1361
|
// left alone. The DESIGN says what a chain of them composes into.
|
|
1112
1362
|
(0, import_datalog4.rule)(
|
|
1113
|
-
"
|
|
1114
|
-
[(0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("cls"),
|
|
1363
|
+
"hop",
|
|
1364
|
+
[(0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("cls"), INSTANCE_STEP],
|
|
1115
1365
|
[
|
|
1116
1366
|
(0, import_datalog4.lit)("call", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("c")),
|
|
1117
1367
|
(0, import_datalog4.lit)("readsProperty", (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("o"), (0, import_datalog4.variable)("m")),
|
|
@@ -1128,8 +1378,8 @@ var RESOLUTION_RULES = [
|
|
|
1128
1378
|
// instead of as the receiver. The argument having to reach the base a
|
|
1129
1379
|
// pack named is what keeps an unrelated `get` out.
|
|
1130
1380
|
(0, import_datalog4.rule)(
|
|
1131
|
-
"
|
|
1132
|
-
[(0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("cls"),
|
|
1381
|
+
"hop",
|
|
1382
|
+
[(0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("cls"), INSTANCE_STEP],
|
|
1133
1383
|
[
|
|
1134
1384
|
(0, import_datalog4.lit)("call", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("c")),
|
|
1135
1385
|
(0, import_datalog4.lit)("readsProperty", (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("o"), (0, import_datalog4.variable)("m")),
|
|
@@ -1146,8 +1396,8 @@ var RESOLUTION_RULES = [
|
|
|
1146
1396
|
// anything, keyed on the module it was imported from so a project
|
|
1147
1397
|
// function spelled the same way is not mistaken for it.
|
|
1148
1398
|
(0, import_datalog4.rule)(
|
|
1149
|
-
"
|
|
1150
|
-
[(0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("cls"),
|
|
1399
|
+
"hop",
|
|
1400
|
+
[(0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("cls"), INSTANCE_STEP],
|
|
1151
1401
|
[
|
|
1152
1402
|
(0, import_datalog4.lit)("call", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("c")),
|
|
1153
1403
|
(0, import_datalog4.lit)("comesFrom", (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("mod"), (0, import_datalog4.variable)("n")),
|
|
@@ -1157,10 +1407,24 @@ var RESOLUTION_RULES = [
|
|
|
1157
1407
|
],
|
|
1158
1408
|
"declared import finder"
|
|
1159
1409
|
),
|
|
1410
|
+
// A block opened over a library's own constructor. The pack says
|
|
1411
|
+
// entering one gives back the object it built, so the name the block
|
|
1412
|
+
// opens is that call.
|
|
1413
|
+
(0, import_datalog4.rule)(
|
|
1414
|
+
"hop",
|
|
1415
|
+
[(0, import_datalog4.variable)("y"), (0, import_datalog4.variable)("r"), VALUE_STEP],
|
|
1416
|
+
[
|
|
1417
|
+
(0, import_datalog4.lit)("entersAs", (0, import_datalog4.variable)("y"), (0, import_datalog4.variable)("r")),
|
|
1418
|
+
(0, import_datalog4.lit)("call", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("c")),
|
|
1419
|
+
(0, import_datalog4.lit)("comesFrom", (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("mod"), (0, import_datalog4.variable)("n")),
|
|
1420
|
+
(0, import_datalog4.lit)("entersAsSelf", (0, import_datalog4.variable)("mod"), (0, import_datalog4.variable)("n"))
|
|
1421
|
+
],
|
|
1422
|
+
"context manager returns self"
|
|
1423
|
+
),
|
|
1160
1424
|
// Wrapper transparency, derived: calling a factory that returns a
|
|
1161
1425
|
// function which calls its parameter k steps to argument k.
|
|
1162
1426
|
(0, import_datalog4.rule)(
|
|
1163
|
-
"
|
|
1427
|
+
"hop",
|
|
1164
1428
|
[(0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("a"), VALUE_STEP],
|
|
1165
1429
|
[
|
|
1166
1430
|
(0, import_datalog4.lit)("call", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("c")),
|
|
@@ -1174,7 +1438,7 @@ var RESOLUTION_RULES = [
|
|
|
1174
1438
|
// argument k. The callee has to come from the library the pack said,
|
|
1175
1439
|
// so a local object spelled the same way is not mistaken for it.
|
|
1176
1440
|
(0, import_datalog4.rule)(
|
|
1177
|
-
"
|
|
1441
|
+
"hop",
|
|
1178
1442
|
[(0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("a"), VALUE_STEP],
|
|
1179
1443
|
[
|
|
1180
1444
|
(0, import_datalog4.lit)("calleeName", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("n")),
|
|
@@ -1188,44 +1452,441 @@ var RESOLUTION_RULES = [
|
|
|
1188
1452
|
// The one step that runs a function forwards: a call steps to what
|
|
1189
1453
|
// the function it invokes returns.
|
|
1190
1454
|
(0, import_datalog4.rule)(
|
|
1191
|
-
"
|
|
1455
|
+
"hop",
|
|
1192
1456
|
[(0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("ret"), RESULT_STEP],
|
|
1193
1457
|
[(0, import_datalog4.lit)("invokes", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("f")), (0, import_datalog4.lit)("returnsValue", (0, import_datalog4.variable)("f"), (0, import_datalog4.variable)("ret"))],
|
|
1194
1458
|
"call result"
|
|
1195
1459
|
),
|
|
1196
|
-
//
|
|
1197
|
-
//
|
|
1198
|
-
//
|
|
1460
|
+
// What a function says it gives back when its body never states a
|
|
1461
|
+
// value. The adapter stays quiet about the annotation whenever the
|
|
1462
|
+
// body does state one, so the two never answer the same question.
|
|
1463
|
+
(0, import_datalog4.rule)(
|
|
1464
|
+
"hop",
|
|
1465
|
+
[(0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("cls"), RESULT_STEP],
|
|
1466
|
+
[
|
|
1467
|
+
(0, import_datalog4.lit)("invokes", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("f")),
|
|
1468
|
+
(0, import_datalog4.lit)("returnsClass", (0, import_datalog4.variable)("f"), (0, import_datalog4.variable)("x")),
|
|
1469
|
+
(0, import_datalog4.lit)("comesTo", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("cls")),
|
|
1470
|
+
(0, import_datalog4.lit)("objectValue", (0, import_datalog4.variable)("cls"))
|
|
1471
|
+
],
|
|
1472
|
+
"declared return type"
|
|
1473
|
+
),
|
|
1474
|
+
// Where a walk gets to, under the strongest step it took: value, then
|
|
1475
|
+
// instance, then result. The walk so far comes first, so demand stays
|
|
1476
|
+
// on the value asked about; the README says what the other order cost.
|
|
1199
1477
|
(0, import_datalog4.rule)(
|
|
1200
1478
|
"reaches",
|
|
1201
1479
|
[(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("z"), (0, import_datalog4.variable)("kind")],
|
|
1202
1480
|
[(0, import_datalog4.lit)("stepsTo", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("z"), (0, import_datalog4.variable)("kind"))]
|
|
1203
1481
|
),
|
|
1482
|
+
// A rule per pair rather than one leaving the next step's kind free. A
|
|
1483
|
+
// free kind is a second question about the same relation, and a
|
|
1484
|
+
// demand-driven run then derives both to answer either.
|
|
1485
|
+
...STEP_LATTICE.map(
|
|
1486
|
+
({ soFar, next, took }) => (0, import_datalog4.rule)(
|
|
1487
|
+
"reaches",
|
|
1488
|
+
[(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("z"), took],
|
|
1489
|
+
[
|
|
1490
|
+
(0, import_datalog4.lit)("reaches", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("y"), soFar),
|
|
1491
|
+
(0, import_datalog4.lit)("stepsTo", (0, import_datalog4.variable)("y"), (0, import_datalog4.variable)("z"), next)
|
|
1492
|
+
]
|
|
1493
|
+
)
|
|
1494
|
+
),
|
|
1495
|
+
// A context is an allocation site, or nothing at all for a value read
|
|
1496
|
+
// outside every site. Both are stated, so a rule that starts a walk
|
|
1497
|
+
// binds its context from a premise rather than from a negation.
|
|
1498
|
+
(0, import_datalog4.rule)("context", [NO_CONTEXT], [], "no context"),
|
|
1499
|
+
(0, import_datalog4.rule)(
|
|
1500
|
+
"context",
|
|
1501
|
+
[(0, import_datalog4.variable)("site")],
|
|
1502
|
+
[(0, import_datalog4.lit)("allocates", (0, import_datalog4.variable)("site"), (0, import_datalog4.variable)("cls"))],
|
|
1503
|
+
"site context"
|
|
1504
|
+
),
|
|
1505
|
+
// The same closure, with the context the walk started under and the
|
|
1506
|
+
// context it arrived under. It takes `hop`, because an argument and a
|
|
1507
|
+
// property read have their own rules below.
|
|
1508
|
+
(0, import_datalog4.rule)(
|
|
1509
|
+
"reachesUnder",
|
|
1510
|
+
[(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("z"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("kind")],
|
|
1511
|
+
[(0, import_datalog4.lit)("context", (0, import_datalog4.variable)("c")), (0, import_datalog4.lit)("hop", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("z"), (0, import_datalog4.variable)("kind"))],
|
|
1512
|
+
"under one hop"
|
|
1513
|
+
),
|
|
1514
|
+
...STEP_LATTICE.map(
|
|
1515
|
+
({ soFar, next, took }) => (0, import_datalog4.rule)(
|
|
1516
|
+
"reachesUnder",
|
|
1517
|
+
[(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("z"), (0, import_datalog4.variable)("c2"), took],
|
|
1518
|
+
[
|
|
1519
|
+
(0, import_datalog4.lit)("reachesUnder", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("y"), (0, import_datalog4.variable)("c2"), soFar),
|
|
1520
|
+
(0, import_datalog4.lit)("hop", (0, import_datalog4.variable)("y"), (0, import_datalog4.variable)("z"), next)
|
|
1521
|
+
]
|
|
1522
|
+
)
|
|
1523
|
+
),
|
|
1524
|
+
// The receiver read under a site is that site. The ordinary hop from a
|
|
1525
|
+
// receiver to its class stays in `hop`, so `self` under any context
|
|
1526
|
+
// still comes to the class a single-answer reader wants.
|
|
1204
1527
|
(0, import_datalog4.rule)(
|
|
1205
|
-
"
|
|
1206
|
-
[(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("
|
|
1528
|
+
"reachesUnder",
|
|
1529
|
+
[(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("c"), VALUE_STEP],
|
|
1530
|
+
[(0, import_datalog4.lit)("instanceOf", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("cls")), (0, import_datalog4.lit)("allocates", (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("cls"))],
|
|
1531
|
+
"receiver is the site"
|
|
1532
|
+
),
|
|
1533
|
+
(0, import_datalog4.rule)(
|
|
1534
|
+
"reachesUnder",
|
|
1535
|
+
[(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("c2"), (0, import_datalog4.variable)("c2"), (0, import_datalog4.variable)("kind")],
|
|
1207
1536
|
[
|
|
1208
|
-
(0, import_datalog4.lit)("
|
|
1209
|
-
(0, import_datalog4.lit)("
|
|
1537
|
+
(0, import_datalog4.lit)("reachesUnder", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("y"), (0, import_datalog4.variable)("c2"), (0, import_datalog4.variable)("kind")),
|
|
1538
|
+
(0, import_datalog4.lit)("instanceOf", (0, import_datalog4.variable)("y"), (0, import_datalog4.variable)("cls")),
|
|
1539
|
+
(0, import_datalog4.lit)("allocates", (0, import_datalog4.variable)("c2"), (0, import_datalog4.variable)("cls"))
|
|
1540
|
+
],
|
|
1541
|
+
"reached receiver is the site"
|
|
1542
|
+
),
|
|
1543
|
+
// The object an expression refers to under a context. A site is an
|
|
1544
|
+
// answer here, unlike `objectOf`, and the class an instance is one of
|
|
1545
|
+
// is an answer only under no context.
|
|
1546
|
+
(0, import_datalog4.rule)(
|
|
1547
|
+
"objectOfUnder",
|
|
1548
|
+
[(0, import_datalog4.variable)("site"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("site")],
|
|
1549
|
+
[(0, import_datalog4.lit)("context", (0, import_datalog4.variable)("c")), (0, import_datalog4.lit)("allocates", (0, import_datalog4.variable)("site"), (0, import_datalog4.variable)("cls"))],
|
|
1550
|
+
"site is its own object"
|
|
1551
|
+
),
|
|
1552
|
+
(0, import_datalog4.rule)(
|
|
1553
|
+
"objectOfUnder",
|
|
1554
|
+
[(0, import_datalog4.variable)("o"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("site")],
|
|
1555
|
+
[
|
|
1556
|
+
(0, import_datalog4.lit)("reachesUnder", (0, import_datalog4.variable)("o"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("site"), (0, import_datalog4.variable)("c2"), VALUE_STEP),
|
|
1557
|
+
(0, import_datalog4.lit)("allocates", (0, import_datalog4.variable)("site"), (0, import_datalog4.variable)("cls"))
|
|
1558
|
+
],
|
|
1559
|
+
"name of a site"
|
|
1560
|
+
),
|
|
1561
|
+
(0, import_datalog4.rule)(
|
|
1562
|
+
"objectOfUnder",
|
|
1563
|
+
[(0, import_datalog4.variable)("o"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("obj")],
|
|
1564
|
+
[
|
|
1565
|
+
(0, import_datalog4.lit)("reachesUnder", (0, import_datalog4.variable)("o"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("obj"), (0, import_datalog4.variable)("c2"), VALUE_STEP),
|
|
1566
|
+
(0, import_datalog4.lit)("objectValue", (0, import_datalog4.variable)("obj"))
|
|
1567
|
+
],
|
|
1568
|
+
"written object under a context"
|
|
1569
|
+
),
|
|
1570
|
+
(0, import_datalog4.rule)(
|
|
1571
|
+
"objectOfUnder",
|
|
1572
|
+
[(0, import_datalog4.variable)("o"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("obj")],
|
|
1573
|
+
[
|
|
1574
|
+
(0, import_datalog4.lit)("reachesUnder", (0, import_datalog4.variable)("o"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("obj"), (0, import_datalog4.variable)("c2"), RESULT_STEP),
|
|
1575
|
+
(0, import_datalog4.lit)("objectValue", (0, import_datalog4.variable)("obj"))
|
|
1576
|
+
],
|
|
1577
|
+
"returned object under a context"
|
|
1578
|
+
),
|
|
1579
|
+
(0, import_datalog4.rule)(
|
|
1580
|
+
"objectOfUnder",
|
|
1581
|
+
[(0, import_datalog4.variable)("o"), NO_CONTEXT, (0, import_datalog4.variable)("cls")],
|
|
1582
|
+
[
|
|
1583
|
+
(0, import_datalog4.lit)(
|
|
1584
|
+
"reachesUnder",
|
|
1585
|
+
(0, import_datalog4.variable)("o"),
|
|
1586
|
+
NO_CONTEXT,
|
|
1587
|
+
(0, import_datalog4.variable)("cls"),
|
|
1588
|
+
NO_CONTEXT,
|
|
1589
|
+
INSTANCE_STEP
|
|
1590
|
+
),
|
|
1591
|
+
(0, import_datalog4.lit)("objectValue", (0, import_datalog4.variable)("cls"))
|
|
1592
|
+
],
|
|
1593
|
+
"class reached with no context"
|
|
1594
|
+
),
|
|
1595
|
+
(0, import_datalog4.rule)(
|
|
1596
|
+
"objectOfUnder",
|
|
1597
|
+
[(0, import_datalog4.variable)("o"), NO_CONTEXT, (0, import_datalog4.variable)("cls")],
|
|
1598
|
+
[(0, import_datalog4.lit)("instanceOf", (0, import_datalog4.variable)("o"), (0, import_datalog4.variable)("cls"))],
|
|
1599
|
+
"receiver class with no context"
|
|
1600
|
+
),
|
|
1601
|
+
(0, import_datalog4.rule)(
|
|
1602
|
+
"objectOfUnder",
|
|
1603
|
+
[(0, import_datalog4.variable)("o"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("o")],
|
|
1604
|
+
[(0, import_datalog4.lit)("context", (0, import_datalog4.variable)("c")), (0, import_datalog4.lit)("objectValue", (0, import_datalog4.variable)("o"))],
|
|
1605
|
+
"object under a context is itself"
|
|
1606
|
+
),
|
|
1607
|
+
// A property read goes on under the site the object was made at, so a
|
|
1608
|
+
// field read off two constructions gives each one its own value. A
|
|
1609
|
+
// class or a literal object keeps the context the walk was already in.
|
|
1610
|
+
(0, import_datalog4.rule)(
|
|
1611
|
+
"reachesUnder",
|
|
1612
|
+
[(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("held"), (0, import_datalog4.variable)("site"), VALUE_STEP],
|
|
1613
|
+
[
|
|
1614
|
+
(0, import_datalog4.lit)("context", (0, import_datalog4.variable)("c")),
|
|
1615
|
+
(0, import_datalog4.lit)("readsProperty", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("o"), (0, import_datalog4.variable)("n")),
|
|
1616
|
+
(0, import_datalog4.lit)("objectOfUnder", (0, import_datalog4.variable)("o"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("site")),
|
|
1617
|
+
(0, import_datalog4.lit)("allocates", (0, import_datalog4.variable)("site"), (0, import_datalog4.variable)("cls")),
|
|
1618
|
+
(0, import_datalog4.lit)("contains", (0, import_datalog4.variable)("site"), (0, import_datalog4.variable)("n"), (0, import_datalog4.variable)("held"))
|
|
1619
|
+
],
|
|
1620
|
+
"property read at a site"
|
|
1621
|
+
),
|
|
1622
|
+
(0, import_datalog4.rule)(
|
|
1623
|
+
"reachesUnder",
|
|
1624
|
+
[(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("held"), (0, import_datalog4.variable)("c"), VALUE_STEP],
|
|
1625
|
+
[
|
|
1626
|
+
(0, import_datalog4.lit)("context", (0, import_datalog4.variable)("c")),
|
|
1627
|
+
(0, import_datalog4.lit)("readsProperty", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("o"), (0, import_datalog4.variable)("n")),
|
|
1628
|
+
(0, import_datalog4.lit)("objectOfUnder", (0, import_datalog4.variable)("o"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("obj")),
|
|
1629
|
+
(0, import_datalog4.lit)("objectValue", (0, import_datalog4.variable)("obj")),
|
|
1630
|
+
(0, import_datalog4.lit)("contains", (0, import_datalog4.variable)("obj"), (0, import_datalog4.variable)("n"), (0, import_datalog4.variable)("held"))
|
|
1631
|
+
],
|
|
1632
|
+
"property read off an object"
|
|
1633
|
+
),
|
|
1634
|
+
(0, import_datalog4.rule)(
|
|
1635
|
+
"reachesUnder",
|
|
1636
|
+
[(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("held"), (0, import_datalog4.variable)("site"), (0, import_datalog4.variable)("kind")],
|
|
1637
|
+
[
|
|
1638
|
+
(0, import_datalog4.lit)("reachesUnder", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("y"), (0, import_datalog4.variable)("c2"), (0, import_datalog4.variable)("kind")),
|
|
1639
|
+
(0, import_datalog4.lit)("readsProperty", (0, import_datalog4.variable)("y"), (0, import_datalog4.variable)("o"), (0, import_datalog4.variable)("n")),
|
|
1640
|
+
(0, import_datalog4.lit)("objectOfUnder", (0, import_datalog4.variable)("o"), (0, import_datalog4.variable)("c2"), (0, import_datalog4.variable)("site")),
|
|
1641
|
+
(0, import_datalog4.lit)("allocates", (0, import_datalog4.variable)("site"), (0, import_datalog4.variable)("cls")),
|
|
1642
|
+
(0, import_datalog4.lit)("contains", (0, import_datalog4.variable)("site"), (0, import_datalog4.variable)("n"), (0, import_datalog4.variable)("held"))
|
|
1643
|
+
],
|
|
1644
|
+
"reached property read at a site"
|
|
1645
|
+
),
|
|
1646
|
+
(0, import_datalog4.rule)(
|
|
1647
|
+
"reachesUnder",
|
|
1648
|
+
[(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("held"), (0, import_datalog4.variable)("c2"), (0, import_datalog4.variable)("kind")],
|
|
1649
|
+
[
|
|
1650
|
+
(0, import_datalog4.lit)("reachesUnder", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("y"), (0, import_datalog4.variable)("c2"), (0, import_datalog4.variable)("kind")),
|
|
1651
|
+
(0, import_datalog4.lit)("readsProperty", (0, import_datalog4.variable)("y"), (0, import_datalog4.variable)("o"), (0, import_datalog4.variable)("n")),
|
|
1652
|
+
(0, import_datalog4.lit)("objectOfUnder", (0, import_datalog4.variable)("o"), (0, import_datalog4.variable)("c2"), (0, import_datalog4.variable)("obj")),
|
|
1653
|
+
(0, import_datalog4.lit)("objectValue", (0, import_datalog4.variable)("obj")),
|
|
1654
|
+
(0, import_datalog4.lit)("contains", (0, import_datalog4.variable)("obj"), (0, import_datalog4.variable)("n"), (0, import_datalog4.variable)("held"))
|
|
1655
|
+
],
|
|
1656
|
+
"reached property read off an object"
|
|
1657
|
+
),
|
|
1658
|
+
// A parameter goes on at the argument, under the context its caller
|
|
1659
|
+
// was read in, and only from the calls that run the function under the
|
|
1660
|
+
// context the walk is in. This is the one hop that changes context.
|
|
1661
|
+
(0, import_datalog4.rule)(
|
|
1662
|
+
"reachesUnder",
|
|
1663
|
+
[(0, import_datalog4.variable)("p"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("a"), (0, import_datalog4.variable)("c3"), VALUE_STEP],
|
|
1664
|
+
[
|
|
1665
|
+
(0, import_datalog4.lit)("context", (0, import_datalog4.variable)("c")),
|
|
1666
|
+
(0, import_datalog4.lit)("paramOf", (0, import_datalog4.variable)("f"), (0, import_datalog4.variable)("i"), (0, import_datalog4.variable)("p")),
|
|
1667
|
+
(0, import_datalog4.lit)("entersUnder", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("f"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("c3")),
|
|
1668
|
+
(0, import_datalog4.lit)("callArg", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("i"), (0, import_datalog4.variable)("a"))
|
|
1669
|
+
],
|
|
1670
|
+
"argument under a context"
|
|
1671
|
+
),
|
|
1672
|
+
(0, import_datalog4.rule)(
|
|
1673
|
+
"reachesUnder",
|
|
1674
|
+
[(0, import_datalog4.variable)("p"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("a"), (0, import_datalog4.variable)("c3"), VALUE_STEP],
|
|
1675
|
+
[
|
|
1676
|
+
(0, import_datalog4.lit)("context", (0, import_datalog4.variable)("c")),
|
|
1677
|
+
(0, import_datalog4.lit)("paramNamed", (0, import_datalog4.variable)("f"), (0, import_datalog4.variable)("n"), (0, import_datalog4.variable)("p")),
|
|
1678
|
+
(0, import_datalog4.lit)("entersUnder", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("f"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("c3")),
|
|
1679
|
+
(0, import_datalog4.lit)("callKeywordArg", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("n"), (0, import_datalog4.variable)("a"))
|
|
1680
|
+
],
|
|
1681
|
+
"keyword argument under a context"
|
|
1682
|
+
),
|
|
1683
|
+
(0, import_datalog4.rule)(
|
|
1684
|
+
"reachesUnder",
|
|
1685
|
+
[(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("a"), (0, import_datalog4.variable)("c3"), (0, import_datalog4.variable)("kind")],
|
|
1686
|
+
[
|
|
1687
|
+
(0, import_datalog4.lit)("reachesUnder", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("p"), (0, import_datalog4.variable)("c2"), (0, import_datalog4.variable)("kind")),
|
|
1688
|
+
(0, import_datalog4.lit)("paramOf", (0, import_datalog4.variable)("f"), (0, import_datalog4.variable)("i"), (0, import_datalog4.variable)("p")),
|
|
1689
|
+
(0, import_datalog4.lit)("entersUnder", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("f"), (0, import_datalog4.variable)("c2"), (0, import_datalog4.variable)("c3")),
|
|
1690
|
+
(0, import_datalog4.lit)("callArg", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("i"), (0, import_datalog4.variable)("a"))
|
|
1691
|
+
],
|
|
1692
|
+
"reached argument under a context"
|
|
1693
|
+
),
|
|
1694
|
+
(0, import_datalog4.rule)(
|
|
1695
|
+
"reachesUnder",
|
|
1696
|
+
[(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("a"), (0, import_datalog4.variable)("c3"), (0, import_datalog4.variable)("kind")],
|
|
1697
|
+
[
|
|
1698
|
+
(0, import_datalog4.lit)("reachesUnder", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("p"), (0, import_datalog4.variable)("c2"), (0, import_datalog4.variable)("kind")),
|
|
1699
|
+
(0, import_datalog4.lit)("paramNamed", (0, import_datalog4.variable)("f"), (0, import_datalog4.variable)("n"), (0, import_datalog4.variable)("p")),
|
|
1700
|
+
(0, import_datalog4.lit)("entersUnder", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("f"), (0, import_datalog4.variable)("c2"), (0, import_datalog4.variable)("c3")),
|
|
1701
|
+
(0, import_datalog4.lit)("callKeywordArg", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("n"), (0, import_datalog4.variable)("a"))
|
|
1702
|
+
],
|
|
1703
|
+
"reached keyword argument under a context"
|
|
1704
|
+
),
|
|
1705
|
+
// Which call runs which function under which context. A construction
|
|
1706
|
+
// runs its constructor under the site it makes, a method call runs
|
|
1707
|
+
// under the site its receiver is, and anything else under no context.
|
|
1708
|
+
(0, import_datalog4.rule)(
|
|
1709
|
+
"entersUnder",
|
|
1710
|
+
[(0, import_datalog4.variable)("site"), (0, import_datalog4.variable)("ctor"), (0, import_datalog4.variable)("site"), (0, import_datalog4.variable)("caller")],
|
|
1711
|
+
[
|
|
1712
|
+
(0, import_datalog4.lit)("allocates", (0, import_datalog4.variable)("site"), (0, import_datalog4.variable)("cls")),
|
|
1713
|
+
(0, import_datalog4.lit)("runsConstructor", (0, import_datalog4.variable)("cls"), (0, import_datalog4.variable)("ctor")),
|
|
1714
|
+
(0, import_datalog4.lit)("callUnder", (0, import_datalog4.variable)("site"), (0, import_datalog4.variable)("caller"))
|
|
1715
|
+
],
|
|
1716
|
+
"construction enters its constructor"
|
|
1717
|
+
),
|
|
1718
|
+
(0, import_datalog4.rule)(
|
|
1719
|
+
"entersUnder",
|
|
1720
|
+
[(0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("f"), (0, import_datalog4.variable)("site"), (0, import_datalog4.variable)("caller")],
|
|
1721
|
+
[
|
|
1722
|
+
(0, import_datalog4.lit)("call", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("cal")),
|
|
1723
|
+
(0, import_datalog4.lit)("readsProperty", (0, import_datalog4.variable)("cal"), (0, import_datalog4.variable)("o"), (0, import_datalog4.variable)("m")),
|
|
1724
|
+
(0, import_datalog4.lit)("objectOfUnder", (0, import_datalog4.variable)("o"), (0, import_datalog4.variable)("caller"), (0, import_datalog4.variable)("site")),
|
|
1725
|
+
(0, import_datalog4.lit)("allocates", (0, import_datalog4.variable)("site"), (0, import_datalog4.variable)("cls")),
|
|
1726
|
+
(0, import_datalog4.lit)("contains", (0, import_datalog4.variable)("site"), (0, import_datalog4.variable)("m"), (0, import_datalog4.variable)("f")),
|
|
1727
|
+
(0, import_datalog4.lit)("callUnder", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("caller"))
|
|
1728
|
+
],
|
|
1729
|
+
"method call enters under its receiver"
|
|
1730
|
+
),
|
|
1731
|
+
// A call written as a name runs with whatever receiver the body
|
|
1732
|
+
// around it has, so a plain function called from a method keeps the
|
|
1733
|
+
// site rather than taking every caller of it.
|
|
1734
|
+
(0, import_datalog4.rule)(
|
|
1735
|
+
"entersUnder",
|
|
1736
|
+
[(0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("f"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("c")],
|
|
1737
|
+
[
|
|
1738
|
+
(0, import_datalog4.lit)("context", (0, import_datalog4.variable)("c")),
|
|
1739
|
+
(0, import_datalog4.lit)("callsNamed", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("f")),
|
|
1740
|
+
(0, import_datalog4.lit)("callUnder", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("c"))
|
|
1741
|
+
],
|
|
1742
|
+
"named call enters under the site it is made in"
|
|
1743
|
+
),
|
|
1744
|
+
(0, import_datalog4.rule)(
|
|
1745
|
+
"entersUnder",
|
|
1746
|
+
[(0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("f"), NO_CONTEXT, (0, import_datalog4.variable)("caller")],
|
|
1747
|
+
[
|
|
1748
|
+
(0, import_datalog4.lit)("callsFunction", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("f")),
|
|
1749
|
+
(0, import_datalog4.lit)("callUnder", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("caller"))
|
|
1750
|
+
],
|
|
1751
|
+
"call enters with no context"
|
|
1752
|
+
),
|
|
1753
|
+
// The constructor a construction runs, the ancestry included, so a
|
|
1754
|
+
// subclass that declares none still fills in what it inherits.
|
|
1755
|
+
(0, import_datalog4.rule)(
|
|
1756
|
+
"runsConstructor",
|
|
1757
|
+
[(0, import_datalog4.variable)("cls"), (0, import_datalog4.variable)("f")],
|
|
1758
|
+
[(0, import_datalog4.lit)("initializes", (0, import_datalog4.variable)("cls"), (0, import_datalog4.variable)("f"))]
|
|
1759
|
+
),
|
|
1760
|
+
(0, import_datalog4.rule)(
|
|
1761
|
+
"runsConstructor",
|
|
1762
|
+
[(0, import_datalog4.variable)("cls"), (0, import_datalog4.variable)("f")],
|
|
1763
|
+
[
|
|
1764
|
+
(0, import_datalog4.lit)("extends", (0, import_datalog4.variable)("cls"), (0, import_datalog4.variable)("b")),
|
|
1765
|
+
(0, import_datalog4.lit)("comesTo", (0, import_datalog4.variable)("b"), (0, import_datalog4.variable)("base")),
|
|
1766
|
+
(0, import_datalog4.lit)("runsConstructor", (0, import_datalog4.variable)("base"), (0, import_datalog4.variable)("f"))
|
|
1210
1767
|
]
|
|
1211
1768
|
),
|
|
1212
|
-
//
|
|
1213
|
-
//
|
|
1214
|
-
// demand-driven run then derives both to answer either.
|
|
1769
|
+
// Which body a call is written in. One adapter states the call it
|
|
1770
|
+
// found and another states the callee, so both spellings are read.
|
|
1215
1771
|
(0, import_datalog4.rule)(
|
|
1216
|
-
"
|
|
1217
|
-
[(0, import_datalog4.variable)("
|
|
1772
|
+
"callInBody",
|
|
1773
|
+
[(0, import_datalog4.variable)("f"), (0, import_datalog4.variable)("r")],
|
|
1774
|
+
[(0, import_datalog4.lit)("bodyCallsDeep", (0, import_datalog4.variable)("f"), (0, import_datalog4.variable)("r")), (0, import_datalog4.lit)("call", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("c"))]
|
|
1775
|
+
),
|
|
1776
|
+
(0, import_datalog4.rule)(
|
|
1777
|
+
"callInBody",
|
|
1778
|
+
[(0, import_datalog4.variable)("f"), (0, import_datalog4.variable)("r")],
|
|
1779
|
+
[(0, import_datalog4.lit)("bodyCallsDeep", (0, import_datalog4.variable)("f"), (0, import_datalog4.variable)("c")), (0, import_datalog4.lit)("call", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("c"))]
|
|
1780
|
+
),
|
|
1781
|
+
// The context a call is made under: every site of the class whose
|
|
1782
|
+
// method or constructor it is written in, and no context for a call
|
|
1783
|
+
// outside every method body.
|
|
1784
|
+
(0, import_datalog4.rule)(
|
|
1785
|
+
"callUnder",
|
|
1786
|
+
[(0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("site")],
|
|
1787
|
+
[
|
|
1788
|
+
(0, import_datalog4.lit)("callInBody", (0, import_datalog4.variable)("f"), (0, import_datalog4.variable)("r")),
|
|
1789
|
+
(0, import_datalog4.lit)("holdsProperty", (0, import_datalog4.variable)("cls"), (0, import_datalog4.variable)("m"), (0, import_datalog4.variable)("f")),
|
|
1790
|
+
(0, import_datalog4.lit)("allocates", (0, import_datalog4.variable)("site"), (0, import_datalog4.variable)("cls"))
|
|
1791
|
+
],
|
|
1792
|
+
"call in a method"
|
|
1793
|
+
),
|
|
1794
|
+
(0, import_datalog4.rule)(
|
|
1795
|
+
"callUnder",
|
|
1796
|
+
[(0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("site")],
|
|
1218
1797
|
[
|
|
1219
|
-
(0, import_datalog4.lit)("
|
|
1220
|
-
(0, import_datalog4.lit)("
|
|
1798
|
+
(0, import_datalog4.lit)("callInBody", (0, import_datalog4.variable)("f"), (0, import_datalog4.variable)("r")),
|
|
1799
|
+
(0, import_datalog4.lit)("initializes", (0, import_datalog4.variable)("cls"), (0, import_datalog4.variable)("f")),
|
|
1800
|
+
(0, import_datalog4.lit)("allocates", (0, import_datalog4.variable)("site"), (0, import_datalog4.variable)("cls"))
|
|
1801
|
+
],
|
|
1802
|
+
"call in a constructor"
|
|
1803
|
+
),
|
|
1804
|
+
// A plain function entered under a site makes its own calls under
|
|
1805
|
+
// that site, so a chain of plain functions off one method keeps it.
|
|
1806
|
+
(0, import_datalog4.rule)(
|
|
1807
|
+
"callUnder",
|
|
1808
|
+
[(0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("c")],
|
|
1809
|
+
[
|
|
1810
|
+
(0, import_datalog4.lit)("callOutsideMethod", (0, import_datalog4.variable)("r")),
|
|
1811
|
+
(0, import_datalog4.lit)("callInBody", (0, import_datalog4.variable)("f"), (0, import_datalog4.variable)("r")),
|
|
1812
|
+
(0, import_datalog4.lit)("entersUnder", (0, import_datalog4.variable)("into"), (0, import_datalog4.variable)("f"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("c4"))
|
|
1813
|
+
],
|
|
1814
|
+
"call in a function entered under a site"
|
|
1815
|
+
),
|
|
1816
|
+
(0, import_datalog4.rule)(
|
|
1817
|
+
"callUnder",
|
|
1818
|
+
[(0, import_datalog4.variable)("r"), NO_CONTEXT],
|
|
1819
|
+
[(0, import_datalog4.lit)("callOutsideMethod", (0, import_datalog4.variable)("r"))],
|
|
1820
|
+
"call outside every method"
|
|
1821
|
+
),
|
|
1822
|
+
// The two questions a caller puts under a context, stopping where
|
|
1823
|
+
// `isWrittenAs` and `comesTo` stop, whatever context the walk ended in.
|
|
1824
|
+
(0, import_datalog4.rule)(
|
|
1825
|
+
"isWrittenAsUnder",
|
|
1826
|
+
[(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("x")],
|
|
1827
|
+
[(0, import_datalog4.lit)("context", (0, import_datalog4.variable)("c")), (0, import_datalog4.lit)("writtenValue", (0, import_datalog4.variable)("x"))]
|
|
1828
|
+
),
|
|
1829
|
+
(0, import_datalog4.rule)(
|
|
1830
|
+
"isWrittenAsUnder",
|
|
1831
|
+
[(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("x")],
|
|
1832
|
+
[(0, import_datalog4.lit)("context", (0, import_datalog4.variable)("c")), (0, import_datalog4.lit)("objectValue", (0, import_datalog4.variable)("x"))]
|
|
1833
|
+
),
|
|
1834
|
+
(0, import_datalog4.rule)(
|
|
1835
|
+
"isWrittenAsUnder",
|
|
1836
|
+
[(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("z")],
|
|
1837
|
+
[
|
|
1838
|
+
(0, import_datalog4.lit)("reachesUnder", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("z"), (0, import_datalog4.variable)("c2"), VALUE_STEP),
|
|
1839
|
+
(0, import_datalog4.lit)("writtenValue", (0, import_datalog4.variable)("z"))
|
|
1221
1840
|
]
|
|
1222
1841
|
),
|
|
1223
1842
|
(0, import_datalog4.rule)(
|
|
1224
|
-
"
|
|
1225
|
-
[(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("
|
|
1843
|
+
"isWrittenAsUnder",
|
|
1844
|
+
[(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("z")],
|
|
1845
|
+
[
|
|
1846
|
+
(0, import_datalog4.lit)("reachesUnder", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("z"), (0, import_datalog4.variable)("c2"), VALUE_STEP),
|
|
1847
|
+
(0, import_datalog4.lit)("objectValue", (0, import_datalog4.variable)("z"))
|
|
1848
|
+
]
|
|
1849
|
+
),
|
|
1850
|
+
(0, import_datalog4.rule)(
|
|
1851
|
+
"comesToUnder",
|
|
1852
|
+
[(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("x")],
|
|
1853
|
+
[(0, import_datalog4.lit)("context", (0, import_datalog4.variable)("c")), (0, import_datalog4.lit)("func", (0, import_datalog4.variable)("x"))]
|
|
1854
|
+
),
|
|
1855
|
+
(0, import_datalog4.rule)(
|
|
1856
|
+
"comesToUnder",
|
|
1857
|
+
[(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("x")],
|
|
1858
|
+
[(0, import_datalog4.lit)("context", (0, import_datalog4.variable)("c")), (0, import_datalog4.lit)("objectValue", (0, import_datalog4.variable)("x"))]
|
|
1859
|
+
),
|
|
1860
|
+
(0, import_datalog4.rule)(
|
|
1861
|
+
"comesToUnder",
|
|
1862
|
+
[(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("z")],
|
|
1863
|
+
[
|
|
1864
|
+
(0, import_datalog4.lit)("reachesUnder", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("z"), (0, import_datalog4.variable)("c2"), VALUE_STEP),
|
|
1865
|
+
(0, import_datalog4.lit)("func", (0, import_datalog4.variable)("z"))
|
|
1866
|
+
]
|
|
1867
|
+
),
|
|
1868
|
+
(0, import_datalog4.rule)(
|
|
1869
|
+
"comesToUnder",
|
|
1870
|
+
[(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("z")],
|
|
1871
|
+
[
|
|
1872
|
+
(0, import_datalog4.lit)("reachesUnder", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("z"), (0, import_datalog4.variable)("c2"), VALUE_STEP),
|
|
1873
|
+
(0, import_datalog4.lit)("objectValue", (0, import_datalog4.variable)("z"))
|
|
1874
|
+
]
|
|
1875
|
+
),
|
|
1876
|
+
(0, import_datalog4.rule)(
|
|
1877
|
+
"comesToUnder",
|
|
1878
|
+
[(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("z")],
|
|
1879
|
+
[
|
|
1880
|
+
(0, import_datalog4.lit)("reachesUnder", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("z"), (0, import_datalog4.variable)("c2"), INSTANCE_STEP),
|
|
1881
|
+
(0, import_datalog4.lit)("func", (0, import_datalog4.variable)("z"))
|
|
1882
|
+
]
|
|
1883
|
+
),
|
|
1884
|
+
(0, import_datalog4.rule)(
|
|
1885
|
+
"comesToUnder",
|
|
1886
|
+
[(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("z")],
|
|
1226
1887
|
[
|
|
1227
|
-
(0, import_datalog4.lit)("
|
|
1228
|
-
(0, import_datalog4.lit)("
|
|
1888
|
+
(0, import_datalog4.lit)("reachesUnder", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("z"), (0, import_datalog4.variable)("c2"), INSTANCE_STEP),
|
|
1889
|
+
(0, import_datalog4.lit)("objectValue", (0, import_datalog4.variable)("z"))
|
|
1229
1890
|
]
|
|
1230
1891
|
),
|
|
1231
1892
|
// What a value comes down to: the walk that never ran a call, stopped
|
|
@@ -1243,6 +1904,18 @@ var RESOLUTION_RULES = [
|
|
|
1243
1904
|
[(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("z")],
|
|
1244
1905
|
[(0, import_datalog4.lit)("reaches", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("z"), VALUE_STEP), (0, import_datalog4.lit)("objectValue", (0, import_datalog4.variable)("z"))]
|
|
1245
1906
|
),
|
|
1907
|
+
// An instance walk stops the same way, so a method read off
|
|
1908
|
+
// `new App()` still finds what the class declares.
|
|
1909
|
+
(0, import_datalog4.rule)(
|
|
1910
|
+
"comesTo",
|
|
1911
|
+
[(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("z")],
|
|
1912
|
+
[(0, import_datalog4.lit)("reaches", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("z"), INSTANCE_STEP), (0, import_datalog4.lit)("func", (0, import_datalog4.variable)("z"))]
|
|
1913
|
+
),
|
|
1914
|
+
(0, import_datalog4.rule)(
|
|
1915
|
+
"comesTo",
|
|
1916
|
+
[(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("z")],
|
|
1917
|
+
[(0, import_datalog4.lit)("reaches", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("z"), INSTANCE_STEP), (0, import_datalog4.lit)("objectValue", (0, import_datalog4.variable)("z"))]
|
|
1918
|
+
),
|
|
1246
1919
|
// The same stopping condition, for the walk that ran a call. A call
|
|
1247
1920
|
// gets no `comesTo` answer on purpose: coming back with what a
|
|
1248
1921
|
// factory returned would fight the unwrapping answer.
|
|
@@ -1283,6 +1956,13 @@ var RESOLUTION_RULES = [
|
|
|
1283
1956
|
(0, import_datalog4.lit)("isWrittenAs", (0, import_datalog4.variable)("ret"), (0, import_datalog4.variable)("z"))
|
|
1284
1957
|
]
|
|
1285
1958
|
),
|
|
1959
|
+
// Which expression running f hands back, whether f returns it, writes
|
|
1960
|
+
// it into a name first, or ends on it as a shorthand body.
|
|
1961
|
+
(0, import_datalog4.rule)(
|
|
1962
|
+
"returnsCall",
|
|
1963
|
+
[(0, import_datalog4.variable)("f"), (0, import_datalog4.variable)("c")],
|
|
1964
|
+
[(0, import_datalog4.lit)("returnsValue", (0, import_datalog4.variable)("f"), (0, import_datalog4.variable)("v")), (0, import_datalog4.lit)("isWrittenAs", (0, import_datalog4.variable)("v"), (0, import_datalog4.variable)("c"))]
|
|
1965
|
+
),
|
|
1286
1966
|
// What one call site put in a parameter, told apart from what the
|
|
1287
1967
|
// other callers passed.
|
|
1288
1968
|
(0, import_datalog4.rule)(
|
|
@@ -1380,18 +2060,34 @@ var RESOLUTION_RULES = [
|
|
|
1380
2060
|
[(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("obj")],
|
|
1381
2061
|
[(0, import_datalog4.lit)("givesBack", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("obj")), (0, import_datalog4.lit)("objectValue", (0, import_datalog4.variable)("obj"))]
|
|
1382
2062
|
),
|
|
2063
|
+
// A construction is the object it made, and so is any name for it.
|
|
2064
|
+
// The class stays an answer too, so an instance whose site is not in
|
|
2065
|
+
// the run still reads what the class stores.
|
|
2066
|
+
(0, import_datalog4.rule)(
|
|
2067
|
+
"objectOf",
|
|
2068
|
+
[(0, import_datalog4.variable)("site"), (0, import_datalog4.variable)("site")],
|
|
2069
|
+
[(0, import_datalog4.lit)("allocates", (0, import_datalog4.variable)("site"), (0, import_datalog4.variable)("c"))]
|
|
2070
|
+
),
|
|
2071
|
+
(0, import_datalog4.rule)(
|
|
2072
|
+
"objectOf",
|
|
2073
|
+
[(0, import_datalog4.variable)("o"), (0, import_datalog4.variable)("site")],
|
|
2074
|
+
[
|
|
2075
|
+
(0, import_datalog4.lit)("reaches", (0, import_datalog4.variable)("o"), (0, import_datalog4.variable)("site"), VALUE_STEP),
|
|
2076
|
+
(0, import_datalog4.lit)("allocates", (0, import_datalog4.variable)("site"), (0, import_datalog4.variable)("c"))
|
|
2077
|
+
]
|
|
2078
|
+
),
|
|
1383
2079
|
// Which calls a function, found by the name the call is written as
|
|
1384
2080
|
// rather than by resolving every callee in the project. A caller knows
|
|
1385
2081
|
// the function and wants its call sites, so both of these start from
|
|
1386
2082
|
// the function. Starting from `call` instead asks what every call in
|
|
1387
2083
|
// the project imports, which was 72% of everything derived.
|
|
1388
2084
|
(0, import_datalog4.rule)(
|
|
1389
|
-
"
|
|
2085
|
+
"callsNamed",
|
|
1390
2086
|
[(0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("f")],
|
|
1391
2087
|
[(0, import_datalog4.lit)("binds", (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("f")), (0, import_datalog4.lit)("call", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("c"))]
|
|
1392
2088
|
),
|
|
1393
2089
|
(0, import_datalog4.rule)(
|
|
1394
|
-
"
|
|
2090
|
+
"callsNamed",
|
|
1395
2091
|
[(0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("f")],
|
|
1396
2092
|
[
|
|
1397
2093
|
(0, import_datalog4.lit)("moduleExport", (0, import_datalog4.variable)("m"), (0, import_datalog4.variable)("n"), (0, import_datalog4.variable)("f")),
|
|
@@ -1402,7 +2098,7 @@ var RESOLUTION_RULES = [
|
|
|
1402
2098
|
// The same, for a language whose adapter writes the import down as a
|
|
1403
2099
|
// declaration and the call's callee as the name referring to it.
|
|
1404
2100
|
(0, import_datalog4.rule)(
|
|
1405
|
-
"
|
|
2101
|
+
"callsNamed",
|
|
1406
2102
|
[(0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("f")],
|
|
1407
2103
|
[
|
|
1408
2104
|
(0, import_datalog4.lit)("moduleExport", (0, import_datalog4.variable)("m"), (0, import_datalog4.variable)("n"), (0, import_datalog4.variable)("f")),
|
|
@@ -1411,6 +2107,62 @@ var RESOLUTION_RULES = [
|
|
|
1411
2107
|
(0, import_datalog4.lit)("call", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("c"))
|
|
1412
2108
|
]
|
|
1413
2109
|
),
|
|
2110
|
+
// `const f = (x) => ...` declares the name and puts the parameters on
|
|
2111
|
+
// the arrow, so everything above arrives at the declaration and
|
|
2112
|
+
// `paramOf` is about the arrow. One binds hop joins the two.
|
|
2113
|
+
(0, import_datalog4.rule)(
|
|
2114
|
+
"callsNamed",
|
|
2115
|
+
[(0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("f")],
|
|
2116
|
+
[(0, import_datalog4.lit)("binds", (0, import_datalog4.variable)("g"), (0, import_datalog4.variable)("f")), (0, import_datalog4.lit)("callsNamed", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("g"))]
|
|
2117
|
+
),
|
|
2118
|
+
// Every one of those, and the binds hop again over the whole
|
|
2119
|
+
// relation, so a property holding a name for a function is reached
|
|
2120
|
+
// the way it was before the two were told apart.
|
|
2121
|
+
(0, import_datalog4.rule)("callsFunction", [(0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("f")], [(0, import_datalog4.lit)("callsNamed", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("f"))]),
|
|
2122
|
+
(0, import_datalog4.rule)(
|
|
2123
|
+
"callsFunction",
|
|
2124
|
+
[(0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("f")],
|
|
2125
|
+
[(0, import_datalog4.lit)("binds", (0, import_datalog4.variable)("g"), (0, import_datalog4.variable)("f")), (0, import_datalog4.lit)("callsFunction", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("g"))]
|
|
2126
|
+
),
|
|
2127
|
+
// A function written on an object, called off it: `client.get(o)`.
|
|
2128
|
+
// The receiver comes from the object through `refersToObject`, not from
|
|
2129
|
+
// `objectOf`: a walk from every reader of the name was most of a run.
|
|
2130
|
+
(0, import_datalog4.rule)(
|
|
2131
|
+
"callsFunction",
|
|
2132
|
+
[(0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("f")],
|
|
2133
|
+
[
|
|
2134
|
+
(0, import_datalog4.lit)("holdsProperty", (0, import_datalog4.variable)("obj"), (0, import_datalog4.variable)("n"), (0, import_datalog4.variable)("f")),
|
|
2135
|
+
(0, import_datalog4.lit)("refersToObject", (0, import_datalog4.variable)("o"), (0, import_datalog4.variable)("obj")),
|
|
2136
|
+
(0, import_datalog4.lit)("readsProperty", (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("o"), (0, import_datalog4.variable)("n")),
|
|
2137
|
+
(0, import_datalog4.lit)("call", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("c"))
|
|
2138
|
+
]
|
|
2139
|
+
),
|
|
2140
|
+
// The expressions that refer to an object literal by binding alone: the
|
|
2141
|
+
// declaration written as it, a reference or import of that, and a
|
|
2142
|
+
// fallback over any of those. Asked from the object, so it visits only them.
|
|
2143
|
+
(0, import_datalog4.rule)("refersToObject", [(0, import_datalog4.variable)("obj"), (0, import_datalog4.variable)("obj")], [(0, import_datalog4.lit)("objectValue", (0, import_datalog4.variable)("obj"))]),
|
|
2144
|
+
(0, import_datalog4.rule)(
|
|
2145
|
+
"refersToObject",
|
|
2146
|
+
[(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("obj")],
|
|
2147
|
+
[(0, import_datalog4.lit)("refersToObject", (0, import_datalog4.variable)("y"), (0, import_datalog4.variable)("obj")), (0, import_datalog4.lit)("binds", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("y"))]
|
|
2148
|
+
),
|
|
2149
|
+
(0, import_datalog4.rule)(
|
|
2150
|
+
"refersToObject",
|
|
2151
|
+
[(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("obj")],
|
|
2152
|
+
[
|
|
2153
|
+
(0, import_datalog4.lit)("refersToObject", (0, import_datalog4.variable)("y"), (0, import_datalog4.variable)("obj")),
|
|
2154
|
+
(0, import_datalog4.lit)("moduleExport", (0, import_datalog4.variable)("m"), (0, import_datalog4.variable)("n"), (0, import_datalog4.variable)("y")),
|
|
2155
|
+
(0, import_datalog4.lit)("imports", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("m"), (0, import_datalog4.variable)("n"))
|
|
2156
|
+
]
|
|
2157
|
+
),
|
|
2158
|
+
(0, import_datalog4.rule)(
|
|
2159
|
+
"refersToObject",
|
|
2160
|
+
[(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("obj")],
|
|
2161
|
+
[
|
|
2162
|
+
(0, import_datalog4.lit)("refersToObject", (0, import_datalog4.variable)("b"), (0, import_datalog4.variable)("obj")),
|
|
2163
|
+
(0, import_datalog4.lit)("fallbackBranch", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("b"))
|
|
2164
|
+
]
|
|
2165
|
+
),
|
|
1414
2166
|
// What an object contains, its base class included, so a method the base
|
|
1415
2167
|
// declares is found on a subclass that never overrode it. A method both
|
|
1416
2168
|
// declare gives two, and the caller decides. This is its own relation
|
|
@@ -1428,7 +2180,8 @@ var RESOLUTION_RULES = [
|
|
|
1428
2180
|
(0, import_datalog4.lit)("extends", (0, import_datalog4.variable)("cls"), (0, import_datalog4.variable)("base")),
|
|
1429
2181
|
(0, import_datalog4.lit)("comesTo", (0, import_datalog4.variable)("base"), (0, import_datalog4.variable)("baseCls")),
|
|
1430
2182
|
(0, import_datalog4.lit)("contains", (0, import_datalog4.variable)("baseCls"), (0, import_datalog4.variable)("n"), (0, import_datalog4.variable)("held"))
|
|
1431
|
-
]
|
|
2183
|
+
],
|
|
2184
|
+
BASE_CLASS_RULE
|
|
1432
2185
|
),
|
|
1433
2186
|
// An association is read off an instance as a property, and stating
|
|
1434
2187
|
// it as `contains` is what puts it on the ancestry rule, so a concern
|
|
@@ -1452,6 +2205,69 @@ var RESOLUTION_RULES = [
|
|
|
1452
2205
|
],
|
|
1453
2206
|
"constructed association"
|
|
1454
2207
|
),
|
|
2208
|
+
// What the constructor put on the receiver. The class is the object
|
|
2209
|
+
// for an instance whose own site is not in the run.
|
|
2210
|
+
(0, import_datalog4.rule)(
|
|
2211
|
+
"contains",
|
|
2212
|
+
[(0, import_datalog4.variable)("cls"), (0, import_datalog4.variable)("n"), (0, import_datalog4.variable)("held")],
|
|
2213
|
+
[
|
|
2214
|
+
(0, import_datalog4.lit)("initializes", (0, import_datalog4.variable)("cls"), (0, import_datalog4.variable)("f")),
|
|
2215
|
+
(0, import_datalog4.lit)("storesProperty", (0, import_datalog4.variable)("f"), (0, import_datalog4.variable)("n"), (0, import_datalog4.variable)("held"))
|
|
2216
|
+
],
|
|
2217
|
+
"constructor store"
|
|
2218
|
+
),
|
|
2219
|
+
// What any other method of the class put there. Two methods writing
|
|
2220
|
+
// one name give two rows, since nothing here orders them.
|
|
2221
|
+
(0, import_datalog4.rule)(
|
|
2222
|
+
"contains",
|
|
2223
|
+
[(0, import_datalog4.variable)("cls"), (0, import_datalog4.variable)("n"), (0, import_datalog4.variable)("held")],
|
|
2224
|
+
[
|
|
2225
|
+
(0, import_datalog4.lit)("holdsProperty", (0, import_datalog4.variable)("cls"), (0, import_datalog4.variable)("m"), (0, import_datalog4.variable)("f")),
|
|
2226
|
+
(0, import_datalog4.lit)("storesProperty", (0, import_datalog4.variable)("f"), (0, import_datalog4.variable)("n"), (0, import_datalog4.variable)("held"))
|
|
2227
|
+
],
|
|
2228
|
+
"method store"
|
|
2229
|
+
),
|
|
2230
|
+
// A write through a name rather than through the receiver,
|
|
2231
|
+
// `client.timeout = 5`, which lands on whatever that name refers to.
|
|
2232
|
+
(0, import_datalog4.rule)(
|
|
2233
|
+
"contains",
|
|
2234
|
+
[(0, import_datalog4.variable)("obj"), (0, import_datalog4.variable)("n"), (0, import_datalog4.variable)("held")],
|
|
2235
|
+
[
|
|
2236
|
+
(0, import_datalog4.lit)("storesProperty", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("n"), (0, import_datalog4.variable)("held")),
|
|
2237
|
+
(0, import_datalog4.lit)("objectOf", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("obj"))
|
|
2238
|
+
],
|
|
2239
|
+
"named receiver store"
|
|
2240
|
+
),
|
|
2241
|
+
// A call written with a class's own name, which is how most languages
|
|
2242
|
+
// spell a construction. A language that spells one some other way
|
|
2243
|
+
// states its own rule for this, the way Ruby does for `Const.new`.
|
|
2244
|
+
(0, import_datalog4.rule)(
|
|
2245
|
+
"constructsNamed",
|
|
2246
|
+
[(0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("cls")],
|
|
2247
|
+
[(0, import_datalog4.lit)("objectValue", (0, import_datalog4.variable)("cls")), (0, import_datalog4.lit)("callsNamed", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("cls"))]
|
|
2248
|
+
),
|
|
2249
|
+
// Each construction is an object of its own containing what its
|
|
2250
|
+
// class stores, so two sites are two objects.
|
|
2251
|
+
(0, import_datalog4.rule)(
|
|
2252
|
+
"contains",
|
|
2253
|
+
[(0, import_datalog4.variable)("site"), (0, import_datalog4.variable)("n"), (0, import_datalog4.variable)("held")],
|
|
2254
|
+
[
|
|
2255
|
+
(0, import_datalog4.lit)("allocates", (0, import_datalog4.variable)("site"), (0, import_datalog4.variable)("cls")),
|
|
2256
|
+
(0, import_datalog4.lit)("contains", (0, import_datalog4.variable)("cls"), (0, import_datalog4.variable)("n"), (0, import_datalog4.variable)("held"))
|
|
2257
|
+
],
|
|
2258
|
+
"allocated instance"
|
|
2259
|
+
),
|
|
2260
|
+
// A call that makes one of a class. Every finder a pack declared is
|
|
2261
|
+
// one too, so `User.find(1)` is a site the same way `User.new` is.
|
|
2262
|
+
(0, import_datalog4.rule)(
|
|
2263
|
+
"allocates",
|
|
2264
|
+
[(0, import_datalog4.variable)("site"), (0, import_datalog4.variable)("cls")],
|
|
2265
|
+
[
|
|
2266
|
+
(0, import_datalog4.lit)("call", (0, import_datalog4.variable)("site"), (0, import_datalog4.variable)("c")),
|
|
2267
|
+
(0, import_datalog4.lit)("stepsTo", (0, import_datalog4.variable)("site"), (0, import_datalog4.variable)("cls"), INSTANCE_STEP)
|
|
2268
|
+
],
|
|
2269
|
+
"allocation site"
|
|
2270
|
+
),
|
|
1455
2271
|
// The library base a class's ancestry arrives at, however many of a
|
|
1456
2272
|
// project's own classes sit in between. A base the run declares has a
|
|
1457
2273
|
// node to keep walking from; one it does not has only a name.
|
|
@@ -1541,8 +2357,8 @@ var RESOLUTION_RULES = [
|
|
|
1541
2357
|
]
|
|
1542
2358
|
),
|
|
1543
2359
|
// Where a name comes from, when what it refers to lives outside the
|
|
1544
|
-
// source being read. A walk ends at
|
|
1545
|
-
//
|
|
2360
|
+
// source being read. A walk ends at what the source writes out, so it
|
|
2361
|
+
// never reaches a library's own function; these rules do.
|
|
1546
2362
|
(0, import_datalog4.rule)(
|
|
1547
2363
|
"comesFrom",
|
|
1548
2364
|
[(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("m"), (0, import_datalog4.variable)("n")],
|
|
@@ -1556,6 +2372,28 @@ var RESOLUTION_RULES = [
|
|
|
1556
2372
|
(0, import_datalog4.lit)("imports", (0, import_datalog4.variable)("y"), (0, import_datalog4.variable)("m"), (0, import_datalog4.variable)("n"))
|
|
1557
2373
|
]
|
|
1558
2374
|
),
|
|
2375
|
+
// A member read off a whole-module import: the member's own name is
|
|
2376
|
+
// what the module exports, so `fastapi.APIRouter` comes from
|
|
2377
|
+
// fastapi's `APIRouter`. Directly, or through a name for the module.
|
|
2378
|
+
(0, import_datalog4.rule)(
|
|
2379
|
+
"comesFrom",
|
|
2380
|
+
[(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("m"), (0, import_datalog4.variable)("n")],
|
|
2381
|
+
[
|
|
2382
|
+
(0, import_datalog4.lit)("readsProperty", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("ns"), (0, import_datalog4.variable)("n")),
|
|
2383
|
+
(0, import_datalog4.lit)("imports", (0, import_datalog4.variable)("ns"), (0, import_datalog4.variable)("m"), NAMESPACE_IMPORT)
|
|
2384
|
+
],
|
|
2385
|
+
NAMESPACE_MEMBER_RULE
|
|
2386
|
+
),
|
|
2387
|
+
(0, import_datalog4.rule)(
|
|
2388
|
+
"comesFrom",
|
|
2389
|
+
[(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("m"), (0, import_datalog4.variable)("n")],
|
|
2390
|
+
[
|
|
2391
|
+
(0, import_datalog4.lit)("readsProperty", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("o"), (0, import_datalog4.variable)("n")),
|
|
2392
|
+
(0, import_datalog4.lit)("reaches", (0, import_datalog4.variable)("o"), (0, import_datalog4.variable)("ns"), VALUE_STEP),
|
|
2393
|
+
(0, import_datalog4.lit)("imports", (0, import_datalog4.variable)("ns"), (0, import_datalog4.variable)("m"), NAMESPACE_IMPORT)
|
|
2394
|
+
],
|
|
2395
|
+
NAMESPACE_MEMBER_RULE
|
|
2396
|
+
),
|
|
1559
2397
|
// Calling f ends up calling the name n that module m exports, one
|
|
1560
2398
|
// hop through f's own body or deeper through a wrapper of a wrapper.
|
|
1561
2399
|
// Several results is normal: a composed decorator applies them all.
|
|
@@ -1585,6 +2423,13 @@ var RESOLUTION_RULES = [
|
|
|
1585
2423
|
[(0, import_datalog4.lit)("comesTo", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("z")), (0, import_datalog4.lit)("func", (0, import_datalog4.variable)("z"))]
|
|
1586
2424
|
)
|
|
1587
2425
|
];
|
|
2426
|
+
function alsoSteps(rules) {
|
|
2427
|
+
return [
|
|
2428
|
+
...rules,
|
|
2429
|
+
...rules.filter((r) => r.head.relation === "hop").map((r) => ({ ...r, head: { ...r.head, relation: "stepsTo" } }))
|
|
2430
|
+
];
|
|
2431
|
+
}
|
|
2432
|
+
var RESOLUTION_RULES = alsoSteps(STATED_RULES);
|
|
1588
2433
|
var RESOLUTION_QUESTIONS = [
|
|
1589
2434
|
(0, import_datalog4.rule)(
|
|
1590
2435
|
"wantedResolves",
|
|
@@ -1607,12 +2452,55 @@ var RESOLUTION_QUESTIONS = [
|
|
|
1607
2452
|
[(0, import_datalog4.lit)("wanted", (0, import_datalog4.variable)("x")), (0, import_datalog4.lit)("isWrittenAs", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("z"))]
|
|
1608
2453
|
),
|
|
1609
2454
|
// A call is given no `comesTo`, so this is the only way to ask what
|
|
1610
|
-
// object one arrives at, and
|
|
1611
|
-
//
|
|
2455
|
+
// object one arrives at, and a demand-driven run derives `objectOf`
|
|
2456
|
+
// nowhere without it. An allocation site is not one of the answers.
|
|
1612
2457
|
(0, import_datalog4.rule)(
|
|
1613
2458
|
"wantedObjectOf",
|
|
1614
2459
|
[(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("z")],
|
|
1615
|
-
[
|
|
2460
|
+
[
|
|
2461
|
+
(0, import_datalog4.lit)("wanted", (0, import_datalog4.variable)("x")),
|
|
2462
|
+
(0, import_datalog4.lit)("objectOf", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("z")),
|
|
2463
|
+
(0, import_datalog4.lit)("objectValue", (0, import_datalog4.variable)("z"))
|
|
2464
|
+
]
|
|
2465
|
+
),
|
|
2466
|
+
// The same three questions under one allocation site, keyed by the
|
|
2467
|
+
// value and the site both. An allocation site is an answer here,
|
|
2468
|
+
// unlike `wantedObjectOf`, since a site is what a context is.
|
|
2469
|
+
(0, import_datalog4.rule)(
|
|
2470
|
+
"wantedIsWrittenAsUnder",
|
|
2471
|
+
[(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("z")],
|
|
2472
|
+
[
|
|
2473
|
+
(0, import_datalog4.lit)("wantedUnder", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("c")),
|
|
2474
|
+
(0, import_datalog4.lit)("isWrittenAsUnder", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("z"))
|
|
2475
|
+
]
|
|
2476
|
+
),
|
|
2477
|
+
// Where a class was made, for a caller about to ask a value question
|
|
2478
|
+
// under each. Going through `constructsNamed` keeps the demand on the
|
|
2479
|
+
// calls written with the class's name rather than on every call.
|
|
2480
|
+
(0, import_datalog4.rule)(
|
|
2481
|
+
"wantedAllocatedAt",
|
|
2482
|
+
[(0, import_datalog4.variable)("cls"), (0, import_datalog4.variable)("site")],
|
|
2483
|
+
[
|
|
2484
|
+
(0, import_datalog4.lit)("wantedSites", (0, import_datalog4.variable)("cls")),
|
|
2485
|
+
(0, import_datalog4.lit)("constructsNamed", (0, import_datalog4.variable)("site"), (0, import_datalog4.variable)("cls")),
|
|
2486
|
+
(0, import_datalog4.lit)("allocates", (0, import_datalog4.variable)("site"), (0, import_datalog4.variable)("cls"))
|
|
2487
|
+
]
|
|
2488
|
+
),
|
|
2489
|
+
(0, import_datalog4.rule)(
|
|
2490
|
+
"wantedComesToUnder",
|
|
2491
|
+
[(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("z")],
|
|
2492
|
+
[
|
|
2493
|
+
(0, import_datalog4.lit)("wantedUnder", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("c")),
|
|
2494
|
+
(0, import_datalog4.lit)("comesToUnder", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("z"))
|
|
2495
|
+
]
|
|
2496
|
+
),
|
|
2497
|
+
(0, import_datalog4.rule)(
|
|
2498
|
+
"wantedObjectOfUnder",
|
|
2499
|
+
[(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("z")],
|
|
2500
|
+
[
|
|
2501
|
+
(0, import_datalog4.lit)("wantedUnder", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("c")),
|
|
2502
|
+
(0, import_datalog4.lit)("objectOfUnder", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("z"))
|
|
2503
|
+
]
|
|
1616
2504
|
),
|
|
1617
2505
|
// The same for the function a call returns: `app.use(requireCaller(config))`
|
|
1618
2506
|
// registers what the factory gives back, and `resolves` on the call
|
|
@@ -1629,6 +2517,19 @@ var RESOLUTION_QUESTIONS = [
|
|
|
1629
2517
|
[(0, import_datalog4.variable)("p"), (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("z")],
|
|
1630
2518
|
[(0, import_datalog4.lit)("wanted", (0, import_datalog4.variable)("p")), (0, import_datalog4.lit)("paramAt", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("p"), (0, import_datalog4.variable)("z"))]
|
|
1631
2519
|
),
|
|
2520
|
+
// The argument as the caller wrote it. A parameter given a GraphQL
|
|
2521
|
+
// document has no `paramAt` answer, since that settles through
|
|
2522
|
+
// `comesTo`, which stops at a function or an object.
|
|
2523
|
+
(0, import_datalog4.rule)(
|
|
2524
|
+
"wantedPassesArgument",
|
|
2525
|
+
[(0, import_datalog4.variable)("p"), (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("a")],
|
|
2526
|
+
[(0, import_datalog4.lit)("wanted", (0, import_datalog4.variable)("p")), (0, import_datalog4.lit)("passesArgument", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("p"), (0, import_datalog4.variable)("a"))]
|
|
2527
|
+
),
|
|
2528
|
+
(0, import_datalog4.rule)(
|
|
2529
|
+
"wantedReturnsCall",
|
|
2530
|
+
[(0, import_datalog4.variable)("f"), (0, import_datalog4.variable)("c")],
|
|
2531
|
+
[(0, import_datalog4.lit)("wanted", (0, import_datalog4.variable)("f")), (0, import_datalog4.lit)("returnsCall", (0, import_datalog4.variable)("f"), (0, import_datalog4.variable)("c"))]
|
|
2532
|
+
),
|
|
1632
2533
|
(0, import_datalog4.rule)(
|
|
1633
2534
|
"wantedComesFrom",
|
|
1634
2535
|
[(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("m"), (0, import_datalog4.variable)("n")],
|
|
@@ -1892,36 +2793,62 @@ var RESOLUTION_QUESTIONS = [
|
|
|
1892
2793
|
var ANSWER_RELATIONS = [
|
|
1893
2794
|
...new Set(RESOLUTION_QUESTIONS.map((r) => r.head.relation))
|
|
1894
2795
|
];
|
|
2796
|
+
var UNDER_ANSWER_RELATIONS = [
|
|
2797
|
+
"wantedIsWrittenAsUnder",
|
|
2798
|
+
"wantedComesToUnder",
|
|
2799
|
+
"wantedObjectOfUnder"
|
|
2800
|
+
];
|
|
1895
2801
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1896
2802
|
0 && (module.exports = {
|
|
1897
2803
|
ANSWER_RELATIONS,
|
|
1898
2804
|
ASKING_RELATIONS,
|
|
2805
|
+
BASE_CLASS_RULE,
|
|
1899
2806
|
FACT_CONTRACT_CASES,
|
|
2807
|
+
INSTANCE_STEP,
|
|
1900
2808
|
NAMESPACE_IMPORT,
|
|
1901
2809
|
NAMESPACE_IMPORT_NAME,
|
|
2810
|
+
NAMESPACE_MEMBER_RULE,
|
|
2811
|
+
NO_CONTEXT,
|
|
2812
|
+
NO_CONTEXT_NAME,
|
|
1902
2813
|
RESOLUTION_QUESTIONS,
|
|
1903
2814
|
RESOLUTION_RULES,
|
|
1904
2815
|
RESULT_STEP,
|
|
2816
|
+
UNDER_ANSWER_RELATIONS,
|
|
2817
|
+
UNDER_QUESTION_ROW_BUDGET,
|
|
2818
|
+
UNDER_RUN_ROW_BUDGET,
|
|
1905
2819
|
VALUE_STEP,
|
|
2820
|
+
addPackWords,
|
|
1906
2821
|
agreedMountPrefix,
|
|
2822
|
+
allocationSitesOf,
|
|
2823
|
+
alsoSteps,
|
|
2824
|
+
answersByKey,
|
|
1907
2825
|
askResolution,
|
|
2826
|
+
askResolutionUnder,
|
|
1908
2827
|
calleeOutcomeOf,
|
|
1909
2828
|
calleeOutcomes,
|
|
1910
2829
|
checkFactContract,
|
|
2830
|
+
comesToUnder,
|
|
1911
2831
|
couldBeSettled,
|
|
1912
2832
|
explainResolutionProof,
|
|
1913
2833
|
explainResolvedKey,
|
|
2834
|
+
isWrittenAsUnder,
|
|
1914
2835
|
joinMountedPath,
|
|
1915
2836
|
mountPathsOf,
|
|
1916
2837
|
nodeOfKey,
|
|
2838
|
+
objectOfUnder,
|
|
1917
2839
|
placeholderValues,
|
|
1918
2840
|
queryFacts,
|
|
1919
2841
|
renderExplanation,
|
|
1920
2842
|
resolutionProgram,
|
|
2843
|
+
resolutionUnderProgram,
|
|
1921
2844
|
singleAnswers,
|
|
1922
2845
|
startsAtName,
|
|
2846
|
+
underQuestionSpend,
|
|
1923
2847
|
valueLeftByWrites,
|
|
1924
2848
|
writesRunInOrder,
|
|
1925
2849
|
writtenSourcesOf,
|
|
1926
|
-
writtenValueOf
|
|
2850
|
+
writtenValueOf,
|
|
2851
|
+
writtenValueUnder,
|
|
2852
|
+
writtenValuesByKey,
|
|
2853
|
+
writtenValuesOf
|
|
1927
2854
|
});
|