@suss/resolution 0.21.0 → 0.22.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 CHANGED
@@ -23,6 +23,8 @@ func(f) f is a function
23
23
  objectValue(o) o is an object written out literally
24
24
  writtenValue(x) x is an expression written out in source
25
25
  rather than a name for one
26
+ placeholderValue(x) x is a written value a later write is
27
+ expected to replace, such as None or nil
26
28
  holdsProperty(o, n, x) object o holds x under the name n
27
29
  readsProperty(x, o, n) x is the expression o.n
28
30
  binds(x, y) the name x is declared as y
@@ -97,6 +99,18 @@ Each question is that one closure with its own stopping condition. So
97
99
  adding a construct is one step and every question gets it, and adding a
98
100
  question is a stopping condition and no steps at all.
99
101
 
102
+ The closure is written with the walk so far first and the next hop after
103
+ it: `reaches(x, z) <- reaches(x, y), stepsTo(y, z)`. The order matters
104
+ under demand. Every question here asks about one value, and with the
105
+ walk first, the demand stays on that value and each round extends the
106
+ walks it already has by one hop. Written hop first, `reaches(x, z) <-
107
+ stepsTo(x, y), reaches(y, z)`, a question about `x` becomes a question
108
+ about every `y` a hop leads to, so the closure is derived from every
109
+ value the walk passes through, and each new walk is joined back against
110
+ every hop that lands on its start. Extracting the TypeScript adapter's
111
+ own sources, the hop first order spent two seconds in the closure, and
112
+ the walk first order spends forty milliseconds.
113
+
100
114
  ## What comes out
101
115
 
102
116
  ```
@@ -226,6 +240,30 @@ The construction end needs no fact of its own. Every call is already a
226
240
  `call` fact, a `new` expression included, and the join against
227
241
  `comesFrom` is what makes one of them a subject seed.
228
242
 
243
+ A call is written as itself, the same base case that makes a class its
244
+ own ancestor at the top of the chain. So when an adapter asks
245
+ `wantedSubjectWritten` about a call directly, the answers include the
246
+ call itself next to whatever the walk reaches. A call with one other
247
+ answer would count as two and be refused as ambiguous. `singleAnswers`
248
+ drops the row whose answer is its own key before counting, and every
249
+ adapter reads the relation through it.
250
+
251
+ A name written as a placeholder before a guard fills it in, `_client =
252
+ None` at module level and `_client = make_client()` inside a getter, is
253
+ two answers the same way. An adapter marks the placeholder write with
254
+ `placeholderValue(x)` and passes those keys to `singleAnswers`, which
255
+ sets them aside whenever the key has another answer. A name written only
256
+ as a placeholder keeps that answer. The TypeScript store does the same
257
+ for `null` and `undefined` in `sameConstructionAcrossWrites`.
258
+
259
+ A name bound to a call is a separate case. Its one answer is the call,
260
+ and the rule that says a call is written as what its callee returns
261
+ only fires for the call itself, never for a name that reaches one. An
262
+ adapter that wants the deeper answer asks `wantedSubject` a second
263
+ time with the call as the subject and takes that answer. The
264
+ TypeScript store does the same in `resolveWrittenValue` and in
265
+ `subjectConstructionOf`, whenever a name resolves to a call.
266
+
229
267
  ## Explaining an answer
230
268
 
231
269
  Evaluate the same rules under `@suss/datalog`'s `witnesses` algebra and