@suss/resolution 0.30.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 CHANGED
@@ -22,34 +22,52 @@ 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,
31
37
  VALUE_STEP: () => VALUE_STEP,
38
+ addPackWords: () => addPackWords,
32
39
  agreedMountPrefix: () => agreedMountPrefix,
40
+ allocationSitesOf: () => allocationSitesOf,
41
+ alsoSteps: () => alsoSteps,
42
+ answersByKey: () => answersByKey,
33
43
  askResolution: () => askResolution,
44
+ askResolutionUnder: () => askResolutionUnder,
34
45
  calleeOutcomeOf: () => calleeOutcomeOf,
35
46
  calleeOutcomes: () => calleeOutcomes,
36
47
  checkFactContract: () => checkFactContract,
48
+ comesToUnder: () => comesToUnder,
37
49
  couldBeSettled: () => couldBeSettled,
38
50
  explainResolutionProof: () => explainResolutionProof,
39
51
  explainResolvedKey: () => explainResolvedKey,
52
+ isWrittenAsUnder: () => isWrittenAsUnder,
40
53
  joinMountedPath: () => joinMountedPath,
41
54
  mountPathsOf: () => mountPathsOf,
42
55
  nodeOfKey: () => nodeOfKey,
56
+ objectOfUnder: () => objectOfUnder,
43
57
  placeholderValues: () => placeholderValues,
44
58
  queryFacts: () => queryFacts,
45
59
  renderExplanation: () => renderExplanation,
46
60
  resolutionProgram: () => resolutionProgram,
61
+ resolutionUnderProgram: () => resolutionUnderProgram,
47
62
  singleAnswers: () => singleAnswers,
48
63
  startsAtName: () => startsAtName,
49
64
  valueLeftByWrites: () => valueLeftByWrites,
50
65
  writesRunInOrder: () => writesRunInOrder,
51
66
  writtenSourcesOf: () => writtenSourcesOf,
52
- writtenValueOf: () => writtenValueOf
67
+ writtenValueOf: () => writtenValueOf,
68
+ writtenValueUnder: () => writtenValueUnder,
69
+ writtenValuesByKey: () => writtenValuesByKey,
70
+ writtenValuesOf: () => writtenValuesOf
53
71
  });
54
72
  module.exports = __toCommonJS(index_exports);
55
73
 
@@ -57,6 +75,8 @@ module.exports = __toCommonJS(index_exports);
57
75
  var import_datalog = require("@suss/datalog");
58
76
  var ASKING_RELATIONS = [
59
77
  "wanted",
78
+ "wantedUnder",
79
+ "wantedSites",
60
80
  "wantedOrigin",
61
81
  "wantedCallOrigin",
62
82
  "wantedExportsOf",
@@ -66,8 +86,12 @@ var ASKING_RELATIONS = [
66
86
  ];
67
87
  var NO_LANGUAGE_RULES = [];
68
88
  var programs = /* @__PURE__ */ new WeakMap();
69
- function resolutionProgram(languageRules = NO_LANGUAGE_RULES) {
70
- const built = programs.get(languageRules);
89
+ var underPrograms = /* @__PURE__ */ new WeakMap();
90
+ var contextFreeAnswers = () => ANSWER_RELATIONS.filter(
91
+ (relation) => !UNDER_ANSWER_RELATIONS.includes(relation)
92
+ );
93
+ function builtProgram(languageRules, cache, complete) {
94
+ const built = cache.get(languageRules);
71
95
  if (built !== void 0) {
72
96
  return built;
73
97
  }
@@ -76,10 +100,16 @@ function resolutionProgram(languageRules = NO_LANGUAGE_RULES) {
76
100
  ...languageRules,
77
101
  ...RESOLUTION_QUESTIONS
78
102
  ];
79
- const program = process.env.SUSS_RESOLUTION_ON_DEMAND === "0" ? { rules, demandDriven: [], demands: [] } : (0, import_datalog.deriveOnDemand)(rules, ANSWER_RELATIONS);
80
- programs.set(languageRules, program);
103
+ const program = process.env.SUSS_RESOLUTION_ON_DEMAND === "0" ? { rules, demandDriven: [], demands: [] } : (0, import_datalog.deriveOnDemand)(rules, complete);
104
+ cache.set(languageRules, program);
81
105
  return program;
82
106
  }
107
+ function resolutionProgram(languageRules = NO_LANGUAGE_RULES) {
108
+ return builtProgram(languageRules, programs, contextFreeAnswers());
109
+ }
110
+ function resolutionUnderProgram(languageRules = NO_LANGUAGE_RULES) {
111
+ return builtProgram(languageRules, underPrograms, ANSWER_RELATIONS);
112
+ }
83
113
  function queryFacts(program) {
84
114
  if (program.demandDriven.length === 0) {
85
115
  return [];
@@ -116,6 +146,29 @@ function askResolution(db, keys, asking = "wanted", program = resolutionProgram(
116
146
  (0, import_datalog.clearRelations)(db, program.rules, forget);
117
147
  }
118
148
  }
149
+ var askedUnderByDb = /* @__PURE__ */ new WeakMap();
150
+ function askResolutionUnder(db, pairs, program = resolutionUnderProgram()) {
151
+ let asked = askedUnderByDb.get(db);
152
+ if (asked === void 0) {
153
+ asked = /* @__PURE__ */ new Set();
154
+ askedUnderByDb.set(db, asked);
155
+ }
156
+ const fresh = [...pairs].filter(
157
+ ([key, site]) => !asked.has((0, import_datalog.tupleKey)([key, site]))
158
+ );
159
+ if (fresh.length === 0) {
160
+ return;
161
+ }
162
+ for (const [key, site] of fresh) {
163
+ asked.add((0, import_datalog.tupleKey)([key, site]));
164
+ db.add("wantedUnder", [key, site]);
165
+ }
166
+ (0, import_datalog.evaluate)(db, program.rules);
167
+ const forget = queryFacts(program);
168
+ if (forget.length > 0) {
169
+ (0, import_datalog.clearRelations)(db, program.rules, forget);
170
+ }
171
+ }
119
172
 
120
173
  // src/callee.ts
121
174
  var UNDECLARED = { kind: "undeclared" };
@@ -544,6 +597,12 @@ var DEFAULT_PHRASES = {
544
597
  "last write": ({ tuple, describe }) => ({
545
598
  reason: `${describe(tuple[0])} is written more than once, and the last write leaves it as ${describe(tuple[1])}`
546
599
  }),
600
+ "one of several writes": ({ tuple, describe }) => ({
601
+ reason: `${describe(tuple[0])} is written more than once, and one of those writes makes it ${describe(tuple[1])}`,
602
+ assumptions: [
603
+ `nothing says which write to ${describe(tuple[0])} ran last, so every write it has is a possible value`
604
+ ]
605
+ }),
547
606
  fallback: ({ tuple, describe }) => ({
548
607
  reason: `${describe(tuple[0])} is a fallback expression, and ${describe(tuple[1])} is the branch that resolves`
549
608
  }),
@@ -560,7 +619,7 @@ var DEFAULT_PHRASES = {
560
619
  "property read": ({ tuple, premises, describe }) => {
561
620
  const [, object, name] = premises[0].tuple;
562
621
  const contains = premises[2];
563
- const inherited = contains.kind === "derived" && contains.premises.length > 1;
622
+ const inherited = contains.kind === "derived" && (0, import_datalog2.ruleLabel)(contains.rule) === BASE_CLASS_RULE;
564
623
  return {
565
624
  reason: `${describe(tuple[0])} reads ${String(name)} off ${describe(object)}, which contains ${describe(tuple[1])}`,
566
625
  notes: inherited ? [`${String(name)} comes from a base class`] : []
@@ -639,7 +698,8 @@ var CHAIN_RELATIONS = /* @__PURE__ */ new Set([
639
698
  "isWrittenAs",
640
699
  "comesFrom",
641
700
  "reaches",
642
- "stepsTo"
701
+ "stepsTo",
702
+ "hop"
643
703
  ]);
644
704
  function inlineChain(proof, state) {
645
705
  const explained = explainResolutionProof(proof, {
@@ -695,6 +755,17 @@ function importStep(proof, state) {
695
755
  assumptions: []
696
756
  };
697
757
  }
758
+ function namespaceMemberStep(proof, state) {
759
+ const [x, module2, name] = proof.tuple;
760
+ return {
761
+ from: x,
762
+ to: module2,
763
+ rule: NAMESPACE_MEMBER_RULE,
764
+ reason: `${state.describe(x)} reads ${String(name)} off ${state.describe(module2)}, which is imported whole`,
765
+ notes: [],
766
+ assumptions: []
767
+ };
768
+ }
698
769
  var flattenInto = (proof, state) => {
699
770
  if (proof.kind === "truncated") {
700
771
  state.truncated = true;
@@ -704,7 +775,7 @@ var flattenInto = (proof, state) => {
704
775
  return;
705
776
  }
706
777
  const relation = proof.relation;
707
- if (relation === "stepsTo") {
778
+ if (relation === "stepsTo" || relation === "hop") {
708
779
  state.steps.push(stepFrom(proof, state));
709
780
  return;
710
781
  }
@@ -715,6 +786,10 @@ var flattenInto = (proof, state) => {
715
786
  return;
716
787
  }
717
788
  if (relation === "comesFrom") {
789
+ if ((0, import_datalog2.ruleLabel)(proof.rule) === NAMESPACE_MEMBER_RULE) {
790
+ state.steps.push(namespaceMemberStep(proof, state));
791
+ return;
792
+ }
718
793
  if (proof.premises.length === 2) {
719
794
  flattenInto(proof.premises[0], state);
720
795
  state.steps.push(importStep(proof.premises[1], state));
@@ -891,6 +966,37 @@ function nodeOfKey(rootsByFile, key) {
891
966
  return null;
892
967
  }
893
968
 
969
+ // src/packWords.ts
970
+ function addPackWords(db, words) {
971
+ for (const word of words.givesBackOne ?? []) {
972
+ db.add("givesBackOne", [word.base, word.method]);
973
+ }
974
+ for (const word of words.givesBackOneOfArgument ?? []) {
975
+ db.add("givesBackOneOfArgument", [
976
+ word.base,
977
+ word.method,
978
+ String(word.argument)
979
+ ]);
980
+ }
981
+ for (const word of words.givesBackOneOfImport ?? []) {
982
+ db.add("givesBackOneOfImport", [
983
+ word.module,
984
+ word.name,
985
+ String(word.argument)
986
+ ]);
987
+ }
988
+ for (const word of words.entersAsSelf ?? []) {
989
+ db.add("entersAsSelf", [word.module, word.name]);
990
+ }
991
+ for (const word of words.unwrapsByName ?? []) {
992
+ db.add("unwrapsByName", [word.callee, String(word.argument)]);
993
+ db.add("wrapperModule", [word.callee, word.module]);
994
+ }
995
+ for (const word of words.associationConstructor ?? []) {
996
+ db.add("associationConstructor", [word.module, word.name]);
997
+ }
998
+ }
999
+
894
1000
  // src/session.ts
895
1001
  var import_datalog3 = require("@suss/datalog");
896
1002
  function explainResolvedKey(options) {
@@ -946,7 +1052,7 @@ function explainResolvedKey(options) {
946
1052
 
947
1053
  // src/singleAnswer.ts
948
1054
  var NO_PLACEHOLDERS = /* @__PURE__ */ new Set();
949
- function singleAnswers(rows, placeholders = NO_PLACEHOLDERS) {
1055
+ function answersByKey(rows, placeholders = NO_PLACEHOLDERS) {
950
1056
  const candidates = /* @__PURE__ */ new Map();
951
1057
  for (const row of rows) {
952
1058
  const key = String(row[0]);
@@ -958,9 +1064,15 @@ function singleAnswers(rows, placeholders = NO_PLACEHOLDERS) {
958
1064
  set.add(answer);
959
1065
  candidates.set(key, set);
960
1066
  }
961
- const settled = /* @__PURE__ */ new Map();
1067
+ const answers = /* @__PURE__ */ new Map();
962
1068
  for (const [key, set] of candidates) {
963
- const answers = withoutPlaceholders(set, placeholders);
1069
+ answers.set(key, withoutPlaceholders(set, placeholders));
1070
+ }
1071
+ return answers;
1072
+ }
1073
+ function singleAnswers(rows, placeholders = NO_PLACEHOLDERS) {
1074
+ const settled = /* @__PURE__ */ new Map();
1075
+ for (const [key, answers] of answersByKey(rows, placeholders)) {
964
1076
  if (answers.length === 1) {
965
1077
  settled.set(key, answers[0]);
966
1078
  }
@@ -978,6 +1090,28 @@ function withoutPlaceholders(answers, placeholders) {
978
1090
  return kept;
979
1091
  }
980
1092
 
1093
+ // src/underContext.ts
1094
+ function answersUnder(db, relation, key, site) {
1095
+ return db.lookup(relation, 0, key).filter((row) => String(row[1]) === site).map((row) => String(row[2]));
1096
+ }
1097
+ function isWrittenAsUnder(db, key, site) {
1098
+ return answersUnder(db, "wantedIsWrittenAsUnder", key, site);
1099
+ }
1100
+ function comesToUnder(db, key, site) {
1101
+ return answersUnder(db, "wantedComesToUnder", key, site);
1102
+ }
1103
+ function objectOfUnder(db, key, site) {
1104
+ return answersUnder(db, "wantedObjectOfUnder", key, site);
1105
+ }
1106
+ function writtenValueUnder(db, key, site) {
1107
+ const rows = isWrittenAsUnder(db, key, site).map((answer) => [key, answer]);
1108
+ const answers = answersByKey(rows, placeholderValues(db)).get(key) ?? [];
1109
+ return answers.length === 1 ? answers[0] : null;
1110
+ }
1111
+ function allocationSitesOf(db, cls) {
1112
+ return db.lookup("wantedAllocatedAt", 0, cls).map((row) => String(row[1]));
1113
+ }
1114
+
981
1115
  // src/writes.ts
982
1116
  function valueLeftByWrites(writes, ordered) {
983
1117
  const deciding = writes.filter((write) => !write.narrowsName);
@@ -1008,23 +1142,58 @@ function sharedConstruction(writes) {
1008
1142
  }
1009
1143
 
1010
1144
  // src/writtenValue.ts
1011
- function writtenValueOf(db, key, ask) {
1012
- const placeholders = placeholderValues(db);
1013
- const direct = singleAnswers(db.facts("wantedIsWrittenAs"), placeholders).get(
1014
- key
1015
- );
1016
- if (direct === void 0) {
1017
- return null;
1145
+ var WRITTEN_AS = "wantedIsWrittenAs";
1146
+ function writtenValueOf(db, key, ask, relation = WRITTEN_AS) {
1147
+ const answers = settledByKey(db, [key], ask, relation).get(key) ?? [];
1148
+ return answers.length === 1 ? answers[0] : null;
1149
+ }
1150
+ function writtenValuesOf(db, key, ask, relation = WRITTEN_AS) {
1151
+ const settled = settledByKey(db, [key], ask, relation).get(key) ?? [];
1152
+ return settled.length > 0 ? settled : writesLeft(db, key);
1153
+ }
1154
+ function writtenValuesByKey(db, keys, ask, relation = WRITTEN_AS) {
1155
+ const one = /* @__PURE__ */ new Map();
1156
+ for (const [key, answers] of settledByKey(db, keys, ask, relation)) {
1157
+ if (answers.length === 1) {
1158
+ one.set(key, answers[0]);
1159
+ }
1018
1160
  }
1019
- const isCall = db.facts("call").some((row) => String(row[0]) === direct);
1020
- if (!isCall) {
1161
+ return one;
1162
+ }
1163
+ function settledByKey(db, keys, ask, relation) {
1164
+ const placeholders = placeholderValues(db);
1165
+ const byKey = answersByKey(db.facts(relation), placeholders);
1166
+ const direct = new Map(keys.map((key) => [key, byKey.get(key) ?? []]));
1167
+ const calls = new Set(db.facts("call").map((row) => String(row[0])));
1168
+ const throughCalls = [...direct.values()].flat().filter((answer) => calls.has(answer));
1169
+ if (throughCalls.length === 0) {
1021
1170
  return direct;
1022
1171
  }
1023
- ask([direct]);
1024
- const deeper = singleAnswers(db.facts("wantedIsWrittenAs"), placeholders).get(
1025
- direct
1172
+ ask(throughCalls);
1173
+ const deeper = singleAnswers(db.facts(relation), placeholders);
1174
+ return new Map(
1175
+ [...direct].map(([key, answers]) => [
1176
+ key,
1177
+ collapseCalls(answers, calls, deeper)
1178
+ ])
1026
1179
  );
1027
- return deeper ?? direct;
1180
+ }
1181
+ function collapseCalls(direct, calls, deeper) {
1182
+ return [
1183
+ ...new Set(
1184
+ direct.map(
1185
+ (answer) => calls.has(answer) ? deeper.get(answer) ?? answer : answer
1186
+ )
1187
+ )
1188
+ ];
1189
+ }
1190
+ function writesLeft(db, key) {
1191
+ const unstated = db.facts("writesUnstated").some((row) => String(row[0]) === key);
1192
+ if (unstated) {
1193
+ return [];
1194
+ }
1195
+ const candidates = answersByKey(db.facts("mayHold"), placeholderValues(db)).get(key) ?? [];
1196
+ return candidates.length > 1 ? candidates : [];
1028
1197
  }
1029
1198
 
1030
1199
  // src/index.ts
@@ -1032,38 +1201,61 @@ var import_datalog4 = require("@suss/datalog");
1032
1201
  var VALUE_STEP = (0, import_datalog4.constant)("value");
1033
1202
  var NAMESPACE_IMPORT_NAME = "*";
1034
1203
  var NAMESPACE_IMPORT = (0, import_datalog4.constant)(NAMESPACE_IMPORT_NAME);
1204
+ var NAMESPACE_MEMBER_RULE = "namespace member";
1205
+ var BASE_CLASS_RULE = "base class";
1206
+ var INSTANCE_STEP = (0, import_datalog4.constant)("instance");
1035
1207
  var RESULT_STEP = (0, import_datalog4.constant)("result");
1036
- var RESOLUTION_RULES = [
1208
+ var NO_CONTEXT_NAME = "none";
1209
+ var NO_CONTEXT = (0, import_datalog4.constant)(NO_CONTEXT_NAME);
1210
+ var STEP_LATTICE = [
1211
+ { soFar: VALUE_STEP, next: (0, import_datalog4.variable)("kind"), took: (0, import_datalog4.variable)("kind") },
1212
+ { soFar: INSTANCE_STEP, next: VALUE_STEP, took: INSTANCE_STEP },
1213
+ { soFar: INSTANCE_STEP, next: INSTANCE_STEP, took: INSTANCE_STEP },
1214
+ { soFar: INSTANCE_STEP, next: RESULT_STEP, took: RESULT_STEP },
1215
+ { soFar: RESULT_STEP, next: VALUE_STEP, took: RESULT_STEP },
1216
+ { soFar: RESULT_STEP, next: INSTANCE_STEP, took: RESULT_STEP },
1217
+ { soFar: RESULT_STEP, next: RESULT_STEP, took: RESULT_STEP }
1218
+ ];
1219
+ var STATED_RULES = [
1037
1220
  // Aliasing: const x = y, or an identifier referencing a declaration.
1038
1221
  // A language with a hop of its own, like JavaScript's `.bind`, states
1039
1222
  // it as a step too, or every question but `comesTo` misses it.
1040
1223
  (0, import_datalog4.rule)(
1041
- "stepsTo",
1224
+ "hop",
1042
1225
  [(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("y"), VALUE_STEP],
1043
1226
  [(0, import_datalog4.lit)("binds", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("y"))],
1044
1227
  "alias"
1045
1228
  ),
1046
1229
  // 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, so such a name steps nowhere at all.
1230
+ // there. The adapter works out which write that is, and stays quiet
1231
+ // when control flow decides; the rule below takes that name instead.
1049
1232
  (0, import_datalog4.rule)(
1050
- "stepsTo",
1233
+ "hop",
1051
1234
  [(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("y"), VALUE_STEP],
1052
1235
  [(0, import_datalog4.lit)("endsHolding", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("y"))],
1053
1236
  "last write"
1054
1237
  ),
1238
+ // A name whose writes nothing orders leads to each of them, so a
1239
+ // caller that can use several values gets them all and one that needs
1240
+ // a single value gets none. A write stating no value stops every step.
1241
+ (0, import_datalog4.rule)(
1242
+ "hop",
1243
+ [(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("y"), VALUE_STEP],
1244
+ [(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"))],
1245
+ "one of several writes"
1246
+ ),
1055
1247
  // A fallback says the value is one of its branches, so each branch is
1056
1248
  // a step. A branch that resolves to nothing makes no claim, and two
1057
1249
  // branches resolving to different things fail the single-answer policy.
1058
1250
  (0, import_datalog4.rule)(
1059
- "stepsTo",
1251
+ "hop",
1060
1252
  [(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("b"), VALUE_STEP],
1061
1253
  [(0, import_datalog4.lit)("fallbackBranch", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("b"))],
1062
1254
  "fallback"
1063
1255
  ),
1064
1256
  // An import steps to what the module exports under that name.
1065
1257
  (0, import_datalog4.rule)(
1066
- "stepsTo",
1258
+ "hop",
1067
1259
  [(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("value"), VALUE_STEP],
1068
1260
  [
1069
1261
  (0, import_datalog4.lit)("imports", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("m"), (0, import_datalog4.variable)("n")),
@@ -1097,8 +1289,8 @@ var RESOLUTION_RULES = [
1097
1289
  // a method read off the result is the one the class declares. The
1098
1290
  // caveat below is about a factory function, and a class is not one.
1099
1291
  (0, import_datalog4.rule)(
1100
- "stepsTo",
1101
- [(0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("cls"), VALUE_STEP],
1292
+ "hop",
1293
+ [(0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("cls"), INSTANCE_STEP],
1102
1294
  [
1103
1295
  (0, import_datalog4.lit)("call", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("c")),
1104
1296
  (0, import_datalog4.lit)("comesTo", (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("cls")),
@@ -1106,12 +1298,21 @@ var RESOLUTION_RULES = [
1106
1298
  ],
1107
1299
  "class instance"
1108
1300
  ),
1301
+ // The receiver a method is called on. Being one of a class is the
1302
+ // same hop a construction takes, so a method read off `self` finds
1303
+ // what the class declares.
1304
+ (0, import_datalog4.rule)(
1305
+ "hop",
1306
+ [(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("cls"), INSTANCE_STEP],
1307
+ [(0, import_datalog4.lit)("instanceOf", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("cls"))],
1308
+ "receiver instance"
1309
+ ),
1109
1310
  // A finder the library declares, keyed on the base a pack named so a
1110
1311
  // project class with a method of the same name on another hierarchy is
1111
1312
  // left alone. The DESIGN says what a chain of them composes into.
1112
1313
  (0, import_datalog4.rule)(
1113
- "stepsTo",
1114
- [(0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("cls"), VALUE_STEP],
1314
+ "hop",
1315
+ [(0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("cls"), INSTANCE_STEP],
1115
1316
  [
1116
1317
  (0, import_datalog4.lit)("call", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("c")),
1117
1318
  (0, import_datalog4.lit)("readsProperty", (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("o"), (0, import_datalog4.variable)("m")),
@@ -1128,8 +1329,8 @@ var RESOLUTION_RULES = [
1128
1329
  // instead of as the receiver. The argument having to reach the base a
1129
1330
  // pack named is what keeps an unrelated `get` out.
1130
1331
  (0, import_datalog4.rule)(
1131
- "stepsTo",
1132
- [(0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("cls"), VALUE_STEP],
1332
+ "hop",
1333
+ [(0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("cls"), INSTANCE_STEP],
1133
1334
  [
1134
1335
  (0, import_datalog4.lit)("call", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("c")),
1135
1336
  (0, import_datalog4.lit)("readsProperty", (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("o"), (0, import_datalog4.variable)("m")),
@@ -1146,8 +1347,8 @@ var RESOLUTION_RULES = [
1146
1347
  // anything, keyed on the module it was imported from so a project
1147
1348
  // function spelled the same way is not mistaken for it.
1148
1349
  (0, import_datalog4.rule)(
1149
- "stepsTo",
1150
- [(0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("cls"), VALUE_STEP],
1350
+ "hop",
1351
+ [(0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("cls"), INSTANCE_STEP],
1151
1352
  [
1152
1353
  (0, import_datalog4.lit)("call", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("c")),
1153
1354
  (0, import_datalog4.lit)("comesFrom", (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("mod"), (0, import_datalog4.variable)("n")),
@@ -1157,10 +1358,24 @@ var RESOLUTION_RULES = [
1157
1358
  ],
1158
1359
  "declared import finder"
1159
1360
  ),
1361
+ // A block opened over a library's own constructor. The pack says
1362
+ // entering one gives back the object it built, so the name the block
1363
+ // opens is that call.
1364
+ (0, import_datalog4.rule)(
1365
+ "hop",
1366
+ [(0, import_datalog4.variable)("y"), (0, import_datalog4.variable)("r"), VALUE_STEP],
1367
+ [
1368
+ (0, import_datalog4.lit)("entersAs", (0, import_datalog4.variable)("y"), (0, import_datalog4.variable)("r")),
1369
+ (0, import_datalog4.lit)("call", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("c")),
1370
+ (0, import_datalog4.lit)("comesFrom", (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("mod"), (0, import_datalog4.variable)("n")),
1371
+ (0, import_datalog4.lit)("entersAsSelf", (0, import_datalog4.variable)("mod"), (0, import_datalog4.variable)("n"))
1372
+ ],
1373
+ "context manager returns self"
1374
+ ),
1160
1375
  // Wrapper transparency, derived: calling a factory that returns a
1161
1376
  // function which calls its parameter k steps to argument k.
1162
1377
  (0, import_datalog4.rule)(
1163
- "stepsTo",
1378
+ "hop",
1164
1379
  [(0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("a"), VALUE_STEP],
1165
1380
  [
1166
1381
  (0, import_datalog4.lit)("call", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("c")),
@@ -1174,7 +1389,7 @@ var RESOLUTION_RULES = [
1174
1389
  // argument k. The callee has to come from the library the pack said,
1175
1390
  // so a local object spelled the same way is not mistaken for it.
1176
1391
  (0, import_datalog4.rule)(
1177
- "stepsTo",
1392
+ "hop",
1178
1393
  [(0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("a"), VALUE_STEP],
1179
1394
  [
1180
1395
  (0, import_datalog4.lit)("calleeName", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("n")),
@@ -1188,44 +1403,441 @@ var RESOLUTION_RULES = [
1188
1403
  // The one step that runs a function forwards: a call steps to what
1189
1404
  // the function it invokes returns.
1190
1405
  (0, import_datalog4.rule)(
1191
- "stepsTo",
1406
+ "hop",
1192
1407
  [(0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("ret"), RESULT_STEP],
1193
1408
  [(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
1409
  "call result"
1195
1410
  ),
1196
- // Where a walk gets to, and whether it ran a call on the way. The walk
1197
- // so far comes first, so demand stays on the value asked about; the
1198
- // README says what the other order cost.
1411
+ // What a function says it gives back when its body never states a
1412
+ // value. The adapter stays quiet about the annotation whenever the
1413
+ // body does state one, so the two never answer the same question.
1414
+ (0, import_datalog4.rule)(
1415
+ "hop",
1416
+ [(0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("cls"), RESULT_STEP],
1417
+ [
1418
+ (0, import_datalog4.lit)("invokes", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("f")),
1419
+ (0, import_datalog4.lit)("returnsClass", (0, import_datalog4.variable)("f"), (0, import_datalog4.variable)("x")),
1420
+ (0, import_datalog4.lit)("comesTo", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("cls")),
1421
+ (0, import_datalog4.lit)("objectValue", (0, import_datalog4.variable)("cls"))
1422
+ ],
1423
+ "declared return type"
1424
+ ),
1425
+ // Where a walk gets to, under the strongest step it took: value, then
1426
+ // instance, then result. The walk so far comes first, so demand stays
1427
+ // on the value asked about; the README says what the other order cost.
1199
1428
  (0, import_datalog4.rule)(
1200
1429
  "reaches",
1201
1430
  [(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("z"), (0, import_datalog4.variable)("kind")],
1202
1431
  [(0, import_datalog4.lit)("stepsTo", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("z"), (0, import_datalog4.variable)("kind"))]
1203
1432
  ),
1433
+ // A rule per pair rather than one leaving the next step's kind free. A
1434
+ // free kind is a second question about the same relation, and a
1435
+ // demand-driven run then derives both to answer either.
1436
+ ...STEP_LATTICE.map(
1437
+ ({ soFar, next, took }) => (0, import_datalog4.rule)(
1438
+ "reaches",
1439
+ [(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("z"), took],
1440
+ [
1441
+ (0, import_datalog4.lit)("reaches", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("y"), soFar),
1442
+ (0, import_datalog4.lit)("stepsTo", (0, import_datalog4.variable)("y"), (0, import_datalog4.variable)("z"), next)
1443
+ ]
1444
+ )
1445
+ ),
1446
+ // A context is an allocation site, or nothing at all for a value read
1447
+ // outside every site. Both are stated, so a rule that starts a walk
1448
+ // binds its context from a premise rather than from a negation.
1449
+ (0, import_datalog4.rule)("context", [NO_CONTEXT], [], "no context"),
1450
+ (0, import_datalog4.rule)(
1451
+ "context",
1452
+ [(0, import_datalog4.variable)("site")],
1453
+ [(0, import_datalog4.lit)("allocates", (0, import_datalog4.variable)("site"), (0, import_datalog4.variable)("cls"))],
1454
+ "site context"
1455
+ ),
1456
+ // The same closure, with the context the walk started under and the
1457
+ // context it arrived under. It takes `hop`, because an argument and a
1458
+ // property read have their own rules below.
1459
+ (0, import_datalog4.rule)(
1460
+ "reachesUnder",
1461
+ [(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")],
1462
+ [(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"))],
1463
+ "under one hop"
1464
+ ),
1465
+ ...STEP_LATTICE.map(
1466
+ ({ soFar, next, took }) => (0, import_datalog4.rule)(
1467
+ "reachesUnder",
1468
+ [(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("z"), (0, import_datalog4.variable)("c2"), took],
1469
+ [
1470
+ (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),
1471
+ (0, import_datalog4.lit)("hop", (0, import_datalog4.variable)("y"), (0, import_datalog4.variable)("z"), next)
1472
+ ]
1473
+ )
1474
+ ),
1475
+ // The receiver read under a site is that site. The ordinary hop from a
1476
+ // receiver to its class stays in `hop`, so `self` under any context
1477
+ // still comes to the class a single-answer reader wants.
1204
1478
  (0, import_datalog4.rule)(
1205
- "reaches",
1206
- [(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("z"), (0, import_datalog4.variable)("kind")],
1479
+ "reachesUnder",
1480
+ [(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("c"), VALUE_STEP],
1481
+ [(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"))],
1482
+ "receiver is the site"
1483
+ ),
1484
+ (0, import_datalog4.rule)(
1485
+ "reachesUnder",
1486
+ [(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
1487
  [
1208
- (0, import_datalog4.lit)("reaches", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("y"), VALUE_STEP),
1209
- (0, import_datalog4.lit)("stepsTo", (0, import_datalog4.variable)("y"), (0, import_datalog4.variable)("z"), (0, import_datalog4.variable)("kind"))
1488
+ (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")),
1489
+ (0, import_datalog4.lit)("instanceOf", (0, import_datalog4.variable)("y"), (0, import_datalog4.variable)("cls")),
1490
+ (0, import_datalog4.lit)("allocates", (0, import_datalog4.variable)("c2"), (0, import_datalog4.variable)("cls"))
1491
+ ],
1492
+ "reached receiver is the site"
1493
+ ),
1494
+ // The object an expression refers to under a context. A site is an
1495
+ // answer here, unlike `objectOf`, and the class an instance is one of
1496
+ // is an answer only under no context.
1497
+ (0, import_datalog4.rule)(
1498
+ "objectOfUnder",
1499
+ [(0, import_datalog4.variable)("site"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("site")],
1500
+ [(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"))],
1501
+ "site is its own object"
1502
+ ),
1503
+ (0, import_datalog4.rule)(
1504
+ "objectOfUnder",
1505
+ [(0, import_datalog4.variable)("o"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("site")],
1506
+ [
1507
+ (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),
1508
+ (0, import_datalog4.lit)("allocates", (0, import_datalog4.variable)("site"), (0, import_datalog4.variable)("cls"))
1509
+ ],
1510
+ "name of a site"
1511
+ ),
1512
+ (0, import_datalog4.rule)(
1513
+ "objectOfUnder",
1514
+ [(0, import_datalog4.variable)("o"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("obj")],
1515
+ [
1516
+ (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),
1517
+ (0, import_datalog4.lit)("objectValue", (0, import_datalog4.variable)("obj"))
1518
+ ],
1519
+ "written object under a context"
1520
+ ),
1521
+ (0, import_datalog4.rule)(
1522
+ "objectOfUnder",
1523
+ [(0, import_datalog4.variable)("o"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("obj")],
1524
+ [
1525
+ (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),
1526
+ (0, import_datalog4.lit)("objectValue", (0, import_datalog4.variable)("obj"))
1527
+ ],
1528
+ "returned object under a context"
1529
+ ),
1530
+ (0, import_datalog4.rule)(
1531
+ "objectOfUnder",
1532
+ [(0, import_datalog4.variable)("o"), NO_CONTEXT, (0, import_datalog4.variable)("cls")],
1533
+ [
1534
+ (0, import_datalog4.lit)(
1535
+ "reachesUnder",
1536
+ (0, import_datalog4.variable)("o"),
1537
+ NO_CONTEXT,
1538
+ (0, import_datalog4.variable)("cls"),
1539
+ NO_CONTEXT,
1540
+ INSTANCE_STEP
1541
+ ),
1542
+ (0, import_datalog4.lit)("objectValue", (0, import_datalog4.variable)("cls"))
1543
+ ],
1544
+ "class reached with no context"
1545
+ ),
1546
+ (0, import_datalog4.rule)(
1547
+ "objectOfUnder",
1548
+ [(0, import_datalog4.variable)("o"), NO_CONTEXT, (0, import_datalog4.variable)("cls")],
1549
+ [(0, import_datalog4.lit)("instanceOf", (0, import_datalog4.variable)("o"), (0, import_datalog4.variable)("cls"))],
1550
+ "receiver class with no context"
1551
+ ),
1552
+ (0, import_datalog4.rule)(
1553
+ "objectOfUnder",
1554
+ [(0, import_datalog4.variable)("o"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("o")],
1555
+ [(0, import_datalog4.lit)("context", (0, import_datalog4.variable)("c")), (0, import_datalog4.lit)("objectValue", (0, import_datalog4.variable)("o"))],
1556
+ "object under a context is itself"
1557
+ ),
1558
+ // A property read goes on under the site the object was made at, so a
1559
+ // field read off two constructions gives each one its own value. A
1560
+ // class or a literal object keeps the context the walk was already in.
1561
+ (0, import_datalog4.rule)(
1562
+ "reachesUnder",
1563
+ [(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("held"), (0, import_datalog4.variable)("site"), VALUE_STEP],
1564
+ [
1565
+ (0, import_datalog4.lit)("context", (0, import_datalog4.variable)("c")),
1566
+ (0, import_datalog4.lit)("readsProperty", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("o"), (0, import_datalog4.variable)("n")),
1567
+ (0, import_datalog4.lit)("objectOfUnder", (0, import_datalog4.variable)("o"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("site")),
1568
+ (0, import_datalog4.lit)("allocates", (0, import_datalog4.variable)("site"), (0, import_datalog4.variable)("cls")),
1569
+ (0, import_datalog4.lit)("contains", (0, import_datalog4.variable)("site"), (0, import_datalog4.variable)("n"), (0, import_datalog4.variable)("held"))
1570
+ ],
1571
+ "property read at a site"
1572
+ ),
1573
+ (0, import_datalog4.rule)(
1574
+ "reachesUnder",
1575
+ [(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("held"), (0, import_datalog4.variable)("c"), VALUE_STEP],
1576
+ [
1577
+ (0, import_datalog4.lit)("context", (0, import_datalog4.variable)("c")),
1578
+ (0, import_datalog4.lit)("readsProperty", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("o"), (0, import_datalog4.variable)("n")),
1579
+ (0, import_datalog4.lit)("objectOfUnder", (0, import_datalog4.variable)("o"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("obj")),
1580
+ (0, import_datalog4.lit)("objectValue", (0, import_datalog4.variable)("obj")),
1581
+ (0, import_datalog4.lit)("contains", (0, import_datalog4.variable)("obj"), (0, import_datalog4.variable)("n"), (0, import_datalog4.variable)("held"))
1582
+ ],
1583
+ "property read off an object"
1584
+ ),
1585
+ (0, import_datalog4.rule)(
1586
+ "reachesUnder",
1587
+ [(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")],
1588
+ [
1589
+ (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")),
1590
+ (0, import_datalog4.lit)("readsProperty", (0, import_datalog4.variable)("y"), (0, import_datalog4.variable)("o"), (0, import_datalog4.variable)("n")),
1591
+ (0, import_datalog4.lit)("objectOfUnder", (0, import_datalog4.variable)("o"), (0, import_datalog4.variable)("c2"), (0, import_datalog4.variable)("site")),
1592
+ (0, import_datalog4.lit)("allocates", (0, import_datalog4.variable)("site"), (0, import_datalog4.variable)("cls")),
1593
+ (0, import_datalog4.lit)("contains", (0, import_datalog4.variable)("site"), (0, import_datalog4.variable)("n"), (0, import_datalog4.variable)("held"))
1594
+ ],
1595
+ "reached property read at a site"
1596
+ ),
1597
+ (0, import_datalog4.rule)(
1598
+ "reachesUnder",
1599
+ [(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")],
1600
+ [
1601
+ (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")),
1602
+ (0, import_datalog4.lit)("readsProperty", (0, import_datalog4.variable)("y"), (0, import_datalog4.variable)("o"), (0, import_datalog4.variable)("n")),
1603
+ (0, import_datalog4.lit)("objectOfUnder", (0, import_datalog4.variable)("o"), (0, import_datalog4.variable)("c2"), (0, import_datalog4.variable)("obj")),
1604
+ (0, import_datalog4.lit)("objectValue", (0, import_datalog4.variable)("obj")),
1605
+ (0, import_datalog4.lit)("contains", (0, import_datalog4.variable)("obj"), (0, import_datalog4.variable)("n"), (0, import_datalog4.variable)("held"))
1606
+ ],
1607
+ "reached property read off an object"
1608
+ ),
1609
+ // A parameter goes on at the argument, under the context its caller
1610
+ // was read in, and only from the calls that run the function under the
1611
+ // context the walk is in. This is the one hop that changes context.
1612
+ (0, import_datalog4.rule)(
1613
+ "reachesUnder",
1614
+ [(0, import_datalog4.variable)("p"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("a"), (0, import_datalog4.variable)("c3"), VALUE_STEP],
1615
+ [
1616
+ (0, import_datalog4.lit)("context", (0, import_datalog4.variable)("c")),
1617
+ (0, import_datalog4.lit)("paramOf", (0, import_datalog4.variable)("f"), (0, import_datalog4.variable)("i"), (0, import_datalog4.variable)("p")),
1618
+ (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")),
1619
+ (0, import_datalog4.lit)("callArg", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("i"), (0, import_datalog4.variable)("a"))
1620
+ ],
1621
+ "argument under a context"
1622
+ ),
1623
+ (0, import_datalog4.rule)(
1624
+ "reachesUnder",
1625
+ [(0, import_datalog4.variable)("p"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("a"), (0, import_datalog4.variable)("c3"), VALUE_STEP],
1626
+ [
1627
+ (0, import_datalog4.lit)("context", (0, import_datalog4.variable)("c")),
1628
+ (0, import_datalog4.lit)("paramNamed", (0, import_datalog4.variable)("f"), (0, import_datalog4.variable)("n"), (0, import_datalog4.variable)("p")),
1629
+ (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")),
1630
+ (0, import_datalog4.lit)("callKeywordArg", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("n"), (0, import_datalog4.variable)("a"))
1631
+ ],
1632
+ "keyword argument under a context"
1633
+ ),
1634
+ (0, import_datalog4.rule)(
1635
+ "reachesUnder",
1636
+ [(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")],
1637
+ [
1638
+ (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")),
1639
+ (0, import_datalog4.lit)("paramOf", (0, import_datalog4.variable)("f"), (0, import_datalog4.variable)("i"), (0, import_datalog4.variable)("p")),
1640
+ (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")),
1641
+ (0, import_datalog4.lit)("callArg", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("i"), (0, import_datalog4.variable)("a"))
1642
+ ],
1643
+ "reached argument under a context"
1644
+ ),
1645
+ (0, import_datalog4.rule)(
1646
+ "reachesUnder",
1647
+ [(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")],
1648
+ [
1649
+ (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")),
1650
+ (0, import_datalog4.lit)("paramNamed", (0, import_datalog4.variable)("f"), (0, import_datalog4.variable)("n"), (0, import_datalog4.variable)("p")),
1651
+ (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")),
1652
+ (0, import_datalog4.lit)("callKeywordArg", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("n"), (0, import_datalog4.variable)("a"))
1653
+ ],
1654
+ "reached keyword argument under a context"
1655
+ ),
1656
+ // Which call runs which function under which context. A construction
1657
+ // runs its constructor under the site it makes, a method call runs
1658
+ // under the site its receiver is, and anything else under no context.
1659
+ (0, import_datalog4.rule)(
1660
+ "entersUnder",
1661
+ [(0, import_datalog4.variable)("site"), (0, import_datalog4.variable)("ctor"), (0, import_datalog4.variable)("site"), (0, import_datalog4.variable)("caller")],
1662
+ [
1663
+ (0, import_datalog4.lit)("allocates", (0, import_datalog4.variable)("site"), (0, import_datalog4.variable)("cls")),
1664
+ (0, import_datalog4.lit)("runsConstructor", (0, import_datalog4.variable)("cls"), (0, import_datalog4.variable)("ctor")),
1665
+ (0, import_datalog4.lit)("callUnder", (0, import_datalog4.variable)("site"), (0, import_datalog4.variable)("caller"))
1666
+ ],
1667
+ "construction enters its constructor"
1668
+ ),
1669
+ (0, import_datalog4.rule)(
1670
+ "entersUnder",
1671
+ [(0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("f"), (0, import_datalog4.variable)("site"), (0, import_datalog4.variable)("caller")],
1672
+ [
1673
+ (0, import_datalog4.lit)("call", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("cal")),
1674
+ (0, import_datalog4.lit)("readsProperty", (0, import_datalog4.variable)("cal"), (0, import_datalog4.variable)("o"), (0, import_datalog4.variable)("m")),
1675
+ (0, import_datalog4.lit)("objectOfUnder", (0, import_datalog4.variable)("o"), (0, import_datalog4.variable)("caller"), (0, import_datalog4.variable)("site")),
1676
+ (0, import_datalog4.lit)("allocates", (0, import_datalog4.variable)("site"), (0, import_datalog4.variable)("cls")),
1677
+ (0, import_datalog4.lit)("contains", (0, import_datalog4.variable)("site"), (0, import_datalog4.variable)("m"), (0, import_datalog4.variable)("f")),
1678
+ (0, import_datalog4.lit)("callUnder", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("caller"))
1679
+ ],
1680
+ "method call enters under its receiver"
1681
+ ),
1682
+ // A call written as a name runs with whatever receiver the body
1683
+ // around it has, so a plain function called from a method keeps the
1684
+ // site rather than taking every caller of it.
1685
+ (0, import_datalog4.rule)(
1686
+ "entersUnder",
1687
+ [(0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("f"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("c")],
1688
+ [
1689
+ (0, import_datalog4.lit)("context", (0, import_datalog4.variable)("c")),
1690
+ (0, import_datalog4.lit)("callsNamed", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("f")),
1691
+ (0, import_datalog4.lit)("callUnder", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("c"))
1692
+ ],
1693
+ "named call enters under the site it is made in"
1694
+ ),
1695
+ (0, import_datalog4.rule)(
1696
+ "entersUnder",
1697
+ [(0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("f"), NO_CONTEXT, (0, import_datalog4.variable)("caller")],
1698
+ [
1699
+ (0, import_datalog4.lit)("callsFunction", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("f")),
1700
+ (0, import_datalog4.lit)("callUnder", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("caller"))
1701
+ ],
1702
+ "call enters with no context"
1703
+ ),
1704
+ // The constructor a construction runs, the ancestry included, so a
1705
+ // subclass that declares none still fills in what it inherits.
1706
+ (0, import_datalog4.rule)(
1707
+ "runsConstructor",
1708
+ [(0, import_datalog4.variable)("cls"), (0, import_datalog4.variable)("f")],
1709
+ [(0, import_datalog4.lit)("initializes", (0, import_datalog4.variable)("cls"), (0, import_datalog4.variable)("f"))]
1710
+ ),
1711
+ (0, import_datalog4.rule)(
1712
+ "runsConstructor",
1713
+ [(0, import_datalog4.variable)("cls"), (0, import_datalog4.variable)("f")],
1714
+ [
1715
+ (0, import_datalog4.lit)("extends", (0, import_datalog4.variable)("cls"), (0, import_datalog4.variable)("b")),
1716
+ (0, import_datalog4.lit)("comesTo", (0, import_datalog4.variable)("b"), (0, import_datalog4.variable)("base")),
1717
+ (0, import_datalog4.lit)("runsConstructor", (0, import_datalog4.variable)("base"), (0, import_datalog4.variable)("f"))
1210
1718
  ]
1211
1719
  ),
1212
- // Two rules rather than one leaving the next step's kind free. A free
1213
- // kind is a second question about the same relation, and a
1214
- // demand-driven run then derives both to answer either.
1720
+ // Which body a call is written in. One adapter states the call it
1721
+ // found and another states the callee, so both spellings are read.
1215
1722
  (0, import_datalog4.rule)(
1216
- "reaches",
1217
- [(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("z"), RESULT_STEP],
1723
+ "callInBody",
1724
+ [(0, import_datalog4.variable)("f"), (0, import_datalog4.variable)("r")],
1725
+ [(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"))]
1726
+ ),
1727
+ (0, import_datalog4.rule)(
1728
+ "callInBody",
1729
+ [(0, import_datalog4.variable)("f"), (0, import_datalog4.variable)("r")],
1730
+ [(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"))]
1731
+ ),
1732
+ // The context a call is made under: every site of the class whose
1733
+ // method or constructor it is written in, and no context for a call
1734
+ // outside every method body.
1735
+ (0, import_datalog4.rule)(
1736
+ "callUnder",
1737
+ [(0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("site")],
1738
+ [
1739
+ (0, import_datalog4.lit)("callInBody", (0, import_datalog4.variable)("f"), (0, import_datalog4.variable)("r")),
1740
+ (0, import_datalog4.lit)("holdsProperty", (0, import_datalog4.variable)("cls"), (0, import_datalog4.variable)("m"), (0, import_datalog4.variable)("f")),
1741
+ (0, import_datalog4.lit)("allocates", (0, import_datalog4.variable)("site"), (0, import_datalog4.variable)("cls"))
1742
+ ],
1743
+ "call in a method"
1744
+ ),
1745
+ (0, import_datalog4.rule)(
1746
+ "callUnder",
1747
+ [(0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("site")],
1218
1748
  [
1219
- (0, import_datalog4.lit)("reaches", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("y"), RESULT_STEP),
1220
- (0, import_datalog4.lit)("stepsTo", (0, import_datalog4.variable)("y"), (0, import_datalog4.variable)("z"), VALUE_STEP)
1749
+ (0, import_datalog4.lit)("callInBody", (0, import_datalog4.variable)("f"), (0, import_datalog4.variable)("r")),
1750
+ (0, import_datalog4.lit)("initializes", (0, import_datalog4.variable)("cls"), (0, import_datalog4.variable)("f")),
1751
+ (0, import_datalog4.lit)("allocates", (0, import_datalog4.variable)("site"), (0, import_datalog4.variable)("cls"))
1752
+ ],
1753
+ "call in a constructor"
1754
+ ),
1755
+ // A plain function entered under a site makes its own calls under
1756
+ // that site, so a chain of plain functions off one method keeps it.
1757
+ (0, import_datalog4.rule)(
1758
+ "callUnder",
1759
+ [(0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("c")],
1760
+ [
1761
+ (0, import_datalog4.lit)("callOutsideMethod", (0, import_datalog4.variable)("r")),
1762
+ (0, import_datalog4.lit)("callInBody", (0, import_datalog4.variable)("f"), (0, import_datalog4.variable)("r")),
1763
+ (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"))
1764
+ ],
1765
+ "call in a function entered under a site"
1766
+ ),
1767
+ (0, import_datalog4.rule)(
1768
+ "callUnder",
1769
+ [(0, import_datalog4.variable)("r"), NO_CONTEXT],
1770
+ [(0, import_datalog4.lit)("callOutsideMethod", (0, import_datalog4.variable)("r"))],
1771
+ "call outside every method"
1772
+ ),
1773
+ // The two questions a caller puts under a context, stopping where
1774
+ // `isWrittenAs` and `comesTo` stop, whatever context the walk ended in.
1775
+ (0, import_datalog4.rule)(
1776
+ "isWrittenAsUnder",
1777
+ [(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("x")],
1778
+ [(0, import_datalog4.lit)("context", (0, import_datalog4.variable)("c")), (0, import_datalog4.lit)("writtenValue", (0, import_datalog4.variable)("x"))]
1779
+ ),
1780
+ (0, import_datalog4.rule)(
1781
+ "isWrittenAsUnder",
1782
+ [(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("x")],
1783
+ [(0, import_datalog4.lit)("context", (0, import_datalog4.variable)("c")), (0, import_datalog4.lit)("objectValue", (0, import_datalog4.variable)("x"))]
1784
+ ),
1785
+ (0, import_datalog4.rule)(
1786
+ "isWrittenAsUnder",
1787
+ [(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("z")],
1788
+ [
1789
+ (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),
1790
+ (0, import_datalog4.lit)("writtenValue", (0, import_datalog4.variable)("z"))
1221
1791
  ]
1222
1792
  ),
1223
1793
  (0, import_datalog4.rule)(
1224
- "reaches",
1225
- [(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("z"), RESULT_STEP],
1794
+ "isWrittenAsUnder",
1795
+ [(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("z")],
1796
+ [
1797
+ (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),
1798
+ (0, import_datalog4.lit)("objectValue", (0, import_datalog4.variable)("z"))
1799
+ ]
1800
+ ),
1801
+ (0, import_datalog4.rule)(
1802
+ "comesToUnder",
1803
+ [(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("x")],
1804
+ [(0, import_datalog4.lit)("context", (0, import_datalog4.variable)("c")), (0, import_datalog4.lit)("func", (0, import_datalog4.variable)("x"))]
1805
+ ),
1806
+ (0, import_datalog4.rule)(
1807
+ "comesToUnder",
1808
+ [(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("x")],
1809
+ [(0, import_datalog4.lit)("context", (0, import_datalog4.variable)("c")), (0, import_datalog4.lit)("objectValue", (0, import_datalog4.variable)("x"))]
1810
+ ),
1811
+ (0, import_datalog4.rule)(
1812
+ "comesToUnder",
1813
+ [(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("z")],
1814
+ [
1815
+ (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),
1816
+ (0, import_datalog4.lit)("func", (0, import_datalog4.variable)("z"))
1817
+ ]
1818
+ ),
1819
+ (0, import_datalog4.rule)(
1820
+ "comesToUnder",
1821
+ [(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("z")],
1226
1822
  [
1227
- (0, import_datalog4.lit)("reaches", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("y"), RESULT_STEP),
1228
- (0, import_datalog4.lit)("stepsTo", (0, import_datalog4.variable)("y"), (0, import_datalog4.variable)("z"), RESULT_STEP)
1823
+ (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),
1824
+ (0, import_datalog4.lit)("objectValue", (0, import_datalog4.variable)("z"))
1825
+ ]
1826
+ ),
1827
+ (0, import_datalog4.rule)(
1828
+ "comesToUnder",
1829
+ [(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("z")],
1830
+ [
1831
+ (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),
1832
+ (0, import_datalog4.lit)("func", (0, import_datalog4.variable)("z"))
1833
+ ]
1834
+ ),
1835
+ (0, import_datalog4.rule)(
1836
+ "comesToUnder",
1837
+ [(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("z")],
1838
+ [
1839
+ (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),
1840
+ (0, import_datalog4.lit)("objectValue", (0, import_datalog4.variable)("z"))
1229
1841
  ]
1230
1842
  ),
1231
1843
  // What a value comes down to: the walk that never ran a call, stopped
@@ -1243,6 +1855,18 @@ var RESOLUTION_RULES = [
1243
1855
  [(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("z")],
1244
1856
  [(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
1857
  ),
1858
+ // An instance walk stops the same way, so a method read off
1859
+ // `new App()` still finds what the class declares.
1860
+ (0, import_datalog4.rule)(
1861
+ "comesTo",
1862
+ [(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("z")],
1863
+ [(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"))]
1864
+ ),
1865
+ (0, import_datalog4.rule)(
1866
+ "comesTo",
1867
+ [(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("z")],
1868
+ [(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"))]
1869
+ ),
1246
1870
  // The same stopping condition, for the walk that ran a call. A call
1247
1871
  // gets no `comesTo` answer on purpose: coming back with what a
1248
1872
  // factory returned would fight the unwrapping answer.
@@ -1283,6 +1907,13 @@ var RESOLUTION_RULES = [
1283
1907
  (0, import_datalog4.lit)("isWrittenAs", (0, import_datalog4.variable)("ret"), (0, import_datalog4.variable)("z"))
1284
1908
  ]
1285
1909
  ),
1910
+ // Which expression running f hands back, whether f returns it, writes
1911
+ // it into a name first, or ends on it as a shorthand body.
1912
+ (0, import_datalog4.rule)(
1913
+ "returnsCall",
1914
+ [(0, import_datalog4.variable)("f"), (0, import_datalog4.variable)("c")],
1915
+ [(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"))]
1916
+ ),
1286
1917
  // What one call site put in a parameter, told apart from what the
1287
1918
  // other callers passed.
1288
1919
  (0, import_datalog4.rule)(
@@ -1380,18 +2011,34 @@ var RESOLUTION_RULES = [
1380
2011
  [(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("obj")],
1381
2012
  [(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
2013
  ),
2014
+ // A construction is the object it made, and so is any name for it.
2015
+ // The class stays an answer too, so an instance whose site is not in
2016
+ // the run still reads what the class stores.
2017
+ (0, import_datalog4.rule)(
2018
+ "objectOf",
2019
+ [(0, import_datalog4.variable)("site"), (0, import_datalog4.variable)("site")],
2020
+ [(0, import_datalog4.lit)("allocates", (0, import_datalog4.variable)("site"), (0, import_datalog4.variable)("c"))]
2021
+ ),
2022
+ (0, import_datalog4.rule)(
2023
+ "objectOf",
2024
+ [(0, import_datalog4.variable)("o"), (0, import_datalog4.variable)("site")],
2025
+ [
2026
+ (0, import_datalog4.lit)("reaches", (0, import_datalog4.variable)("o"), (0, import_datalog4.variable)("site"), VALUE_STEP),
2027
+ (0, import_datalog4.lit)("allocates", (0, import_datalog4.variable)("site"), (0, import_datalog4.variable)("c"))
2028
+ ]
2029
+ ),
1383
2030
  // Which calls a function, found by the name the call is written as
1384
2031
  // rather than by resolving every callee in the project. A caller knows
1385
2032
  // the function and wants its call sites, so both of these start from
1386
2033
  // the function. Starting from `call` instead asks what every call in
1387
2034
  // the project imports, which was 72% of everything derived.
1388
2035
  (0, import_datalog4.rule)(
1389
- "callsFunction",
2036
+ "callsNamed",
1390
2037
  [(0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("f")],
1391
2038
  [(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
2039
  ),
1393
2040
  (0, import_datalog4.rule)(
1394
- "callsFunction",
2041
+ "callsNamed",
1395
2042
  [(0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("f")],
1396
2043
  [
1397
2044
  (0, import_datalog4.lit)("moduleExport", (0, import_datalog4.variable)("m"), (0, import_datalog4.variable)("n"), (0, import_datalog4.variable)("f")),
@@ -1402,7 +2049,7 @@ var RESOLUTION_RULES = [
1402
2049
  // The same, for a language whose adapter writes the import down as a
1403
2050
  // declaration and the call's callee as the name referring to it.
1404
2051
  (0, import_datalog4.rule)(
1405
- "callsFunction",
2052
+ "callsNamed",
1406
2053
  [(0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("f")],
1407
2054
  [
1408
2055
  (0, import_datalog4.lit)("moduleExport", (0, import_datalog4.variable)("m"), (0, import_datalog4.variable)("n"), (0, import_datalog4.variable)("f")),
@@ -1411,6 +2058,36 @@ var RESOLUTION_RULES = [
1411
2058
  (0, import_datalog4.lit)("call", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("c"))
1412
2059
  ]
1413
2060
  ),
2061
+ // `const f = (x) => ...` declares the name and puts the parameters on
2062
+ // the arrow, so everything above arrives at the declaration and
2063
+ // `paramOf` is about the arrow. One binds hop joins the two.
2064
+ (0, import_datalog4.rule)(
2065
+ "callsNamed",
2066
+ [(0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("f")],
2067
+ [(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"))]
2068
+ ),
2069
+ // Every one of those, and the binds hop again over the whole
2070
+ // relation, so a property holding a name for a function is reached
2071
+ // the way it was before the two were told apart.
2072
+ (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"))]),
2073
+ (0, import_datalog4.rule)(
2074
+ "callsFunction",
2075
+ [(0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("f")],
2076
+ [(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"))]
2077
+ ),
2078
+ // A function written on an object, called off it: `client.get(o)`.
2079
+ // Every rule above joins on a name the callee binds to, and a read of
2080
+ // a property binds to nothing.
2081
+ (0, import_datalog4.rule)(
2082
+ "callsFunction",
2083
+ [(0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("f")],
2084
+ [
2085
+ (0, import_datalog4.lit)("holdsProperty", (0, import_datalog4.variable)("obj"), (0, import_datalog4.variable)("n"), (0, import_datalog4.variable)("f")),
2086
+ (0, import_datalog4.lit)("readsProperty", (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("o"), (0, import_datalog4.variable)("n")),
2087
+ (0, import_datalog4.lit)("objectOf", (0, import_datalog4.variable)("o"), (0, import_datalog4.variable)("obj")),
2088
+ (0, import_datalog4.lit)("call", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("c"))
2089
+ ]
2090
+ ),
1414
2091
  // What an object contains, its base class included, so a method the base
1415
2092
  // declares is found on a subclass that never overrode it. A method both
1416
2093
  // declare gives two, and the caller decides. This is its own relation
@@ -1428,7 +2105,8 @@ var RESOLUTION_RULES = [
1428
2105
  (0, import_datalog4.lit)("extends", (0, import_datalog4.variable)("cls"), (0, import_datalog4.variable)("base")),
1429
2106
  (0, import_datalog4.lit)("comesTo", (0, import_datalog4.variable)("base"), (0, import_datalog4.variable)("baseCls")),
1430
2107
  (0, import_datalog4.lit)("contains", (0, import_datalog4.variable)("baseCls"), (0, import_datalog4.variable)("n"), (0, import_datalog4.variable)("held"))
1431
- ]
2108
+ ],
2109
+ BASE_CLASS_RULE
1432
2110
  ),
1433
2111
  // An association is read off an instance as a property, and stating
1434
2112
  // it as `contains` is what puts it on the ancestry rule, so a concern
@@ -1452,6 +2130,69 @@ var RESOLUTION_RULES = [
1452
2130
  ],
1453
2131
  "constructed association"
1454
2132
  ),
2133
+ // What the constructor put on the receiver. The class is the object
2134
+ // for an instance whose own site is not in the run.
2135
+ (0, import_datalog4.rule)(
2136
+ "contains",
2137
+ [(0, import_datalog4.variable)("cls"), (0, import_datalog4.variable)("n"), (0, import_datalog4.variable)("held")],
2138
+ [
2139
+ (0, import_datalog4.lit)("initializes", (0, import_datalog4.variable)("cls"), (0, import_datalog4.variable)("f")),
2140
+ (0, import_datalog4.lit)("storesProperty", (0, import_datalog4.variable)("f"), (0, import_datalog4.variable)("n"), (0, import_datalog4.variable)("held"))
2141
+ ],
2142
+ "constructor store"
2143
+ ),
2144
+ // What any other method of the class put there. Two methods writing
2145
+ // one name give two rows, since nothing here orders them.
2146
+ (0, import_datalog4.rule)(
2147
+ "contains",
2148
+ [(0, import_datalog4.variable)("cls"), (0, import_datalog4.variable)("n"), (0, import_datalog4.variable)("held")],
2149
+ [
2150
+ (0, import_datalog4.lit)("holdsProperty", (0, import_datalog4.variable)("cls"), (0, import_datalog4.variable)("m"), (0, import_datalog4.variable)("f")),
2151
+ (0, import_datalog4.lit)("storesProperty", (0, import_datalog4.variable)("f"), (0, import_datalog4.variable)("n"), (0, import_datalog4.variable)("held"))
2152
+ ],
2153
+ "method store"
2154
+ ),
2155
+ // A write through a name rather than through the receiver,
2156
+ // `client.timeout = 5`, which lands on whatever that name refers to.
2157
+ (0, import_datalog4.rule)(
2158
+ "contains",
2159
+ [(0, import_datalog4.variable)("obj"), (0, import_datalog4.variable)("n"), (0, import_datalog4.variable)("held")],
2160
+ [
2161
+ (0, import_datalog4.lit)("storesProperty", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("n"), (0, import_datalog4.variable)("held")),
2162
+ (0, import_datalog4.lit)("objectOf", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("obj"))
2163
+ ],
2164
+ "named receiver store"
2165
+ ),
2166
+ // A call written with a class's own name, which is how most languages
2167
+ // spell a construction. A language that spells one some other way
2168
+ // states its own rule for this, the way Ruby does for `Const.new`.
2169
+ (0, import_datalog4.rule)(
2170
+ "constructsNamed",
2171
+ [(0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("cls")],
2172
+ [(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"))]
2173
+ ),
2174
+ // Each construction is an object of its own containing what its
2175
+ // class stores, so two sites are two objects.
2176
+ (0, import_datalog4.rule)(
2177
+ "contains",
2178
+ [(0, import_datalog4.variable)("site"), (0, import_datalog4.variable)("n"), (0, import_datalog4.variable)("held")],
2179
+ [
2180
+ (0, import_datalog4.lit)("allocates", (0, import_datalog4.variable)("site"), (0, import_datalog4.variable)("cls")),
2181
+ (0, import_datalog4.lit)("contains", (0, import_datalog4.variable)("cls"), (0, import_datalog4.variable)("n"), (0, import_datalog4.variable)("held"))
2182
+ ],
2183
+ "allocated instance"
2184
+ ),
2185
+ // A call that makes one of a class. Every finder a pack declared is
2186
+ // one too, so `User.find(1)` is a site the same way `User.new` is.
2187
+ (0, import_datalog4.rule)(
2188
+ "allocates",
2189
+ [(0, import_datalog4.variable)("site"), (0, import_datalog4.variable)("cls")],
2190
+ [
2191
+ (0, import_datalog4.lit)("call", (0, import_datalog4.variable)("site"), (0, import_datalog4.variable)("c")),
2192
+ (0, import_datalog4.lit)("stepsTo", (0, import_datalog4.variable)("site"), (0, import_datalog4.variable)("cls"), INSTANCE_STEP)
2193
+ ],
2194
+ "allocation site"
2195
+ ),
1455
2196
  // The library base a class's ancestry arrives at, however many of a
1456
2197
  // project's own classes sit in between. A base the run declares has a
1457
2198
  // node to keep walking from; one it does not has only a name.
@@ -1541,8 +2282,8 @@ var RESOLUTION_RULES = [
1541
2282
  ]
1542
2283
  ),
1543
2284
  // Where a name comes from, when what it refers to lives outside the
1544
- // source being read. A walk ends at something written out in source,
1545
- // so it never reaches a library's own function.
2285
+ // source being read. A walk ends at what the source writes out, so it
2286
+ // never reaches a library's own function; these rules do.
1546
2287
  (0, import_datalog4.rule)(
1547
2288
  "comesFrom",
1548
2289
  [(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("m"), (0, import_datalog4.variable)("n")],
@@ -1556,6 +2297,28 @@ var RESOLUTION_RULES = [
1556
2297
  (0, import_datalog4.lit)("imports", (0, import_datalog4.variable)("y"), (0, import_datalog4.variable)("m"), (0, import_datalog4.variable)("n"))
1557
2298
  ]
1558
2299
  ),
2300
+ // A member read off a whole-module import: the member's own name is
2301
+ // what the module exports, so `fastapi.APIRouter` comes from
2302
+ // fastapi's `APIRouter`. Directly, or through a name for the module.
2303
+ (0, import_datalog4.rule)(
2304
+ "comesFrom",
2305
+ [(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("m"), (0, import_datalog4.variable)("n")],
2306
+ [
2307
+ (0, import_datalog4.lit)("readsProperty", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("ns"), (0, import_datalog4.variable)("n")),
2308
+ (0, import_datalog4.lit)("imports", (0, import_datalog4.variable)("ns"), (0, import_datalog4.variable)("m"), NAMESPACE_IMPORT)
2309
+ ],
2310
+ NAMESPACE_MEMBER_RULE
2311
+ ),
2312
+ (0, import_datalog4.rule)(
2313
+ "comesFrom",
2314
+ [(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("m"), (0, import_datalog4.variable)("n")],
2315
+ [
2316
+ (0, import_datalog4.lit)("readsProperty", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("o"), (0, import_datalog4.variable)("n")),
2317
+ (0, import_datalog4.lit)("reaches", (0, import_datalog4.variable)("o"), (0, import_datalog4.variable)("ns"), VALUE_STEP),
2318
+ (0, import_datalog4.lit)("imports", (0, import_datalog4.variable)("ns"), (0, import_datalog4.variable)("m"), NAMESPACE_IMPORT)
2319
+ ],
2320
+ NAMESPACE_MEMBER_RULE
2321
+ ),
1559
2322
  // Calling f ends up calling the name n that module m exports, one
1560
2323
  // hop through f's own body or deeper through a wrapper of a wrapper.
1561
2324
  // Several results is normal: a composed decorator applies them all.
@@ -1585,6 +2348,13 @@ var RESOLUTION_RULES = [
1585
2348
  [(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
2349
  )
1587
2350
  ];
2351
+ function alsoSteps(rules) {
2352
+ return [
2353
+ ...rules,
2354
+ ...rules.filter((r) => r.head.relation === "hop").map((r) => ({ ...r, head: { ...r.head, relation: "stepsTo" } }))
2355
+ ];
2356
+ }
2357
+ var RESOLUTION_RULES = alsoSteps(STATED_RULES);
1588
2358
  var RESOLUTION_QUESTIONS = [
1589
2359
  (0, import_datalog4.rule)(
1590
2360
  "wantedResolves",
@@ -1607,12 +2377,55 @@ var RESOLUTION_QUESTIONS = [
1607
2377
  [(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
2378
  ),
1609
2379
  // A call is given no `comesTo`, so this is the only way to ask what
1610
- // object one arrives at, and without it a demand-driven run derives
1611
- // `objectOf` nowhere.
2380
+ // object one arrives at, and a demand-driven run derives `objectOf`
2381
+ // nowhere without it. An allocation site is not one of the answers.
1612
2382
  (0, import_datalog4.rule)(
1613
2383
  "wantedObjectOf",
1614
2384
  [(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("z")],
1615
- [(0, import_datalog4.lit)("wanted", (0, import_datalog4.variable)("x")), (0, import_datalog4.lit)("objectOf", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("z"))]
2385
+ [
2386
+ (0, import_datalog4.lit)("wanted", (0, import_datalog4.variable)("x")),
2387
+ (0, import_datalog4.lit)("objectOf", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("z")),
2388
+ (0, import_datalog4.lit)("objectValue", (0, import_datalog4.variable)("z"))
2389
+ ]
2390
+ ),
2391
+ // The same three questions under one allocation site, keyed by the
2392
+ // value and the site both. An allocation site is an answer here,
2393
+ // unlike `wantedObjectOf`, since a site is what a context is.
2394
+ (0, import_datalog4.rule)(
2395
+ "wantedIsWrittenAsUnder",
2396
+ [(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("z")],
2397
+ [
2398
+ (0, import_datalog4.lit)("wantedUnder", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("c")),
2399
+ (0, import_datalog4.lit)("isWrittenAsUnder", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("z"))
2400
+ ]
2401
+ ),
2402
+ // Where a class was made, for a caller about to ask a value question
2403
+ // under each. Going through `constructsNamed` keeps the demand on the
2404
+ // calls written with the class's name rather than on every call.
2405
+ (0, import_datalog4.rule)(
2406
+ "wantedAllocatedAt",
2407
+ [(0, import_datalog4.variable)("cls"), (0, import_datalog4.variable)("site")],
2408
+ [
2409
+ (0, import_datalog4.lit)("wantedSites", (0, import_datalog4.variable)("cls")),
2410
+ (0, import_datalog4.lit)("constructsNamed", (0, import_datalog4.variable)("site"), (0, import_datalog4.variable)("cls")),
2411
+ (0, import_datalog4.lit)("allocates", (0, import_datalog4.variable)("site"), (0, import_datalog4.variable)("cls"))
2412
+ ]
2413
+ ),
2414
+ (0, import_datalog4.rule)(
2415
+ "wantedComesToUnder",
2416
+ [(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("z")],
2417
+ [
2418
+ (0, import_datalog4.lit)("wantedUnder", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("c")),
2419
+ (0, import_datalog4.lit)("comesToUnder", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("z"))
2420
+ ]
2421
+ ),
2422
+ (0, import_datalog4.rule)(
2423
+ "wantedObjectOfUnder",
2424
+ [(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("z")],
2425
+ [
2426
+ (0, import_datalog4.lit)("wantedUnder", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("c")),
2427
+ (0, import_datalog4.lit)("objectOfUnder", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("z"))
2428
+ ]
1616
2429
  ),
1617
2430
  // The same for the function a call returns: `app.use(requireCaller(config))`
1618
2431
  // registers what the factory gives back, and `resolves` on the call
@@ -1629,6 +2442,19 @@ var RESOLUTION_QUESTIONS = [
1629
2442
  [(0, import_datalog4.variable)("p"), (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("z")],
1630
2443
  [(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
2444
  ),
2445
+ // The argument as the caller wrote it. A parameter given a GraphQL
2446
+ // document has no `paramAt` answer, since that settles through
2447
+ // `comesTo`, which stops at a function or an object.
2448
+ (0, import_datalog4.rule)(
2449
+ "wantedPassesArgument",
2450
+ [(0, import_datalog4.variable)("p"), (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("a")],
2451
+ [(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"))]
2452
+ ),
2453
+ (0, import_datalog4.rule)(
2454
+ "wantedReturnsCall",
2455
+ [(0, import_datalog4.variable)("f"), (0, import_datalog4.variable)("c")],
2456
+ [(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"))]
2457
+ ),
1632
2458
  (0, import_datalog4.rule)(
1633
2459
  "wantedComesFrom",
1634
2460
  [(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("m"), (0, import_datalog4.variable)("n")],
@@ -1892,36 +2718,59 @@ var RESOLUTION_QUESTIONS = [
1892
2718
  var ANSWER_RELATIONS = [
1893
2719
  ...new Set(RESOLUTION_QUESTIONS.map((r) => r.head.relation))
1894
2720
  ];
2721
+ var UNDER_ANSWER_RELATIONS = [
2722
+ "wantedIsWrittenAsUnder",
2723
+ "wantedComesToUnder",
2724
+ "wantedObjectOfUnder"
2725
+ ];
1895
2726
  // Annotate the CommonJS export names for ESM import in node:
1896
2727
  0 && (module.exports = {
1897
2728
  ANSWER_RELATIONS,
1898
2729
  ASKING_RELATIONS,
2730
+ BASE_CLASS_RULE,
1899
2731
  FACT_CONTRACT_CASES,
2732
+ INSTANCE_STEP,
1900
2733
  NAMESPACE_IMPORT,
1901
2734
  NAMESPACE_IMPORT_NAME,
2735
+ NAMESPACE_MEMBER_RULE,
2736
+ NO_CONTEXT,
2737
+ NO_CONTEXT_NAME,
1902
2738
  RESOLUTION_QUESTIONS,
1903
2739
  RESOLUTION_RULES,
1904
2740
  RESULT_STEP,
2741
+ UNDER_ANSWER_RELATIONS,
1905
2742
  VALUE_STEP,
2743
+ addPackWords,
1906
2744
  agreedMountPrefix,
2745
+ allocationSitesOf,
2746
+ alsoSteps,
2747
+ answersByKey,
1907
2748
  askResolution,
2749
+ askResolutionUnder,
1908
2750
  calleeOutcomeOf,
1909
2751
  calleeOutcomes,
1910
2752
  checkFactContract,
2753
+ comesToUnder,
1911
2754
  couldBeSettled,
1912
2755
  explainResolutionProof,
1913
2756
  explainResolvedKey,
2757
+ isWrittenAsUnder,
1914
2758
  joinMountedPath,
1915
2759
  mountPathsOf,
1916
2760
  nodeOfKey,
2761
+ objectOfUnder,
1917
2762
  placeholderValues,
1918
2763
  queryFacts,
1919
2764
  renderExplanation,
1920
2765
  resolutionProgram,
2766
+ resolutionUnderProgram,
1921
2767
  singleAnswers,
1922
2768
  startsAtName,
1923
2769
  valueLeftByWrites,
1924
2770
  writesRunInOrder,
1925
2771
  writtenSourcesOf,
1926
- writtenValueOf
2772
+ writtenValueOf,
2773
+ writtenValueUnder,
2774
+ writtenValuesByKey,
2775
+ writtenValuesOf
1927
2776
  });