@bjornpagen/bumbledb 0.5.0 → 0.7.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/COOKBOOK.md +140 -136
- package/README.md +24 -11
- package/dist/closed.d.ts +7 -5
- package/dist/closed.d.ts.map +1 -1
- package/dist/closed.js +4 -1
- package/dist/closed.js.map +1 -1
- package/dist/count.js +1 -1
- package/dist/count.js.map +1 -1
- package/dist/db.d.ts +110 -73
- package/dist/db.d.ts.map +1 -1
- package/dist/db.js +172 -116
- package/dist/db.js.map +1 -1
- package/dist/exhume.d.ts +22 -10
- package/dist/exhume.d.ts.map +1 -1
- package/dist/exhume.js +42 -9
- package/dist/exhume.js.map +1 -1
- package/dist/face.d.ts +10 -6
- package/dist/face.d.ts.map +1 -1
- package/dist/face.js.map +1 -1
- package/dist/fields.d.ts +38 -16
- package/dist/fields.d.ts.map +1 -1
- package/dist/fields.js +33 -8
- package/dist/fields.js.map +1 -1
- package/dist/index.d.ts +9 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -2
- package/dist/index.js.map +1 -1
- package/dist/lower.d.ts +9 -9
- package/dist/lower.d.ts.map +1 -1
- package/dist/lower.js +17 -12
- package/dist/lower.js.map +1 -1
- package/dist/marshal.d.ts +17 -7
- package/dist/marshal.d.ts.map +1 -1
- package/dist/marshal.js +32 -10
- package/dist/marshal.js.map +1 -1
- package/dist/native.d.ts +60 -9
- package/dist/native.d.ts.map +1 -1
- package/dist/native.js.map +1 -1
- package/dist/query/atom.d.ts +199 -203
- package/dist/query/atom.d.ts.map +1 -1
- package/dist/query/atom.js +39 -48
- package/dist/query/atom.js.map +1 -1
- package/dist/query/find.d.ts +116 -0
- package/dist/query/find.d.ts.map +1 -0
- package/dist/query/{select.js → find.js} +22 -22
- package/dist/query/find.js.map +1 -0
- package/dist/query/lower.d.ts +131 -158
- package/dist/query/lower.d.ts.map +1 -1
- package/dist/query/lower.js +505 -494
- package/dist/query/lower.js.map +1 -1
- package/dist/query/predicate.d.ts +22 -14
- package/dist/query/predicate.d.ts.map +1 -1
- package/dist/query/predicate.js +35 -42
- package/dist/query/predicate.js.map +1 -1
- package/dist/query/run.d.ts +8 -8
- package/dist/query/run.d.ts.map +1 -1
- package/dist/query/run.js +16 -21
- package/dist/query/run.js.map +1 -1
- package/dist/query/scope.d.ts +139 -74
- package/dist/query/scope.d.ts.map +1 -1
- package/dist/query/scope.js +80 -33
- package/dist/query/scope.js.map +1 -1
- package/dist/relation.d.ts.map +1 -1
- package/dist/relation.js +3 -1
- package/dist/relation.js.map +1 -1
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +12 -2
- package/dist/schema.js.map +1 -1
- package/dist/spec.d.ts +20 -10
- package/dist/spec.d.ts.map +1 -1
- package/dist/spec.js.map +1 -1
- package/dist/statements.d.ts +22 -2
- package/dist/statements.d.ts.map +1 -1
- package/dist/statements.js +26 -5
- package/dist/statements.js.map +1 -1
- package/package.json +3 -3
- package/src/closed.ts +13 -7
- package/src/count.ts +1 -1
- package/src/db.ts +293 -177
- package/src/exhume.ts +48 -11
- package/src/face.ts +13 -6
- package/src/fields.ts +51 -15
- package/src/index.ts +12 -8
- package/src/lower.ts +17 -12
- package/src/marshal.ts +38 -13
- package/src/native.ts +59 -8
- package/src/query/atom.ts +297 -275
- package/src/query/find.ts +212 -0
- package/src/query/lower.ts +692 -724
- package/src/query/predicate.ts +37 -45
- package/src/query/run.ts +17 -22
- package/src/query/scope.ts +184 -90
- package/src/relation.ts +3 -1
- package/src/schema.ts +14 -2
- package/src/spec.ts +21 -9
- package/src/statements.ts +30 -6
- package/dist/query/select.d.ts +0 -128
- package/dist/query/select.d.ts.map +0 -1
- package/dist/query/select.js.map +0 -1
- package/src/query/select.ts +0 -215
package/src/query/atom.ts
CHANGED
|
@@ -1,86 +1,61 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Atoms and conditions,
|
|
3
|
-
* rule, mirroring the engine IR variant for variant
|
|
2
|
+
* Atoms and conditions, REFERENCE-IDENTITY edition — the body vocabulary of
|
|
3
|
+
* a rule, mirroring the engine IR variant for variant
|
|
4
4
|
* (`bumbledb/crates/bumbledb/src/ir.rs`, the bijection target;
|
|
5
5
|
* `docs/architecture/20-query-ir.md` normative). A `match` binding record
|
|
6
|
-
* binds fields to
|
|
7
|
-
* — a closed-reference field's literal is its
|
|
8
|
-
* ARRAY of names there is membership
|
|
9
|
-
* by owner ruling; see {@link BindingInput})
|
|
6
|
+
* binds fields to VARIABLES (minted by {@link v}), params, ∈-set params, or
|
|
7
|
+
* bare structural literals — a closed-reference field's literal is its
|
|
8
|
+
* handle NAME, and a plain ARRAY of names there is membership
|
|
10
9
|
* (unmentioned fields ARE the wildcard — no wildcard value exists);
|
|
11
10
|
* `not(Rel, {...})` is negation-as-position (anti-join); `eq`/`ne` and the
|
|
12
11
|
* order roster, `pointIn` (the one spelling of `ir::CmpOp::PointIn`,
|
|
13
12
|
* always lowered interval-left), `allen` (the 13-bit mask pair
|
|
14
13
|
* comparison), and `and`/`or` (the input condition-tree grammar) complete
|
|
15
14
|
* the roster. Nothing beyond the IR exists here — and the walls the engine
|
|
16
|
-
* enforces at prepare are TYPES first: a
|
|
17
|
-
* fields
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
15
|
+
* enforces at prepare are TYPES first: a variable joins only class-equal
|
|
16
|
+
* fields, judged at every binding position against the var's MINT slot
|
|
17
|
+
* ({@link MintSlotOf}); because {@link JoinOk} is an equality, that ALONE
|
|
18
|
+
* makes every cross-binding join transitively class-equal (the env/sibling
|
|
19
|
+
* checks the name-keyed edition needed are gone). An interval-typed var
|
|
20
|
+
* under a non-`pointIn` comparison is unwritable. BOUNDNESS (a negated
|
|
21
|
+
* atom's variables must be positively bound) is the one check types cannot
|
|
22
|
+
* carry — object identity is invisible to TS — so it is a construction-time
|
|
23
|
+
* wall only.
|
|
24
24
|
*
|
|
25
25
|
* This module also owns the plain runtime DATA a built rule is made of
|
|
26
26
|
* (`RuleData`/`RecData` and friends): frozen values the lowering walks —
|
|
27
|
-
* pure data, so lowering stays a pure,
|
|
27
|
+
* pure data (variable references included), so lowering stays a pure,
|
|
28
|
+
* stable function of the query value.
|
|
28
29
|
*/
|
|
29
30
|
|
|
30
31
|
import * as errors from "@superbuilders/errors"
|
|
31
|
-
import type { AnyClosed } from "#closed.ts"
|
|
32
32
|
import type { AnyField, ClosedIdField, ClosedRoster, Infer, IntervalValue } from "#fields.ts"
|
|
33
33
|
import type { ClassLookup, ClassRecordOf, SchemaClasses } from "#law.ts"
|
|
34
34
|
import type {
|
|
35
|
+
AnyVar,
|
|
35
36
|
ClassedField,
|
|
36
37
|
Duration,
|
|
37
|
-
EnvShape,
|
|
38
38
|
JoinOk,
|
|
39
39
|
MaskParam,
|
|
40
|
+
MatchFields,
|
|
41
|
+
MatchOwner,
|
|
42
|
+
MintSlotOf,
|
|
40
43
|
Param,
|
|
44
|
+
ParamsRecord,
|
|
41
45
|
ParamValueAt,
|
|
42
46
|
SetParam,
|
|
43
|
-
ShapeOf
|
|
44
|
-
Var
|
|
47
|
+
ShapeOf
|
|
45
48
|
} from "#query/scope.ts"
|
|
46
|
-
import { isTerm } from "#query/scope.ts"
|
|
47
|
-
import type {
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* What a query atom matches over: an ordinary relation or a CLOSED
|
|
51
|
-
* vocabulary (ψ query atoms — the engine folds a resolvable closed atom
|
|
52
|
-
* into a plan-constant member set at prepare, or joins the L1-resident
|
|
53
|
-
* virtual image when the shape does not fold; the SDK never pre-folds and
|
|
54
|
-
* never knows which — transparency is the contract).
|
|
55
|
-
*/
|
|
56
|
-
type MatchOwner = AnyRelation | AnyClosed
|
|
49
|
+
import { inferred, isTerm } from "#query/scope.ts"
|
|
50
|
+
import type { FieldsShape } from "#relation.ts"
|
|
57
51
|
|
|
58
52
|
/**
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
* union rides into ψ id bindings and joins exactly as it does on a
|
|
63
|
-
* referencing column) first, then the declared payload columns read
|
|
64
|
-
* through the typed `columns` carrier (the one source of payload typing —
|
|
65
|
-
* no parallel column table exists). The runtime twin is `sealedFieldsOf` in
|
|
66
|
-
* `#query/lower.ts`; the id-first ordinal shift the two tiers share is
|
|
67
|
-
* pinned by the lowering golden.
|
|
68
|
-
*/
|
|
69
|
-
type MatchFields<R extends MatchOwner> = R extends AnyClosed
|
|
70
|
-
? { readonly id: R["id"] } & R["columns"]
|
|
71
|
-
: R extends AnyRelation
|
|
72
|
-
? RelationFields<R>
|
|
73
|
-
: never
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* One atom-binding position as runtime data. `literalSet` is a membership
|
|
77
|
-
* ARRAY at a closed-reference field, folded into the program: `name` is
|
|
78
|
-
* the content-addressed registry key its dense `ParamId` is minted under
|
|
79
|
-
* (the lowering rides the existing param-set term; the SDK itself supplies
|
|
80
|
-
* the translated member set at every execute — never the host).
|
|
53
|
+
* One atom-binding position as runtime data. A variable rides BY REFERENCE
|
|
54
|
+
* (`ref`) — object identity is the join. `literalSet` is a membership
|
|
55
|
+
* ARRAY at a closed-reference field, folded into the program.
|
|
81
56
|
*/
|
|
82
57
|
type BindingTermData =
|
|
83
|
-
| { readonly kind: "var"; readonly
|
|
58
|
+
| { readonly kind: "var"; readonly ref: AnyVar }
|
|
84
59
|
| { readonly kind: "param"; readonly name: string }
|
|
85
60
|
| { readonly kind: "setParam"; readonly name: string }
|
|
86
61
|
| { readonly kind: "literalSet"; readonly name: string; readonly members: readonly string[] }
|
|
@@ -103,12 +78,12 @@ interface AtomData {
|
|
|
103
78
|
/** One comparison operator name (mirrors `ir::CmpOp`). */
|
|
104
79
|
type CmpKind = "eq" | "ne" | "lt" | "le" | "gt" | "ge" | "pointIn" | "allen"
|
|
105
80
|
|
|
106
|
-
/** One comparison side as runtime data. */
|
|
81
|
+
/** One comparison side as runtime data (variables and the measure ride BY REFERENCE). */
|
|
107
82
|
type CmpTermData =
|
|
108
|
-
| { readonly kind: "var"; readonly
|
|
83
|
+
| { readonly kind: "var"; readonly ref: AnyVar }
|
|
109
84
|
| { readonly kind: "param"; readonly name: string }
|
|
110
85
|
| { readonly kind: "setParam"; readonly name: string }
|
|
111
|
-
| { readonly kind: "measure"; readonly
|
|
86
|
+
| { readonly kind: "measure"; readonly ref: AnyVar }
|
|
112
87
|
| { readonly kind: "literal"; readonly value: unknown }
|
|
113
88
|
|
|
114
89
|
/** The `allen` mask position as runtime data. */
|
|
@@ -133,48 +108,63 @@ interface TreeData {
|
|
|
133
108
|
/** Any condition node as runtime data. */
|
|
134
109
|
type CondData = CmpData | TreeData
|
|
135
110
|
|
|
136
|
-
/** One aggregate's runtime description (
|
|
111
|
+
/** One aggregate's runtime description (find vocabulary, over variable REFERENCES). */
|
|
137
112
|
type AggData =
|
|
138
113
|
| { readonly op: "count" }
|
|
139
|
-
| { readonly op: "countDistinct"; readonly over:
|
|
140
|
-
| {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
| { readonly
|
|
147
|
-
|
|
114
|
+
| { readonly op: "countDistinct"; readonly over: AnyVar }
|
|
115
|
+
| {
|
|
116
|
+
readonly op: "fold"
|
|
117
|
+
readonly fold: "sum" | "min" | "max"
|
|
118
|
+
readonly over: AnyVar | { readonly duration: AnyVar }
|
|
119
|
+
}
|
|
120
|
+
| { readonly op: "arg"; readonly direction: "argMax" | "argMin"; readonly over: AnyVar; readonly key: AnyVar }
|
|
121
|
+
| { readonly op: "pack"; readonly over: AnyVar }
|
|
122
|
+
|
|
123
|
+
/** One classified find entry as runtime data (variables and the measure ride BY REFERENCE). */
|
|
124
|
+
type FindEntryData =
|
|
125
|
+
| { readonly kind: "var"; readonly over: AnyVar }
|
|
126
|
+
| { readonly kind: "measure"; readonly over: AnyVar }
|
|
148
127
|
| { readonly kind: "aggregate"; readonly agg: AggData }
|
|
149
128
|
|
|
150
129
|
/**
|
|
151
|
-
* One answer column: its name (the row object key
|
|
152
|
-
*
|
|
153
|
-
*
|
|
154
|
-
*
|
|
155
|
-
*
|
|
156
|
-
*
|
|
130
|
+
* One answer column: its name (the row object key — the find record's key,
|
|
131
|
+
* so renames are real and a duplicate column is unrepresentable), its entry,
|
|
132
|
+
* the classed mint SLOT its values flow from (a projected var or an
|
|
133
|
+
* Arg-carried payload; `undefined` for counts/folds/measures/pack, which
|
|
134
|
+
* derive numbers or intervals), and — when that slot is a closed reference —
|
|
135
|
+
* the roster the decode lifts row ids back to handle NAMES through
|
|
136
|
+
* (`undefined` on every bare column). The slice is SDK-side marshaling data
|
|
137
|
+
* only: the wire `ProgramIr` never carries it.
|
|
157
138
|
*/
|
|
158
|
-
interface
|
|
139
|
+
interface FindColumn {
|
|
159
140
|
readonly name: string
|
|
160
|
-
readonly entry:
|
|
141
|
+
readonly entry: FindEntryData
|
|
161
142
|
readonly closed: ClosedRoster | undefined
|
|
143
|
+
readonly slot: ClassedField | undefined
|
|
162
144
|
}
|
|
163
145
|
|
|
164
|
-
/**
|
|
146
|
+
/**
|
|
147
|
+
* One body item of a rule, in written order. The idb join is a NAMED record
|
|
148
|
+
* over the rec's head keys (`key`) bound to local variables (`ref`) — the
|
|
149
|
+
* typed wall a record's unordered keys would otherwise lose.
|
|
150
|
+
*/
|
|
165
151
|
type RuleItem =
|
|
166
152
|
| { readonly kind: "atom"; readonly atom: AtomData }
|
|
167
153
|
| { readonly kind: "negated"; readonly atom: AtomData }
|
|
168
|
-
| {
|
|
154
|
+
| {
|
|
155
|
+
readonly kind: "idb"
|
|
156
|
+
readonly rec: RecData
|
|
157
|
+
readonly bindings: ReadonlyArray<{ readonly key: string; readonly ref: AnyVar }>
|
|
158
|
+
/** `true` on a negated finished-stratum atom (`r.not(rec, {...})`): probed through its anti-probe, binds nothing. */
|
|
159
|
+
readonly negated: boolean
|
|
160
|
+
}
|
|
169
161
|
| { readonly kind: "cond"; readonly cond: CondData }
|
|
170
162
|
|
|
171
163
|
/**
|
|
172
164
|
* One use of a parameter inside a rule, in written order: the census the
|
|
173
165
|
* query-level registry folds (first use mints the dense `ParamId`, first
|
|
174
166
|
* FIELD-ANCHORED use types the wire). `members` is present exactly on a
|
|
175
|
-
* membership-array use
|
|
176
|
-
* names the SDK itself translates and supplies at execute — the entry
|
|
177
|
-
* never appears in the host's params object.
|
|
167
|
+
* membership-array use.
|
|
178
168
|
*/
|
|
179
169
|
interface ParamUse {
|
|
180
170
|
readonly name: string
|
|
@@ -187,9 +177,7 @@ interface ParamUse {
|
|
|
187
177
|
/** One complete rule as runtime data. */
|
|
188
178
|
interface RuleData {
|
|
189
179
|
readonly items: readonly RuleItem[]
|
|
190
|
-
readonly
|
|
191
|
-
/** Variable name → the classed slot its FIRST positive binding carries (the runtime env — descriptor + class). */
|
|
192
|
-
readonly varFields: Readonly<Record<string, ClassedField>>
|
|
180
|
+
readonly finds: readonly FindColumn[]
|
|
193
181
|
readonly paramUses: readonly ParamUse[]
|
|
194
182
|
}
|
|
195
183
|
|
|
@@ -205,23 +193,15 @@ interface RecData {
|
|
|
205
193
|
|
|
206
194
|
/**
|
|
207
195
|
* What a binding position of field `F` accepts: a bare structural literal
|
|
208
|
-
* of the field's value type, a
|
|
209
|
-
* field is interval-typed, a bare point literal
|
|
210
|
-
*
|
|
211
|
-
* membership; an interval-typed term is value equality). A
|
|
212
|
-
* CLOSED-reference field additionally takes a plain ARRAY of handle names
|
|
213
|
-
* read as membership — `kind: ["Practice", "Review"]` (the drizzle law:
|
|
214
|
-
* set membership is an array, never an operator). Arrays are CLOSED-ONLY
|
|
215
|
-
* in this packet by owner ruling: ordinary u64/str membership already has
|
|
216
|
-
* its spelling through `r.inSet` params; widening literal arrays to every
|
|
217
|
-
* literal-capable kind is a separate future taste call — deliberately not
|
|
218
|
-
* done here.
|
|
196
|
+
* of the field's value type, a variable/param/∈-set-param term — and, when
|
|
197
|
+
* the field is interval-typed, a bare point literal. A CLOSED-reference
|
|
198
|
+
* field additionally takes a plain ARRAY of handle names read as membership.
|
|
219
199
|
*/
|
|
220
200
|
type BindingInput<F extends AnyField> =
|
|
221
201
|
| Infer<F>
|
|
222
202
|
| (F extends ClosedIdField ? readonly Infer<F>[] : never)
|
|
223
203
|
| (F extends { readonly kind: "interval" } ? bigint : never)
|
|
224
|
-
|
|
|
204
|
+
| AnyVar
|
|
225
205
|
| Param<string>
|
|
226
206
|
| SetParam<string>
|
|
227
207
|
|
|
@@ -237,8 +217,8 @@ type MatchShape<F extends FieldsShape> = {
|
|
|
237
217
|
/**
|
|
238
218
|
* One field position of a bindings record as a classed slot: the declared
|
|
239
219
|
* descriptor plus the slot's law-computed class, read off the relation's
|
|
240
|
-
* class record (`CR`
|
|
241
|
-
*
|
|
220
|
+
* class record (`CR`). The one shape a binding position's join judgment
|
|
221
|
+
* compares against.
|
|
242
222
|
*/
|
|
243
223
|
type SlotAt<F extends FieldsShape, CR, K> = {
|
|
244
224
|
readonly field: F[K & keyof F]
|
|
@@ -246,49 +226,20 @@ type SlotAt<F extends FieldsShape, CR, K> = {
|
|
|
246
226
|
}
|
|
247
227
|
|
|
248
228
|
/**
|
|
249
|
-
* The
|
|
250
|
-
*
|
|
229
|
+
* The per-property join judgment of a bindings record: a VARIABLE binding
|
|
230
|
+
* must join its own MINT slot to the position slot (a cross-class reuse maps
|
|
231
|
+
* the property to `never`). Because {@link JoinOk} is an equality, judging
|
|
232
|
+
* every position against the mint slot makes all cross-binding joins
|
|
233
|
+
* mutually class-equal by transitivity — no env or sibling arm is needed.
|
|
251
234
|
*/
|
|
252
|
-
type
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
* sibling must be class-equal too. Without this arm two FIRST occurrences
|
|
261
|
-
* of one name (a record the environment has not seen yet) would meet no
|
|
262
|
-
* check at all — the intra-atom join would silently cross classes.
|
|
263
|
-
*/
|
|
264
|
-
type SiblingJoinOk<F extends FieldsShape, CR, B, K extends keyof B, N extends string> = false extends {
|
|
265
|
-
[K2 in Exclude<keyof B & keyof F, K>]: B[K2] extends Var<N> ? JoinOk<SlotAt<F, CR, K2>, SlotAt<F, CR, K>> : true
|
|
266
|
-
}[Exclude<keyof B & keyof F, K>]
|
|
267
|
-
? false
|
|
268
|
-
: true
|
|
269
|
-
|
|
270
|
-
/**
|
|
271
|
-
* The per-property join judgment of a bindings record: a var binding must
|
|
272
|
-
* be class-equal to the rule environment's binding of the name AND to
|
|
273
|
-
* every same-named sibling of its own record (a cross-class reuse maps
|
|
274
|
-
* the property to `never` — the compile error the old value brand carried,
|
|
275
|
-
* now law-born off the schema type's class map).
|
|
276
|
-
*/
|
|
277
|
-
type BindingOk<Env extends EnvShape, F extends FieldsShape, CR, B, K extends keyof B> =
|
|
278
|
-
B[K] extends Var<infer N extends string>
|
|
279
|
-
? [EnvJoinOk<Env, F, CR, K, N>, SiblingJoinOk<F, CR, B, K, N>] extends [true, true]
|
|
280
|
-
? true
|
|
281
|
-
: false
|
|
282
|
-
: true
|
|
283
|
-
|
|
284
|
-
/** The validated bindings record (intersect with the inferred `B` — errors land on the offending property). */
|
|
285
|
-
type CheckBindings<Env extends EnvShape, F extends FieldsShape, CR, B> = {
|
|
286
|
-
readonly [K in keyof B]: K extends keyof F ? (BindingOk<Env, F, CR, B, K> extends true ? B[K] : never) : never
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
/** The environment a bindings record contributes: var name → the bound slot (descriptor + class). */
|
|
290
|
-
type BindEnv<F extends FieldsShape, CR, B> = {
|
|
291
|
-
readonly [K in keyof B & keyof F as B[K] extends Var<infer N extends string> ? N : never]: SlotAt<F, CR, K>
|
|
235
|
+
type CheckBindings<Classes extends SchemaClasses, F extends FieldsShape, CR, B> = {
|
|
236
|
+
readonly [K in keyof B]: K extends keyof F
|
|
237
|
+
? B[K] extends AnyVar
|
|
238
|
+
? JoinOk<MintSlotOf<Classes, B[K]>, SlotAt<F, CR, K>> extends true
|
|
239
|
+
? B[K]
|
|
240
|
+
: never
|
|
241
|
+
: B[K]
|
|
242
|
+
: never
|
|
292
243
|
}
|
|
293
244
|
|
|
294
245
|
/** The params-object fragments a bindings record contributes (one union member per param use). */
|
|
@@ -302,8 +253,8 @@ type BindParams<F extends FieldsShape, B> = {
|
|
|
302
253
|
|
|
303
254
|
/**
|
|
304
255
|
* One comparison VALUE: op plus its operands, raw — the runtime
|
|
305
|
-
* representation carries the
|
|
306
|
-
*
|
|
256
|
+
* representation carries the operands (variable references included), so
|
|
257
|
+
* `.where`'s judgment and the params inference both read the value itself.
|
|
307
258
|
* `mask` is populated exactly for `allen`.
|
|
308
259
|
*/
|
|
309
260
|
interface Cmp<Op extends CmpKind, L, R, M = undefined> {
|
|
@@ -324,9 +275,9 @@ interface Tree<Ch extends readonly AnyTreeChild[]> {
|
|
|
324
275
|
/**
|
|
325
276
|
* One negated-atom VALUE — negation is a position in the rule (anti-join
|
|
326
277
|
* over sets, no null trick): a binding satisfies it iff NO fact matches.
|
|
327
|
-
* Its variables must be positively bound in the rule —
|
|
328
|
-
*
|
|
329
|
-
*
|
|
278
|
+
* Its variables must be positively bound in the rule — a construction-time
|
|
279
|
+
* wall (BOUNDNESS is invisible to the type tier), before the engine's own
|
|
280
|
+
* refusal.
|
|
330
281
|
*/
|
|
331
282
|
interface NotAtom<R extends MatchOwner, B> {
|
|
332
283
|
readonly cond: "not"
|
|
@@ -334,6 +285,35 @@ interface NotAtom<R extends MatchOwner, B> {
|
|
|
334
285
|
readonly bindings: B
|
|
335
286
|
}
|
|
336
287
|
|
|
288
|
+
/**
|
|
289
|
+
* A recursive predicate as a NEGATION target — the structural half of the
|
|
290
|
+
* rec reference (`data` carries rules, never fields, so an EDB or closed
|
|
291
|
+
* owner can never match it and the `not()` overloads stay disjoint).
|
|
292
|
+
*/
|
|
293
|
+
interface RecTarget {
|
|
294
|
+
readonly name: string
|
|
295
|
+
readonly data: RecData
|
|
296
|
+
readonly [inferred]?: { readonly params: ParamsRecord; readonly head: HeadShapeOf }
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/** The head signature a threaded rec target carries (`undefined` before its first rule seals one). */
|
|
300
|
+
type HeadShapeOf = Readonly<Record<string, ClassedField>> | undefined
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* One negated FINISHED-STRATUM atom — negation OF a lower stratum is
|
|
304
|
+
* engine-legal (the strata judge refuses only negation *through* a cycle:
|
|
305
|
+
* a finished set is what keeps the operator monotone), and this value is
|
|
306
|
+
* its one spelling: `r.not(reach, { c })` in an output rule rejects every
|
|
307
|
+
* binding the finished stratum extends, through the engine's anti-probe.
|
|
308
|
+
* Binds nothing, only rejects — every variable it names must be positively
|
|
309
|
+
* bound in the rule (the same safety rule as EDB negation).
|
|
310
|
+
*/
|
|
311
|
+
interface NotIdbAtom<Target extends RecTarget, B> {
|
|
312
|
+
readonly cond: "notIdb"
|
|
313
|
+
readonly target: Target
|
|
314
|
+
readonly bindings: B
|
|
315
|
+
}
|
|
316
|
+
|
|
337
317
|
/** Any comparison value. */
|
|
338
318
|
type AnyCmp = Cmp<CmpKind, unknown, unknown, unknown>
|
|
339
319
|
|
|
@@ -343,23 +323,26 @@ type AnyTreeChild = AnyCmp | Tree<readonly AnyTreeChild[]>
|
|
|
343
323
|
/** Any negated-atom value. */
|
|
344
324
|
type AnyNotAtom = NotAtom<MatchOwner, unknown>
|
|
345
325
|
|
|
346
|
-
/** Any
|
|
347
|
-
type
|
|
326
|
+
/** Any negated finished-stratum value. */
|
|
327
|
+
type AnyNotIdbAtom = NotIdbAtom<RecTarget, unknown>
|
|
328
|
+
|
|
329
|
+
/** Any `.where` input: a comparison, a condition tree, or a negated atom (EDB, closed, or finished stratum). */
|
|
330
|
+
type AnyCond = AnyCmp | Tree<readonly AnyTreeChild[]> | AnyNotAtom | AnyNotIdbAtom
|
|
348
331
|
|
|
349
332
|
/** What `eq`'s right side accepts (`ParamSet` is `Eq`-only — the IR's rule). */
|
|
350
|
-
type EqRight =
|
|
333
|
+
type EqRight = AnyVar | Param<string> | SetParam<string> | bigint | string | boolean | Uint8Array | IntervalValue
|
|
351
334
|
|
|
352
335
|
/** What `ne`'s right side accepts. */
|
|
353
|
-
type NeRight =
|
|
336
|
+
type NeRight = AnyVar | Param<string> | bigint | string | boolean | Uint8Array | IntervalValue
|
|
354
337
|
|
|
355
338
|
/** One side of an order comparison: orderable terms only (the IR's comparison rules). */
|
|
356
|
-
type OrderSide =
|
|
339
|
+
type OrderSide = AnyVar | Param<string> | Duration | bigint
|
|
357
340
|
|
|
358
341
|
/** The point side of `pointIn`. */
|
|
359
|
-
type PointSide =
|
|
342
|
+
type PointSide = AnyVar | Param<string> | bigint
|
|
360
343
|
|
|
361
344
|
/** The interval side of `pointIn`/`allen`. */
|
|
362
|
-
type IntervalSide =
|
|
345
|
+
type IntervalSide = AnyVar | Param<string> | IntervalValue
|
|
363
346
|
|
|
364
347
|
/** Builds one comparison value. */
|
|
365
348
|
function comparison<Op extends CmpKind, L, R, M>(op: Op, lhs: L, rhs: R, mask: M): Cmp<Op, L, R, M> {
|
|
@@ -381,17 +364,17 @@ function assertTermSide(op: string, lhs: unknown, rhs: unknown): void {
|
|
|
381
364
|
|
|
382
365
|
/**
|
|
383
366
|
* The equality comparison (`ir::CmpOp::Eq`) — a bound variable against a
|
|
384
|
-
* variable (var-to-var unification,
|
|
385
|
-
*
|
|
386
|
-
*
|
|
387
|
-
*
|
|
367
|
+
* variable (var-to-var unification, class-equal by the join judgment), a
|
|
368
|
+
* param (typed by the variable), an ∈-set param (`Eq`-only), or a bare
|
|
369
|
+
* literal of the variable's own value type. Prefer direct placement in
|
|
370
|
+
* `match` where punning applies.
|
|
388
371
|
*/
|
|
389
|
-
function eq<L extends
|
|
372
|
+
function eq<L extends AnyVar, const R extends EqRight>(left: L, right: R): Cmp<"eq", L, R> {
|
|
390
373
|
return comparison("eq", left, right, undefined)
|
|
391
374
|
}
|
|
392
375
|
|
|
393
376
|
/** Typed disequality (`ir::CmpOp::Ne`). "Not in set" has no operator — write a negated atom. */
|
|
394
|
-
function ne<L extends
|
|
377
|
+
function ne<L extends AnyVar, const R extends NeRight>(left: L, right: R): Cmp<"ne", L, R> {
|
|
395
378
|
return comparison("ne", left, right, undefined)
|
|
396
379
|
}
|
|
397
380
|
|
|
@@ -429,12 +412,8 @@ function ge<const L extends OrderSide, const R extends OrderSide>(left: L, right
|
|
|
429
412
|
* Point membership as a predicate (`ir::CmpOp::PointIn`) — THE one
|
|
430
413
|
* spelling: `pointIn(t, w)` holds iff `w.start ≤ t < w.end`. The IR
|
|
431
414
|
* orders the operands interval-left, point-right; the value stores them
|
|
432
|
-
* that way whatever the surface argument order
|
|
433
|
-
*
|
|
434
|
-
* domain — the bug-hunt fix, now also a type-level guarantee).
|
|
435
|
-
* Interval ⊇ interval is NOT this operator; that predicate is
|
|
436
|
-
* `allen(a, ALLEN.covers, b)` — the name `covers` belongs to the Allen
|
|
437
|
-
* roster alone (the canonical-utterance law: one meaning, one spelling).
|
|
415
|
+
* that way whatever the surface argument order. Interval ⊇ interval is NOT
|
|
416
|
+
* this operator; that predicate is `allen(a, ALLEN.covers, b)`.
|
|
438
417
|
*/
|
|
439
418
|
function pointIn<const P extends PointSide, const I extends IntervalSide>(point: P, interval: I): Cmp<"pointIn", I, P> {
|
|
440
419
|
assertTermSide("pointIn", point, interval)
|
|
@@ -444,17 +423,14 @@ function pointIn<const P extends PointSide, const I extends IntervalSide>(point:
|
|
|
444
423
|
/**
|
|
445
424
|
* The 13-bit mask range: bits above the low 13 are unrepresentable in the
|
|
446
425
|
* engine's `AllenMask` (`bumbledb/crates/bumbledb/src/allen.rs`:
|
|
447
|
-
* `AllenMask::new` refuses them)
|
|
448
|
-
* moved to construction where the message can name the constants.
|
|
426
|
+
* `AllenMask::new` refuses them).
|
|
449
427
|
*/
|
|
450
428
|
const ALLEN_ALL_BITS = (1 << 13) - 1
|
|
451
429
|
|
|
452
430
|
/**
|
|
453
431
|
* The Allen coordinate system's named constants — the 13 basics in the
|
|
454
|
-
* engine's palindromic bit order
|
|
455
|
-
* `
|
|
456
|
-
* plus the workload composites, values identical to the engine's. Compose
|
|
457
|
-
* with `|`: `ALLEN.before | ALLEN.meets`.
|
|
432
|
+
* engine's palindromic bit order plus the workload composites, values
|
|
433
|
+
* identical to the engine's. Compose with `|`: `ALLEN.before | ALLEN.meets`.
|
|
458
434
|
*/
|
|
459
435
|
const ALLEN = Object.freeze({
|
|
460
436
|
before: 1 << 0,
|
|
@@ -484,9 +460,7 @@ const ALLEN = Object.freeze({
|
|
|
484
460
|
* THE interval-pair comparison (`ir::CmpOp::Allen`): two interval terms of
|
|
485
461
|
* one element type, satisfied iff the pair's classification is in the
|
|
486
462
|
* 13-bit mask — a literal built from the `ALLEN` constants, or a mask
|
|
487
|
-
* parameter (`r.maskParam`).
|
|
488
|
-
* two distinct typed rejections; nothing is pre-judged here beyond the
|
|
489
|
-
* representable bit range.
|
|
463
|
+
* parameter (`r.maskParam`).
|
|
490
464
|
*/
|
|
491
465
|
function allen<const A extends IntervalSide, const M extends number | MaskParam<string>, const B extends IntervalSide>(
|
|
492
466
|
left: A,
|
|
@@ -515,148 +489,193 @@ function and<const C extends readonly AnyTreeChild[]>(...children: C): Tree<C> {
|
|
|
515
489
|
/**
|
|
516
490
|
* Disjunction node of the input condition grammar (`ConditionTree::Or`) —
|
|
517
491
|
* the one place the surface admits a nested OR; validation distributes it
|
|
518
|
-
* to DNF rules engine-side
|
|
519
|
-
* its algebraic reading (false: the rule denotes nothing).
|
|
492
|
+
* to DNF rules engine-side. `Or([])` keeps its algebraic reading (false).
|
|
520
493
|
*/
|
|
521
494
|
function or<const C extends readonly AnyTreeChild[]>(...children: C): Tree<C> {
|
|
522
495
|
return Object.freeze({ cond: "tree", op: "or", children: Object.freeze(children) })
|
|
523
496
|
}
|
|
524
497
|
|
|
525
498
|
/**
|
|
526
|
-
* Negation — anti-join over sets: `not(Rel, { field:
|
|
499
|
+
* Negation — anti-join over sets: `not(Rel, { field: someVar, ... })`
|
|
527
500
|
* rejects every binding some matching fact extends. A negated atom binds
|
|
528
501
|
* nothing, only rejects: every variable it names must be positively bound
|
|
529
|
-
* in the rule,
|
|
530
|
-
*
|
|
531
|
-
*
|
|
532
|
-
*
|
|
533
|
-
*
|
|
502
|
+
* in the rule, a construction-time wall (the engine's safety refusal stands
|
|
503
|
+
* behind it). A CLOSED owner is legal here too — and so is a FINISHED
|
|
504
|
+
* STRATUM: `not(reach, { c })` in an output rule negates the rec's
|
|
505
|
+
* finished set (a named record over its head keys, variables only — the
|
|
506
|
+
* same wall `idb()` holds), the one spelling of the engine-legal
|
|
507
|
+
* complement query (`(n) | Node(id: n), !reach(n);` on the Rust surface).
|
|
534
508
|
*/
|
|
535
|
-
function not<R extends MatchOwner, const B extends MatchShape<MatchFields<R>>>(
|
|
536
|
-
|
|
509
|
+
function not<R extends MatchOwner, const B extends MatchShape<MatchFields<R>>>(relation: R, bindings: B): NotAtom<R, B>
|
|
510
|
+
function not<Target extends RecTarget, const B extends Readonly<Record<string, AnyVar>>>(
|
|
511
|
+
target: Target,
|
|
537
512
|
bindings: B
|
|
538
|
-
):
|
|
539
|
-
|
|
540
|
-
|
|
513
|
+
): NotIdbAtom<Target, B>
|
|
514
|
+
function not(
|
|
515
|
+
relation: MatchOwner | RecTarget,
|
|
516
|
+
bindings: Readonly<Record<string, unknown>>
|
|
517
|
+
): NotAtom<MatchOwner, unknown> | NotIdbAtom<RecTarget, unknown> {
|
|
518
|
+
if (isRecTarget(relation)) {
|
|
519
|
+
return Object.freeze({ cond: "notIdb" as const, target: relation, bindings })
|
|
520
|
+
}
|
|
521
|
+
return Object.freeze({ cond: "not" as const, relation, bindings })
|
|
541
522
|
}
|
|
542
523
|
|
|
543
524
|
/**
|
|
544
|
-
*
|
|
545
|
-
*
|
|
546
|
-
*
|
|
547
|
-
* (`docs/architecture/10-data-model.md` § orderability — order on it is
|
|
548
|
-
* refused exactly as the enum's ordinal order was), so every
|
|
549
|
-
* order-comparison and fold position refuses closed-bound terms — this
|
|
550
|
-
* judgment is the one gate they all read, and the construction-time
|
|
551
|
-
* validations in `#query/lower.ts` are its runtime twin.
|
|
525
|
+
* THE negation-target discriminant: a rec's runtime data carries its rules,
|
|
526
|
+
* a relation's its fields (and a closed relation's its handle roster) — the
|
|
527
|
+
* shapes are disjoint by construction, so the dispatch is total.
|
|
552
528
|
*/
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
: Env[N]["field"]["kind"] extends "u64" | "i64"
|
|
557
|
-
? true
|
|
558
|
-
: false
|
|
559
|
-
: false
|
|
529
|
+
function isRecTarget(value: MatchOwner | RecTarget): value is RecTarget {
|
|
530
|
+
return "rules" in value.data
|
|
531
|
+
}
|
|
560
532
|
|
|
561
|
-
/**
|
|
562
|
-
|
|
563
|
-
|
|
533
|
+
/**
|
|
534
|
+
* Whether a variable's OWN field is orderable (u64/i64). A CLOSED reference
|
|
535
|
+
* is excluded even though its kind is `u64`: a vocabulary's declaration-id
|
|
536
|
+
* order is an accident, not semantics (`docs/architecture/10-data-model.md`
|
|
537
|
+
* § orderability), so every order-comparison and fold position refuses
|
|
538
|
+
* closed-bound terms — this judgment is the one gate they all read, and the
|
|
539
|
+
* construction-time validations in `#query/lower.ts` are its runtime twin.
|
|
540
|
+
*/
|
|
541
|
+
type OrderVarOk<V extends AnyVar> = V["field"] extends { readonly closed: ClosedRoster }
|
|
542
|
+
? false
|
|
543
|
+
: V["field"]["kind"] extends "u64" | "i64"
|
|
564
544
|
? true
|
|
565
545
|
: false
|
|
566
|
-
: false
|
|
567
546
|
|
|
568
|
-
/**
|
|
569
|
-
type
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
547
|
+
/** Whether a variable's OWN field is interval-typed. */
|
|
548
|
+
type IntervalVarOk<V extends AnyVar> = V["field"]["kind"] extends "interval" ? true : false
|
|
549
|
+
|
|
550
|
+
/** One order-comparison side's judgment (off the term's own field). */
|
|
551
|
+
type OrderSideOk<T> = T extends AnyVar
|
|
552
|
+
? OrderVarOk<T>
|
|
553
|
+
: T extends Duration<infer V extends AnyVar>
|
|
554
|
+
? IntervalVarOk<V>
|
|
555
|
+
: true
|
|
575
556
|
|
|
576
557
|
/** One point side's judgment. */
|
|
577
|
-
type PointSideOk<
|
|
558
|
+
type PointSideOk<T> = T extends AnyVar ? OrderVarOk<T> : true
|
|
578
559
|
|
|
579
560
|
/** One interval side's judgment. */
|
|
580
|
-
type IntervalSideOk<
|
|
581
|
-
|
|
582
|
-
/** The `eq`/`ne` judgment:
|
|
583
|
-
type EqOk<
|
|
584
|
-
|
|
585
|
-
?
|
|
586
|
-
?
|
|
587
|
-
? M extends keyof Env
|
|
588
|
-
? JoinOk<Env[N], Env[M]>
|
|
589
|
-
: false
|
|
590
|
-
: R extends Param<string> | SetParam<string>
|
|
591
|
-
? true
|
|
592
|
-
: [R] extends [Infer<Env[N]["field"]>]
|
|
593
|
-
? true
|
|
594
|
-
: false
|
|
561
|
+
type IntervalSideOk<T> = T extends AnyVar ? IntervalVarOk<T> : true
|
|
562
|
+
|
|
563
|
+
/** The `eq`/`ne` judgment: var-var joins by mint slot; var-literal is exact-typed by the var's own field. */
|
|
564
|
+
type EqOk<Classes extends SchemaClasses, L, R> = L extends AnyVar
|
|
565
|
+
? R extends AnyVar
|
|
566
|
+
? JoinOk<MintSlotOf<Classes, L>, MintSlotOf<Classes, R>> extends true
|
|
567
|
+
? true
|
|
595
568
|
: false
|
|
596
|
-
:
|
|
569
|
+
: R extends Param<string> | SetParam<string>
|
|
570
|
+
? true
|
|
571
|
+
: [R] extends [Infer<L["field"]>]
|
|
572
|
+
? true
|
|
573
|
+
: false
|
|
574
|
+
: false
|
|
597
575
|
|
|
598
|
-
/** One negated-atom binding's judgment: a
|
|
599
|
-
type NotBindingOk<
|
|
600
|
-
|
|
576
|
+
/** One negated-atom binding's judgment: a variable must be class-equal (boundness is a runtime wall). */
|
|
577
|
+
type NotBindingOk<Classes extends SchemaClasses, S extends ClassedField, T> = T extends AnyVar
|
|
578
|
+
? JoinOk<MintSlotOf<Classes, T>, S> extends true
|
|
579
|
+
? true
|
|
580
|
+
: false
|
|
581
|
+
: true
|
|
601
582
|
|
|
602
583
|
/** The whole negated atom's judgment (`CR` — the negated relation's class record off the schema class map). */
|
|
603
|
-
type NotOk<
|
|
604
|
-
[K in keyof B]: NotBindingOk<
|
|
584
|
+
type NotOk<Classes extends SchemaClasses, F extends FieldsShape, CR, B> = false extends {
|
|
585
|
+
[K in keyof B]: NotBindingOk<Classes, SlotAt<F, CR, K>, B[K]>
|
|
605
586
|
}[keyof B]
|
|
606
587
|
? false
|
|
607
588
|
: true
|
|
608
589
|
|
|
590
|
+
/** Reads a rec target's sealed head signature off its inference slot (`undefined` on an unthreaded handle). */
|
|
591
|
+
type RecHeadOf<T> = T extends { readonly [inferred]?: infer S }
|
|
592
|
+
? Exclude<S, undefined> extends { readonly head: infer H }
|
|
593
|
+
? H
|
|
594
|
+
: undefined
|
|
595
|
+
: undefined
|
|
596
|
+
|
|
597
|
+
/** Reads a rec target's params record off its inference slot. */
|
|
598
|
+
type RecParamsOf<T> = T extends { readonly [inferred]?: infer S }
|
|
599
|
+
? Exclude<S, undefined> extends { readonly params: infer P }
|
|
600
|
+
? P
|
|
601
|
+
: never
|
|
602
|
+
: never
|
|
603
|
+
|
|
604
|
+
/** One negated finished-stratum position's judgment: a variable, class-equal to its head slot when the head is carried. */
|
|
605
|
+
type NotIdbBindingOk<Classes extends SchemaClasses, HeadSlot, V> = V extends AnyVar
|
|
606
|
+
? HeadSlot extends ClassedField
|
|
607
|
+
? JoinOk<HeadSlot, MintSlotOf<Classes, V>> extends true
|
|
608
|
+
? true
|
|
609
|
+
: false
|
|
610
|
+
: true
|
|
611
|
+
: false
|
|
612
|
+
|
|
609
613
|
/**
|
|
610
|
-
*
|
|
611
|
-
*
|
|
612
|
-
*
|
|
613
|
-
*
|
|
614
|
-
*
|
|
615
|
-
* relation's class record is resolved through `Classes` by its name). The
|
|
616
|
-
* leading `[AnyTreeChild] extends [C]` arm is the recursion's base case:
|
|
617
|
-
* at an UNRESOLVED constraint (the whole condition union — or a tree's
|
|
618
|
-
* child union, which is the union itself) the judgment is vacuously true —
|
|
619
|
-
* without it the constraint instantiation recurses into itself.
|
|
614
|
+
* The whole negated finished-stratum atom's judgment — the negation twin of
|
|
615
|
+
* the `idb()` chain's `CheckIdbBindings`: when the target carries its head
|
|
616
|
+
* (a threaded rec handle), the bindings record's key set must EXACTLY equal
|
|
617
|
+
* the head's and each variable must be class-equal to its head slot; an
|
|
618
|
+
* unthreaded handle still takes variables only.
|
|
620
619
|
*/
|
|
621
|
-
type
|
|
620
|
+
type NotIdbOk<Classes extends SchemaClasses, Head, B> =
|
|
621
|
+
Head extends Readonly<Record<string, ClassedField>>
|
|
622
|
+
? [keyof B] extends [keyof Head]
|
|
623
|
+
? [keyof Head] extends [keyof B]
|
|
624
|
+
? false extends { [K in keyof B]: NotIdbBindingOk<Classes, Head[K & keyof Head], B[K]> }[keyof B]
|
|
625
|
+
? false
|
|
626
|
+
: true
|
|
627
|
+
: false
|
|
628
|
+
: false
|
|
629
|
+
: false extends { [K in keyof B]: B[K] extends AnyVar ? true : false }[keyof B]
|
|
630
|
+
? false
|
|
631
|
+
: true
|
|
632
|
+
|
|
633
|
+
/**
|
|
634
|
+
* One condition's judgment — the type-level twin of the engine's comparison
|
|
635
|
+
* roster: class-equal joins (off the mint slots), orderable order sides (an
|
|
636
|
+
* interval var under a non-`pointIn` op is exactly here refused),
|
|
637
|
+
* kind-correct `pointIn`/`allen` sides, and negated-atom class safety. The
|
|
638
|
+
* leading `[AnyTreeChild] extends [C]` arm is the recursion's base case.
|
|
639
|
+
*/
|
|
640
|
+
type CondOkBool<Classes extends SchemaClasses, C> = [AnyTreeChild] extends [C]
|
|
622
641
|
? true
|
|
623
642
|
: C extends Cmp<infer Op, infer L, infer R, unknown>
|
|
624
643
|
? Op extends "eq" | "ne"
|
|
625
|
-
? EqOk<
|
|
644
|
+
? EqOk<Classes, L, R>
|
|
626
645
|
: Op extends "lt" | "le" | "gt" | "ge"
|
|
627
|
-
? [OrderSideOk<
|
|
646
|
+
? [OrderSideOk<L>, OrderSideOk<R>] extends [true, true]
|
|
628
647
|
? true
|
|
629
648
|
: false
|
|
630
649
|
: Op extends "pointIn"
|
|
631
|
-
? [IntervalSideOk<
|
|
650
|
+
? [IntervalSideOk<L>, PointSideOk<R>] extends [true, true]
|
|
632
651
|
? true
|
|
633
652
|
: false
|
|
634
653
|
: Op extends "allen"
|
|
635
|
-
? [IntervalSideOk<
|
|
654
|
+
? [IntervalSideOk<L>, IntervalSideOk<R>] extends [true, true]
|
|
636
655
|
? true
|
|
637
656
|
: false
|
|
638
657
|
: false
|
|
639
658
|
: C extends Tree<infer Ch extends readonly AnyTreeChild[]>
|
|
640
|
-
? false extends CondOkBool<
|
|
659
|
+
? false extends CondOkBool<Classes, Ch[number]>
|
|
641
660
|
? false
|
|
642
661
|
: true
|
|
643
|
-
: C extends
|
|
644
|
-
?
|
|
645
|
-
:
|
|
662
|
+
: C extends NotIdbAtom<infer T extends RecTarget, infer B>
|
|
663
|
+
? NotIdbOk<Classes, RecHeadOf<T>, B>
|
|
664
|
+
: C extends NotAtom<infer R extends MatchOwner, infer B>
|
|
665
|
+
? NotOk<Classes, MatchFields<R>, ClassRecordOf<Classes, R["name"]>, B>
|
|
666
|
+
: false
|
|
646
667
|
|
|
647
668
|
/** The validated `.where` argument (intersect with the inferred condition type). */
|
|
648
|
-
type CheckCond<
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
? { readonly [Q in P]: Infer<
|
|
656
|
-
:
|
|
657
|
-
|
|
658
|
-
: never
|
|
659
|
-
: never
|
|
669
|
+
type CheckCond<Classes extends SchemaClasses, C> = CondOkBool<Classes, C> extends true ? C : never
|
|
670
|
+
|
|
671
|
+
/** The `eq`/`ne` params contribution: the param typed by the left variable's own field. */
|
|
672
|
+
type EqParams<L, R> = L extends AnyVar
|
|
673
|
+
? R extends Param<infer P extends string>
|
|
674
|
+
? { readonly [Q in P]: Infer<L["field"]> }
|
|
675
|
+
: R extends SetParam<infer P extends string>
|
|
676
|
+
? { readonly [Q in P]: readonly Infer<L["field"]>[] }
|
|
677
|
+
: never
|
|
678
|
+
: never
|
|
660
679
|
|
|
661
680
|
/** An order side's params contribution (order params are always `bigint`). */
|
|
662
681
|
type OrderSideParams<T> = T extends Param<infer P extends string> ? { readonly [Q in P]: bigint } : never
|
|
@@ -670,14 +689,13 @@ type MaskParams<M> = M extends MaskParam<infer P extends string> ? { readonly [Q
|
|
|
670
689
|
/**
|
|
671
690
|
* One condition's params-object fragments (a union; the rule builder folds
|
|
672
691
|
* them into the inferred `Params` record) — every param typed by its use.
|
|
673
|
-
* The leading arm is the same base case as {@link CondOkBool}'s
|
|
674
|
-
* unresolved constraint contributes nothing.
|
|
692
|
+
* The leading arm is the same base case as {@link CondOkBool}'s.
|
|
675
693
|
*/
|
|
676
|
-
type CondParams<
|
|
694
|
+
type CondParams<C> = [AnyTreeChild] extends [C]
|
|
677
695
|
? never
|
|
678
696
|
: C extends Cmp<infer Op, infer L, infer R, infer M>
|
|
679
697
|
? Op extends "eq" | "ne"
|
|
680
|
-
? EqParams<
|
|
698
|
+
? EqParams<L, R>
|
|
681
699
|
: Op extends "lt" | "le" | "gt" | "ge"
|
|
682
700
|
? OrderSideParams<L> | OrderSideParams<R>
|
|
683
701
|
: Op extends "pointIn"
|
|
@@ -686,16 +704,18 @@ type CondParams<Env extends EnvShape, C> = [AnyTreeChild] extends [C]
|
|
|
686
704
|
? IntervalSideParams<L> | IntervalSideParams<R> | MaskParams<M>
|
|
687
705
|
: never
|
|
688
706
|
: C extends Tree<infer Ch extends readonly AnyTreeChild[]>
|
|
689
|
-
? CondParams<
|
|
690
|
-
: C extends
|
|
691
|
-
?
|
|
692
|
-
:
|
|
707
|
+
? CondParams<Ch[number]>
|
|
708
|
+
: C extends NotIdbAtom<infer T extends RecTarget, unknown>
|
|
709
|
+
? RecParamsOf<T>
|
|
710
|
+
: C extends NotAtom<infer R extends MatchOwner, infer B>
|
|
711
|
+
? BindParams<MatchFields<R>, B>
|
|
712
|
+
: never
|
|
693
713
|
|
|
694
714
|
/** The flattened params record one bindings record contributes. */
|
|
695
715
|
type BindParamsShape<F extends FieldsShape, B> = ShapeOf<BindParams<F, B>>
|
|
696
716
|
|
|
697
717
|
/** The flattened params record one condition contributes. */
|
|
698
|
-
type CondParamsShape<
|
|
718
|
+
type CondParamsShape<C> = ShapeOf<CondParams<C>>
|
|
699
719
|
|
|
700
720
|
export type {
|
|
701
721
|
AggData,
|
|
@@ -704,7 +724,6 @@ export type {
|
|
|
704
724
|
AnyNotAtom,
|
|
705
725
|
AnyTreeChild,
|
|
706
726
|
AtomData,
|
|
707
|
-
BindEnv,
|
|
708
727
|
BindingEntry,
|
|
709
728
|
BindingInput,
|
|
710
729
|
BindingTermData,
|
|
@@ -720,6 +739,8 @@ export type {
|
|
|
720
739
|
CondOkBool,
|
|
721
740
|
CondParams,
|
|
722
741
|
CondParamsShape,
|
|
742
|
+
FindColumn,
|
|
743
|
+
FindEntryData,
|
|
723
744
|
IntervalSide,
|
|
724
745
|
IntervalVarOk,
|
|
725
746
|
MaskData,
|
|
@@ -727,15 +748,16 @@ export type {
|
|
|
727
748
|
MatchOwner,
|
|
728
749
|
MatchShape,
|
|
729
750
|
NotAtom,
|
|
751
|
+
NotIdbAtom,
|
|
730
752
|
OrderSide,
|
|
731
753
|
OrderVarOk,
|
|
732
754
|
ParamUse,
|
|
733
755
|
PointSide,
|
|
734
756
|
RecData,
|
|
757
|
+
RecTarget,
|
|
735
758
|
RuleData,
|
|
736
759
|
RuleItem,
|
|
737
|
-
|
|
738
|
-
SelectEntryData,
|
|
760
|
+
SlotAt,
|
|
739
761
|
Tree,
|
|
740
762
|
TreeData
|
|
741
763
|
}
|