effect-qb 0.13.0 → 0.14.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.
Files changed (54) hide show
  1. package/README.md +6 -1431
  2. package/dist/mysql.js +1678 -355
  3. package/dist/postgres/metadata.js +2724 -0
  4. package/dist/postgres.js +7197 -5433
  5. package/package.json +8 -10
  6. package/src/internal/column-state.ts +84 -10
  7. package/src/internal/column.ts +556 -34
  8. package/src/internal/datatypes/define.ts +0 -30
  9. package/src/internal/executor.ts +45 -11
  10. package/src/internal/expression-ast.ts +4 -0
  11. package/src/internal/expression.ts +1 -1
  12. package/src/internal/implication-runtime.ts +171 -0
  13. package/src/internal/mysql-query.ts +7173 -0
  14. package/src/internal/mysql-renderer.ts +2 -2
  15. package/src/internal/plan.ts +14 -4
  16. package/src/internal/{query-factory.ts → postgres-query.ts} +619 -167
  17. package/src/internal/postgres-renderer.ts +2 -2
  18. package/src/internal/postgres-schema-model.ts +144 -0
  19. package/src/internal/predicate-analysis.ts +10 -0
  20. package/src/internal/predicate-context.ts +112 -36
  21. package/src/internal/predicate-formula.ts +31 -19
  22. package/src/internal/predicate-normalize.ts +177 -106
  23. package/src/internal/predicate-runtime.ts +676 -0
  24. package/src/internal/query.ts +455 -39
  25. package/src/internal/renderer.ts +2 -2
  26. package/src/internal/runtime-schema.ts +74 -20
  27. package/src/internal/schema-ddl.ts +55 -0
  28. package/src/internal/schema-derivation.ts +93 -21
  29. package/src/internal/schema-expression.ts +44 -0
  30. package/src/internal/sql-expression-renderer.ts +95 -31
  31. package/src/internal/table-options.ts +87 -7
  32. package/src/internal/table.ts +104 -41
  33. package/src/mysql/column.ts +1 -0
  34. package/src/mysql/datatypes/index.ts +17 -2
  35. package/src/mysql/function/core.ts +1 -0
  36. package/src/mysql/function/index.ts +1 -0
  37. package/src/mysql/private/query.ts +1 -13
  38. package/src/mysql/query.ts +5 -0
  39. package/src/postgres/cast.ts +31 -0
  40. package/src/postgres/column.ts +26 -0
  41. package/src/postgres/datatypes/index.ts +40 -5
  42. package/src/postgres/function/core.ts +12 -0
  43. package/src/postgres/function/index.ts +2 -1
  44. package/src/postgres/function/json.ts +499 -2
  45. package/src/postgres/metadata.ts +31 -0
  46. package/src/postgres/private/query.ts +1 -13
  47. package/src/postgres/query.ts +5 -2
  48. package/src/postgres/schema-expression.ts +16 -0
  49. package/src/postgres/schema-management.ts +204 -0
  50. package/src/postgres/schema.ts +35 -0
  51. package/src/postgres/table.ts +307 -41
  52. package/src/postgres/type.ts +4 -0
  53. package/src/postgres.ts +14 -0
  54. package/CHANGELOG.md +0 -134
@@ -19,7 +19,7 @@ export interface PostgresRenderResult {
19
19
  /**
20
20
  * Renders the current query AST into Postgres SQL plus bind parameters.
21
21
  */
22
- export const renderPostgresPlan = <PlanValue extends Query.QueryPlan<any, any, any, any, any, any, any, any, any>>(
22
+ export const renderPostgresPlan = <PlanValue extends Query.QueryPlan<any, any, any, any, any, any, any, any, any, any>>(
23
23
  plan: Query.DialectCompatiblePlan<PlanValue, "postgres">
24
24
  ): PostgresRenderResult => {
25
25
  const state: RenderState = {
@@ -28,7 +28,7 @@ export const renderPostgresPlan = <PlanValue extends Query.QueryPlan<any, any, a
28
28
  cteNames: new Set<string>()
29
29
  }
30
30
  const rendered = renderQueryAst(
31
- Query.getAst(plan as Query.QueryPlan<any, any, any, any, any, any, any, any, any>) as any,
31
+ Query.getAst(plan as Query.QueryPlan<any, any, any, any, any, any, any, any, any, any>) as any,
32
32
  state,
33
33
  postgresDialect
34
34
  )
@@ -0,0 +1,144 @@
1
+ import * as Table from "./table.js"
2
+ import type { AnyColumnDefinition } from "./column-state.js"
3
+ import { normalizeDdlExpressionSql } from "./schema-ddl.js"
4
+ import type { TableOptionSpec } from "./table-options.js"
5
+ import type { EnumDefinition } from "../postgres/schema-management.js"
6
+ import { EnumTypeId } from "../postgres/schema-management.js"
7
+
8
+ export interface EnumModel {
9
+ readonly kind: "enum"
10
+ readonly schemaName?: string
11
+ readonly name: string
12
+ readonly values: readonly string[]
13
+ }
14
+
15
+ export interface ColumnModel {
16
+ readonly name: string
17
+ readonly ddlType: string
18
+ readonly dbTypeKind: string
19
+ readonly typeKind?: string
20
+ readonly typeSchema?: string
21
+ readonly nullable: boolean
22
+ readonly hasDefault: boolean
23
+ readonly generated: boolean
24
+ readonly defaultSql?: string
25
+ readonly generatedSql?: string
26
+ readonly identity?: {
27
+ readonly generation: "always" | "byDefault"
28
+ }
29
+ readonly column?: AnyColumnDefinition
30
+ }
31
+
32
+ export interface TableModel {
33
+ readonly kind: "table"
34
+ readonly schemaName?: string
35
+ readonly name: string
36
+ readonly columns: readonly ColumnModel[]
37
+ readonly options: readonly TableOptionSpec[]
38
+ readonly table?: Table.AnyTable
39
+ }
40
+
41
+ export interface SchemaModel {
42
+ readonly dialect: "postgres"
43
+ readonly enums: readonly EnumModel[]
44
+ readonly tables: readonly TableModel[]
45
+ }
46
+
47
+ export const isTableDefinition = (value: unknown): value is Table.AnyTable =>
48
+ value !== null &&
49
+ (typeof value === "object" || typeof value === "function") &&
50
+ Table.TypeId in value
51
+
52
+ export const isEnumDefinition = (value: unknown): value is EnumDefinition =>
53
+ typeof value === "object" && value !== null && EnumTypeId in value
54
+
55
+ export const toTableModel = (table: Table.AnyTable): TableModel => {
56
+ const state = table[Table.TypeId]
57
+ const fields = state.fields as Record<string, AnyColumnDefinition>
58
+ const columns = Object.entries(fields).map(([name, column]) => {
59
+ const metadata = column.metadata
60
+ const enumDefinition = metadata.enum
61
+ const ddlType = metadata.ddlType ?? metadata.dbType.kind
62
+ return {
63
+ name,
64
+ ddlType,
65
+ dbTypeKind: enumDefinition?.name ?? column.metadata.dbType.kind,
66
+ typeKind: enumDefinition === undefined ? undefined : "e",
67
+ typeSchema: enumDefinition?.schemaName,
68
+ nullable: column.metadata.nullable,
69
+ hasDefault: column.metadata.hasDefault,
70
+ generated: column.metadata.generated,
71
+ defaultSql: column.metadata.defaultValue === undefined
72
+ ? undefined
73
+ : normalizeDdlExpressionSql(column.metadata.defaultValue),
74
+ generatedSql: column.metadata.generatedValue === undefined
75
+ ? undefined
76
+ : normalizeDdlExpressionSql(column.metadata.generatedValue),
77
+ identity: column.metadata.identity,
78
+ column
79
+ }
80
+ }) satisfies ReadonlyArray<ColumnModel>
81
+ return {
82
+ kind: "table",
83
+ schemaName: state.schemaName,
84
+ name: state.baseName,
85
+ columns,
86
+ options: table[Table.OptionsSymbol],
87
+ table
88
+ }
89
+ }
90
+
91
+ export const toEnumModel = (definition: EnumDefinition): EnumModel => ({
92
+ kind: "enum",
93
+ schemaName: definition.schemaName,
94
+ name: definition.name,
95
+ values: [...definition.values]
96
+ })
97
+
98
+ const enumModelsOfTable = (table: Table.AnyTable): readonly EnumModel[] => {
99
+ const state = table[Table.TypeId]
100
+ const fields = state.fields as Record<string, AnyColumnDefinition>
101
+ return Object.values(fields)
102
+ .flatMap((column) => column.metadata.enum === undefined
103
+ ? []
104
+ : [{
105
+ kind: "enum" as const,
106
+ schemaName: column.metadata.enum.schemaName,
107
+ name: column.metadata.enum.name,
108
+ values: [...column.metadata.enum.values]
109
+ } satisfies EnumModel
110
+ ])
111
+ }
112
+
113
+ export const fromDiscoveredValues = (values: ReadonlyArray<unknown>): SchemaModel => {
114
+ const tables = values.filter(isTableDefinition).map(toTableModel)
115
+ const enums = new Map<string, EnumModel>()
116
+ for (const value of values) {
117
+ if (isEnumDefinition(value)) {
118
+ enums.set(enumKey(value.schemaName, value.name), toEnumModel(value))
119
+ } else if (isTableDefinition(value)) {
120
+ for (const enumModel of enumModelsOfTable(value)) {
121
+ const key = enumKey(enumModel.schemaName, enumModel.name)
122
+ const existing = enums.get(key)
123
+ if (existing === undefined) {
124
+ enums.set(key, enumModel)
125
+ continue
126
+ }
127
+ if (JSON.stringify(existing.values) !== JSON.stringify(enumModel.values)) {
128
+ throw new Error(`Conflicting enum definitions discovered for '${key}'`)
129
+ }
130
+ }
131
+ }
132
+ }
133
+ return {
134
+ dialect: "postgres",
135
+ enums: [...enums.values()],
136
+ tables
137
+ }
138
+ }
139
+
140
+ export const tableKey = (schemaName: string | undefined, name: string): string =>
141
+ `${schemaName ?? "public"}.${name}`
142
+
143
+ export const enumKey = (schemaName: string | undefined, name: string): string =>
144
+ `${schemaName ?? "public"}.${name}`
@@ -36,6 +36,16 @@ type ContradictionFromNegation<
36
36
  Formula extends PredicateFormula
37
37
  > = IsContradiction<And<Assumptions, Not<Formula>>>
38
38
 
39
+ export type ContradictsFormula<
40
+ Assumptions extends PredicateFormula,
41
+ Formula extends PredicateFormula
42
+ > = ContradictoryAssumption<Assumptions, Formula>
43
+
44
+ export type ImpliesFormula<
45
+ Assumptions extends PredicateFormula,
46
+ Formula extends PredicateFormula
47
+ > = ContradictionFromNegation<Assumptions, Formula>
48
+
39
49
  export type AssumeFormulaTrue<
40
50
  Assumptions extends PredicateFormula,
41
51
  Formula extends PredicateFormula
@@ -7,6 +7,7 @@ export interface Context<
7
7
  NonNullKeys extends string = never,
8
8
  NullKeys extends string = never,
9
9
  EqLiterals = {},
10
+ NeqLiterals = {},
10
11
  SourceNames extends string = never,
11
12
  Contradiction extends boolean = false,
12
13
  Unknown extends boolean = false
@@ -14,13 +15,22 @@ export interface Context<
14
15
  readonly nonNullKeys: NonNullKeys
15
16
  readonly nullKeys: NullKeys
16
17
  readonly eqLiterals: EqLiterals
18
+ readonly neqLiterals: NeqLiterals
17
19
  readonly sourceNames: SourceNames
18
20
  readonly contradiction: Contradiction
19
21
  readonly unknown: Unknown
20
22
  }
21
23
 
22
24
  export type EmptyContext = Context
23
- type AnyContext = Context<string, string, Record<string, string>, string, boolean, boolean>
25
+ type AnyContext = Context<
26
+ string,
27
+ string,
28
+ Record<string, string>,
29
+ Record<string, string>,
30
+ string,
31
+ boolean,
32
+ boolean
33
+ >
24
34
 
25
35
  type Frame<
26
36
  Formula extends PredicateFormula = PredicateFormula,
@@ -41,6 +51,15 @@ type EqLiteralValueOf<
41
51
  : never
42
52
  : never
43
53
 
54
+ type NeqLiteralValuesOf<
55
+ NeqLiterals,
56
+ Key extends string
57
+ > = NeqLiterals extends Record<string, string>
58
+ ? Key extends keyof NeqLiterals
59
+ ? NeqLiterals[Key]
60
+ : never
61
+ : never
62
+
44
63
  type MergeEqLiteralMaps<Left, Right> = {
45
64
  readonly [K in Extract<keyof Left | keyof Right, string>]:
46
65
  K extends keyof Left
@@ -54,6 +73,17 @@ type MergeEqLiteralMaps<Left, Right> = {
54
73
  : never
55
74
  }
56
75
 
76
+ type MergeNeqLiteralMaps<Left, Right> = {
77
+ readonly [K in Extract<keyof Left | keyof Right, string>]:
78
+ K extends keyof Left
79
+ ? K extends keyof Right
80
+ ? Left[K] | Right[K]
81
+ : Left[K]
82
+ : K extends keyof Right
83
+ ? Right[K]
84
+ : never
85
+ }
86
+
57
87
  type FilterNeverValues<Map> = {
58
88
  readonly [K in keyof Map as Map[K] extends never ? never : K]: Map[K]
59
89
  }
@@ -62,6 +92,7 @@ type MarkContradiction<Ctx extends AnyContext> = Context<
62
92
  Ctx["nonNullKeys"],
63
93
  Ctx["nullKeys"],
64
94
  Ctx["eqLiterals"],
95
+ Ctx["neqLiterals"],
65
96
  Ctx["sourceNames"],
66
97
  true,
67
98
  Ctx["unknown"]
@@ -71,6 +102,7 @@ type MarkUnknown<Ctx extends AnyContext> = Context<
71
102
  Ctx["nonNullKeys"],
72
103
  Ctx["nullKeys"],
73
104
  Ctx["eqLiterals"],
105
+ Ctx["neqLiterals"],
74
106
  Ctx["sourceNames"],
75
107
  Ctx["contradiction"],
76
108
  true
@@ -83,6 +115,7 @@ type AddNonNull<
83
115
  Ctx["nonNullKeys"] | Key,
84
116
  Ctx["nullKeys"],
85
117
  Ctx["eqLiterals"],
118
+ Ctx["neqLiterals"],
86
119
  Ctx["sourceNames"] | SourceNameOfKey<Key>,
87
120
  Key extends Ctx["nullKeys"] ? true : Ctx["contradiction"],
88
121
  Ctx["unknown"]
@@ -95,6 +128,7 @@ type AddNull<
95
128
  Ctx["nonNullKeys"],
96
129
  Ctx["nullKeys"] | Key,
97
130
  Ctx["eqLiterals"],
131
+ Ctx["neqLiterals"],
98
132
  Ctx["sourceNames"] | SourceNameOfKey<Key>,
99
133
  Key extends Ctx["nonNullKeys"] ? true : Ctx["contradiction"],
100
134
  Ctx["unknown"]
@@ -108,11 +142,20 @@ type AddEqLiteral<
108
142
  Ctx["nonNullKeys"] | Key,
109
143
  Ctx["nullKeys"],
110
144
  FilterNeverValues<MergeEqLiteralMaps<Ctx["eqLiterals"], { readonly [K in Key]: Value }>>,
145
+ Ctx["neqLiterals"],
111
146
  Ctx["sourceNames"] | SourceNameOfKey<Key>,
112
147
  EqLiteralValueOf<Ctx["eqLiterals"], Key> extends never
113
- ? Key extends Ctx["nullKeys"] ? true : Ctx["contradiction"]
148
+ ? NeqLiteralValuesOf<Ctx["neqLiterals"], Key> extends infer NeqValues
149
+ ? Value extends NeqValues
150
+ ? true
151
+ : Key extends Ctx["nullKeys"] ? true : Ctx["contradiction"]
152
+ : true
114
153
  : EqLiteralValueOf<Ctx["eqLiterals"], Key> extends Value
115
- ? Key extends Ctx["nullKeys"] ? true : Ctx["contradiction"]
154
+ ? NeqLiteralValuesOf<Ctx["neqLiterals"], Key> extends infer NeqValues
155
+ ? Value extends NeqValues
156
+ ? true
157
+ : Key extends Ctx["nullKeys"] ? true : Ctx["contradiction"]
158
+ : true
116
159
  : true,
117
160
  Ctx["unknown"]
118
161
  >
@@ -120,8 +163,22 @@ type AddEqLiteral<
120
163
  type AddNeqLiteral<
121
164
  Ctx extends AnyContext,
122
165
  Key extends string,
123
- _Value extends string
124
- > = AddNonNull<Ctx, Key>
166
+ Value extends string
167
+ > = Context<
168
+ Ctx["nonNullKeys"] | Key,
169
+ Ctx["nullKeys"],
170
+ Ctx["eqLiterals"],
171
+ FilterNeverValues<MergeNeqLiteralMaps<Ctx["neqLiterals"], { readonly [K in Key]: Value }>>,
172
+ Ctx["sourceNames"] | SourceNameOfKey<Key>,
173
+ EqLiteralValueOf<Ctx["eqLiterals"], Key> extends infer EqValue
174
+ ? [EqValue] extends [never]
175
+ ? Key extends Ctx["nullKeys"] ? true : Ctx["contradiction"]
176
+ : EqValue extends Value
177
+ ? true
178
+ : Key extends Ctx["nullKeys"] ? true : Ctx["contradiction"]
179
+ : true,
180
+ Ctx["unknown"]
181
+ >
125
182
 
126
183
  type ApplyEqColumn<
127
184
  Ctx extends AnyContext,
@@ -177,7 +234,7 @@ type ApplyNegativeAtom<
177
234
  : Atom extends NonNullAtom<infer Key extends string>
178
235
  ? AddNull<Ctx, Key>
179
236
  : Atom extends EqLiteralAtom<infer Key extends string, infer Value extends string>
180
- ? AddNonNull<Ctx, Key>
237
+ ? AddNeqLiteral<Ctx, Key, Value>
181
238
  : Atom extends NeqLiteralAtom<infer Key extends string, infer Value extends string>
182
239
  ? AddEqLiteral<Ctx, Key, Value>
183
240
  : Atom extends EqColumnAtom<infer Left extends string, infer Right extends string>
@@ -189,12 +246,9 @@ type ApplyNegativeAtom<
189
246
  type FramesFromItems<
190
247
  Items extends readonly PredicateFormula[],
191
248
  Direction extends Polarity
192
- > = Items extends readonly [
193
- infer Head extends PredicateFormula,
194
- ...infer Tail extends readonly PredicateFormula[]
195
- ]
196
- ? readonly [Frame<Head, Direction>, ...FramesFromItems<Tail, Direction>]
197
- : readonly []
249
+ > = {
250
+ readonly [K in keyof Items]: Items[K] extends PredicateFormula ? Frame<Items[K], Direction> : never
251
+ } & readonly Frame[]
198
252
 
199
253
  type IntersectEqLiteralMaps<
200
254
  Left,
@@ -203,6 +257,14 @@ type IntersectEqLiteralMaps<
203
257
  readonly [K in Extract<keyof Left, keyof Right>]: Left[K] extends Right[K] ? Left[K] : never
204
258
  }>
205
259
 
260
+ type IntersectNeqLiteralMaps<
261
+ Left,
262
+ Right
263
+ > = FilterNeverValues<{
264
+ readonly [K in Extract<keyof Left, keyof Right>]:
265
+ Extract<Left[K], Right[K]> extends never ? never : Extract<Left[K], Right[K]>
266
+ }>
267
+
206
268
  type IntersectContexts<
207
269
  Left extends AnyContext,
208
270
  Right extends AnyContext
@@ -210,6 +272,7 @@ type IntersectContexts<
210
272
  Extract<Left["nonNullKeys"], Right["nonNullKeys"]>,
211
273
  Extract<Left["nullKeys"], Right["nullKeys"]>,
212
274
  IntersectEqLiteralMaps<Left["eqLiterals"], Right["eqLiterals"]>,
275
+ IntersectNeqLiteralMaps<Left["neqLiterals"], Right["neqLiterals"]>,
213
276
  Extract<Left["sourceNames"], Right["sourceNames"]>,
214
277
  Left["contradiction"] extends true
215
278
  ? Right["contradiction"]
@@ -228,7 +291,7 @@ type AnalyzeAnyBranches<
228
291
  infer Head extends PredicateFormula,
229
292
  ...infer Tail extends readonly PredicateFormula[]
230
293
  ]
231
- ? AnalyzeStack<Ctx, readonly [Frame<Head, Direction>]> extends infer Branch extends AnyContext
294
+ ? AnalyzeBranch<Ctx, Head, Direction> extends infer Branch extends AnyContext
232
295
  ? Branch["contradiction"] extends true
233
296
  ? AnalyzeAnyBranches<Ctx, Tail, Direction, Current>
234
297
  : [Current] extends [never]
@@ -241,6 +304,41 @@ type AnalyzeAnyBranches<
241
304
 
242
305
  type Flip<Direction extends Polarity> = Direction extends "positive" ? "negative" : "positive"
243
306
 
307
+ type AnalyzeBranch<
308
+ Ctx extends AnyContext,
309
+ Formula extends PredicateFormula,
310
+ Direction extends Polarity
311
+ > = AnalyzeStack<Ctx, readonly [Frame<Formula, Direction>]>
312
+
313
+ type AnalyzeFrame<
314
+ Ctx extends AnyContext,
315
+ Formula extends PredicateFormula,
316
+ Direction extends Polarity,
317
+ Tail extends readonly Frame[]
318
+ > = [Formula] extends [TrueFormula]
319
+ ? Direction extends "positive"
320
+ ? AnalyzeStack<Ctx, Tail>
321
+ : MarkContradiction<Ctx>
322
+ : [Formula] extends [FalseFormula]
323
+ ? Direction extends "positive"
324
+ ? MarkContradiction<Ctx>
325
+ : AnalyzeStack<Ctx, Tail>
326
+ : [Formula] extends [AtomFormula<infer Atom extends PredicateAtom>]
327
+ ? Direction extends "positive"
328
+ ? AnalyzeStack<ApplyAtom<Ctx, Atom>, Tail>
329
+ : AnalyzeStack<ApplyNegativeAtom<Ctx, Atom>, Tail>
330
+ : [Formula] extends [NotFormula<infer Item extends PredicateFormula>]
331
+ ? AnalyzeStack<Ctx, readonly [Frame<Item, Flip<Direction>>, ...Tail]>
332
+ : [Formula] extends [AllFormula<infer Items extends readonly PredicateFormula[]>]
333
+ ? Direction extends "positive"
334
+ ? AnalyzeStack<Ctx, readonly [...FramesFromItems<Items, "positive">, ...Tail]>
335
+ : AnalyzeStack<AnalyzeAnyBranches<Ctx, Items, "negative">, Tail>
336
+ : [Formula] extends [AnyFormula<infer Items extends readonly PredicateFormula[]>]
337
+ ? Direction extends "positive"
338
+ ? AnalyzeStack<AnalyzeAnyBranches<Ctx, Items, "positive">, Tail>
339
+ : AnalyzeStack<Ctx, readonly [...FramesFromItems<Items, "negative">, ...Tail]>
340
+ : AnalyzeStack<MarkUnknown<Ctx>, Tail>
341
+
244
342
  export type AnalyzeStack<
245
343
  Ctx extends AnyContext,
246
344
  Stack extends readonly Frame[]
@@ -250,29 +348,7 @@ export type AnalyzeStack<
250
348
  infer Head extends Frame,
251
349
  ...infer Tail extends readonly Frame[]
252
350
  ]
253
- ? Head["formula"] extends TrueFormula
254
- ? Head["polarity"] extends "positive"
255
- ? AnalyzeStack<Ctx, Tail>
256
- : MarkContradiction<Ctx>
257
- : Head["formula"] extends FalseFormula
258
- ? Head["polarity"] extends "positive"
259
- ? MarkContradiction<Ctx>
260
- : AnalyzeStack<Ctx, Tail>
261
- : Head["formula"] extends AtomFormula<infer Atom extends PredicateAtom>
262
- ? Head["polarity"] extends "positive"
263
- ? AnalyzeStack<ApplyAtom<Ctx, Atom>, Tail>
264
- : AnalyzeStack<ApplyNegativeAtom<Ctx, Atom>, Tail>
265
- : Head["formula"] extends NotFormula<infer Item extends PredicateFormula>
266
- ? AnalyzeStack<Ctx, readonly [Frame<Item, Flip<Head["polarity"]>>, ...Tail]>
267
- : Head["formula"] extends AllFormula<infer Items extends readonly PredicateFormula[]>
268
- ? Head["polarity"] extends "positive"
269
- ? AnalyzeStack<Ctx, readonly [...FramesFromItems<Items, "positive">, ...Tail]>
270
- : AnalyzeStack<AnalyzeAnyBranches<Ctx, Items, "negative">, Tail>
271
- : Head["formula"] extends AnyFormula<infer Items extends readonly PredicateFormula[]>
272
- ? Head["polarity"] extends "positive"
273
- ? AnalyzeStack<AnalyzeAnyBranches<Ctx, Items, "positive">, Tail>
274
- : AnalyzeStack<Ctx, readonly [...FramesFromItems<Items, "negative">, ...Tail]>
275
- : AnalyzeStack<MarkUnknown<Ctx>, Tail>
351
+ ? AnalyzeFrame<Ctx, Head["formula"], Head["polarity"], Tail>
276
352
  : Ctx
277
353
 
278
354
  export type AnalyzeFormula<Formula extends PredicateFormula> =
@@ -62,27 +62,39 @@ type NormalizeAnyItems<
62
62
  : NormalizeAnyItems<Tail, [...Current, Head]>
63
63
  : Current
64
64
 
65
- export type NormalizeBooleanConstants<Formula extends PredicateFormula> =
66
- Formula extends AllFormula<infer Items extends readonly PredicateFormula[]>
67
- ? NormalizeAllItems<Items> extends [FalseFormula]
65
+ type CollapseNormalizedAll<
66
+ Items extends readonly PredicateFormula[]
67
+ > = NormalizeAllItems<Items> extends infer Normalized extends readonly PredicateFormula[]
68
+ ? [Normalized] extends [readonly [FalseFormula]]
69
+ ? FalseFormula
70
+ : [Normalized] extends [readonly []]
71
+ ? TrueFormula
72
+ : [Normalized] extends [readonly [infer Only extends PredicateFormula]]
73
+ ? Only
74
+ : AllFormula<Normalized>
75
+ : never
76
+
77
+ type CollapseNormalizedAny<
78
+ Items extends readonly PredicateFormula[]
79
+ > = NormalizeAnyItems<Items> extends infer Normalized extends readonly PredicateFormula[]
80
+ ? [Normalized] extends [readonly [TrueFormula]]
81
+ ? TrueFormula
82
+ : [Normalized] extends [readonly []]
68
83
  ? FalseFormula
69
- : NormalizeAllItems<Items> extends readonly []
70
- ? TrueFormula
71
- : NormalizeAllItems<Items> extends readonly [infer Only extends PredicateFormula]
72
- ? Only
73
- : AllFormula<NormalizeAllItems<Items>>
74
- : Formula extends AnyFormula<infer Items extends readonly PredicateFormula[]>
75
- ? NormalizeAnyItems<Items> extends [TrueFormula]
76
- ? TrueFormula
77
- : NormalizeAnyItems<Items> extends readonly []
78
- ? FalseFormula
79
- : NormalizeAnyItems<Items> extends readonly [infer Only extends PredicateFormula]
80
- ? Only
81
- : AnyFormula<NormalizeAnyItems<Items>>
82
- : Formula extends NotFormula<infer Item extends PredicateFormula>
83
- ? Item extends TrueFormula
84
+ : [Normalized] extends [readonly [infer Only extends PredicateFormula]]
85
+ ? Only
86
+ : AnyFormula<Normalized>
87
+ : never
88
+
89
+ export type NormalizeBooleanConstants<Formula extends PredicateFormula> =
90
+ [Formula] extends [AllFormula<infer Items extends readonly PredicateFormula[]>]
91
+ ? CollapseNormalizedAll<Items>
92
+ : [Formula] extends [AnyFormula<infer Items extends readonly PredicateFormula[]>]
93
+ ? CollapseNormalizedAny<Items>
94
+ : [Formula] extends [NotFormula<infer Item extends PredicateFormula>]
95
+ ? [Item] extends [TrueFormula]
84
96
  ? FalseFormula
85
- : Item extends FalseFormula
97
+ : [Item] extends [FalseFormula]
86
98
  ? TrueFormula
87
99
  : Formula
88
100
  : Formula