@bjornpagen/bumbledb 0.4.0 → 0.5.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 +181 -47
- package/README.md +4 -2
- package/dist/closed.d.ts +30 -2
- package/dist/closed.d.ts.map +1 -1
- package/dist/closed.js +66 -20
- package/dist/closed.js.map +1 -1
- package/dist/db.d.ts +33 -6
- package/dist/db.d.ts.map +1 -1
- package/dist/db.js +87 -70
- package/dist/db.js.map +1 -1
- package/dist/exhume.d.ts.map +1 -1
- package/dist/exhume.js +1 -14
- package/dist/exhume.js.map +1 -1
- package/dist/face.d.ts +1 -1
- package/dist/face.d.ts.map +1 -1
- package/dist/face.js +2 -1
- package/dist/face.js.map +1 -1
- package/dist/fields.d.ts +18 -1
- package/dist/fields.d.ts.map +1 -1
- package/dist/fields.js +44 -16
- package/dist/fields.js.map +1 -1
- package/dist/index.d.ts +11 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -4
- package/dist/index.js.map +1 -1
- package/dist/law.d.ts +2 -1
- package/dist/law.d.ts.map +1 -1
- package/dist/law.js +15 -14
- package/dist/law.js.map +1 -1
- package/dist/lower.d.ts.map +1 -1
- package/dist/lower.js +1 -7
- package/dist/lower.js.map +1 -1
- package/dist/marshal.d.ts.map +1 -1
- package/dist/marshal.js +15 -27
- package/dist/marshal.js.map +1 -1
- package/dist/native.d.ts +21 -2
- package/dist/native.d.ts.map +1 -1
- package/dist/native.js +20 -3
- package/dist/native.js.map +1 -1
- package/dist/order.d.ts +36 -0
- package/dist/order.d.ts.map +1 -0
- package/dist/order.js +135 -0
- package/dist/order.js.map +1 -0
- package/dist/query/atom.d.ts +18 -15
- package/dist/query/atom.d.ts.map +1 -1
- package/dist/query/atom.js +9 -16
- package/dist/query/atom.js.map +1 -1
- package/dist/query/lower.d.ts +5 -8
- package/dist/query/lower.d.ts.map +1 -1
- package/dist/query/lower.js +87 -76
- package/dist/query/lower.js.map +1 -1
- package/dist/query/predicate.d.ts.map +1 -1
- package/dist/query/predicate.js +34 -2
- package/dist/query/predicate.js.map +1 -1
- package/dist/query/run.d.ts.map +1 -1
- package/dist/query/run.js +1 -2
- package/dist/query/run.js.map +1 -1
- package/dist/query/scope.d.ts +2 -16
- package/dist/query/scope.d.ts.map +1 -1
- package/dist/query/scope.js +7 -47
- package/dist/query/scope.js.map +1 -1
- package/dist/relation.d.ts +9 -22
- package/dist/relation.d.ts.map +1 -1
- package/dist/relation.js +9 -28
- package/dist/relation.js.map +1 -1
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +7 -31
- package/dist/schema.js.map +1 -1
- package/dist/statements.d.ts +5 -2
- package/dist/statements.d.ts.map +1 -1
- package/dist/statements.js +30 -35
- package/dist/statements.js.map +1 -1
- package/package.json +2 -5
- package/src/closed.ts +73 -28
- package/src/db.ts +122 -84
- package/src/exhume.ts +1 -15
- package/src/face.ts +4 -3
- package/src/fields.ts +58 -16
- package/src/index.ts +10 -8
- package/src/law.ts +15 -14
- package/src/lower.ts +2 -9
- package/src/marshal.ts +15 -31
- package/src/native.ts +22 -4
- package/src/order.ts +156 -0
- package/src/query/atom.ts +13 -21
- package/src/query/lower.ts +90 -91
- package/src/query/predicate.ts +39 -4
- package/src/query/run.ts +1 -3
- package/src/query/scope.ts +7 -59
- package/src/relation.ts +9 -51
- package/src/schema.ts +7 -33
- package/src/statements.ts +33 -38
package/src/marshal.ts
CHANGED
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
|
|
30
30
|
import * as errors from "@superbuilders/errors"
|
|
31
31
|
import type { AnyField, ClosedRoster } from "#fields.ts"
|
|
32
|
+
import { isIntervalValue, literalShapeError, rosterOf } from "#fields.ts"
|
|
32
33
|
import type { FactValue } from "#native.ts"
|
|
33
34
|
import type { AnyRelation, Fact, FreshKeys, RelationData } from "#relation.ts"
|
|
34
35
|
|
|
@@ -66,23 +67,6 @@ type KeyFact<R extends AnyRelation> = [FreshKeys<R>] extends [never]
|
|
|
66
67
|
? Partial<Fact<R>>
|
|
67
68
|
: { [K in FreshKeys<R>]: Fact<R>[K] }
|
|
68
69
|
|
|
69
|
-
/** The typed shape refusal of the row marshaler — a genuine failure, never data. */
|
|
70
|
-
function cellShapeError(context: string, expected: string, value: unknown): Error {
|
|
71
|
-
return errors.new(`${context}: expected ${expected}, got ${typeof value}`)
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/** Narrows an interval cell: a plain object with bigint start/end. */
|
|
75
|
-
function isIntervalCell(value: unknown): value is { readonly start: bigint; readonly end: bigint } {
|
|
76
|
-
return (
|
|
77
|
-
typeof value === "object" &&
|
|
78
|
-
value !== null &&
|
|
79
|
-
"start" in value &&
|
|
80
|
-
"end" in value &&
|
|
81
|
-
typeof value.start === "bigint" &&
|
|
82
|
-
typeof value.end === "bigint"
|
|
83
|
-
)
|
|
84
|
-
}
|
|
85
|
-
|
|
86
70
|
/**
|
|
87
71
|
* Reprojects any host object to a string-indexed record — the boundary
|
|
88
72
|
* through which generic fact objects (whose type parameters carry no index
|
|
@@ -121,7 +105,7 @@ function closedCellOf(context: string, closed: ClosedRoster, name: string): Fact
|
|
|
121
105
|
*/
|
|
122
106
|
function handleOf(context: string, closed: ClosedRoster, cell: FactValue): string {
|
|
123
107
|
if (typeof cell !== "bigint") {
|
|
124
|
-
throw
|
|
108
|
+
throw literalShapeError(context, `a ${closed.name} handle id (bigint)`, cell)
|
|
125
109
|
}
|
|
126
110
|
const handle = closed.handles[Number(cell)]
|
|
127
111
|
if (handle === undefined) {
|
|
@@ -144,29 +128,30 @@ function handleOf(context: string, closed: ClosedRoster, cell: FactValue): strin
|
|
|
144
128
|
* boundary.
|
|
145
129
|
*/
|
|
146
130
|
function cellOf(context: string, field: AnyField, value: unknown): FactValue {
|
|
147
|
-
|
|
131
|
+
const roster = rosterOf(field)
|
|
132
|
+
if (roster !== undefined) {
|
|
148
133
|
if (typeof value !== "string") {
|
|
149
|
-
throw
|
|
134
|
+
throw literalShapeError(context, `a ${roster.name} handle name (string)`, value)
|
|
150
135
|
}
|
|
151
|
-
return closedCellOf(context,
|
|
136
|
+
return closedCellOf(context, roster, value)
|
|
152
137
|
}
|
|
153
138
|
switch (field.kind) {
|
|
154
139
|
case "bool": {
|
|
155
140
|
if (typeof value !== "boolean") {
|
|
156
|
-
throw
|
|
141
|
+
throw literalShapeError(context, "boolean", value)
|
|
157
142
|
}
|
|
158
143
|
return value
|
|
159
144
|
}
|
|
160
145
|
case "u64":
|
|
161
146
|
case "i64": {
|
|
162
147
|
if (typeof value !== "bigint") {
|
|
163
|
-
throw
|
|
148
|
+
throw literalShapeError(context, "bigint", value)
|
|
164
149
|
}
|
|
165
150
|
return value
|
|
166
151
|
}
|
|
167
152
|
case "str": {
|
|
168
153
|
if (typeof value !== "string") {
|
|
169
|
-
throw
|
|
154
|
+
throw literalShapeError(context, "string", value)
|
|
170
155
|
}
|
|
171
156
|
/**
|
|
172
157
|
* A lone surrogate would be lossily replaced with U+FFFD at the
|
|
@@ -176,19 +161,19 @@ function cellOf(context: string, field: AnyField, value: unknown): FactValue {
|
|
|
176
161
|
* lookup lowers through.
|
|
177
162
|
*/
|
|
178
163
|
if (!value.isWellFormed()) {
|
|
179
|
-
throw
|
|
164
|
+
throw literalShapeError(context, "well-formed string", value)
|
|
180
165
|
}
|
|
181
166
|
return value
|
|
182
167
|
}
|
|
183
168
|
case "bytes": {
|
|
184
169
|
if (!(value instanceof Uint8Array)) {
|
|
185
|
-
throw
|
|
170
|
+
throw literalShapeError(context, "Uint8Array", value)
|
|
186
171
|
}
|
|
187
172
|
return value
|
|
188
173
|
}
|
|
189
174
|
case "interval": {
|
|
190
|
-
if (!
|
|
191
|
-
throw
|
|
175
|
+
if (!isIntervalValue(value)) {
|
|
176
|
+
throw literalShapeError(context, "interval ({ start, end } bigints)", value)
|
|
192
177
|
}
|
|
193
178
|
return { start: value.start, end: value.end }
|
|
194
179
|
}
|
|
@@ -289,10 +274,9 @@ function factOf<R extends AnyRelation>(relation: R, row: readonly FactValue[]):
|
|
|
289
274
|
if (cell === undefined) {
|
|
290
275
|
throw errors.new(`relation ${data.name}: row cell ${ordinal} (${declared.name}) is absent`)
|
|
291
276
|
}
|
|
277
|
+
const roster = rosterOf(declared.field)
|
|
292
278
|
decoded[declared.name] =
|
|
293
|
-
|
|
294
|
-
? handleOf(`relation ${data.name} field ${declared.name}`, declared.field.closed, cell)
|
|
295
|
-
: cell
|
|
279
|
+
roster !== undefined ? handleOf(`relation ${data.name} field ${declared.name}`, roster, cell) : cell
|
|
296
280
|
})
|
|
297
281
|
Object.freeze(decoded)
|
|
298
282
|
if (!isCompleteFact(relation, decoded)) {
|
package/src/native.ts
CHANGED
|
@@ -241,7 +241,7 @@ interface Violation {
|
|
|
241
241
|
}
|
|
242
242
|
|
|
243
243
|
/**
|
|
244
|
-
* `dbCreate`/`dbOpen`'s domain outcome. `schemaError`
|
|
244
|
+
* `dbCreate`/`dbOpen`'s domain outcome. `schemaError` spans both spec
|
|
245
245
|
* resolution (unresolvable names, banned spellings — every issue in one
|
|
246
246
|
* message) and schema validation at the declaration boundary;
|
|
247
247
|
* `newtypeMismatch` is the coherence wall's own kind — a spec whose
|
|
@@ -471,8 +471,12 @@ interface Native {
|
|
|
471
471
|
* The sole platform this release ships (PRD-03 ruling 1: prebuilt-only,
|
|
472
472
|
* darwin-arm64). The per-platform-package structure below makes adding
|
|
473
473
|
* `darwin-x64`/`linux-*`/`win32-*` pure addition — one more `os`/`cpu`-gated
|
|
474
|
-
* package plus a CI matrix — never a redesign
|
|
475
|
-
*
|
|
474
|
+
* package plus a CI matrix — never a redesign. This constant names the
|
|
475
|
+
* shipped set for the unsupported-platform message; the build's
|
|
476
|
+
* `PUBLISH_PLATFORM` (`scripts/platform.ts` — src cannot import scripts,
|
|
477
|
+
* the packaging boundary) and the `ts/.gitignore` carve-out spell the same
|
|
478
|
+
* target, and the single-source pin in `test/build-platform.test.ts` holds
|
|
479
|
+
* all three in lockstep.
|
|
476
480
|
*/
|
|
477
481
|
const SHIPPED_PLATFORMS = "darwin-arm64"
|
|
478
482
|
|
|
@@ -536,6 +540,20 @@ function loadNativeBinding(platform: string, arch: string): Native {
|
|
|
536
540
|
*/
|
|
537
541
|
const native: Native = loadNativeBinding(process.platform, process.arch)
|
|
538
542
|
|
|
543
|
+
/**
|
|
544
|
+
* The bridge guard — THE one wrapper every native call crosses (db.ts and
|
|
545
|
+
* exhume.ts both import it): runs one native call and wraps anything it
|
|
546
|
+
* throws, so marshal-shape refusals and handle-lifecycle refusals cross as
|
|
547
|
+
* genuine typed failures, never bare foreign errors.
|
|
548
|
+
*/
|
|
549
|
+
function bridged<T>(context: string, run: () => T): T {
|
|
550
|
+
const result = errors.trySync(run)
|
|
551
|
+
if (result.error) {
|
|
552
|
+
throw errors.wrap(result.error, context)
|
|
553
|
+
}
|
|
554
|
+
return result.data
|
|
555
|
+
}
|
|
556
|
+
|
|
539
557
|
export type {
|
|
540
558
|
AggOpIr,
|
|
541
559
|
AtomIr,
|
|
@@ -577,4 +595,4 @@ export type {
|
|
|
577
595
|
ViolationFact,
|
|
578
596
|
WriteFromResult
|
|
579
597
|
}
|
|
580
|
-
export { loadNativeBinding, native }
|
|
598
|
+
export { bridged, loadNativeBinding, native, SHIPPED_PLATFORMS }
|
package/src/order.ts
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Host-side answer ordering — the census-fired convenience
|
|
3
|
+
* (`docs/architecture/70-api.md` § the freeze ledger). Answers are SETS and
|
|
4
|
+
* the ENGINE NEVER ORDERS; the language owns the sort (`rows.sort(...)`)
|
|
5
|
+
* and the limit (`.slice(0, n)`) — the drizzle law. What JS lacks is a
|
|
6
|
+
* number-returning comparator over the SDK's bigint-bearing cells, so the
|
|
7
|
+
* SDK ships exactly that: sort keys are DATA — a bare column name is
|
|
8
|
+
* ascending (the punning spelling; no `asc` wrapper exists — one spelling
|
|
9
|
+
* per meaning) and `desc(name)` is the one descending spelling — folded by
|
|
10
|
+
* `by(...)` into one row-typed comparator. Cross-type cells cannot arise
|
|
11
|
+
* within one column (one column, one domain), and the cell order is TOTAL
|
|
12
|
+
* anyway (the type-rank wall), so the comparator never throws.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import type { FactValue } from "#native.ts"
|
|
16
|
+
|
|
17
|
+
/** One DESCENDING sort key, plain data — built by {@link desc}. */
|
|
18
|
+
interface Desc<K extends string> {
|
|
19
|
+
readonly key: K
|
|
20
|
+
readonly desc: true
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** One sort key: a bare column name (ascending — the punning spelling) or `desc(name)`. */
|
|
24
|
+
type SortKey<K extends string> = K | Desc<K>
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* The type-rank wall: boolean 0, bigint 1, string 2, bytes 3, interval 4.
|
|
28
|
+
* One column carries one domain, so a mixed pair never arises from decoded
|
|
29
|
+
* answer rows — the wall exists to keep the cell order TOTAL (never a
|
|
30
|
+
* throw), not to be reached.
|
|
31
|
+
*/
|
|
32
|
+
function cellRank(value: FactValue): number {
|
|
33
|
+
if (typeof value === "boolean") {
|
|
34
|
+
return 0
|
|
35
|
+
}
|
|
36
|
+
if (typeof value === "bigint") {
|
|
37
|
+
return 1
|
|
38
|
+
}
|
|
39
|
+
if (typeof value === "string") {
|
|
40
|
+
return 2
|
|
41
|
+
}
|
|
42
|
+
if (value instanceof Uint8Array) {
|
|
43
|
+
return 3
|
|
44
|
+
}
|
|
45
|
+
return 4
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* One cell against one cell. Same-type arms: boolean orders false < true;
|
|
50
|
+
* bigint by `<`/`>`; string by the host language's own `<`/`>` (flavor,
|
|
51
|
+
* recorded); bytes bytewise over the shared prefix, then by length;
|
|
52
|
+
* intervals by start, then end. A mixed pair falls through to the
|
|
53
|
+
* type-rank wall.
|
|
54
|
+
*/
|
|
55
|
+
function cellCmp(left: FactValue, right: FactValue): number {
|
|
56
|
+
if (typeof left === "boolean" && typeof right === "boolean") {
|
|
57
|
+
if (left === right) {
|
|
58
|
+
return 0
|
|
59
|
+
}
|
|
60
|
+
if (left) {
|
|
61
|
+
return 1
|
|
62
|
+
}
|
|
63
|
+
return -1
|
|
64
|
+
}
|
|
65
|
+
if (typeof left === "bigint" && typeof right === "bigint") {
|
|
66
|
+
if (left < right) {
|
|
67
|
+
return -1
|
|
68
|
+
}
|
|
69
|
+
if (left > right) {
|
|
70
|
+
return 1
|
|
71
|
+
}
|
|
72
|
+
return 0
|
|
73
|
+
}
|
|
74
|
+
if (typeof left === "string" && typeof right === "string") {
|
|
75
|
+
if (left < right) {
|
|
76
|
+
return -1
|
|
77
|
+
}
|
|
78
|
+
if (left > right) {
|
|
79
|
+
return 1
|
|
80
|
+
}
|
|
81
|
+
return 0
|
|
82
|
+
}
|
|
83
|
+
if (left instanceof Uint8Array && right instanceof Uint8Array) {
|
|
84
|
+
const shared = Math.min(left.length, right.length)
|
|
85
|
+
for (let index = 0; index < shared; index += 1) {
|
|
86
|
+
const leftByte = left[index]
|
|
87
|
+
const rightByte = right[index]
|
|
88
|
+
// `index < shared` keeps both reads in bounds; the `undefined`
|
|
89
|
+
// arms are the checker's indexed-access tax, never taken.
|
|
90
|
+
if (leftByte !== undefined && rightByte !== undefined && leftByte !== rightByte) {
|
|
91
|
+
return leftByte - rightByte
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return left.length - right.length
|
|
95
|
+
}
|
|
96
|
+
if (
|
|
97
|
+
typeof left === "object" &&
|
|
98
|
+
!(left instanceof Uint8Array) &&
|
|
99
|
+
typeof right === "object" &&
|
|
100
|
+
!(right instanceof Uint8Array)
|
|
101
|
+
) {
|
|
102
|
+
if (left.start < right.start) {
|
|
103
|
+
return -1
|
|
104
|
+
}
|
|
105
|
+
if (left.start > right.start) {
|
|
106
|
+
return 1
|
|
107
|
+
}
|
|
108
|
+
if (left.end < right.end) {
|
|
109
|
+
return -1
|
|
110
|
+
}
|
|
111
|
+
if (left.end > right.end) {
|
|
112
|
+
return 1
|
|
113
|
+
}
|
|
114
|
+
return 0
|
|
115
|
+
}
|
|
116
|
+
return cellRank(left) - cellRank(right)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/** Marks one sort key DESCENDING — the single descending spelling (a bare name is already ascending). */
|
|
120
|
+
function desc<const K extends string>(key: K): Desc<K> {
|
|
121
|
+
const marker: Desc<K> = { key, desc: true }
|
|
122
|
+
return Object.freeze(marker)
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Folds sort keys into ONE comparator typed against the row —
|
|
127
|
+
* `Row extends Readonly<Record<K, FactValue>>` — so a key the row lacks, or
|
|
128
|
+
* a column typed `number` (outside the cell domain), is a COMPILE error at
|
|
129
|
+
* the `.sort` call site: the laws typed the columns, and the row type
|
|
130
|
+
* carries that proof here (parse-don't-validate). The generic RETURN is the
|
|
131
|
+
* load-bearing trick: `rows.sort(by("rank"))` instantiates `Row` from the
|
|
132
|
+
* array's own element type and checks the key set right there.
|
|
133
|
+
*/
|
|
134
|
+
function by<const K extends string>(
|
|
135
|
+
first: SortKey<K>,
|
|
136
|
+
...rest: ReadonlyArray<SortKey<K>>
|
|
137
|
+
): <Row extends Readonly<Record<K, FactValue>>>(left: Row, right: Row) => number {
|
|
138
|
+
const entries = [first, ...rest].map(function normalizeKey(sortKey): { readonly key: K; readonly factor: 1 | -1 } {
|
|
139
|
+
if (typeof sortKey === "string") {
|
|
140
|
+
return { key: sortKey, factor: 1 }
|
|
141
|
+
}
|
|
142
|
+
return { key: sortKey.key, factor: -1 }
|
|
143
|
+
})
|
|
144
|
+
return function compare<Row extends Readonly<Record<K, FactValue>>>(left: Row, right: Row): number {
|
|
145
|
+
for (const entry of entries) {
|
|
146
|
+
const order = cellCmp(left[entry.key], right[entry.key]) * entry.factor
|
|
147
|
+
if (order !== 0) {
|
|
148
|
+
return order
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return 0
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
export type { Desc, SortKey }
|
|
156
|
+
export { by, desc }
|
package/src/query/atom.ts
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* by owner ruling; see {@link BindingInput})
|
|
10
10
|
* (unmentioned fields ARE the wildcard — no wildcard value exists);
|
|
11
11
|
* `not(Rel, {...})` is negation-as-position (anti-join); `eq`/`ne` and the
|
|
12
|
-
* order roster, `pointIn
|
|
12
|
+
* order roster, `pointIn` (the one spelling of `ir::CmpOp::PointIn`,
|
|
13
13
|
* always lowered interval-left), `allen` (the 13-bit mask pair
|
|
14
14
|
* comparison), and `and`/`or` (the input condition-tree grammar) complete
|
|
15
15
|
* the roster. Nothing beyond the IR exists here — and the walls the engine
|
|
@@ -62,7 +62,7 @@ type MatchOwner = AnyRelation | AnyClosed
|
|
|
62
62
|
* union rides into ψ id bindings and joins exactly as it does on a
|
|
63
63
|
* referencing column) first, then the declared payload columns read
|
|
64
64
|
* through the typed `columns` carrier (the one source of payload typing —
|
|
65
|
-
* no parallel column table exists). The runtime twin is `
|
|
65
|
+
* no parallel column table exists). The runtime twin is `sealedFieldsOf` in
|
|
66
66
|
* `#query/lower.ts`; the id-first ordinal shift the two tiers share is
|
|
67
67
|
* pinned by the lowering golden.
|
|
68
68
|
*/
|
|
@@ -355,10 +355,10 @@ type NeRight = Var<string> | Param<string> | bigint | string | boolean | Uint8Ar
|
|
|
355
355
|
/** One side of an order comparison: orderable terms only (the IR's comparison rules). */
|
|
356
356
|
type OrderSide = Var<string> | Param<string> | Duration<string> | bigint
|
|
357
357
|
|
|
358
|
-
/** The point side of `pointIn
|
|
358
|
+
/** The point side of `pointIn`. */
|
|
359
359
|
type PointSide = Var<string> | Param<string> | bigint
|
|
360
360
|
|
|
361
|
-
/** The interval side of `pointIn`/`
|
|
361
|
+
/** The interval side of `pointIn`/`allen`. */
|
|
362
362
|
type IntervalSide = Var<string> | Param<string> | IntervalValue
|
|
363
363
|
|
|
364
364
|
/** Builds one comparison value. */
|
|
@@ -426,29 +426,21 @@ function ge<const L extends OrderSide, const R extends OrderSide>(left: L, right
|
|
|
426
426
|
}
|
|
427
427
|
|
|
428
428
|
/**
|
|
429
|
-
* Point membership as a predicate (`ir::CmpOp::PointIn`)
|
|
429
|
+
* Point membership as a predicate (`ir::CmpOp::PointIn`) — THE one
|
|
430
430
|
* spelling: `pointIn(t, w)` holds iff `w.start ≤ t < w.end`. The IR
|
|
431
431
|
* orders the operands interval-left, point-right; the value stores them
|
|
432
|
-
* that way whatever the surface
|
|
432
|
+
* that way whatever the surface argument order (a literal `span(...)`
|
|
433
|
+
* interval operand is legal and tags by the point sibling's element
|
|
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).
|
|
433
438
|
*/
|
|
434
439
|
function pointIn<const P extends PointSide, const I extends IntervalSide>(point: P, interval: I): Cmp<"pointIn", I, P> {
|
|
435
440
|
assertTermSide("pointIn", point, interval)
|
|
436
441
|
return comparison("pointIn", interval, point, undefined)
|
|
437
442
|
}
|
|
438
443
|
|
|
439
|
-
/**
|
|
440
|
-
* Point membership, coverage spelling — `covers(w, t)` is `pointIn(t, w)`
|
|
441
|
-
* with the interval written first (the IR's own operand order; a literal
|
|
442
|
-
* `span(...)` left operand is legal and tags by the point sibling's
|
|
443
|
-
* element domain — the bug-hunt fix, now also a type-level guarantee).
|
|
444
|
-
* Interval ⊇ interval is NOT this operator; that predicate is
|
|
445
|
-
* `allen(a, ALLEN.covers, b)`.
|
|
446
|
-
*/
|
|
447
|
-
function covers<const I extends IntervalSide, const P extends PointSide>(interval: I, point: P): Cmp<"pointIn", I, P> {
|
|
448
|
-
assertTermSide("covers", interval, point)
|
|
449
|
-
return comparison("pointIn", interval, point, undefined)
|
|
450
|
-
}
|
|
451
|
-
|
|
452
444
|
/**
|
|
453
445
|
* The 13-bit mask range: bits above the low 13 are unrepresentable in the
|
|
454
446
|
* engine's `AllenMask` (`bumbledb/crates/bumbledb/src/allen.rs`:
|
|
@@ -619,7 +611,7 @@ type NotOk<Env extends EnvShape, F extends FieldsShape, CR, B> = false extends {
|
|
|
619
611
|
* twin of the engine's comparison roster: class-equal joins (off the
|
|
620
612
|
* schema type's class map), orderable order sides (an interval var under a
|
|
621
613
|
* non-`pointIn` op is exactly here refused), kind-correct
|
|
622
|
-
* `pointIn`/`
|
|
614
|
+
* `pointIn`/`allen` sides, and negated-atom safety (the negated
|
|
623
615
|
* relation's class record is resolved through `Classes` by its name). The
|
|
624
616
|
* leading `[AnyTreeChild] extends [C]` arm is the recursion's base case:
|
|
625
617
|
* at an UNRESOLVED constraint (the whole condition union — or a tree's
|
|
@@ -747,4 +739,4 @@ export type {
|
|
|
747
739
|
Tree,
|
|
748
740
|
TreeData
|
|
749
741
|
}
|
|
750
|
-
export { ALLEN, allen, and, comparison,
|
|
742
|
+
export { ALLEN, ALLEN_ALL_BITS, allen, and, comparison, eq, ge, gt, le, lt, ne, not, or, pointIn }
|