@suss/resolution 0.31.2 → 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 +167 -13
- package/dist/index.js +167 -13
- 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,6 +80,7 @@ var ASKING_RELATIONS = [
|
|
|
80
80
|
"wanted",
|
|
81
81
|
"wantedUnder",
|
|
82
82
|
"wantedSites",
|
|
83
|
+
"wantedEnvObject",
|
|
83
84
|
"wantedOrigin",
|
|
84
85
|
"wantedCallOrigin",
|
|
85
86
|
"wantedExportsOf",
|
|
@@ -1119,6 +1120,16 @@ function answersByKey(rows, placeholders = NO_PLACEHOLDERS) {
|
|
|
1119
1120
|
}
|
|
1120
1121
|
return answers;
|
|
1121
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
|
+
}
|
|
1122
1133
|
function singleAnswers(rows, placeholders = NO_PLACEHOLDERS) {
|
|
1123
1134
|
const settled = /* @__PURE__ */ new Map();
|
|
1124
1135
|
for (const [key, answers] of answersByKey(rows, placeholders)) {
|
|
@@ -1210,38 +1221,42 @@ function writtenValuesByKey(db, keys, ask, relation = WRITTEN_AS) {
|
|
|
1210
1221
|
return one;
|
|
1211
1222
|
}
|
|
1212
1223
|
function settledByKey(db, keys, ask, relation) {
|
|
1213
|
-
const
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
const
|
|
1217
|
-
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));
|
|
1218
1228
|
if (throughCalls.length === 0) {
|
|
1219
1229
|
return direct;
|
|
1220
1230
|
}
|
|
1221
1231
|
ask(throughCalls);
|
|
1222
|
-
const deeper = singleAnswers(db.facts(relation), placeholders);
|
|
1223
1232
|
return new Map(
|
|
1224
1233
|
[...direct].map(([key, answers]) => [
|
|
1225
1234
|
key,
|
|
1226
|
-
collapseCalls(
|
|
1235
|
+
collapseCalls(db, relation, answers)
|
|
1227
1236
|
])
|
|
1228
1237
|
);
|
|
1229
1238
|
}
|
|
1230
|
-
function
|
|
1239
|
+
function isCall(db, key) {
|
|
1240
|
+
return db.lookup("call", 0, key).length > 0;
|
|
1241
|
+
}
|
|
1242
|
+
function collapseCalls(db, relation, direct) {
|
|
1231
1243
|
return [
|
|
1232
1244
|
...new Set(
|
|
1233
1245
|
direct.map(
|
|
1234
|
-
(answer) =>
|
|
1246
|
+
(answer) => isCall(db, answer) ? behindCall(db, relation, answer) : answer
|
|
1235
1247
|
)
|
|
1236
1248
|
)
|
|
1237
1249
|
];
|
|
1238
1250
|
}
|
|
1251
|
+
function behindCall(db, relation, call) {
|
|
1252
|
+
const answers = answersFor2(db, relation, call);
|
|
1253
|
+
return answers.length === 1 ? answers[0] : call;
|
|
1254
|
+
}
|
|
1239
1255
|
function writesLeft(db, key) {
|
|
1240
|
-
|
|
1241
|
-
if (unstated) {
|
|
1256
|
+
if (db.has("writesUnstated", [key])) {
|
|
1242
1257
|
return [];
|
|
1243
1258
|
}
|
|
1244
|
-
const candidates =
|
|
1259
|
+
const candidates = answersFor2(db, "mayHold", key);
|
|
1245
1260
|
return candidates.length > 1 ? candidates : [];
|
|
1246
1261
|
}
|
|
1247
1262
|
|
|
@@ -1994,6 +2009,89 @@ var STATED_RULES = [
|
|
|
1994
2009
|
(0, import_datalog4.lit)("callKeywordArg", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("n"), (0, import_datalog4.variable)("a"))
|
|
1995
2010
|
]
|
|
1996
2011
|
),
|
|
2012
|
+
// The expressions that refer to a parameter by binding alone. An
|
|
2013
|
+
// adapter may key a read of the parameter as the parameter itself,
|
|
2014
|
+
// or as its own node linked by binds; both arrive here.
|
|
2015
|
+
(0, import_datalog4.rule)(
|
|
2016
|
+
"refersToParam",
|
|
2017
|
+
[(0, import_datalog4.variable)("p"), (0, import_datalog4.variable)("p")],
|
|
2018
|
+
[(0, import_datalog4.lit)("paramOf", (0, import_datalog4.variable)("f"), (0, import_datalog4.variable)("k"), (0, import_datalog4.variable)("p"))]
|
|
2019
|
+
),
|
|
2020
|
+
(0, import_datalog4.rule)(
|
|
2021
|
+
"refersToParam",
|
|
2022
|
+
[(0, import_datalog4.variable)("p"), (0, import_datalog4.variable)("p")],
|
|
2023
|
+
[(0, import_datalog4.lit)("paramNamed", (0, import_datalog4.variable)("f"), (0, import_datalog4.variable)("n"), (0, import_datalog4.variable)("p"))]
|
|
2024
|
+
),
|
|
2025
|
+
(0, import_datalog4.rule)(
|
|
2026
|
+
"refersToParam",
|
|
2027
|
+
[(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("p")],
|
|
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"))]
|
|
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
|
+
),
|
|
2075
|
+
// A parameter whose value is an environment variable's name: a read
|
|
2076
|
+
// site takes its name from it, or it is handed on to a parameter that
|
|
2077
|
+
// does. Asked from the site, so the recursion runs callee to caller.
|
|
2078
|
+
(0, import_datalog4.rule)(
|
|
2079
|
+
"paramNamesEnv",
|
|
2080
|
+
[(0, import_datalog4.variable)("p"), (0, import_datalog4.variable)("site")],
|
|
2081
|
+
[
|
|
2082
|
+
(0, import_datalog4.lit)("readsEnvNamed", (0, import_datalog4.variable)("site"), (0, import_datalog4.variable)("x")),
|
|
2083
|
+
(0, import_datalog4.lit)("refersToParam", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("p"))
|
|
2084
|
+
]
|
|
2085
|
+
),
|
|
2086
|
+
(0, import_datalog4.rule)(
|
|
2087
|
+
"paramNamesEnv",
|
|
2088
|
+
[(0, import_datalog4.variable)("p"), (0, import_datalog4.variable)("site")],
|
|
2089
|
+
[
|
|
2090
|
+
(0, import_datalog4.lit)("refersToParam", (0, import_datalog4.variable)("a"), (0, import_datalog4.variable)("p")),
|
|
2091
|
+
(0, import_datalog4.lit)("passesArgument", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("q"), (0, import_datalog4.variable)("a")),
|
|
2092
|
+
(0, import_datalog4.lit)("paramNamesEnv", (0, import_datalog4.variable)("q"), (0, import_datalog4.variable)("site"))
|
|
2093
|
+
]
|
|
2094
|
+
),
|
|
1997
2095
|
// Which module's export a re-exported name forwards to, however
|
|
1998
2096
|
// many barrels deep the forwarding runs.
|
|
1999
2097
|
(0, import_datalog4.rule)(
|
|
@@ -2137,10 +2235,25 @@ var STATED_RULES = [
|
|
|
2137
2235
|
(0, import_datalog4.lit)("call", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("c"))
|
|
2138
2236
|
]
|
|
2139
2237
|
),
|
|
2140
|
-
//
|
|
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
|
|
2141
2251
|
// declaration written as it, a reference or import of that, and a
|
|
2142
2252
|
// fallback over any of those. Asked from the object, so it visits only them.
|
|
2143
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"))]),
|
|
2144
2257
|
(0, import_datalog4.rule)(
|
|
2145
2258
|
"refersToObject",
|
|
2146
2259
|
[(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("obj")],
|
|
@@ -2530,6 +2643,34 @@ var RESOLUTION_QUESTIONS = [
|
|
|
2530
2643
|
[(0, import_datalog4.variable)("f"), (0, import_datalog4.variable)("c")],
|
|
2531
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"))]
|
|
2532
2645
|
),
|
|
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.
|
|
2649
|
+
(0, import_datalog4.rule)(
|
|
2650
|
+
"wantedParamNamesEnv",
|
|
2651
|
+
[(0, import_datalog4.variable)("p"), (0, import_datalog4.variable)("site")],
|
|
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"))]
|
|
2673
|
+
),
|
|
2533
2674
|
(0, import_datalog4.rule)(
|
|
2534
2675
|
"wantedComesFrom",
|
|
2535
2676
|
[(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("m"), (0, import_datalog4.variable)("n")],
|
|
@@ -2746,6 +2887,19 @@ var RESOLUTION_QUESTIONS = [
|
|
|
2746
2887
|
[(0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("n")],
|
|
2747
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"))]
|
|
2748
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
|
+
),
|
|
2749
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"))]),
|
|
2750
2904
|
(0, import_datalog4.rule)(
|
|
2751
2905
|
"anchorChain",
|
package/dist/index.js
CHANGED
|
@@ -13,6 +13,7 @@ var ASKING_RELATIONS = [
|
|
|
13
13
|
"wanted",
|
|
14
14
|
"wantedUnder",
|
|
15
15
|
"wantedSites",
|
|
16
|
+
"wantedEnvObject",
|
|
16
17
|
"wantedOrigin",
|
|
17
18
|
"wantedCallOrigin",
|
|
18
19
|
"wantedExportsOf",
|
|
@@ -1052,6 +1053,16 @@ function answersByKey(rows, placeholders = NO_PLACEHOLDERS) {
|
|
|
1052
1053
|
}
|
|
1053
1054
|
return answers;
|
|
1054
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
|
+
}
|
|
1055
1066
|
function singleAnswers(rows, placeholders = NO_PLACEHOLDERS) {
|
|
1056
1067
|
const settled = /* @__PURE__ */ new Map();
|
|
1057
1068
|
for (const [key, answers] of answersByKey(rows, placeholders)) {
|
|
@@ -1143,38 +1154,42 @@ function writtenValuesByKey(db, keys, ask, relation = WRITTEN_AS) {
|
|
|
1143
1154
|
return one;
|
|
1144
1155
|
}
|
|
1145
1156
|
function settledByKey(db, keys, ask, relation) {
|
|
1146
|
-
const
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
const
|
|
1150
|
-
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));
|
|
1151
1161
|
if (throughCalls.length === 0) {
|
|
1152
1162
|
return direct;
|
|
1153
1163
|
}
|
|
1154
1164
|
ask(throughCalls);
|
|
1155
|
-
const deeper = singleAnswers(db.facts(relation), placeholders);
|
|
1156
1165
|
return new Map(
|
|
1157
1166
|
[...direct].map(([key, answers]) => [
|
|
1158
1167
|
key,
|
|
1159
|
-
collapseCalls(
|
|
1168
|
+
collapseCalls(db, relation, answers)
|
|
1160
1169
|
])
|
|
1161
1170
|
);
|
|
1162
1171
|
}
|
|
1163
|
-
function
|
|
1172
|
+
function isCall(db, key) {
|
|
1173
|
+
return db.lookup("call", 0, key).length > 0;
|
|
1174
|
+
}
|
|
1175
|
+
function collapseCalls(db, relation, direct) {
|
|
1164
1176
|
return [
|
|
1165
1177
|
...new Set(
|
|
1166
1178
|
direct.map(
|
|
1167
|
-
(answer) =>
|
|
1179
|
+
(answer) => isCall(db, answer) ? behindCall(db, relation, answer) : answer
|
|
1168
1180
|
)
|
|
1169
1181
|
)
|
|
1170
1182
|
];
|
|
1171
1183
|
}
|
|
1184
|
+
function behindCall(db, relation, call) {
|
|
1185
|
+
const answers = answersFor2(db, relation, call);
|
|
1186
|
+
return answers.length === 1 ? answers[0] : call;
|
|
1187
|
+
}
|
|
1172
1188
|
function writesLeft(db, key) {
|
|
1173
|
-
|
|
1174
|
-
if (unstated) {
|
|
1189
|
+
if (db.has("writesUnstated", [key])) {
|
|
1175
1190
|
return [];
|
|
1176
1191
|
}
|
|
1177
|
-
const candidates =
|
|
1192
|
+
const candidates = answersFor2(db, "mayHold", key);
|
|
1178
1193
|
return candidates.length > 1 ? candidates : [];
|
|
1179
1194
|
}
|
|
1180
1195
|
|
|
@@ -1927,6 +1942,89 @@ var STATED_RULES = [
|
|
|
1927
1942
|
lit("callKeywordArg", v("r"), v("n"), v("a"))
|
|
1928
1943
|
]
|
|
1929
1944
|
),
|
|
1945
|
+
// The expressions that refer to a parameter by binding alone. An
|
|
1946
|
+
// adapter may key a read of the parameter as the parameter itself,
|
|
1947
|
+
// or as its own node linked by binds; both arrive here.
|
|
1948
|
+
rule(
|
|
1949
|
+
"refersToParam",
|
|
1950
|
+
[v("p"), v("p")],
|
|
1951
|
+
[lit("paramOf", v("f"), v("k"), v("p"))]
|
|
1952
|
+
),
|
|
1953
|
+
rule(
|
|
1954
|
+
"refersToParam",
|
|
1955
|
+
[v("p"), v("p")],
|
|
1956
|
+
[lit("paramNamed", v("f"), v("n"), v("p"))]
|
|
1957
|
+
),
|
|
1958
|
+
rule(
|
|
1959
|
+
"refersToParam",
|
|
1960
|
+
[v("x"), v("p")],
|
|
1961
|
+
[lit("refersToParam", v("y"), v("p")), lit("binds", v("x"), v("y"))]
|
|
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
|
+
),
|
|
2008
|
+
// A parameter whose value is an environment variable's name: a read
|
|
2009
|
+
// site takes its name from it, or it is handed on to a parameter that
|
|
2010
|
+
// does. Asked from the site, so the recursion runs callee to caller.
|
|
2011
|
+
rule(
|
|
2012
|
+
"paramNamesEnv",
|
|
2013
|
+
[v("p"), v("site")],
|
|
2014
|
+
[
|
|
2015
|
+
lit("readsEnvNamed", v("site"), v("x")),
|
|
2016
|
+
lit("refersToParam", v("x"), v("p"))
|
|
2017
|
+
]
|
|
2018
|
+
),
|
|
2019
|
+
rule(
|
|
2020
|
+
"paramNamesEnv",
|
|
2021
|
+
[v("p"), v("site")],
|
|
2022
|
+
[
|
|
2023
|
+
lit("refersToParam", v("a"), v("p")),
|
|
2024
|
+
lit("passesArgument", v("r"), v("q"), v("a")),
|
|
2025
|
+
lit("paramNamesEnv", v("q"), v("site"))
|
|
2026
|
+
]
|
|
2027
|
+
),
|
|
1930
2028
|
// Which module's export a re-exported name forwards to, however
|
|
1931
2029
|
// many barrels deep the forwarding runs.
|
|
1932
2030
|
rule(
|
|
@@ -2070,10 +2168,25 @@ var STATED_RULES = [
|
|
|
2070
2168
|
lit("call", v("r"), v("c"))
|
|
2071
2169
|
]
|
|
2072
2170
|
),
|
|
2073
|
-
//
|
|
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
|
|
2074
2184
|
// declaration written as it, a reference or import of that, and a
|
|
2075
2185
|
// fallback over any of those. Asked from the object, so it visits only them.
|
|
2076
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"))]),
|
|
2077
2190
|
rule(
|
|
2078
2191
|
"refersToObject",
|
|
2079
2192
|
[v("x"), v("obj")],
|
|
@@ -2463,6 +2576,34 @@ var RESOLUTION_QUESTIONS = [
|
|
|
2463
2576
|
[v("f"), v("c")],
|
|
2464
2577
|
[lit("wanted", v("f")), lit("returnsCall", v("f"), v("c"))]
|
|
2465
2578
|
),
|
|
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.
|
|
2582
|
+
rule(
|
|
2583
|
+
"wantedParamNamesEnv",
|
|
2584
|
+
[v("p"), v("site")],
|
|
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"))]
|
|
2606
|
+
),
|
|
2466
2607
|
rule(
|
|
2467
2608
|
"wantedComesFrom",
|
|
2468
2609
|
[v("x"), v("m"), v("n")],
|
|
@@ -2679,6 +2820,19 @@ var RESOLUTION_QUESTIONS = [
|
|
|
2679
2820
|
[v("c"), v("n")],
|
|
2680
2821
|
[lit("ancestryChain", v("c"), v("b")), lit("declaresName", v("b"), v("n"))]
|
|
2681
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
|
+
),
|
|
2682
2836
|
rule("anchorChain", [v("x"), v("x")], [lit("wantedAnchor", v("x"))]),
|
|
2683
2837
|
rule(
|
|
2684
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
|
}
|