@bjornpagen/bumbledb 0.1.0 → 0.2.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 +1394 -0
- package/README.md +4 -0
- package/dist/closed.d.ts +60 -37
- package/dist/closed.d.ts.map +1 -1
- package/dist/closed.js +159 -40
- package/dist/closed.js.map +1 -1
- package/dist/count.d.ts +64 -17
- package/dist/count.d.ts.map +1 -1
- package/dist/count.js +37 -14
- package/dist/count.js.map +1 -1
- package/dist/db.d.ts +15 -7
- package/dist/db.d.ts.map +1 -1
- package/dist/db.js +13 -5
- package/dist/db.js.map +1 -1
- package/dist/exhume.d.ts +12 -11
- package/dist/exhume.d.ts.map +1 -1
- package/dist/exhume.js +7 -6
- package/dist/exhume.js.map +1 -1
- package/dist/face.d.ts +79 -19
- package/dist/face.d.ts.map +1 -1
- package/dist/face.js +14 -15
- package/dist/face.js.map +1 -1
- package/dist/fields.d.ts +158 -129
- package/dist/fields.d.ts.map +1 -1
- package/dist/fields.js +80 -81
- package/dist/fields.js.map +1 -1
- package/dist/index.d.ts +21 -21
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -12
- package/dist/index.js.map +1 -1
- package/dist/lower.d.ts +6 -3
- package/dist/lower.d.ts.map +1 -1
- package/dist/lower.js +48 -17
- package/dist/lower.js.map +1 -1
- package/dist/marshal.d.ts +36 -21
- package/dist/marshal.d.ts.map +1 -1
- package/dist/marshal.js +41 -25
- package/dist/marshal.js.map +1 -1
- package/dist/native.js +2 -2
- package/dist/query/atom.d.ts +332 -174
- package/dist/query/atom.d.ts.map +1 -1
- package/dist/query/atom.js +72 -172
- package/dist/query/atom.js.map +1 -1
- package/dist/query/lower.d.ts +295 -107
- package/dist/query/lower.d.ts.map +1 -1
- package/dist/query/lower.js +860 -388
- package/dist/query/lower.js.map +1 -1
- package/dist/query/predicate.d.ts +69 -88
- package/dist/query/predicate.d.ts.map +1 -1
- package/dist/query/predicate.js +118 -72
- package/dist/query/predicate.js.map +1 -1
- package/dist/query/run.d.ts +19 -16
- package/dist/query/run.d.ts.map +1 -1
- package/dist/query/run.js +31 -24
- package/dist/query/run.js.map +1 -1
- package/dist/query/scope.d.ts +139 -123
- package/dist/query/scope.d.ts.map +1 -1
- package/dist/query/scope.js +71 -115
- package/dist/query/scope.js.map +1 -1
- package/dist/query/select.d.ts +102 -80
- package/dist/query/select.d.ts.map +1 -1
- package/dist/query/select.js +39 -34
- package/dist/query/select.js.map +1 -1
- package/dist/relation.d.ts +33 -36
- package/dist/relation.d.ts.map +1 -1
- package/dist/relation.js +15 -16
- package/dist/relation.js.map +1 -1
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +19 -8
- package/dist/schema.js.map +1 -1
- package/dist/spec.d.ts +6 -5
- package/dist/spec.d.ts.map +1 -1
- package/dist/spec.js.map +1 -1
- package/dist/statements.d.ts +56 -31
- package/dist/statements.d.ts.map +1 -1
- package/dist/statements.js +38 -13
- package/dist/statements.js.map +1 -1
- package/package.json +4 -3
- package/src/closed.ts +271 -93
- package/src/count.ts +112 -18
- package/src/db.ts +22 -12
- package/src/exhume.ts +12 -11
- package/src/face.ts +114 -22
- package/src/fields.ts +261 -217
- package/src/index.ts +50 -59
- package/src/lower.ts +62 -20
- package/src/marshal.ts +48 -30
- package/src/native.ts +2 -2
- package/src/query/atom.ts +480 -376
- package/src/query/lower.ts +1341 -542
- package/src/query/predicate.ts +198 -161
- package/src/query/run.ts +35 -25
- package/src/query/scope.ts +188 -218
- package/src/query/select.ts +168 -93
- package/src/relation.ts +38 -44
- package/src/schema.ts +22 -12
- package/src/spec.ts +6 -5
- package/src/statements.ts +69 -26
- package/dist/brand.d.ts +0 -59
- package/dist/brand.d.ts.map +0 -1
- package/dist/brand.js +0 -47
- package/dist/brand.js.map +0 -1
- package/src/brand.ts +0 -82
package/src/query/scope.ts
CHANGED
|
@@ -1,102 +1,143 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Query scope terms
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
2
|
+
* Query scope terms, STRUCTURAL edition: string-named variables and
|
|
3
|
+
* parameters as plain frozen values. A `Var` is a NAME — it is typed by the
|
|
4
|
+
* field it first binds (structurally, off the schema type, through the rule
|
|
5
|
+
* builder's environment), reuse of the name within one rule IS the join,
|
|
6
|
+
* and a domain-mismatched reuse is a compile error (the structural analog
|
|
7
|
+
* of the old brand-equal join — now domain-equal, no value brands
|
|
8
|
+
* anywhere). Params are query-global by name and typed BY USE: the field
|
|
9
|
+
* position or comparison sibling that anchors a param types it, the
|
|
10
|
+
* query's inferred `Params` object is exactly the params the rules use,
|
|
11
|
+
* and a param value that no rule uses simply never registers — the query
|
|
12
|
+
* executes under its own inferred type (the bug-hunt law). This module
|
|
13
|
+
* also owns the environment/typing utilities the whole surface shares:
|
|
14
|
+
* the env shape (var name → field descriptor), the domain-equality
|
|
15
|
+
* judgment, and the record-folding helpers `Params` and `Row` inference
|
|
16
|
+
* ride.
|
|
14
17
|
*/
|
|
15
18
|
|
|
16
|
-
import
|
|
17
|
-
import { phantom } from "#brand.ts"
|
|
18
|
-
import type { AnyClosed } from "#closed.ts"
|
|
19
|
-
import type { FieldData } from "#fields.ts"
|
|
20
|
-
import type { PredicateData } from "#query/predicate.ts"
|
|
21
|
-
import type { AnySchema, SchemaRelation } from "#schema.ts"
|
|
19
|
+
import type { AnyField, Infer } from "#fields.ts"
|
|
22
20
|
|
|
23
21
|
/**
|
|
24
22
|
* The runtime discriminant of query term values. Host literals (bigints,
|
|
25
|
-
* strings, interval objects
|
|
26
|
-
*
|
|
23
|
+
* strings, interval objects) never carry it, so "is this position a term
|
|
24
|
+
* or a literal" is one property probe, never a guess.
|
|
27
25
|
*/
|
|
28
26
|
const term: unique symbol = Symbol("bumbledb.query.term")
|
|
29
27
|
|
|
30
28
|
/**
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
29
|
+
* The carrier of a value's INFERRED types (a rule's row/params, a query's
|
|
30
|
+
* row/params, a rec's params). The property is never present at runtime —
|
|
31
|
+
* it exists so inference rides plain values without any brand on any
|
|
32
|
+
* field value.
|
|
35
33
|
*/
|
|
36
|
-
|
|
34
|
+
const inferred: unique symbol = Symbol("bumbledb.query.inferred")
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* A query variable — a NAME. Its type comes from the field it first binds
|
|
38
|
+
* in the rule (the builder's environment); reusing the name joins, and a
|
|
39
|
+
* cross-domain reuse is a compile error. Identity is the name, strictly
|
|
40
|
+
* rule-scoped: the same name in two rules names two unrelated variables
|
|
41
|
+
* (exactly as the IR scopes `VarId`).
|
|
42
|
+
*/
|
|
43
|
+
interface Var<Name extends string = string> {
|
|
37
44
|
readonly [term]: "var"
|
|
38
|
-
readonly
|
|
39
|
-
readonly field: string
|
|
40
|
-
readonly data: FieldData
|
|
41
|
-
readonly [phantom]?: V
|
|
45
|
+
readonly name: Name
|
|
42
46
|
}
|
|
43
47
|
|
|
44
48
|
/**
|
|
45
|
-
* A scalar query parameter —
|
|
46
|
-
*
|
|
47
|
-
*
|
|
49
|
+
* A scalar query parameter — `r.param("root")`. The name is the key of the
|
|
50
|
+
* typed params object `execute` takes; the type is the element type of the
|
|
51
|
+
* position that anchors it (a field binding, or the bound-variable side of
|
|
52
|
+
* a comparison).
|
|
48
53
|
*/
|
|
49
|
-
interface Param<Name extends string
|
|
54
|
+
interface Param<Name extends string = string> {
|
|
50
55
|
readonly [term]: "param"
|
|
51
56
|
readonly name: Name
|
|
52
|
-
readonly relation: string
|
|
53
|
-
readonly field: string
|
|
54
|
-
readonly data: FieldData
|
|
55
|
-
readonly [phantom]?: V
|
|
56
57
|
}
|
|
57
58
|
|
|
58
59
|
/**
|
|
59
|
-
* A set-valued query parameter (the IR's `ParamSet` term)
|
|
60
|
-
* execution to
|
|
61
|
-
* position matches iff the field value is in the set. Legal
|
|
62
|
-
* bindings (positive and negated) and as the right side of `
|
|
63
|
-
* else, exactly as the IR rules it.
|
|
60
|
+
* A set-valued query parameter (the IR's `ParamSet` term) — `r.inSet("frontier")`:
|
|
61
|
+
* bound at execution to a readonly ARRAY of values of the anchoring field's
|
|
62
|
+
* type; a binding position matches iff the field value is in the set. Legal
|
|
63
|
+
* in atom bindings (positive and negated) and as the right side of `eq` —
|
|
64
|
+
* nowhere else, exactly as the IR rules it.
|
|
64
65
|
*/
|
|
65
|
-
interface
|
|
66
|
-
readonly [term]: "
|
|
66
|
+
interface SetParam<Name extends string = string> {
|
|
67
|
+
readonly [term]: "setParam"
|
|
67
68
|
readonly name: Name
|
|
68
|
-
readonly relation: string
|
|
69
|
-
readonly field: string
|
|
70
|
-
readonly data: FieldData
|
|
71
|
-
readonly [phantom]?: V
|
|
72
69
|
}
|
|
73
70
|
|
|
74
71
|
/**
|
|
75
|
-
* An Allen-mask parameter (the IR's `MaskTerm::Param`)
|
|
76
|
-
* relation as a bind-time argument
|
|
72
|
+
* An Allen-mask parameter (the IR's `MaskTerm::Param`) — the temporal
|
|
73
|
+
* relation as a bind-time argument: one prepared query answers any of the
|
|
77
74
|
* mask questions per execution. Bound to a 13-bit mask number built from
|
|
78
75
|
* the `ALLEN` constants.
|
|
79
76
|
*/
|
|
80
|
-
interface MaskParam<Name extends string> {
|
|
77
|
+
interface MaskParam<Name extends string = string> {
|
|
81
78
|
readonly [term]: "maskParam"
|
|
82
79
|
readonly name: Name
|
|
83
80
|
}
|
|
84
81
|
|
|
85
|
-
/**
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
82
|
+
/**
|
|
83
|
+
* The measure of an interval-typed variable (`ir::Term::Measure`):
|
|
84
|
+
* `|[s, e)| = e − s`, u64 — legal as one side of an order comparison, as a
|
|
85
|
+
* select entry, and as the input of `sum`/`min`/`max`; every other position
|
|
86
|
+
* is unwritable, exactly as the IR rejects it typed. A ray has no finite
|
|
87
|
+
* measure — the engine's `MeasureOfRay` execution error; exclude rays first
|
|
88
|
+
* (`allen` against a bounded window).
|
|
89
|
+
*/
|
|
90
|
+
interface Duration<Name extends string = string> {
|
|
91
|
+
readonly [term]: "duration"
|
|
92
|
+
readonly name: Name
|
|
93
|
+
}
|
|
90
94
|
|
|
91
95
|
/** Any scope term value. */
|
|
92
|
-
type AnyTerm =
|
|
96
|
+
type AnyTerm = Var | Param | SetParam | MaskParam | Duration
|
|
93
97
|
|
|
94
|
-
/** Narrows an unknown
|
|
98
|
+
/** Narrows an unknown position value to a scope term (vs a host literal). */
|
|
95
99
|
function isTerm(value: unknown): value is AnyTerm {
|
|
96
100
|
return typeof value === "object" && value !== null && term in value
|
|
97
101
|
}
|
|
98
102
|
|
|
99
|
-
/**
|
|
103
|
+
/** Builds one variable term. */
|
|
104
|
+
function makeVar<const Name extends string>(name: Name): Var<Name> {
|
|
105
|
+
const value: Var<Name> = { [term]: "var", name }
|
|
106
|
+
return Object.freeze(value)
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/** Builds one scalar-parameter term. */
|
|
110
|
+
function makeParam<const Name extends string>(name: Name): Param<Name> {
|
|
111
|
+
const value: Param<Name> = { [term]: "param", name }
|
|
112
|
+
return Object.freeze(value)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/** Builds one set-parameter term. */
|
|
116
|
+
function makeSetParam<const Name extends string>(name: Name): SetParam<Name> {
|
|
117
|
+
const value: SetParam<Name> = { [term]: "setParam", name }
|
|
118
|
+
return Object.freeze(value)
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/** Builds one Allen-mask-parameter term. */
|
|
122
|
+
function makeMaskParam<const Name extends string>(name: Name): MaskParam<Name> {
|
|
123
|
+
const value: MaskParam<Name> = { [term]: "maskParam", name }
|
|
124
|
+
return Object.freeze(value)
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/** Builds one measure term over an interval-typed variable's name. */
|
|
128
|
+
function makeDuration<const Name extends string>(name: Name): Duration<Name> {
|
|
129
|
+
const value: Duration<Name> = { [term]: "duration", name }
|
|
130
|
+
return Object.freeze(value)
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* A rule's typing environment: variable name → the field descriptor it
|
|
135
|
+
* first bound. Purely a TYPE — the runtime twin is the rule's `varFields`
|
|
136
|
+
* record, and the two are built by the same walk.
|
|
137
|
+
*/
|
|
138
|
+
type EnvShape = Record<string, AnyField>
|
|
139
|
+
|
|
140
|
+
/** A params object type — what `execute` takes and inference carries. */
|
|
100
141
|
type ParamsRecord = Readonly<Record<string, unknown>>
|
|
101
142
|
|
|
102
143
|
/** Flattens an intersection into one displayed object type (hover legibility). */
|
|
@@ -108,194 +149,123 @@ type UnionToIntersection<U> = (U extends unknown ? (member: U) => void : never)
|
|
|
108
149
|
: never
|
|
109
150
|
|
|
110
151
|
/**
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
* array of it, a `MaskParam` a mask number; everything else contributes
|
|
114
|
-
* nothing.
|
|
152
|
+
* Folds a union of per-position record fragments into one flattened record
|
|
153
|
+
* (the machinery both `Params` and `Row` inference ride).
|
|
115
154
|
*/
|
|
116
|
-
type
|
|
117
|
-
readonly [term]: "param"
|
|
118
|
-
readonly name: infer N extends string
|
|
119
|
-
readonly [phantom]?: infer V
|
|
120
|
-
}
|
|
121
|
-
? { readonly [K in N]: Exclude<V, undefined> }
|
|
122
|
-
: T extends {
|
|
123
|
-
readonly [term]: "paramSet"
|
|
124
|
-
readonly name: infer N extends string
|
|
125
|
-
readonly [phantom]?: infer V
|
|
126
|
-
}
|
|
127
|
-
? { readonly [K in N]: readonly Exclude<V, undefined>[] }
|
|
128
|
-
: T extends { readonly [term]: "maskParam"; readonly name: infer N extends string }
|
|
129
|
-
? { readonly [K in N]: number }
|
|
130
|
-
: Record<never, never>
|
|
155
|
+
type ShapeOf<U> = [U] extends [never] ? Record<never, never> : Flatten<UnionToIntersection<U>>
|
|
131
156
|
|
|
132
|
-
/**
|
|
133
|
-
|
|
134
|
-
* params record (the query's `Params` type).
|
|
135
|
-
*/
|
|
136
|
-
type ParamsShape<U> = [U] extends [never] ? Record<never, never> : Flatten<UnionToIntersection<U>>
|
|
157
|
+
/** Reads a field descriptor's domain label (S1: the label IS the domain check). */
|
|
158
|
+
type DomainOf<F extends AnyField> = F["domain"]
|
|
137
159
|
|
|
138
|
-
/** Reads
|
|
139
|
-
type
|
|
160
|
+
/** Reads a field descriptor's width label (`bytes<N>`, `interval<E, W>`); `undefined` when the kind carries none. */
|
|
161
|
+
type WidthOf<F extends AnyField> = F extends { readonly width: infer W } ? W : undefined
|
|
140
162
|
|
|
141
|
-
/**
|
|
142
|
-
|
|
143
|
-
readonly name: string
|
|
144
|
-
readonly shape: "value" | "set" | "mask"
|
|
145
|
-
readonly data: FieldData | undefined
|
|
146
|
-
}
|
|
163
|
+
/** Reads an interval descriptor's element kind; `undefined` on scalar kinds. */
|
|
164
|
+
type ElementOf<F extends AnyField> = F extends { readonly element: infer E } ? E : undefined
|
|
147
165
|
|
|
148
166
|
/**
|
|
149
|
-
* The
|
|
150
|
-
*
|
|
151
|
-
*
|
|
152
|
-
* (
|
|
167
|
+
* The structural join judgment: two field descriptors join iff kind,
|
|
168
|
+
* domain label, width label, and interval element all agree — the
|
|
169
|
+
* string-literal comparison of descriptor shapes that replaced the value
|
|
170
|
+
* brand (design ruling 3).
|
|
153
171
|
*/
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
return {
|
|
165
|
-
theory,
|
|
166
|
-
vars: new Set(),
|
|
167
|
-
params: [],
|
|
168
|
-
paramIndex: new Map(),
|
|
169
|
-
predicates: []
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
+
type JoinOk<A extends AnyField, B extends AnyField> = [A["kind"], DomainOf<A>, WidthOf<A>, ElementOf<A>] extends [
|
|
173
|
+
B["kind"],
|
|
174
|
+
DomainOf<B>,
|
|
175
|
+
WidthOf<B>,
|
|
176
|
+
ElementOf<B>
|
|
177
|
+
]
|
|
178
|
+
? [B["kind"], DomainOf<B>, WidthOf<B>, ElementOf<B>] extends [A["kind"], DomainOf<A>, WidthOf<A>, ElementOf<A>]
|
|
179
|
+
? true
|
|
180
|
+
: false
|
|
181
|
+
: false
|
|
172
182
|
|
|
173
183
|
/**
|
|
174
|
-
* The
|
|
175
|
-
*
|
|
184
|
+
* The runtime twin of {@link JoinOk}: two field descriptors join iff kind,
|
|
185
|
+
* domain label, width label, and interval element all agree — the same
|
|
186
|
+
* structural comparison the type tier makes, judged on the descriptor
|
|
187
|
+
* VALUES (S1 descriptors are honest at runtime). The rule builders throw
|
|
188
|
+
* through this on a domain-unequal variable reuse, so the wall holds for
|
|
189
|
+
* untyped callers too, not only where the compiler can see.
|
|
176
190
|
*/
|
|
177
|
-
function
|
|
178
|
-
|
|
191
|
+
function fieldJoins(a: AnyField, b: AnyField): boolean {
|
|
192
|
+
const widthA = "width" in a ? a.width : undefined
|
|
193
|
+
const widthB = "width" in b ? b.width : undefined
|
|
194
|
+
const elementA = "element" in a ? a.element : undefined
|
|
195
|
+
const elementB = "element" in b ? b.element : undefined
|
|
196
|
+
return a.kind === b.kind && a.domain === b.domain && widthA === widthB && elementA === elementB
|
|
179
197
|
}
|
|
180
198
|
|
|
181
199
|
/**
|
|
182
|
-
*
|
|
183
|
-
*
|
|
184
|
-
* level already carries the brand; this recovers the structural type the
|
|
185
|
-
* lowering and the param marshaler direct by).
|
|
200
|
+
* Renders one field descriptor for join-mismatch diagnostics — the schema
|
|
201
|
+
* grammar's own spelling (`u64 as HolderId`, `interval<i64, 7> as Window`).
|
|
186
202
|
*/
|
|
187
|
-
function
|
|
188
|
-
|
|
189
|
-
if (
|
|
190
|
-
|
|
191
|
-
}
|
|
192
|
-
if (isClosedMember(member)) {
|
|
193
|
-
if (fieldName === "id") {
|
|
194
|
-
return member.id.data
|
|
195
|
-
}
|
|
196
|
-
const column = member.data.columns.find(function byName(candidate) {
|
|
197
|
-
return candidate.name === fieldName
|
|
198
|
-
})
|
|
199
|
-
if (column === undefined) {
|
|
200
|
-
throw errors.new(`closed relation ${relationName} has no column ${fieldName}`)
|
|
201
|
-
}
|
|
202
|
-
return column.field
|
|
203
|
-
}
|
|
204
|
-
const declared = member.data.fields.find(function byName(candidate) {
|
|
205
|
-
return candidate.name === fieldName
|
|
206
|
-
})
|
|
207
|
-
if (declared === undefined) {
|
|
208
|
-
throw errors.new(`relation ${relationName} has no field ${fieldName}`)
|
|
203
|
+
function renderFieldKind(field: AnyField): string {
|
|
204
|
+
let base: string = field.kind
|
|
205
|
+
if (field.kind === "bytes") {
|
|
206
|
+
base = `bytes<${field.width}>`
|
|
209
207
|
}
|
|
210
|
-
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
/** A field reference's runtime half, as the scope factories consume it. */
|
|
214
|
-
interface RefNames {
|
|
215
|
-
readonly relation: string
|
|
216
|
-
readonly field: string
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
/** Declares one variable in the scope (the `$.var` implementation). */
|
|
220
|
-
function scopeVar<V>(registry: QueryRegistry, ref: RefNames): Var<V> {
|
|
221
|
-
const value: Var<V> = Object.freeze({
|
|
222
|
-
[term]: "var" as const,
|
|
223
|
-
relation: ref.relation,
|
|
224
|
-
field: ref.field,
|
|
225
|
-
data: resolveFieldData(registry.theory, ref.relation, ref.field)
|
|
226
|
-
})
|
|
227
|
-
registry.vars.add(value)
|
|
228
|
-
return value
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
/** Rejects a second parameter under an already-taken name. */
|
|
232
|
-
function assertFreshParamName(registry: QueryRegistry, name: string): void {
|
|
233
|
-
const taken = registry.params.some(function byName(entry) {
|
|
234
|
-
return entry.name === name
|
|
235
|
-
})
|
|
236
|
-
if (taken) {
|
|
237
|
-
throw errors.new(
|
|
238
|
-
`query scope already declares a param named ${name} — param names key the execute params object, one declaration each`
|
|
239
|
-
)
|
|
208
|
+
if (field.kind === "interval") {
|
|
209
|
+
base = field.width === undefined ? `interval<${field.element}>` : `interval<${field.element}, ${field.width}>`
|
|
240
210
|
}
|
|
211
|
+
return field.domain === undefined ? base : `${base} as ${field.domain}`
|
|
241
212
|
}
|
|
242
213
|
|
|
243
|
-
/**
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
field: ref.field,
|
|
252
|
-
data
|
|
253
|
-
})
|
|
254
|
-
registry.paramIndex.set(value, registry.params.length)
|
|
255
|
-
registry.params.push(Object.freeze({ name, shape: "value" as const, data }))
|
|
256
|
-
return value
|
|
257
|
-
}
|
|
214
|
+
/**
|
|
215
|
+
* What a PARAM anchored at field `F` accepts at execution: the field's
|
|
216
|
+
* bare value type, exactly. At an interval field the engine resolves the
|
|
217
|
+
* bivalent anchor to the INTERVAL reading (value equality) — the point
|
|
218
|
+
* reading of a param is spelled `pointIn(r.param(...), w)`, whose sibling
|
|
219
|
+
* anchors it element-typed.
|
|
220
|
+
*/
|
|
221
|
+
type ParamValueAt<F extends AnyField> = Infer<F>
|
|
258
222
|
|
|
259
|
-
/**
|
|
260
|
-
|
|
261
|
-
assertFreshParamName(registry, name)
|
|
262
|
-
const data = resolveFieldData(registry.theory, ref.relation, ref.field)
|
|
263
|
-
const value: ParamSet<Name, V> = Object.freeze({
|
|
264
|
-
[term]: "paramSet" as const,
|
|
265
|
-
name,
|
|
266
|
-
relation: ref.relation,
|
|
267
|
-
field: ref.field,
|
|
268
|
-
data
|
|
269
|
-
})
|
|
270
|
-
registry.paramIndex.set(value, registry.params.length)
|
|
271
|
-
registry.params.push(Object.freeze({ name, shape: "set" as const, data }))
|
|
272
|
-
return value
|
|
273
|
-
}
|
|
223
|
+
/** Reads a value's inferred-types carrier (rules, queries, recs). */
|
|
224
|
+
type InferredOf<T> = T extends { readonly [inferred]?: infer S } ? Exclude<S, undefined> : never
|
|
274
225
|
|
|
275
|
-
/**
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
226
|
+
/**
|
|
227
|
+
* One registered parameter of a query, as the wire marshal reads it: the
|
|
228
|
+
* name, the wire shape, the field descriptor (or the measure) that anchored
|
|
229
|
+
* it, and the comparison op the anchor came from (`"binding"` for atom
|
|
230
|
+
* positions) — the op keeps literal tagging op-aware at `pointIn`
|
|
231
|
+
* (the bug-hunt fix, preserved). `anchor` is `undefined` only on a query
|
|
232
|
+
* built but not yet anchored by any rule; lowering and the wire both refuse
|
|
233
|
+
* that state typed.
|
|
234
|
+
*/
|
|
235
|
+
interface ParamEntry {
|
|
236
|
+
readonly name: string
|
|
237
|
+
readonly shape: "value" | "set" | "mask"
|
|
238
|
+
readonly anchor: AnyField | "measure" | undefined
|
|
239
|
+
readonly op: "binding" | "eq" | "ne" | "lt" | "le" | "gt" | "ge" | "pointIn" | "allen"
|
|
282
240
|
}
|
|
283
241
|
|
|
284
242
|
export type {
|
|
285
|
-
AnyParamTerm,
|
|
286
243
|
AnyTerm,
|
|
287
|
-
|
|
244
|
+
DomainOf,
|
|
245
|
+
Duration,
|
|
246
|
+
EnvShape,
|
|
288
247
|
Flatten,
|
|
289
|
-
|
|
248
|
+
InferredOf,
|
|
249
|
+
JoinOk,
|
|
290
250
|
MaskParam,
|
|
291
251
|
Param,
|
|
292
252
|
ParamEntry,
|
|
293
|
-
ParamSet,
|
|
294
253
|
ParamsRecord,
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
254
|
+
ParamValueAt,
|
|
255
|
+
SetParam,
|
|
256
|
+
ShapeOf,
|
|
298
257
|
UnionToIntersection,
|
|
299
258
|
Var
|
|
300
259
|
}
|
|
301
|
-
export {
|
|
260
|
+
export {
|
|
261
|
+
fieldJoins,
|
|
262
|
+
inferred,
|
|
263
|
+
isTerm,
|
|
264
|
+
makeDuration,
|
|
265
|
+
makeMaskParam,
|
|
266
|
+
makeParam,
|
|
267
|
+
makeSetParam,
|
|
268
|
+
makeVar,
|
|
269
|
+
renderFieldKind,
|
|
270
|
+
term
|
|
271
|
+
}
|