typesea 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.
Files changed (285) hide show
  1. package/CHANGELOG.md +67 -6
  2. package/README.md +98 -17
  3. package/dist/adapters/index.d.ts +50 -8
  4. package/dist/adapters/index.d.ts.map +1 -1
  5. package/dist/adapters/index.js +169 -48
  6. package/dist/aot/index.d.ts +18 -2
  7. package/dist/aot/index.d.ts.map +1 -1
  8. package/dist/aot/index.js +93 -14
  9. package/dist/async/index.d.ts +28 -56
  10. package/dist/async/index.d.ts.map +1 -1
  11. package/dist/async/index.js +94 -37
  12. package/dist/builders/composite.d.ts +37 -6
  13. package/dist/builders/composite.d.ts.map +1 -1
  14. package/dist/builders/composite.js +84 -10
  15. package/dist/builders/index.d.ts +2 -0
  16. package/dist/builders/index.d.ts.map +1 -1
  17. package/dist/builders/index.js +2 -0
  18. package/dist/builders/modifier.d.ts +30 -5
  19. package/dist/builders/modifier.d.ts.map +1 -1
  20. package/dist/builders/modifier.js +38 -5
  21. package/dist/builders/object/guard.d.ts +18 -22
  22. package/dist/builders/object/guard.d.ts.map +1 -1
  23. package/dist/builders/object/guard.js +26 -26
  24. package/dist/builders/object/index.d.ts +2 -0
  25. package/dist/builders/object/index.d.ts.map +1 -1
  26. package/dist/builders/object/index.js +2 -0
  27. package/dist/builders/object/schema.d.ts +55 -9
  28. package/dist/builders/object/schema.d.ts.map +1 -1
  29. package/dist/builders/object/schema.js +92 -15
  30. package/dist/builders/object/types.d.ts +5 -31
  31. package/dist/builders/object/types.d.ts.map +1 -1
  32. package/dist/builders/object/types.js +2 -0
  33. package/dist/builders/scalar.d.ts +29 -8
  34. package/dist/builders/scalar.d.ts.map +1 -1
  35. package/dist/builders/scalar.js +33 -8
  36. package/dist/builders/table.d.ts +4 -0
  37. package/dist/builders/table.d.ts.map +1 -1
  38. package/dist/builders/table.js +4 -0
  39. package/dist/builders/types.d.ts +14 -4
  40. package/dist/builders/types.d.ts.map +1 -1
  41. package/dist/builders/types.js +2 -0
  42. package/dist/compile/check-composite.d.ts +22 -1
  43. package/dist/compile/check-composite.d.ts.map +1 -1
  44. package/dist/compile/check-composite.js +564 -24
  45. package/dist/compile/check-scalar.d.ts +78 -0
  46. package/dist/compile/check-scalar.d.ts.map +1 -1
  47. package/dist/compile/check-scalar.js +432 -1
  48. package/dist/compile/check.d.ts +12 -0
  49. package/dist/compile/check.d.ts.map +1 -1
  50. package/dist/compile/check.js +37 -0
  51. package/dist/compile/context.d.ts +47 -9
  52. package/dist/compile/context.d.ts.map +1 -1
  53. package/dist/compile/context.js +51 -8
  54. package/dist/compile/graph-predicate.d.ts +4 -2
  55. package/dist/compile/graph-predicate.d.ts.map +1 -1
  56. package/dist/compile/graph-predicate.js +1907 -171
  57. package/dist/compile/guard.d.ts +15 -24
  58. package/dist/compile/guard.d.ts.map +1 -1
  59. package/dist/compile/guard.js +158 -74
  60. package/dist/compile/index.d.ts +3 -1
  61. package/dist/compile/index.d.ts.map +1 -1
  62. package/dist/compile/index.js +2 -0
  63. package/dist/compile/issue.d.ts +110 -0
  64. package/dist/compile/issue.d.ts.map +1 -1
  65. package/dist/compile/issue.js +184 -1
  66. package/dist/compile/names.d.ts +12 -2
  67. package/dist/compile/names.d.ts.map +1 -1
  68. package/dist/compile/names.js +19 -3
  69. package/dist/compile/predicate.d.ts +24 -0
  70. package/dist/compile/predicate.d.ts.map +1 -1
  71. package/dist/compile/predicate.js +131 -5
  72. package/dist/compile/runtime.d.ts +80 -12
  73. package/dist/compile/runtime.d.ts.map +1 -1
  74. package/dist/compile/runtime.js +25 -6
  75. package/dist/compile/source.d.ts +10 -2
  76. package/dist/compile/source.d.ts.map +1 -1
  77. package/dist/compile/source.js +361 -26
  78. package/dist/compile/types.d.ts +20 -0
  79. package/dist/compile/types.d.ts.map +1 -1
  80. package/dist/compile/types.js +2 -0
  81. package/dist/decoder/index.d.ts +32 -46
  82. package/dist/decoder/index.d.ts.map +1 -1
  83. package/dist/decoder/index.js +102 -38
  84. package/dist/evaluate/check-composite.d.ts +59 -0
  85. package/dist/evaluate/check-composite.d.ts.map +1 -1
  86. package/dist/evaluate/check-composite.js +151 -3
  87. package/dist/evaluate/check-scalar.d.ts +16 -0
  88. package/dist/evaluate/check-scalar.d.ts.map +1 -1
  89. package/dist/evaluate/check-scalar.js +32 -0
  90. package/dist/evaluate/check.d.ts +7 -0
  91. package/dist/evaluate/check.d.ts.map +1 -1
  92. package/dist/evaluate/check.js +43 -0
  93. package/dist/evaluate/index.d.ts +2 -0
  94. package/dist/evaluate/index.d.ts.map +1 -1
  95. package/dist/evaluate/index.js +2 -0
  96. package/dist/evaluate/issue.d.ts +11 -1
  97. package/dist/evaluate/issue.d.ts.map +1 -1
  98. package/dist/evaluate/issue.js +15 -1
  99. package/dist/evaluate/predicate.d.ts +16 -5
  100. package/dist/evaluate/predicate.d.ts.map +1 -1
  101. package/dist/evaluate/predicate.js +20 -5
  102. package/dist/evaluate/shared.d.ts +59 -13
  103. package/dist/evaluate/shared.d.ts.map +1 -1
  104. package/dist/evaluate/shared.js +66 -8
  105. package/dist/evaluate/state.d.ts +35 -13
  106. package/dist/evaluate/state.d.ts.map +1 -1
  107. package/dist/evaluate/state.js +35 -2
  108. package/dist/guard/base.d.ts +79 -29
  109. package/dist/guard/base.d.ts.map +1 -1
  110. package/dist/guard/base.js +91 -29
  111. package/dist/guard/error.d.ts +10 -5
  112. package/dist/guard/error.d.ts.map +1 -1
  113. package/dist/guard/error.js +10 -5
  114. package/dist/guard/index.d.ts +2 -0
  115. package/dist/guard/index.d.ts.map +1 -1
  116. package/dist/guard/index.js +2 -0
  117. package/dist/guard/number.d.ts +26 -11
  118. package/dist/guard/number.d.ts.map +1 -1
  119. package/dist/guard/number.js +30 -11
  120. package/dist/guard/props.d.ts +27 -3
  121. package/dist/guard/props.d.ts.map +1 -1
  122. package/dist/guard/props.js +27 -3
  123. package/dist/guard/read.d.ts +62 -9
  124. package/dist/guard/read.d.ts.map +1 -1
  125. package/dist/guard/read.js +83 -10
  126. package/dist/guard/registry.d.ts +12 -2
  127. package/dist/guard/registry.d.ts.map +1 -1
  128. package/dist/guard/registry.js +15 -3
  129. package/dist/guard/string.d.ts +33 -13
  130. package/dist/guard/string.d.ts.map +1 -1
  131. package/dist/guard/string.js +37 -13
  132. package/dist/guard/types.d.ts +92 -40
  133. package/dist/guard/types.d.ts.map +1 -1
  134. package/dist/guard/types.js +2 -0
  135. package/dist/index.d.ts +1 -1
  136. package/dist/index.d.ts.map +1 -1
  137. package/dist/internal/index.d.ts +42 -6
  138. package/dist/internal/index.d.ts.map +1 -1
  139. package/dist/internal/index.js +51 -8
  140. package/dist/ir/builder.d.ts +16 -126
  141. package/dist/ir/builder.d.ts.map +1 -1
  142. package/dist/ir/builder.js +77 -137
  143. package/dist/ir/freeze.d.ts +4 -0
  144. package/dist/ir/freeze.d.ts.map +1 -1
  145. package/dist/ir/freeze.js +59 -0
  146. package/dist/ir/index.d.ts +3 -1
  147. package/dist/ir/index.d.ts.map +1 -1
  148. package/dist/ir/index.js +2 -0
  149. package/dist/ir/regexp.d.ts +2 -0
  150. package/dist/ir/regexp.d.ts.map +1 -1
  151. package/dist/ir/regexp.js +2 -0
  152. package/dist/ir/types.d.ts +90 -55
  153. package/dist/ir/types.d.ts.map +1 -1
  154. package/dist/ir/types.js +2 -0
  155. package/dist/ir/validate.d.ts +8 -1
  156. package/dist/ir/validate.d.ts.map +1 -1
  157. package/dist/ir/validate.js +477 -61
  158. package/dist/issue/index.d.ts +41 -9
  159. package/dist/issue/index.d.ts.map +1 -1
  160. package/dist/issue/index.js +61 -11
  161. package/dist/json-schema/emit-combinator.d.ts +44 -4
  162. package/dist/json-schema/emit-combinator.d.ts.map +1 -1
  163. package/dist/json-schema/emit-combinator.js +44 -4
  164. package/dist/json-schema/emit-composite.d.ts +10 -0
  165. package/dist/json-schema/emit-composite.d.ts.map +1 -1
  166. package/dist/json-schema/emit-composite.js +15 -1
  167. package/dist/json-schema/emit-scalar.d.ts +26 -3
  168. package/dist/json-schema/emit-scalar.d.ts.map +1 -1
  169. package/dist/json-schema/emit-scalar.js +70 -9
  170. package/dist/json-schema/emit-types.d.ts +11 -1
  171. package/dist/json-schema/emit-types.d.ts.map +1 -1
  172. package/dist/json-schema/emit-types.js +2 -0
  173. package/dist/json-schema/emit.d.ts +12 -1
  174. package/dist/json-schema/emit.d.ts.map +1 -1
  175. package/dist/json-schema/emit.js +12 -1
  176. package/dist/json-schema/freeze.d.ts +13 -2
  177. package/dist/json-schema/freeze.d.ts.map +1 -1
  178. package/dist/json-schema/freeze.js +41 -8
  179. package/dist/json-schema/index.d.ts +16 -2
  180. package/dist/json-schema/index.d.ts.map +1 -1
  181. package/dist/json-schema/index.js +23 -3
  182. package/dist/json-schema/issue.d.ts +4 -1
  183. package/dist/json-schema/issue.d.ts.map +1 -1
  184. package/dist/json-schema/issue.js +4 -1
  185. package/dist/json-schema/read.d.ts +24 -3
  186. package/dist/json-schema/read.d.ts.map +1 -1
  187. package/dist/json-schema/read.js +59 -12
  188. package/dist/json-schema/types.d.ts +38 -15
  189. package/dist/json-schema/types.d.ts.map +1 -1
  190. package/dist/json-schema/types.js +2 -0
  191. package/dist/kind/index.d.ts +15 -28
  192. package/dist/kind/index.d.ts.map +1 -1
  193. package/dist/kind/index.js +15 -10
  194. package/dist/lower/index.d.ts +6 -1
  195. package/dist/lower/index.d.ts.map +1 -1
  196. package/dist/lower/index.js +411 -44
  197. package/dist/message/index.d.ts +46 -10
  198. package/dist/message/index.d.ts.map +1 -1
  199. package/dist/message/index.js +88 -17
  200. package/dist/optimize/algebraic.d.ts +54 -0
  201. package/dist/optimize/algebraic.d.ts.map +1 -0
  202. package/dist/optimize/algebraic.js +314 -0
  203. package/dist/optimize/compact.d.ts +8 -1
  204. package/dist/optimize/compact.d.ts.map +1 -1
  205. package/dist/optimize/compact.js +13 -2
  206. package/dist/optimize/domain.d.ts +16 -0
  207. package/dist/optimize/domain.d.ts.map +1 -0
  208. package/dist/optimize/domain.js +615 -0
  209. package/dist/optimize/fold-boolean.d.ts +17 -2
  210. package/dist/optimize/fold-boolean.d.ts.map +1 -1
  211. package/dist/optimize/fold-boolean.js +59 -14
  212. package/dist/optimize/fold-common.d.ts +43 -8
  213. package/dist/optimize/fold-common.d.ts.map +1 -1
  214. package/dist/optimize/fold-common.js +37 -6
  215. package/dist/optimize/fold-constraints.d.ts +33 -0
  216. package/dist/optimize/fold-constraints.d.ts.map +1 -0
  217. package/dist/optimize/fold-constraints.js +484 -0
  218. package/dist/optimize/fold-scalar.d.ts +98 -13
  219. package/dist/optimize/fold-scalar.d.ts.map +1 -1
  220. package/dist/optimize/fold-scalar.js +98 -13
  221. package/dist/optimize/fold.d.ts +8 -1
  222. package/dist/optimize/fold.d.ts.map +1 -1
  223. package/dist/optimize/fold.js +22 -2
  224. package/dist/optimize/index.d.ts +9 -1
  225. package/dist/optimize/index.d.ts.map +1 -1
  226. package/dist/optimize/index.js +18 -3
  227. package/dist/optimize/map-node.d.ts +3 -1
  228. package/dist/optimize/map-node.d.ts.map +1 -1
  229. package/dist/optimize/map-node.js +45 -3
  230. package/dist/optimize/peephole.d.ts +16 -0
  231. package/dist/optimize/peephole.d.ts.map +1 -0
  232. package/dist/optimize/peephole.js +254 -0
  233. package/dist/optimize/remap.d.ts +2 -0
  234. package/dist/optimize/remap.d.ts.map +1 -1
  235. package/dist/optimize/remap.js +2 -0
  236. package/dist/optimize/rewrite.d.ts +13 -8
  237. package/dist/optimize/rewrite.d.ts.map +1 -1
  238. package/dist/optimize/rewrite.js +13 -8
  239. package/dist/plan/cache.d.ts +9 -3
  240. package/dist/plan/cache.d.ts.map +1 -1
  241. package/dist/plan/cache.js +21 -5
  242. package/dist/plan/index.d.ts +2 -0
  243. package/dist/plan/index.d.ts.map +1 -1
  244. package/dist/plan/index.js +2 -0
  245. package/dist/plan/predicate.d.ts +2 -0
  246. package/dist/plan/predicate.d.ts.map +1 -1
  247. package/dist/plan/predicate.js +268 -29
  248. package/dist/plan/schema-predicate.d.ts +6 -0
  249. package/dist/plan/schema-predicate.d.ts.map +1 -1
  250. package/dist/plan/schema-predicate.js +117 -13
  251. package/dist/plan/types.d.ts +2 -0
  252. package/dist/plan/types.d.ts.map +1 -1
  253. package/dist/plan/types.js +2 -0
  254. package/dist/result/index.d.ts +19 -5
  255. package/dist/result/index.d.ts.map +1 -1
  256. package/dist/result/index.js +10 -2
  257. package/dist/schema/common.d.ts +69 -6
  258. package/dist/schema/common.d.ts.map +1 -1
  259. package/dist/schema/common.js +104 -10
  260. package/dist/schema/freeze.d.ts +4 -0
  261. package/dist/schema/freeze.d.ts.map +1 -1
  262. package/dist/schema/freeze.js +18 -0
  263. package/dist/schema/index.d.ts +3 -0
  264. package/dist/schema/index.d.ts.map +1 -1
  265. package/dist/schema/index.js +3 -0
  266. package/dist/schema/lazy.d.ts +4 -0
  267. package/dist/schema/lazy.d.ts.map +1 -1
  268. package/dist/schema/lazy.js +4 -0
  269. package/dist/schema/literal.d.ts +7 -1
  270. package/dist/schema/literal.d.ts.map +1 -1
  271. package/dist/schema/literal.js +7 -1
  272. package/dist/schema/types.d.ts +20 -96
  273. package/dist/schema/types.d.ts.map +1 -1
  274. package/dist/schema/types.js +5 -1
  275. package/dist/schema/undefined.d.ts +17 -0
  276. package/dist/schema/undefined.d.ts.map +1 -0
  277. package/dist/schema/undefined.js +72 -0
  278. package/dist/schema/validate.d.ts +8 -1
  279. package/dist/schema/validate.d.ts.map +1 -1
  280. package/dist/schema/validate.js +146 -55
  281. package/docs/api.md +57 -0
  282. package/docs/assets/benchmark-headline.svg +163 -0
  283. package/docs/engine-notes.md +58 -15
  284. package/docs/index.html +130 -110
  285. package/package.json +65 -65
@@ -0,0 +1,615 @@
1
+ /**
2
+ * @file domain.ts
3
+ * @brief Validation-domain specialization for dispatch child graphs.
4
+ * @details Optimizer helpers preserve graph equivalence while shrinking redundant nodes
5
+ * before code generation consumes the graph.
6
+ */
7
+ import { NodeTag } from "../kind/index.js";
8
+ import { compactReachable } from "./compact.js";
9
+ import { peepholeGraph } from "./peephole.js";
10
+ import { foldConstants } from "./fold.js";
11
+ import { ensureConst, keep, replace } from "./fold-common.js";
12
+ import { resolveAlias, rewriteNodeDeps } from "./rewrite.js";
13
+ const DomainMask = {
14
+ String: 1 << 0,
15
+ Number: 1 << 1,
16
+ Boolean: 1 << 2,
17
+ BigInt: 1 << 3,
18
+ Symbol: 1 << 4,
19
+ Undefined: 1 << 5,
20
+ Null: 1 << 6,
21
+ Array: 1 << 7,
22
+ Object: 1 << 8,
23
+ Function: 1 << 9
24
+ };
25
+ /**
26
+ * @brief Specialize nested validation graphs with domain knowledge.
27
+ * @details Dispatch nodes already know the primitive domain of each child arm.
28
+ * This pass pushes that fact into child graphs so redundant type checks collapse.
29
+ * @param graph Root graph to specialize.
30
+ * @returns The original graph when no node changed, otherwise a rewritten graph.
31
+ */
32
+ export function specializeDomains(graph) {
33
+ let changed = false;
34
+ const nodes = new Array(graph.nodes.length);
35
+ for (let index = 0; index < graph.nodes.length; index += 1) {
36
+ const node = graph.nodes[index];
37
+ if (node === undefined) {
38
+ continue;
39
+ }
40
+ const specialized = specializeChildDomains(node, graph.nodes);
41
+ nodes[index] = specialized;
42
+ changed = changed || specialized !== node;
43
+ }
44
+ if (!changed) {
45
+ return graph;
46
+ }
47
+ return {
48
+ nodes,
49
+ entry: graph.entry,
50
+ result: graph.result
51
+ };
52
+ }
53
+ /**
54
+ * @brief Execute specialize child domains.
55
+ * @details Optimizer helpers preserve graph equivalence while reducing redundant validation work.
56
+ */
57
+ function specializeChildDomains(node, nodes) {
58
+ switch (node.tag) {
59
+ case NodeTag.And:
60
+ return specializeIterationDomains(node, nodes);
61
+ case NodeTag.ArrayEvery: {
62
+ const itemGraph = specializeDomains(node.itemGraph);
63
+ if (itemGraph === node.itemGraph) {
64
+ return node;
65
+ }
66
+ return {
67
+ ...node,
68
+ itemGraph
69
+ };
70
+ }
71
+ case NodeTag.TupleItems: {
72
+ const itemGraphs = specializeGraphArray(node.itemGraphs);
73
+ if (itemGraphs === node.itemGraphs) {
74
+ return node;
75
+ }
76
+ return {
77
+ ...node,
78
+ itemGraphs
79
+ };
80
+ }
81
+ case NodeTag.RecordEvery: {
82
+ const itemGraph = specializeDomains(node.itemGraph);
83
+ if (itemGraph === node.itemGraph) {
84
+ return node;
85
+ }
86
+ return {
87
+ ...node,
88
+ itemGraph
89
+ };
90
+ }
91
+ case NodeTag.DiscriminantDispatch: {
92
+ const graphs = specializeGraphArray(node.graphs);
93
+ if (graphs === node.graphs) {
94
+ return node;
95
+ }
96
+ return {
97
+ ...node,
98
+ graphs
99
+ };
100
+ }
101
+ case NodeTag.ObjectShape: {
102
+ const entries = specializeObjectShapeEntries(node.entries);
103
+ if (entries === node.entries) {
104
+ return node;
105
+ }
106
+ return {
107
+ ...node,
108
+ entries
109
+ };
110
+ }
111
+ case NodeTag.UnionDispatch: {
112
+ const graphs = specializeGraphsForMasks(node.graphs, node.masks);
113
+ if (graphs === node.graphs) {
114
+ return node;
115
+ }
116
+ return {
117
+ ...node,
118
+ graphs
119
+ };
120
+ }
121
+ case NodeTag.PrimitiveUnion: {
122
+ const graphs = specializeGraphsForMasks(node.graphs, node.masks);
123
+ if (graphs === node.graphs) {
124
+ return node;
125
+ }
126
+ return {
127
+ ...node,
128
+ graphs
129
+ };
130
+ }
131
+ default:
132
+ return node;
133
+ }
134
+ }
135
+ /**
136
+ * @brief Remove container guards already proven by iteration nodes.
137
+ * @details `ArrayEvery(x)` implies `IsArray(x)` and `RecordEvery(x)` implies
138
+ * `IsObject(x)`. Removing the sibling guard keeps the IR closer to the code
139
+ * that will be emitted.
140
+ * @param node Boolean fold node whose operands may contain container domains.
141
+ * @param nodes Graph node table used to inspect operands.
142
+ * @returns Rewritten boolean node, or the original node when nothing changed.
143
+ */
144
+ function specializeIterationDomains(node, nodes) {
145
+ const domains = collectIterationDomains(node.values, nodes);
146
+ if (domains.length === 0) {
147
+ return node;
148
+ }
149
+ let changed = false;
150
+ const values = [];
151
+ for (let index = 0; index < node.values.length; index += 1) {
152
+ const value = node.values[index];
153
+ if (value === undefined) {
154
+ changed = true;
155
+ continue;
156
+ }
157
+ if (isIterationDomainGuard(value, nodes, domains)) {
158
+ /*
159
+ * The iterator node performs the same container guard before it can
160
+ * enter its child graph, so keeping this sibling check is redundant.
161
+ */
162
+ changed = true;
163
+ continue;
164
+ }
165
+ values.push(value);
166
+ }
167
+ if (!changed) {
168
+ return node;
169
+ }
170
+ return {
171
+ id: node.id,
172
+ tag: node.tag,
173
+ deps: values,
174
+ values
175
+ };
176
+ }
177
+ /**
178
+ * @brief Collect domains implied by iteration nodes inside one boolean fold.
179
+ * @details Optimizer helpers preserve graph equivalence while shrinking redundant nodes
180
+ * before code generation consumes the graph.
181
+ * @param values Operand ids from an And/Or-like fold.
182
+ * @param nodes Graph node table used to inspect operands.
183
+ * @returns Iteration domains visible from the operand list.
184
+ */
185
+ function collectIterationDomains(values, nodes) {
186
+ const domains = [];
187
+ for (let index = 0; index < values.length; index += 1) {
188
+ const value = values[index];
189
+ if (value === undefined) {
190
+ continue;
191
+ }
192
+ const node = nodes[value];
193
+ if (node === undefined) {
194
+ continue;
195
+ }
196
+ const domain = readIterationDomain(node);
197
+ if (domain !== undefined) {
198
+ domains.push(domain);
199
+ }
200
+ }
201
+ return domains;
202
+ }
203
+ /**
204
+ * @brief Test whether a boolean operand is redundant due to an iteration domain.
205
+ * @details Optimizer helpers preserve graph equivalence while shrinking redundant nodes
206
+ * before code generation consumes the graph.
207
+ * @param value Candidate guard node id.
208
+ * @param nodes Graph node table used to inspect the candidate.
209
+ * @param domains Domains collected from sibling iteration nodes.
210
+ * @returns True when the candidate guard repeats a sibling iterator guard.
211
+ */
212
+ function isIterationDomainGuard(value, nodes, domains) {
213
+ const node = nodes[value];
214
+ if (node === undefined || !isContainerGuardNode(node)) {
215
+ return false;
216
+ }
217
+ for (let index = 0; index < domains.length; index += 1) {
218
+ const domain = domains[index];
219
+ if (domain?.guard === node.tag && domain.value === node.value) {
220
+ return true;
221
+ }
222
+ }
223
+ return false;
224
+ }
225
+ /**
226
+ * @brief Read the guard implied by an iteration node.
227
+ * @details Optimizer helpers preserve graph equivalence while shrinking redundant nodes
228
+ * before code generation consumes the graph.
229
+ * @param node Candidate graph node.
230
+ * @returns Array/Object guard implied by the node, or undefined.
231
+ */
232
+ function readIterationDomain(node) {
233
+ switch (node.tag) {
234
+ case NodeTag.ArrayEvery:
235
+ case NodeTag.TupleItems:
236
+ return {
237
+ value: node.value,
238
+ guard: NodeTag.IsArray
239
+ };
240
+ case NodeTag.RecordEvery:
241
+ return {
242
+ value: node.value,
243
+ guard: NodeTag.IsObject
244
+ };
245
+ default:
246
+ return undefined;
247
+ }
248
+ }
249
+ /**
250
+ * @brief Test whether a node is a plain container guard over one value edge.
251
+ * @details Optimizer helpers preserve graph equivalence while shrinking redundant nodes
252
+ * before code generation consumes the graph.
253
+ * @param node Candidate graph node.
254
+ * @returns True for array/object guard nodes.
255
+ */
256
+ function isContainerGuardNode(node) {
257
+ return node.tag === NodeTag.IsArray || node.tag === NodeTag.IsObject;
258
+ }
259
+ /**
260
+ * @brief Recursively specialize every graph in a closed graph list.
261
+ * @details Optimizer helpers preserve graph equivalence while shrinking redundant nodes
262
+ * before code generation consumes the graph.
263
+ * @param graphs Child graph list.
264
+ * @returns Original list when no child changed, otherwise a rewritten list.
265
+ */
266
+ function specializeGraphArray(graphs) {
267
+ let changed = false;
268
+ const specialized = new Array(graphs.length);
269
+ for (let index = 0; index < graphs.length; index += 1) {
270
+ const graph = graphs[index];
271
+ if (graph === undefined) {
272
+ continue;
273
+ }
274
+ const next = specializeDomains(graph);
275
+ specialized[index] = next;
276
+ changed = changed || next !== graph;
277
+ }
278
+ return changed ? specialized : graphs;
279
+ }
280
+ /**
281
+ * @brief Specialize child graphs using the dispatch mask assigned to each arm.
282
+ * @details Optimizer helpers preserve graph equivalence while shrinking redundant nodes
283
+ * before code generation consumes the graph.
284
+ * @param graphs Child graph list.
285
+ * @param masks Primitive-domain mask per graph.
286
+ * @returns Original list when no child changed, otherwise a rewritten list.
287
+ */
288
+ function specializeGraphsForMasks(graphs, masks) {
289
+ let changed = false;
290
+ const specialized = new Array(graphs.length);
291
+ for (let index = 0; index < graphs.length; index += 1) {
292
+ const graph = graphs[index];
293
+ const mask = masks[index];
294
+ if (graph === undefined || mask === undefined) {
295
+ continue;
296
+ }
297
+ /*
298
+ * Domain specialization can expose constants, so run the light cleanup
299
+ * stack immediately before the child graph is stored back.
300
+ */
301
+ const child = optimizeGraphForMask(specializeDomains(graph), mask);
302
+ specialized[index] = child;
303
+ changed = changed || child !== graph;
304
+ }
305
+ return changed ? specialized : graphs;
306
+ }
307
+ /**
308
+ * @brief Specialize object-shape entry graphs without touching entry metadata.
309
+ * @details Optimizer helpers preserve graph equivalence while shrinking redundant nodes
310
+ * before code generation consumes the graph.
311
+ * @param entries Object-shape entries.
312
+ * @returns Original entry list when no graph changed, otherwise a rewritten list.
313
+ */
314
+ function specializeObjectShapeEntries(entries) {
315
+ let changed = false;
316
+ const specialized = new Array(entries.length);
317
+ for (let index = 0; index < entries.length; index += 1) {
318
+ const entry = entries[index];
319
+ if (entry === undefined) {
320
+ continue;
321
+ }
322
+ const graph = specializeDomains(entry.graph);
323
+ if (graph === entry.graph) {
324
+ specialized[index] = entry;
325
+ continue;
326
+ }
327
+ changed = true;
328
+ specialized[index] = {
329
+ key: entry.key,
330
+ schema: entry.schema,
331
+ graph,
332
+ presence: entry.presence
333
+ };
334
+ }
335
+ return changed ? specialized : entries;
336
+ }
337
+ /**
338
+ * @brief Specialize and clean a graph for one known primitive-domain mask.
339
+ * @details Optimizer helpers preserve graph equivalence while shrinking redundant nodes
340
+ * before code generation consumes the graph.
341
+ * @param graph Child graph to specialize.
342
+ * @param mask Primitive-domain mask proven by the dispatch parent.
343
+ * @returns Optimized graph for the narrowed domain.
344
+ */
345
+ function optimizeGraphForMask(graph, mask) {
346
+ const specialized = specializeGraphForMask(graph, mask);
347
+ if (specialized === graph) {
348
+ return graph;
349
+ }
350
+ return compactReachable(peepholeGraph(foldConstants(specialized)));
351
+ }
352
+ /**
353
+ * @brief Rewrite one graph under a known input-domain mask.
354
+ * @details Optimizer helpers preserve graph equivalence while shrinking redundant nodes
355
+ * before code generation consumes the graph.
356
+ * @param graph Graph whose root parameter has the supplied mask.
357
+ * @param mask Primitive-domain mask for the graph parameter.
358
+ * @returns Original graph when no node changed, otherwise a rewritten graph.
359
+ */
360
+ function specializeGraphForMask(graph, mask) {
361
+ const originalLength = graph.nodes.length;
362
+ const nodes = graph.nodes.slice();
363
+ const aliases = new Array(nodes.length);
364
+ let changed = false;
365
+ for (let index = 0; index < aliases.length; index += 1) {
366
+ aliases[index] = index;
367
+ }
368
+ for (let index = 0; index < originalLength; index += 1) {
369
+ const node = nodes[index];
370
+ if (node === undefined) {
371
+ continue;
372
+ }
373
+ const rewritten = rewriteNodeDeps(node, aliases);
374
+ const result = specializeNodeForMask(rewritten, nodes, aliases, mask);
375
+ nodes[index] = result.node;
376
+ if (result.replacement !== undefined) {
377
+ /*
378
+ * Replacements are recorded as aliases first. A final rewrite pass
379
+ * then updates every dependency after the alias forest has settled.
380
+ */
381
+ aliases[index] = result.replacement;
382
+ changed = true;
383
+ }
384
+ changed = changed || result.node !== rewritten;
385
+ }
386
+ if (!changed) {
387
+ return graph;
388
+ }
389
+ for (let index = 0; index < aliases.length; index += 1) {
390
+ aliases[index] = resolveAlias(index, aliases);
391
+ }
392
+ const rewritten = new Array(nodes.length);
393
+ for (let index = 0; index < nodes.length; index += 1) {
394
+ const node = nodes[index];
395
+ if (node !== undefined) {
396
+ rewritten[index] = rewriteNodeDeps(node, aliases);
397
+ }
398
+ }
399
+ return {
400
+ nodes: rewritten,
401
+ entry: resolveAlias(graph.entry, aliases),
402
+ result: resolveAlias(graph.result, aliases)
403
+ };
404
+ }
405
+ /**
406
+ * @brief Specialize a single graph node against a primitive-domain mask.
407
+ * @details Optimizer helpers preserve graph equivalence while shrinking redundant nodes
408
+ * before code generation consumes the graph.
409
+ * @param node Node with dependencies already rewritten through current aliases.
410
+ * @param nodes Mutable graph node table used for constants.
411
+ * @param aliases Alias table updated by replacement folds.
412
+ * @param mask Primitive-domain mask proven for the root parameter.
413
+ * @returns Fold decision for the node.
414
+ */
415
+ function specializeNodeForMask(node, nodes, aliases, mask) {
416
+ switch (node.tag) {
417
+ case NodeTag.IsString:
418
+ return specializeUnaryType(node, nodes, aliases, mask, DomainMask.String);
419
+ case NodeTag.IsBoolean:
420
+ return specializeUnaryType(node, nodes, aliases, mask, DomainMask.Boolean);
421
+ case NodeTag.IsBigInt:
422
+ return specializeUnaryType(node, nodes, aliases, mask, DomainMask.BigInt);
423
+ case NodeTag.IsSymbol:
424
+ return specializeUnaryType(node, nodes, aliases, mask, DomainMask.Symbol);
425
+ case NodeTag.IsUndefined:
426
+ return specializeUnaryType(node, nodes, aliases, mask, DomainMask.Undefined);
427
+ case NodeTag.IsNull:
428
+ return specializeUnaryType(node, nodes, aliases, mask, DomainMask.Null);
429
+ case NodeTag.IsArray:
430
+ return specializeUnaryType(node, nodes, aliases, mask, DomainMask.Array);
431
+ case NodeTag.IsObject:
432
+ return specializeUnaryType(node, nodes, aliases, mask, DomainMask.Object);
433
+ case NodeTag.IsNumber:
434
+ case NodeTag.IsInteger:
435
+ return specializeNumericType(node, nodes, aliases, mask);
436
+ case NodeTag.StringMin:
437
+ case NodeTag.StringMax:
438
+ case NodeTag.Regex:
439
+ return specializeStringDomain(node, nodes, aliases, mask);
440
+ case NodeTag.Gte:
441
+ case NodeTag.Lte:
442
+ return specializeNumericDomain(node, nodes, aliases, mask);
443
+ case NodeTag.Equals:
444
+ return specializeEqualityDomain(node, nodes, aliases, mask);
445
+ case NodeTag.ArrayEvery:
446
+ case NodeTag.TupleItems:
447
+ return specializeValueDomain(node, nodes, aliases, mask, DomainMask.Array);
448
+ case NodeTag.RecordEvery:
449
+ case NodeTag.ObjectShape:
450
+ case NodeTag.DiscriminantDispatch:
451
+ case NodeTag.StrictKeys:
452
+ return specializeValueDomain(node, nodes, aliases, mask, DomainMask.Object);
453
+ default:
454
+ return keep(node);
455
+ }
456
+ }
457
+ /**
458
+ * @brief Specialize a unary type guard.
459
+ * @details Optimizer helpers preserve graph equivalence while shrinking redundant nodes
460
+ * before code generation consumes the graph.
461
+ * @param node Guard node whose value edge may point at the root parameter.
462
+ * @param nodes Mutable graph node table used for constants.
463
+ * @param aliases Alias table updated by replacement folds.
464
+ * @param mask Primitive-domain mask proven for the root parameter.
465
+ * @param bit Domain bit represented by the guard.
466
+ * @returns Constant true/false when the mask proves the answer, otherwise keep.
467
+ */
468
+ function specializeUnaryType(node, nodes, aliases, mask, bit) {
469
+ if (!isParamNode(nodes, node.value)) {
470
+ return keep(node);
471
+ }
472
+ if ((mask & bit) === 0) {
473
+ /*
474
+ * The parent dispatch has excluded this type, so the guard is statically
475
+ * false inside this arm.
476
+ */
477
+ return replace(node, ensureConst(nodes, aliases, false));
478
+ }
479
+ if (mask === bit) {
480
+ /*
481
+ * The arm contains only this type, so the guard is statically true and
482
+ * later boolean folding can remove it.
483
+ */
484
+ return replace(node, ensureConst(nodes, aliases, true));
485
+ }
486
+ return keep(node);
487
+ }
488
+ /**
489
+ * @brief Specialize number and integer guards.
490
+ * @details Optimizer helpers preserve graph equivalence while shrinking redundant nodes
491
+ * before code generation consumes the graph.
492
+ * @param node Numeric guard node.
493
+ * @param nodes Mutable graph node table used for constants.
494
+ * @param aliases Alias table updated by replacement folds.
495
+ * @param mask Primitive-domain mask proven for the root parameter.
496
+ * @returns Constant false when number is excluded, otherwise keep.
497
+ */
498
+ function specializeNumericType(node, nodes, aliases, mask) {
499
+ if (isParamNode(nodes, node.value) && (mask & DomainMask.Number) === 0) {
500
+ return replace(node, ensureConst(nodes, aliases, false));
501
+ }
502
+ return keep(node);
503
+ }
504
+ /**
505
+ * @brief Specialize string-only scalar checks.
506
+ * @details Optimizer helpers preserve graph equivalence while shrinking redundant nodes
507
+ * before code generation consumes the graph.
508
+ * @param node String check node.
509
+ * @param nodes Mutable graph node table used for constants.
510
+ * @param aliases Alias table updated by replacement folds.
511
+ * @param mask Primitive-domain mask proven for the root parameter.
512
+ * @returns Constant false when string is excluded, otherwise keep.
513
+ */
514
+ function specializeStringDomain(node, nodes, aliases, mask) {
515
+ if (isParamNode(nodes, node.value) && (mask & DomainMask.String) === 0) {
516
+ return replace(node, ensureConst(nodes, aliases, false));
517
+ }
518
+ return keep(node);
519
+ }
520
+ /**
521
+ * @brief Specialize numeric bound checks.
522
+ * @details Optimizer helpers preserve graph equivalence while shrinking redundant nodes
523
+ * before code generation consumes the graph.
524
+ * @param node Numeric bound node.
525
+ * @param nodes Mutable graph node table used for constants.
526
+ * @param aliases Alias table updated by replacement folds.
527
+ * @param mask Primitive-domain mask proven for the root parameter.
528
+ * @returns Constant false when number is excluded, otherwise keep.
529
+ */
530
+ function specializeNumericDomain(node, nodes, aliases, mask) {
531
+ if (isParamNode(nodes, node.left) && (mask & DomainMask.Number) === 0) {
532
+ return replace(node, ensureConst(nodes, aliases, false));
533
+ }
534
+ return keep(node);
535
+ }
536
+ /**
537
+ * @brief Specialize equality checks against a known primitive domain.
538
+ * @details Optimizer helpers preserve graph equivalence while shrinking redundant nodes
539
+ * before code generation consumes the graph.
540
+ * @param node Equality node.
541
+ * @param nodes Mutable graph node table used for constants.
542
+ * @param aliases Alias table updated by replacement folds.
543
+ * @param mask Primitive-domain mask proven for the root parameter.
544
+ * @returns Constant false when the literal cannot belong to the domain.
545
+ */
546
+ function specializeEqualityDomain(node, nodes, aliases, mask) {
547
+ const left = nodes[node.left];
548
+ const right = nodes[node.right];
549
+ if (left?.tag === NodeTag.Param && right?.tag === NodeTag.Const &&
550
+ (mask & literalMask(right.value)) === 0) {
551
+ return replace(node, ensureConst(nodes, aliases, false));
552
+ }
553
+ if (right?.tag === NodeTag.Param && left?.tag === NodeTag.Const &&
554
+ (mask & literalMask(left.value)) === 0) {
555
+ return replace(node, ensureConst(nodes, aliases, false));
556
+ }
557
+ return keep(node);
558
+ }
559
+ /**
560
+ * @brief Specialize container-value nodes against a known primitive domain.
561
+ * @details Optimizer helpers preserve graph equivalence while shrinking redundant nodes
562
+ * before code generation consumes the graph.
563
+ * @param node Node that may carry a `value` edge.
564
+ * @param nodes Mutable graph node table used for constants.
565
+ * @param aliases Alias table updated by replacement folds.
566
+ * @param mask Primitive-domain mask proven for the root parameter.
567
+ * @param bit Container domain bit required by the node.
568
+ * @returns Constant false when the container type is excluded, otherwise keep.
569
+ */
570
+ function specializeValueDomain(node, nodes, aliases, mask, bit) {
571
+ if (!("value" in node) || typeof node.value !== "number") {
572
+ return keep(node);
573
+ }
574
+ if (isParamNode(nodes, node.value) && (mask & bit) === 0) {
575
+ return replace(node, ensureConst(nodes, aliases, false));
576
+ }
577
+ return keep(node);
578
+ }
579
+ /**
580
+ * @brief Test whether a node id names the root graph parameter.
581
+ * @details Optimizer helpers preserve graph equivalence while shrinking redundant nodes
582
+ * before code generation consumes the graph.
583
+ * @param nodes Graph node table.
584
+ * @param id Candidate node id.
585
+ * @returns True when the id points at a Param node.
586
+ */
587
+ function isParamNode(nodes, id) {
588
+ return nodes[id]?.tag === NodeTag.Param;
589
+ }
590
+ /**
591
+ * @brief Convert a literal value into its primitive-domain mask bit.
592
+ * @details Optimizer helpers preserve graph equivalence while shrinking redundant nodes
593
+ * before code generation consumes the graph.
594
+ * @param value Literal value carried by an Equals node.
595
+ * @returns Domain mask bit for the literal's runtime type.
596
+ */
597
+ function literalMask(value) {
598
+ if (value === null) {
599
+ return DomainMask.Null;
600
+ }
601
+ switch (typeof value) {
602
+ case "string":
603
+ return DomainMask.String;
604
+ case "number":
605
+ return DomainMask.Number;
606
+ case "boolean":
607
+ return DomainMask.Boolean;
608
+ case "bigint":
609
+ return DomainMask.BigInt;
610
+ case "symbol":
611
+ return DomainMask.Symbol;
612
+ case "undefined":
613
+ return DomainMask.Undefined;
614
+ }
615
+ }
@@ -1,15 +1,30 @@
1
1
  /**
2
2
  * @file fold-boolean.ts
3
3
  * @brief Constant folding for boolean fold nodes.
4
+ * @details Optimizer helpers preserve graph equivalence while shrinking redundant nodes
5
+ * before code generation consumes the graph.
4
6
  */
5
7
  import type { BooleanFoldNode, GraphNode, NodeId } from "../ir/index.js";
6
8
  import { type FoldResult } from "./fold-common.js";
7
9
  /**
8
- * @brief fold and.
10
+ * @brief Simplify an `And` fold node using boolean identities and constraints.
11
+ * @details False annihilates the whole conjunction, true disappears, nested
12
+ * conjunctions are flattened, and scalar constraints are canonicalized after
13
+ * algebraic simplification.
14
+ * @param node Boolean fold node to simplify.
15
+ * @param nodes Mutable graph node table for constant interning.
16
+ * @param aliases Mutable alias table updated when a constant is inserted.
17
+ * @returns Fold result for the conjunction.
9
18
  */
10
19
  export declare function foldAnd(node: BooleanFoldNode, nodes: GraphNode[], aliases: NodeId[]): FoldResult;
11
20
  /**
12
- * @brief fold or.
21
+ * @brief Simplify an `Or` fold node using boolean identities and tautologies.
22
+ * @details True satisfies the whole disjunction, false disappears, nested
23
+ * disjunctions are flattened, and duplicate surviving arms are removed.
24
+ * @param node Boolean fold node to simplify.
25
+ * @param nodes Mutable graph node table for constant interning.
26
+ * @param aliases Mutable alias table updated when a constant is inserted.
27
+ * @returns Fold result for the disjunction.
13
28
  */
14
29
  export declare function foldOr(node: BooleanFoldNode, nodes: GraphNode[], aliases: NodeId[]): FoldResult;
15
30
  //# sourceMappingURL=fold-boolean.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"fold-boolean.d.ts","sourceRoot":"","sources":["../../src/optimize/fold-boolean.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACV,eAAe,EACf,SAAS,EACT,MAAM,EACP,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAKL,KAAK,UAAU,EAChB,MAAM,kBAAkB,CAAC;AAE1B;;GAEG;AACH,wBAAgB,OAAO,CACrB,IAAI,EAAE,eAAe,EACrB,KAAK,EAAE,SAAS,EAAE,EAClB,OAAO,EAAE,MAAM,EAAE,GAChB,UAAU,CA+BZ;AAED;;GAEG;AACH,wBAAgB,MAAM,CACpB,IAAI,EAAE,eAAe,EACrB,KAAK,EAAE,SAAS,EAAE,EAClB,OAAO,EAAE,MAAM,EAAE,GAChB,UAAU,CA+BZ"}
1
+ {"version":3,"file":"fold-boolean.d.ts","sourceRoot":"","sources":["../../src/optimize/fold-boolean.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EACR,eAAe,EACf,SAAS,EACT,MAAM,EACT,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAKH,KAAK,UAAU,EAClB,MAAM,kBAAkB,CAAC;AAW1B;;;;;;;;;GASG;AACH,wBAAgB,OAAO,CACnB,IAAI,EAAE,eAAe,EACrB,KAAK,EAAE,SAAS,EAAE,EAClB,OAAO,EAAE,MAAM,EAAE,GAClB,UAAU,CA+CZ;AAED;;;;;;;;GAQG;AACH,wBAAgB,MAAM,CAClB,IAAI,EAAE,eAAe,EACrB,KAAK,EAAE,SAAS,EAAE,EAClB,OAAO,EAAE,MAAM,EAAE,GAClB,UAAU,CA2CZ"}