@suss/resolution 0.32.0 → 0.33.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/README.md +1 -1
- package/dist/index.cjs +125 -17
- package/dist/index.js +125 -17
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -21,7 +21,7 @@ and a handler factory in TypeScript.
|
|
|
21
21
|
## More
|
|
22
22
|
|
|
23
23
|
- [How the rules follow a value](./DESIGN.md)
|
|
24
|
-
- [Documentation](https://
|
|
24
|
+
- [Documentation](https://suss.sh/)
|
|
25
25
|
- [Source and issues](https://github.com/nimbuscloud-ai/suss)
|
|
26
26
|
|
|
27
27
|

|
package/dist/index.cjs
CHANGED
|
@@ -80,7 +80,7 @@ var ASKING_RELATIONS = [
|
|
|
80
80
|
"wanted",
|
|
81
81
|
"wantedUnder",
|
|
82
82
|
"wantedSites",
|
|
83
|
-
"
|
|
83
|
+
"wantedEnvObject",
|
|
84
84
|
"wantedOrigin",
|
|
85
85
|
"wantedCallOrigin",
|
|
86
86
|
"wantedExportsOf",
|
|
@@ -1120,6 +1120,16 @@ function answersByKey(rows, placeholders = NO_PLACEHOLDERS) {
|
|
|
1120
1120
|
}
|
|
1121
1121
|
return answers;
|
|
1122
1122
|
}
|
|
1123
|
+
function answersFor2(db, relation, key) {
|
|
1124
|
+
const rows = db.lookup(relation, 0, key);
|
|
1125
|
+
if (rows.length === 0) {
|
|
1126
|
+
return [];
|
|
1127
|
+
}
|
|
1128
|
+
const placeholders = new Set(
|
|
1129
|
+
rows.map((row) => String(row[1])).filter((answer) => db.has("placeholderValue", [answer]))
|
|
1130
|
+
);
|
|
1131
|
+
return answersByKey(rows, placeholders).get(key) ?? [];
|
|
1132
|
+
}
|
|
1123
1133
|
function singleAnswers(rows, placeholders = NO_PLACEHOLDERS) {
|
|
1124
1134
|
const settled = /* @__PURE__ */ new Map();
|
|
1125
1135
|
for (const [key, answers] of answersByKey(rows, placeholders)) {
|
|
@@ -1211,38 +1221,42 @@ function writtenValuesByKey(db, keys, ask, relation = WRITTEN_AS) {
|
|
|
1211
1221
|
return one;
|
|
1212
1222
|
}
|
|
1213
1223
|
function settledByKey(db, keys, ask, relation) {
|
|
1214
|
-
const
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
const
|
|
1218
|
-
const throughCalls = [...direct.values()].flat().filter((answer) => calls.has(answer));
|
|
1224
|
+
const direct = new Map(
|
|
1225
|
+
keys.map((key) => [key, answersFor2(db, relation, key)])
|
|
1226
|
+
);
|
|
1227
|
+
const throughCalls = [...direct.values()].flat().filter((answer) => isCall(db, answer));
|
|
1219
1228
|
if (throughCalls.length === 0) {
|
|
1220
1229
|
return direct;
|
|
1221
1230
|
}
|
|
1222
1231
|
ask(throughCalls);
|
|
1223
|
-
const deeper = singleAnswers(db.facts(relation), placeholders);
|
|
1224
1232
|
return new Map(
|
|
1225
1233
|
[...direct].map(([key, answers]) => [
|
|
1226
1234
|
key,
|
|
1227
|
-
collapseCalls(
|
|
1235
|
+
collapseCalls(db, relation, answers)
|
|
1228
1236
|
])
|
|
1229
1237
|
);
|
|
1230
1238
|
}
|
|
1231
|
-
function
|
|
1239
|
+
function isCall(db, key) {
|
|
1240
|
+
return db.lookup("call", 0, key).length > 0;
|
|
1241
|
+
}
|
|
1242
|
+
function collapseCalls(db, relation, direct) {
|
|
1232
1243
|
return [
|
|
1233
1244
|
...new Set(
|
|
1234
1245
|
direct.map(
|
|
1235
|
-
(answer) =>
|
|
1246
|
+
(answer) => isCall(db, answer) ? behindCall(db, relation, answer) : answer
|
|
1236
1247
|
)
|
|
1237
1248
|
)
|
|
1238
1249
|
];
|
|
1239
1250
|
}
|
|
1251
|
+
function behindCall(db, relation, call) {
|
|
1252
|
+
const answers = answersFor2(db, relation, call);
|
|
1253
|
+
return answers.length === 1 ? answers[0] : call;
|
|
1254
|
+
}
|
|
1240
1255
|
function writesLeft(db, key) {
|
|
1241
|
-
|
|
1242
|
-
if (unstated) {
|
|
1256
|
+
if (db.has("writesUnstated", [key])) {
|
|
1243
1257
|
return [];
|
|
1244
1258
|
}
|
|
1245
|
-
const candidates =
|
|
1259
|
+
const candidates = answersFor2(db, "mayHold", key);
|
|
1246
1260
|
return candidates.length > 1 ? candidates : [];
|
|
1247
1261
|
}
|
|
1248
1262
|
|
|
@@ -2013,6 +2027,51 @@ var STATED_RULES = [
|
|
|
2013
2027
|
[(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("p")],
|
|
2014
2028
|
[(0, import_datalog4.lit)("refersToParam", (0, import_datalog4.variable)("y"), (0, import_datalog4.variable)("p")), (0, import_datalog4.lit)("binds", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("y"))]
|
|
2015
2029
|
),
|
|
2030
|
+
// An expression whose value is the environment object w: the way a
|
|
2031
|
+
// pack spells it, a name declared as that, or a parameter a caller
|
|
2032
|
+
// handed one of those to, however many calls deep.
|
|
2033
|
+
(0, import_datalog4.rule)(
|
|
2034
|
+
"environmentValue",
|
|
2035
|
+
[(0, import_datalog4.variable)("w"), (0, import_datalog4.variable)("o")],
|
|
2036
|
+
[(0, import_datalog4.lit)("environmentObject", (0, import_datalog4.variable)("w")), (0, import_datalog4.lit)("refersToObject", (0, import_datalog4.variable)("o"), (0, import_datalog4.variable)("w"))]
|
|
2037
|
+
),
|
|
2038
|
+
(0, import_datalog4.rule)(
|
|
2039
|
+
"environmentValue",
|
|
2040
|
+
[(0, import_datalog4.variable)("w"), (0, import_datalog4.variable)("o")],
|
|
2041
|
+
[
|
|
2042
|
+
(0, import_datalog4.lit)("environmentValue", (0, import_datalog4.variable)("w"), (0, import_datalog4.variable)("a")),
|
|
2043
|
+
(0, import_datalog4.lit)("passesArgument", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("p"), (0, import_datalog4.variable)("a")),
|
|
2044
|
+
(0, import_datalog4.lit)("refersToParam", (0, import_datalog4.variable)("o"), (0, import_datalog4.variable)("p"))
|
|
2045
|
+
]
|
|
2046
|
+
),
|
|
2047
|
+
// A parameter that defaults to the environment, for the callers that
|
|
2048
|
+
// pass nothing. `loadConfig(env = process.env)` is written that way
|
|
2049
|
+
// so that most of the program never mentions the environment at all.
|
|
2050
|
+
(0, import_datalog4.rule)(
|
|
2051
|
+
"environmentValue",
|
|
2052
|
+
[(0, import_datalog4.variable)("w"), (0, import_datalog4.variable)("o")],
|
|
2053
|
+
[
|
|
2054
|
+
(0, import_datalog4.lit)("environmentValue", (0, import_datalog4.variable)("w"), (0, import_datalog4.variable)("d")),
|
|
2055
|
+
(0, import_datalog4.lit)("paramDefault", (0, import_datalog4.variable)("p"), (0, import_datalog4.variable)("d")),
|
|
2056
|
+
(0, import_datalog4.lit)("refersToParam", (0, import_datalog4.variable)("o"), (0, import_datalog4.variable)("p"))
|
|
2057
|
+
]
|
|
2058
|
+
),
|
|
2059
|
+
// Which environment object a keyed read takes its entry from. The
|
|
2060
|
+
// object comes first because a project writes a handful of those and
|
|
2061
|
+
// thousands of keyed reads, and the join starts at the small end.
|
|
2062
|
+
(0, import_datalog4.rule)(
|
|
2063
|
+
"environmentRead",
|
|
2064
|
+
[(0, import_datalog4.variable)("w"), (0, import_datalog4.variable)("site"), (0, import_datalog4.variable)("x")],
|
|
2065
|
+
[
|
|
2066
|
+
(0, import_datalog4.lit)("environmentValue", (0, import_datalog4.variable)("w"), (0, import_datalog4.variable)("o")),
|
|
2067
|
+
(0, import_datalog4.lit)("readsKeyed", (0, import_datalog4.variable)("site"), (0, import_datalog4.variable)("o"), (0, import_datalog4.variable)("x"))
|
|
2068
|
+
]
|
|
2069
|
+
),
|
|
2070
|
+
(0, import_datalog4.rule)(
|
|
2071
|
+
"readsEnvNamed",
|
|
2072
|
+
[(0, import_datalog4.variable)("site"), (0, import_datalog4.variable)("x")],
|
|
2073
|
+
[(0, import_datalog4.lit)("environmentRead", (0, import_datalog4.variable)("w"), (0, import_datalog4.variable)("site"), (0, import_datalog4.variable)("x"))]
|
|
2074
|
+
),
|
|
2016
2075
|
// A parameter whose value is an environment variable's name: a read
|
|
2017
2076
|
// site takes its name from it, or it is handed on to a parameter that
|
|
2018
2077
|
// does. Asked from the site, so the recursion runs callee to caller.
|
|
@@ -2176,10 +2235,25 @@ var STATED_RULES = [
|
|
|
2176
2235
|
(0, import_datalog4.lit)("call", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("c"))
|
|
2177
2236
|
]
|
|
2178
2237
|
),
|
|
2179
|
-
//
|
|
2238
|
+
// A name bound to a factory's result, called: `const get =
|
|
2239
|
+
// makeReader(env)` then `get(name)`. Written from the factory's call so
|
|
2240
|
+
// the walk starts where `callsFunction` already has an answer.
|
|
2241
|
+
(0, import_datalog4.rule)(
|
|
2242
|
+
"callsFunction",
|
|
2243
|
+
[(0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("f")],
|
|
2244
|
+
[
|
|
2245
|
+
(0, import_datalog4.lit)("returnsValue", (0, import_datalog4.variable)("g"), (0, import_datalog4.variable)("f")),
|
|
2246
|
+
(0, import_datalog4.lit)("callsFunction", (0, import_datalog4.variable)("r0"), (0, import_datalog4.variable)("g")),
|
|
2247
|
+
(0, import_datalog4.lit)("callsNamed", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("r0"))
|
|
2248
|
+
]
|
|
2249
|
+
),
|
|
2250
|
+
// The expressions that refer to an object by binding alone: the
|
|
2180
2251
|
// declaration written as it, a reference or import of that, and a
|
|
2181
2252
|
// fallback over any of those. Asked from the object, so it visits only them.
|
|
2182
2253
|
(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"))]),
|
|
2254
|
+
// The process environment is an object nothing declares, so a pack
|
|
2255
|
+
// saying which expression spells it is the only way in.
|
|
2256
|
+
(0, import_datalog4.rule)("refersToObject", [(0, import_datalog4.variable)("w"), (0, import_datalog4.variable)("w")], [(0, import_datalog4.lit)("environmentObject", (0, import_datalog4.variable)("w"))]),
|
|
2183
2257
|
(0, import_datalog4.rule)(
|
|
2184
2258
|
"refersToObject",
|
|
2185
2259
|
[(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("obj")],
|
|
@@ -2569,12 +2643,33 @@ var RESOLUTION_QUESTIONS = [
|
|
|
2569
2643
|
[(0, import_datalog4.variable)("f"), (0, import_datalog4.variable)("c")],
|
|
2570
2644
|
[(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"))]
|
|
2571
2645
|
),
|
|
2572
|
-
// Seeded with the
|
|
2573
|
-
//
|
|
2646
|
+
// Seeded with the expressions that spell the environment, a handful
|
|
2647
|
+
// per project. The reads cannot be the seed: one written through a
|
|
2648
|
+
// parameter is nowhere a scan of the source looks.
|
|
2574
2649
|
(0, import_datalog4.rule)(
|
|
2575
2650
|
"wantedParamNamesEnv",
|
|
2576
2651
|
[(0, import_datalog4.variable)("p"), (0, import_datalog4.variable)("site")],
|
|
2577
|
-
[
|
|
2652
|
+
[
|
|
2653
|
+
(0, import_datalog4.lit)("wantedEnvObject", (0, import_datalog4.variable)("w")),
|
|
2654
|
+
(0, import_datalog4.lit)("environmentRead", (0, import_datalog4.variable)("w"), (0, import_datalog4.variable)("site"), (0, import_datalog4.variable)("x")),
|
|
2655
|
+
(0, import_datalog4.lit)("paramNamesEnv", (0, import_datalog4.variable)("p"), (0, import_datalog4.variable)("site"))
|
|
2656
|
+
]
|
|
2657
|
+
),
|
|
2658
|
+
// The same relation asked from one expression. Seeding from the
|
|
2659
|
+
// objects instead would settle it for every expression in the
|
|
2660
|
+
// project, and a caller holding an argument wants only that one.
|
|
2661
|
+
(0, import_datalog4.rule)(
|
|
2662
|
+
"wantedEnvironmentValue",
|
|
2663
|
+
[(0, import_datalog4.variable)("o"), (0, import_datalog4.variable)("w")],
|
|
2664
|
+
[(0, import_datalog4.lit)("wanted", (0, import_datalog4.variable)("o")), (0, import_datalog4.lit)("environmentValue", (0, import_datalog4.variable)("w"), (0, import_datalog4.variable)("o"))]
|
|
2665
|
+
),
|
|
2666
|
+
// Whether an expression is a parameter under another name, for a
|
|
2667
|
+
// caller deciding whether going and reading that parameter's callers
|
|
2668
|
+
// could change the answer it already has.
|
|
2669
|
+
(0, import_datalog4.rule)(
|
|
2670
|
+
"wantedRefersToParam",
|
|
2671
|
+
[(0, import_datalog4.variable)("o"), (0, import_datalog4.variable)("p")],
|
|
2672
|
+
[(0, import_datalog4.lit)("wanted", (0, import_datalog4.variable)("o")), (0, import_datalog4.lit)("refersToParam", (0, import_datalog4.variable)("o"), (0, import_datalog4.variable)("p"))]
|
|
2578
2673
|
),
|
|
2579
2674
|
(0, import_datalog4.rule)(
|
|
2580
2675
|
"wantedComesFrom",
|
|
@@ -2792,6 +2887,19 @@ var RESOLUTION_QUESTIONS = [
|
|
|
2792
2887
|
[(0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("n")],
|
|
2793
2888
|
[(0, import_datalog4.lit)("ancestryChain", (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("b")), (0, import_datalog4.lit)("declaresName", (0, import_datalog4.variable)("b"), (0, import_datalog4.variable)("n"))]
|
|
2794
2889
|
),
|
|
2890
|
+
// The method behind each callback the chain registers, by the event
|
|
2891
|
+
// that runs it. A base registering one reaches every class below it,
|
|
2892
|
+
// and the method may be declared anywhere along the same chain.
|
|
2893
|
+
(0, import_datalog4.rule)(
|
|
2894
|
+
"wantedCallbackMethod",
|
|
2895
|
+
[(0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("event"), (0, import_datalog4.variable)("n"), (0, import_datalog4.variable)("held")],
|
|
2896
|
+
[
|
|
2897
|
+
(0, import_datalog4.lit)("ancestryChain", (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("b")),
|
|
2898
|
+
(0, import_datalog4.lit)("classCallback", (0, import_datalog4.variable)("b"), (0, import_datalog4.variable)("event"), (0, import_datalog4.variable)("n")),
|
|
2899
|
+
(0, import_datalog4.lit)("ancestryChain", (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("b2")),
|
|
2900
|
+
(0, import_datalog4.lit)("holdsProperty", (0, import_datalog4.variable)("b2"), (0, import_datalog4.variable)("n"), (0, import_datalog4.variable)("held"))
|
|
2901
|
+
]
|
|
2902
|
+
),
|
|
2795
2903
|
(0, import_datalog4.rule)("anchorChain", [(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("x")], [(0, import_datalog4.lit)("wantedAnchor", (0, import_datalog4.variable)("x"))]),
|
|
2796
2904
|
(0, import_datalog4.rule)(
|
|
2797
2905
|
"anchorChain",
|
package/dist/index.js
CHANGED
|
@@ -13,7 +13,7 @@ var ASKING_RELATIONS = [
|
|
|
13
13
|
"wanted",
|
|
14
14
|
"wantedUnder",
|
|
15
15
|
"wantedSites",
|
|
16
|
-
"
|
|
16
|
+
"wantedEnvObject",
|
|
17
17
|
"wantedOrigin",
|
|
18
18
|
"wantedCallOrigin",
|
|
19
19
|
"wantedExportsOf",
|
|
@@ -1053,6 +1053,16 @@ function answersByKey(rows, placeholders = NO_PLACEHOLDERS) {
|
|
|
1053
1053
|
}
|
|
1054
1054
|
return answers;
|
|
1055
1055
|
}
|
|
1056
|
+
function answersFor2(db, relation, key) {
|
|
1057
|
+
const rows = db.lookup(relation, 0, key);
|
|
1058
|
+
if (rows.length === 0) {
|
|
1059
|
+
return [];
|
|
1060
|
+
}
|
|
1061
|
+
const placeholders = new Set(
|
|
1062
|
+
rows.map((row) => String(row[1])).filter((answer) => db.has("placeholderValue", [answer]))
|
|
1063
|
+
);
|
|
1064
|
+
return answersByKey(rows, placeholders).get(key) ?? [];
|
|
1065
|
+
}
|
|
1056
1066
|
function singleAnswers(rows, placeholders = NO_PLACEHOLDERS) {
|
|
1057
1067
|
const settled = /* @__PURE__ */ new Map();
|
|
1058
1068
|
for (const [key, answers] of answersByKey(rows, placeholders)) {
|
|
@@ -1144,38 +1154,42 @@ function writtenValuesByKey(db, keys, ask, relation = WRITTEN_AS) {
|
|
|
1144
1154
|
return one;
|
|
1145
1155
|
}
|
|
1146
1156
|
function settledByKey(db, keys, ask, relation) {
|
|
1147
|
-
const
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
const
|
|
1151
|
-
const throughCalls = [...direct.values()].flat().filter((answer) => calls.has(answer));
|
|
1157
|
+
const direct = new Map(
|
|
1158
|
+
keys.map((key) => [key, answersFor2(db, relation, key)])
|
|
1159
|
+
);
|
|
1160
|
+
const throughCalls = [...direct.values()].flat().filter((answer) => isCall(db, answer));
|
|
1152
1161
|
if (throughCalls.length === 0) {
|
|
1153
1162
|
return direct;
|
|
1154
1163
|
}
|
|
1155
1164
|
ask(throughCalls);
|
|
1156
|
-
const deeper = singleAnswers(db.facts(relation), placeholders);
|
|
1157
1165
|
return new Map(
|
|
1158
1166
|
[...direct].map(([key, answers]) => [
|
|
1159
1167
|
key,
|
|
1160
|
-
collapseCalls(
|
|
1168
|
+
collapseCalls(db, relation, answers)
|
|
1161
1169
|
])
|
|
1162
1170
|
);
|
|
1163
1171
|
}
|
|
1164
|
-
function
|
|
1172
|
+
function isCall(db, key) {
|
|
1173
|
+
return db.lookup("call", 0, key).length > 0;
|
|
1174
|
+
}
|
|
1175
|
+
function collapseCalls(db, relation, direct) {
|
|
1165
1176
|
return [
|
|
1166
1177
|
...new Set(
|
|
1167
1178
|
direct.map(
|
|
1168
|
-
(answer) =>
|
|
1179
|
+
(answer) => isCall(db, answer) ? behindCall(db, relation, answer) : answer
|
|
1169
1180
|
)
|
|
1170
1181
|
)
|
|
1171
1182
|
];
|
|
1172
1183
|
}
|
|
1184
|
+
function behindCall(db, relation, call) {
|
|
1185
|
+
const answers = answersFor2(db, relation, call);
|
|
1186
|
+
return answers.length === 1 ? answers[0] : call;
|
|
1187
|
+
}
|
|
1173
1188
|
function writesLeft(db, key) {
|
|
1174
|
-
|
|
1175
|
-
if (unstated) {
|
|
1189
|
+
if (db.has("writesUnstated", [key])) {
|
|
1176
1190
|
return [];
|
|
1177
1191
|
}
|
|
1178
|
-
const candidates =
|
|
1192
|
+
const candidates = answersFor2(db, "mayHold", key);
|
|
1179
1193
|
return candidates.length > 1 ? candidates : [];
|
|
1180
1194
|
}
|
|
1181
1195
|
|
|
@@ -1946,6 +1960,51 @@ var STATED_RULES = [
|
|
|
1946
1960
|
[v("x"), v("p")],
|
|
1947
1961
|
[lit("refersToParam", v("y"), v("p")), lit("binds", v("x"), v("y"))]
|
|
1948
1962
|
),
|
|
1963
|
+
// An expression whose value is the environment object w: the way a
|
|
1964
|
+
// pack spells it, a name declared as that, or a parameter a caller
|
|
1965
|
+
// handed one of those to, however many calls deep.
|
|
1966
|
+
rule(
|
|
1967
|
+
"environmentValue",
|
|
1968
|
+
[v("w"), v("o")],
|
|
1969
|
+
[lit("environmentObject", v("w")), lit("refersToObject", v("o"), v("w"))]
|
|
1970
|
+
),
|
|
1971
|
+
rule(
|
|
1972
|
+
"environmentValue",
|
|
1973
|
+
[v("w"), v("o")],
|
|
1974
|
+
[
|
|
1975
|
+
lit("environmentValue", v("w"), v("a")),
|
|
1976
|
+
lit("passesArgument", v("r"), v("p"), v("a")),
|
|
1977
|
+
lit("refersToParam", v("o"), v("p"))
|
|
1978
|
+
]
|
|
1979
|
+
),
|
|
1980
|
+
// A parameter that defaults to the environment, for the callers that
|
|
1981
|
+
// pass nothing. `loadConfig(env = process.env)` is written that way
|
|
1982
|
+
// so that most of the program never mentions the environment at all.
|
|
1983
|
+
rule(
|
|
1984
|
+
"environmentValue",
|
|
1985
|
+
[v("w"), v("o")],
|
|
1986
|
+
[
|
|
1987
|
+
lit("environmentValue", v("w"), v("d")),
|
|
1988
|
+
lit("paramDefault", v("p"), v("d")),
|
|
1989
|
+
lit("refersToParam", v("o"), v("p"))
|
|
1990
|
+
]
|
|
1991
|
+
),
|
|
1992
|
+
// Which environment object a keyed read takes its entry from. The
|
|
1993
|
+
// object comes first because a project writes a handful of those and
|
|
1994
|
+
// thousands of keyed reads, and the join starts at the small end.
|
|
1995
|
+
rule(
|
|
1996
|
+
"environmentRead",
|
|
1997
|
+
[v("w"), v("site"), v("x")],
|
|
1998
|
+
[
|
|
1999
|
+
lit("environmentValue", v("w"), v("o")),
|
|
2000
|
+
lit("readsKeyed", v("site"), v("o"), v("x"))
|
|
2001
|
+
]
|
|
2002
|
+
),
|
|
2003
|
+
rule(
|
|
2004
|
+
"readsEnvNamed",
|
|
2005
|
+
[v("site"), v("x")],
|
|
2006
|
+
[lit("environmentRead", v("w"), v("site"), v("x"))]
|
|
2007
|
+
),
|
|
1949
2008
|
// A parameter whose value is an environment variable's name: a read
|
|
1950
2009
|
// site takes its name from it, or it is handed on to a parameter that
|
|
1951
2010
|
// does. Asked from the site, so the recursion runs callee to caller.
|
|
@@ -2109,10 +2168,25 @@ var STATED_RULES = [
|
|
|
2109
2168
|
lit("call", v("r"), v("c"))
|
|
2110
2169
|
]
|
|
2111
2170
|
),
|
|
2112
|
-
//
|
|
2171
|
+
// A name bound to a factory's result, called: `const get =
|
|
2172
|
+
// makeReader(env)` then `get(name)`. Written from the factory's call so
|
|
2173
|
+
// the walk starts where `callsFunction` already has an answer.
|
|
2174
|
+
rule(
|
|
2175
|
+
"callsFunction",
|
|
2176
|
+
[v("r"), v("f")],
|
|
2177
|
+
[
|
|
2178
|
+
lit("returnsValue", v("g"), v("f")),
|
|
2179
|
+
lit("callsFunction", v("r0"), v("g")),
|
|
2180
|
+
lit("callsNamed", v("r"), v("r0"))
|
|
2181
|
+
]
|
|
2182
|
+
),
|
|
2183
|
+
// The expressions that refer to an object by binding alone: the
|
|
2113
2184
|
// declaration written as it, a reference or import of that, and a
|
|
2114
2185
|
// fallback over any of those. Asked from the object, so it visits only them.
|
|
2115
2186
|
rule("refersToObject", [v("obj"), v("obj")], [lit("objectValue", v("obj"))]),
|
|
2187
|
+
// The process environment is an object nothing declares, so a pack
|
|
2188
|
+
// saying which expression spells it is the only way in.
|
|
2189
|
+
rule("refersToObject", [v("w"), v("w")], [lit("environmentObject", v("w"))]),
|
|
2116
2190
|
rule(
|
|
2117
2191
|
"refersToObject",
|
|
2118
2192
|
[v("x"), v("obj")],
|
|
@@ -2502,12 +2576,33 @@ var RESOLUTION_QUESTIONS = [
|
|
|
2502
2576
|
[v("f"), v("c")],
|
|
2503
2577
|
[lit("wanted", v("f")), lit("returnsCall", v("f"), v("c"))]
|
|
2504
2578
|
),
|
|
2505
|
-
// Seeded with the
|
|
2506
|
-
//
|
|
2579
|
+
// Seeded with the expressions that spell the environment, a handful
|
|
2580
|
+
// per project. The reads cannot be the seed: one written through a
|
|
2581
|
+
// parameter is nowhere a scan of the source looks.
|
|
2507
2582
|
rule(
|
|
2508
2583
|
"wantedParamNamesEnv",
|
|
2509
2584
|
[v("p"), v("site")],
|
|
2510
|
-
[
|
|
2585
|
+
[
|
|
2586
|
+
lit("wantedEnvObject", v("w")),
|
|
2587
|
+
lit("environmentRead", v("w"), v("site"), v("x")),
|
|
2588
|
+
lit("paramNamesEnv", v("p"), v("site"))
|
|
2589
|
+
]
|
|
2590
|
+
),
|
|
2591
|
+
// The same relation asked from one expression. Seeding from the
|
|
2592
|
+
// objects instead would settle it for every expression in the
|
|
2593
|
+
// project, and a caller holding an argument wants only that one.
|
|
2594
|
+
rule(
|
|
2595
|
+
"wantedEnvironmentValue",
|
|
2596
|
+
[v("o"), v("w")],
|
|
2597
|
+
[lit("wanted", v("o")), lit("environmentValue", v("w"), v("o"))]
|
|
2598
|
+
),
|
|
2599
|
+
// Whether an expression is a parameter under another name, for a
|
|
2600
|
+
// caller deciding whether going and reading that parameter's callers
|
|
2601
|
+
// could change the answer it already has.
|
|
2602
|
+
rule(
|
|
2603
|
+
"wantedRefersToParam",
|
|
2604
|
+
[v("o"), v("p")],
|
|
2605
|
+
[lit("wanted", v("o")), lit("refersToParam", v("o"), v("p"))]
|
|
2511
2606
|
),
|
|
2512
2607
|
rule(
|
|
2513
2608
|
"wantedComesFrom",
|
|
@@ -2725,6 +2820,19 @@ var RESOLUTION_QUESTIONS = [
|
|
|
2725
2820
|
[v("c"), v("n")],
|
|
2726
2821
|
[lit("ancestryChain", v("c"), v("b")), lit("declaresName", v("b"), v("n"))]
|
|
2727
2822
|
),
|
|
2823
|
+
// The method behind each callback the chain registers, by the event
|
|
2824
|
+
// that runs it. A base registering one reaches every class below it,
|
|
2825
|
+
// and the method may be declared anywhere along the same chain.
|
|
2826
|
+
rule(
|
|
2827
|
+
"wantedCallbackMethod",
|
|
2828
|
+
[v("c"), v("event"), v("n"), v("held")],
|
|
2829
|
+
[
|
|
2830
|
+
lit("ancestryChain", v("c"), v("b")),
|
|
2831
|
+
lit("classCallback", v("b"), v("event"), v("n")),
|
|
2832
|
+
lit("ancestryChain", v("c"), v("b2")),
|
|
2833
|
+
lit("holdsProperty", v("b2"), v("n"), v("held"))
|
|
2834
|
+
]
|
|
2835
|
+
),
|
|
2728
2836
|
rule("anchorChain", [v("x"), v("x")], [lit("wantedAnchor", v("x"))]),
|
|
2729
2837
|
rule(
|
|
2730
2838
|
"anchorChain",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@suss/resolution",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.33.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "The rules suss uses to follow a name in TypeScript, Python or Ruby to the function it comes down to.",
|
|
6
6
|
"keywords": [
|
|
@@ -56,6 +56,6 @@
|
|
|
56
56
|
"access": "public"
|
|
57
57
|
},
|
|
58
58
|
"dependencies": {
|
|
59
|
-
"@suss/datalog": "0.
|
|
59
|
+
"@suss/datalog": "0.33.0"
|
|
60
60
|
}
|
|
61
61
|
}
|