@suss/resolution 0.20.0 → 0.21.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +38 -0
- package/dist/index.cjs +32 -30
- package/dist/index.js +32 -30
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -97,6 +97,18 @@ Each question is that one closure with its own stopping condition. So
|
|
|
97
97
|
adding a construct is one step and every question gets it, and adding a
|
|
98
98
|
question is a stopping condition and no steps at all.
|
|
99
99
|
|
|
100
|
+
The closure is written with the walk so far first and the next hop after
|
|
101
|
+
it: `reaches(x, z) <- reaches(x, y), stepsTo(y, z)`. The order matters
|
|
102
|
+
under demand. Every question here asks about one value, and with the
|
|
103
|
+
walk first, the demand stays on that value and each round extends the
|
|
104
|
+
walks it already has by one hop. Written hop first, `reaches(x, z) <-
|
|
105
|
+
stepsTo(x, y), reaches(y, z)`, a question about `x` becomes a question
|
|
106
|
+
about every `y` a hop leads to, so the closure is derived from every
|
|
107
|
+
value the walk passes through, and each new walk is joined back against
|
|
108
|
+
every hop that lands on its start. Extracting the TypeScript adapter's
|
|
109
|
+
own sources, the hop first order spent two seconds in the closure, and
|
|
110
|
+
the walk first order spends forty milliseconds.
|
|
111
|
+
|
|
100
112
|
## What comes out
|
|
101
113
|
|
|
102
114
|
```
|
|
@@ -200,6 +212,32 @@ The demand cone stays on the base facts named above. Nothing here pulls
|
|
|
200
212
|
`reaches` or `callsInto`, so asking about a receiver does not price in
|
|
201
213
|
call-graph closure.
|
|
202
214
|
|
|
215
|
+
## The subject behind a registration
|
|
216
|
+
|
|
217
|
+
Discovery keeps asking one question: is this receiver the app, the
|
|
218
|
+
router, the thing built by calling what a library exports? Which
|
|
219
|
+
`.get(...)` calls are routes and which `.use(...)` calls are mounts
|
|
220
|
+
both hang on the answer, and every language feature that moves a value
|
|
221
|
+
is a place the receiver can be written: a class field, a destructured
|
|
222
|
+
name, a property on an object another file built. Enumerating those
|
|
223
|
+
spellings in a walker loses to the language, so the question is asked
|
|
224
|
+
of the rules instead.
|
|
225
|
+
|
|
226
|
+
The answer comes back in two relations, both seeded by
|
|
227
|
+
`wantedSubject`.
|
|
228
|
+
`wantedSubjectWritten` is the written-value walk from the asked
|
|
229
|
+
receiver, so the asking side can apply the single-answer policy over
|
|
230
|
+
everything the receiver could be. `wantedSubjectConstruction` keeps
|
|
231
|
+
only the answers that are a call or a `new`, and pairs each with where
|
|
232
|
+
its callee was imported from, through however many aliases the callee
|
|
233
|
+
went. The asking side checks that pair against the (module, name) a
|
|
234
|
+
pack declares: exactly one distinct construction with a matching
|
|
235
|
+
origin is the subject, none or several is a refusal.
|
|
236
|
+
|
|
237
|
+
The construction end needs no fact of its own. Every call is already a
|
|
238
|
+
`call` fact, a `new` expression included, and the join against
|
|
239
|
+
`comesFrom` is what makes one of them a subject seed.
|
|
240
|
+
|
|
203
241
|
## Explaining an answer
|
|
204
242
|
|
|
205
243
|
Evaluate the same rules under `@suss/datalog`'s `witnesses` algebra and
|
package/dist/index.cjs
CHANGED
|
@@ -631,9 +631,9 @@ var RESOLUTION_RULES = [
|
|
|
631
631
|
[(0, import_datalog2.lit)("invokes", (0, import_datalog2.variable)("r"), (0, import_datalog2.variable)("f")), (0, import_datalog2.lit)("returnsValue", (0, import_datalog2.variable)("f"), (0, import_datalog2.variable)("ret"))],
|
|
632
632
|
"call result"
|
|
633
633
|
),
|
|
634
|
-
// Where a walk gets to, and whether it ran a call on the way.
|
|
635
|
-
//
|
|
636
|
-
//
|
|
634
|
+
// Where a walk gets to, and whether it ran a call on the way. The walk
|
|
635
|
+
// so far comes first, so demand stays on the value asked about; the
|
|
636
|
+
// README says what the other order cost.
|
|
637
637
|
(0, import_datalog2.rule)(
|
|
638
638
|
"reaches",
|
|
639
639
|
[(0, import_datalog2.variable)("x"), (0, import_datalog2.variable)("z"), (0, import_datalog2.variable)("kind")],
|
|
@@ -643,27 +643,27 @@ var RESOLUTION_RULES = [
|
|
|
643
643
|
"reaches",
|
|
644
644
|
[(0, import_datalog2.variable)("x"), (0, import_datalog2.variable)("z"), (0, import_datalog2.variable)("kind")],
|
|
645
645
|
[
|
|
646
|
-
(0, import_datalog2.lit)("
|
|
647
|
-
(0, import_datalog2.lit)("
|
|
646
|
+
(0, import_datalog2.lit)("reaches", (0, import_datalog2.variable)("x"), (0, import_datalog2.variable)("y"), VALUE_STEP),
|
|
647
|
+
(0, import_datalog2.lit)("stepsTo", (0, import_datalog2.variable)("y"), (0, import_datalog2.variable)("z"), (0, import_datalog2.variable)("kind"))
|
|
648
648
|
]
|
|
649
649
|
),
|
|
650
|
-
// Two rules rather than one leaving the
|
|
651
|
-
//
|
|
650
|
+
// Two rules rather than one leaving the next step's kind free. A free
|
|
651
|
+
// kind is a second question about the same relation, and a
|
|
652
652
|
// demand-driven run then derives both to answer either.
|
|
653
653
|
(0, import_datalog2.rule)(
|
|
654
654
|
"reaches",
|
|
655
655
|
[(0, import_datalog2.variable)("x"), (0, import_datalog2.variable)("z"), RESULT_STEP],
|
|
656
656
|
[
|
|
657
|
-
(0, import_datalog2.lit)("
|
|
658
|
-
(0, import_datalog2.lit)("
|
|
657
|
+
(0, import_datalog2.lit)("reaches", (0, import_datalog2.variable)("x"), (0, import_datalog2.variable)("y"), RESULT_STEP),
|
|
658
|
+
(0, import_datalog2.lit)("stepsTo", (0, import_datalog2.variable)("y"), (0, import_datalog2.variable)("z"), VALUE_STEP)
|
|
659
659
|
]
|
|
660
660
|
),
|
|
661
661
|
(0, import_datalog2.rule)(
|
|
662
662
|
"reaches",
|
|
663
663
|
[(0, import_datalog2.variable)("x"), (0, import_datalog2.variable)("z"), RESULT_STEP],
|
|
664
664
|
[
|
|
665
|
-
(0, import_datalog2.lit)("
|
|
666
|
-
(0, import_datalog2.lit)("
|
|
665
|
+
(0, import_datalog2.lit)("reaches", (0, import_datalog2.variable)("x"), (0, import_datalog2.variable)("y"), RESULT_STEP),
|
|
666
|
+
(0, import_datalog2.lit)("stepsTo", (0, import_datalog2.variable)("y"), (0, import_datalog2.variable)("z"), RESULT_STEP)
|
|
667
667
|
]
|
|
668
668
|
),
|
|
669
669
|
// What a value comes down to: the walk that never ran a call, stopped
|
|
@@ -1009,29 +1009,14 @@ var RESOLUTION_QUESTIONS = [
|
|
|
1009
1009
|
// here demands reaches or callsInto. The chains are closures with
|
|
1010
1010
|
// no depth bound: an alias run of any length resolves.
|
|
1011
1011
|
(0, import_datalog2.rule)("callOriginChain", [(0, import_datalog2.variable)("x"), (0, import_datalog2.variable)("x")], [(0, import_datalog2.lit)("wantedCallOrigin", (0, import_datalog2.variable)("x"))]),
|
|
1012
|
+
// The chain with at least one hop taken, which is what tells a
|
|
1013
|
+
// destructured binding apart from asking about a node directly. The
|
|
1014
|
+
// whole chain is the seed plus those hops.
|
|
1012
1015
|
(0, import_datalog2.rule)(
|
|
1013
1016
|
"callOriginChain",
|
|
1014
1017
|
[(0, import_datalog2.variable)("x"), (0, import_datalog2.variable)("z")],
|
|
1015
|
-
[(0, import_datalog2.lit)("
|
|
1018
|
+
[(0, import_datalog2.lit)("callOriginChainStepped", (0, import_datalog2.variable)("x"), (0, import_datalog2.variable)("z"))]
|
|
1016
1019
|
),
|
|
1017
|
-
(0, import_datalog2.rule)(
|
|
1018
|
-
"callOriginChain",
|
|
1019
|
-
[(0, import_datalog2.variable)("x"), (0, import_datalog2.variable)("z")],
|
|
1020
|
-
[
|
|
1021
|
-
(0, import_datalog2.lit)("callOriginChain", (0, import_datalog2.variable)("x"), (0, import_datalog2.variable)("y")),
|
|
1022
|
-
(0, import_datalog2.lit)("endsHolding", (0, import_datalog2.variable)("y"), (0, import_datalog2.variable)("z"))
|
|
1023
|
-
]
|
|
1024
|
-
),
|
|
1025
|
-
(0, import_datalog2.rule)(
|
|
1026
|
-
"callOriginChain",
|
|
1027
|
-
[(0, import_datalog2.variable)("x"), (0, import_datalog2.variable)("z")],
|
|
1028
|
-
[
|
|
1029
|
-
(0, import_datalog2.lit)("callOriginChain", (0, import_datalog2.variable)("x"), (0, import_datalog2.variable)("y")),
|
|
1030
|
-
(0, import_datalog2.lit)("fallbackBranch", (0, import_datalog2.variable)("y"), (0, import_datalog2.variable)("z"))
|
|
1031
|
-
]
|
|
1032
|
-
),
|
|
1033
|
-
// The chain with at least one hop taken, which is what tells a
|
|
1034
|
-
// destructured binding apart from asking about a node directly.
|
|
1035
1020
|
(0, import_datalog2.rule)(
|
|
1036
1021
|
"callOriginChainStepped",
|
|
1037
1022
|
[(0, import_datalog2.variable)("x"), (0, import_datalog2.variable)("z")],
|
|
@@ -1162,6 +1147,23 @@ var RESOLUTION_QUESTIONS = [
|
|
|
1162
1147
|
(0, import_datalog2.lit)("callsInto", (0, import_datalog2.variable)("g"), (0, import_datalog2.variable)("m"), (0, import_datalog2.variable)("n"))
|
|
1163
1148
|
]
|
|
1164
1149
|
),
|
|
1150
|
+
// Subject identity, its own demand class; the README's subject
|
|
1151
|
+
// section says why the origin pair rides on the written-value walk.
|
|
1152
|
+
(0, import_datalog2.rule)(
|
|
1153
|
+
"wantedSubjectWritten",
|
|
1154
|
+
[(0, import_datalog2.variable)("x"), (0, import_datalog2.variable)("r")],
|
|
1155
|
+
[(0, import_datalog2.lit)("wantedSubject", (0, import_datalog2.variable)("x")), (0, import_datalog2.lit)("isWrittenAs", (0, import_datalog2.variable)("x"), (0, import_datalog2.variable)("r"))]
|
|
1156
|
+
),
|
|
1157
|
+
(0, import_datalog2.rule)(
|
|
1158
|
+
"wantedSubjectConstruction",
|
|
1159
|
+
[(0, import_datalog2.variable)("x"), (0, import_datalog2.variable)("r"), (0, import_datalog2.variable)("m"), (0, import_datalog2.variable)("n")],
|
|
1160
|
+
[
|
|
1161
|
+
(0, import_datalog2.lit)("wantedSubject", (0, import_datalog2.variable)("x")),
|
|
1162
|
+
(0, import_datalog2.lit)("isWrittenAs", (0, import_datalog2.variable)("x"), (0, import_datalog2.variable)("r")),
|
|
1163
|
+
(0, import_datalog2.lit)("call", (0, import_datalog2.variable)("r"), (0, import_datalog2.variable)("c")),
|
|
1164
|
+
(0, import_datalog2.lit)("comesFrom", (0, import_datalog2.variable)("c"), (0, import_datalog2.variable)("m"), (0, import_datalog2.variable)("n"))
|
|
1165
|
+
]
|
|
1166
|
+
),
|
|
1165
1167
|
// The export table of one module, keyed by the module asked about.
|
|
1166
1168
|
// The moduleExport rules flatten re-export chains of any length, and
|
|
1167
1169
|
// the demand cone stays on export facts alone.
|
package/dist/index.js
CHANGED
|
@@ -592,9 +592,9 @@ var RESOLUTION_RULES = [
|
|
|
592
592
|
[lit("invokes", v("r"), v("f")), lit("returnsValue", v("f"), v("ret"))],
|
|
593
593
|
"call result"
|
|
594
594
|
),
|
|
595
|
-
// Where a walk gets to, and whether it ran a call on the way.
|
|
596
|
-
//
|
|
597
|
-
//
|
|
595
|
+
// Where a walk gets to, and whether it ran a call on the way. The walk
|
|
596
|
+
// so far comes first, so demand stays on the value asked about; the
|
|
597
|
+
// README says what the other order cost.
|
|
598
598
|
rule(
|
|
599
599
|
"reaches",
|
|
600
600
|
[v("x"), v("z"), v("kind")],
|
|
@@ -604,27 +604,27 @@ var RESOLUTION_RULES = [
|
|
|
604
604
|
"reaches",
|
|
605
605
|
[v("x"), v("z"), v("kind")],
|
|
606
606
|
[
|
|
607
|
-
lit("
|
|
608
|
-
lit("
|
|
607
|
+
lit("reaches", v("x"), v("y"), VALUE_STEP),
|
|
608
|
+
lit("stepsTo", v("y"), v("z"), v("kind"))
|
|
609
609
|
]
|
|
610
610
|
),
|
|
611
|
-
// Two rules rather than one leaving the
|
|
612
|
-
//
|
|
611
|
+
// Two rules rather than one leaving the next step's kind free. A free
|
|
612
|
+
// kind is a second question about the same relation, and a
|
|
613
613
|
// demand-driven run then derives both to answer either.
|
|
614
614
|
rule(
|
|
615
615
|
"reaches",
|
|
616
616
|
[v("x"), v("z"), RESULT_STEP],
|
|
617
617
|
[
|
|
618
|
-
lit("
|
|
619
|
-
lit("
|
|
618
|
+
lit("reaches", v("x"), v("y"), RESULT_STEP),
|
|
619
|
+
lit("stepsTo", v("y"), v("z"), VALUE_STEP)
|
|
620
620
|
]
|
|
621
621
|
),
|
|
622
622
|
rule(
|
|
623
623
|
"reaches",
|
|
624
624
|
[v("x"), v("z"), RESULT_STEP],
|
|
625
625
|
[
|
|
626
|
-
lit("
|
|
627
|
-
lit("
|
|
626
|
+
lit("reaches", v("x"), v("y"), RESULT_STEP),
|
|
627
|
+
lit("stepsTo", v("y"), v("z"), RESULT_STEP)
|
|
628
628
|
]
|
|
629
629
|
),
|
|
630
630
|
// What a value comes down to: the walk that never ran a call, stopped
|
|
@@ -970,29 +970,14 @@ var RESOLUTION_QUESTIONS = [
|
|
|
970
970
|
// here demands reaches or callsInto. The chains are closures with
|
|
971
971
|
// no depth bound: an alias run of any length resolves.
|
|
972
972
|
rule("callOriginChain", [v("x"), v("x")], [lit("wantedCallOrigin", v("x"))]),
|
|
973
|
+
// The chain with at least one hop taken, which is what tells a
|
|
974
|
+
// destructured binding apart from asking about a node directly. The
|
|
975
|
+
// whole chain is the seed plus those hops.
|
|
973
976
|
rule(
|
|
974
977
|
"callOriginChain",
|
|
975
978
|
[v("x"), v("z")],
|
|
976
|
-
[lit("
|
|
979
|
+
[lit("callOriginChainStepped", v("x"), v("z"))]
|
|
977
980
|
),
|
|
978
|
-
rule(
|
|
979
|
-
"callOriginChain",
|
|
980
|
-
[v("x"), v("z")],
|
|
981
|
-
[
|
|
982
|
-
lit("callOriginChain", v("x"), v("y")),
|
|
983
|
-
lit("endsHolding", v("y"), v("z"))
|
|
984
|
-
]
|
|
985
|
-
),
|
|
986
|
-
rule(
|
|
987
|
-
"callOriginChain",
|
|
988
|
-
[v("x"), v("z")],
|
|
989
|
-
[
|
|
990
|
-
lit("callOriginChain", v("x"), v("y")),
|
|
991
|
-
lit("fallbackBranch", v("y"), v("z"))
|
|
992
|
-
]
|
|
993
|
-
),
|
|
994
|
-
// The chain with at least one hop taken, which is what tells a
|
|
995
|
-
// destructured binding apart from asking about a node directly.
|
|
996
981
|
rule(
|
|
997
982
|
"callOriginChainStepped",
|
|
998
983
|
[v("x"), v("z")],
|
|
@@ -1123,6 +1108,23 @@ var RESOLUTION_QUESTIONS = [
|
|
|
1123
1108
|
lit("callsInto", v("g"), v("m"), v("n"))
|
|
1124
1109
|
]
|
|
1125
1110
|
),
|
|
1111
|
+
// Subject identity, its own demand class; the README's subject
|
|
1112
|
+
// section says why the origin pair rides on the written-value walk.
|
|
1113
|
+
rule(
|
|
1114
|
+
"wantedSubjectWritten",
|
|
1115
|
+
[v("x"), v("r")],
|
|
1116
|
+
[lit("wantedSubject", v("x")), lit("isWrittenAs", v("x"), v("r"))]
|
|
1117
|
+
),
|
|
1118
|
+
rule(
|
|
1119
|
+
"wantedSubjectConstruction",
|
|
1120
|
+
[v("x"), v("r"), v("m"), v("n")],
|
|
1121
|
+
[
|
|
1122
|
+
lit("wantedSubject", v("x")),
|
|
1123
|
+
lit("isWrittenAs", v("x"), v("r")),
|
|
1124
|
+
lit("call", v("r"), v("c")),
|
|
1125
|
+
lit("comesFrom", v("c"), v("m"), v("n"))
|
|
1126
|
+
]
|
|
1127
|
+
),
|
|
1126
1128
|
// The export table of one module, keyed by the module asked about.
|
|
1127
1129
|
// The moduleExport rules flatten re-export chains of any length, and
|
|
1128
1130
|
// the demand cone stays on export facts alone.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@suss/resolution",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.21.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Language-neutral rules for following a value to the function it comes down to.",
|
|
6
6
|
"keywords": [
|
|
@@ -53,6 +53,6 @@
|
|
|
53
53
|
"access": "public"
|
|
54
54
|
},
|
|
55
55
|
"dependencies": {
|
|
56
|
-
"@suss/datalog": "0.
|
|
56
|
+
"@suss/datalog": "0.21.1"
|
|
57
57
|
}
|
|
58
58
|
}
|