1use core::cmp::Ordering::{Equal, Greater, Less};
4use std::cmp::Ordering;
5use std::collections::HashMap;
6use std::hash::Hash;
7
8use variadics::variadic_collections::VariadicSet;
9use variadics::{CloneVariadic, PartialEqVariadic, SplitBySuffix, VariadicExt, var_expr, var_type};
10
11use crate::ght::{GeneralizedHashTrieNode, GhtGet, GhtInner, GhtLeaf};
12use crate::{IsBot, IsTop, LatticeBimorphism, LatticeOrd, Merge};
13
14impl<Head, Node> Merge<GhtInner<Head, Node>> for GhtInner<Head, Node>
15where
16 Node: GeneralizedHashTrieNode + Merge<Node>,
17 Node::Storage: VariadicSet<Schema = Node::Schema>, Self: GeneralizedHashTrieNode,
19 Head: Hash + Eq + Clone,
20{
21 fn merge(&mut self, other: GhtInner<Head, Node>) -> bool {
22 let mut changed = false;
23
24 for (k, v) in other.children {
25 match self.children.entry(k) {
26 std::collections::hash_map::Entry::Occupied(mut occupied) => {
27 changed |= occupied.get_mut().merge_node(v);
28 }
29 std::collections::hash_map::Entry::Vacant(vacant) => {
30 vacant.insert(v);
31 changed = true;
32 }
33 }
34 }
35 changed
36 }
37}
38
39impl<Schema, ValType, Storage> Merge<GhtLeaf<Schema, ValType, Storage>>
40 for GhtLeaf<Schema, ValType, Storage>
41where
42 Schema: Eq + Hash,
43 Storage: VariadicSet<Schema = Schema> + Extend<Schema> + IntoIterator<Item = Schema>,
44{
45 fn merge(&mut self, other: GhtLeaf<Schema, ValType, Storage>) -> bool {
46 let old_len = self.elements.len();
47 self.elements.extend(other.elements);
48 self.elements.len() > old_len
49 }
50}
51
52impl<Head, Node> PartialEq<GhtInner<Head, Node>> for GhtInner<Head, Node>
53where
54 Head: Hash + Eq + 'static + Clone,
55 Node: GeneralizedHashTrieNode + 'static + PartialEq,
56 Node::Storage: VariadicSet<Schema = Node::Schema>, Node::Schema: SplitBySuffix<var_type!(Head, ...Node::SuffixSchema)>,
58 GhtInner<Head, Node>: GhtGet,
59 <GhtInner<Head, Node> as GhtGet>::Get: PartialEq,
60{
61 fn eq(&self, other: &GhtInner<Head, Node>) -> bool {
62 if self.children.len() != other.children.len() {
63 return false;
64 }
65
66 for head in self.iter() {
67 let other_node = other.get(&head);
68 if other_node.is_none() {
69 return false;
70 }
71 let this_node = self.get(&head);
72 if this_node.is_none() {
73 return false;
74 }
75 if this_node.unwrap() != other_node.unwrap() {
76 return false;
77 }
78 }
79 true
80 }
81}
82
83impl<Head, Node> PartialOrd<GhtInner<Head, Node>> for GhtInner<Head, Node>
84where
85 Head: Hash + Eq + 'static + Clone,
86 Node: 'static + GeneralizedHashTrieNode + PartialEq + PartialOrd,
87 Node::Storage: VariadicSet<Schema = Node::Schema>, Node::Schema: SplitBySuffix<var_type!(Head, ...Node::SuffixSchema)>,
89{
90 fn partial_cmp(&self, other: &GhtInner<Head, Node>) -> Option<Ordering> {
91 let mut self_any_greater = false;
92 let mut other_any_greater = false;
93 if self.children.is_empty() && other.children.is_empty() {
94 Some(Equal)
95 } else {
96 #[expect(
97 clippy::disallowed_methods,
98 reason = "nondeterministic iteration order, TODO(mingwei)"
99 )]
100 for k in self.children.keys().chain(other.children.keys()) {
101 match (self.children.get(k), other.children.get(k)) {
102 (Some(self_value), Some(other_value)) => {
103 match self_value.partial_cmp(other_value)? {
104 Greater => {
105 self_any_greater = true;
106 }
107 Less => {
108 other_any_greater = true;
109 }
110 Equal => {}
111 }
112 }
113 (Some(_), None) => {
114 self_any_greater = true;
115 }
116 (None, Some(_)) => {
117 other_any_greater = true;
118 }
119 (None, None) => unreachable!(),
120 }
121 }
122 match (self_any_greater, other_any_greater) {
123 (true, false) => Some(Greater),
124 (false, true) => Some(Less),
125 (false, false) => Some(Equal),
126 (true, true) => unreachable!(),
127 }
128 }
129 }
130}
131
132impl<Schema, SuffixSchema, Storage> PartialOrd<GhtLeaf<Schema, SuffixSchema, Storage>>
133 for GhtLeaf<Schema, SuffixSchema, Storage>
134where
135 Schema: Eq + Hash + PartialEqVariadic,
136 SuffixSchema: Eq + Hash,
137 Storage: VariadicSet<Schema = Schema> + PartialEq,
138{
139 fn partial_cmp(&self, other: &GhtLeaf<Schema, SuffixSchema, Storage>) -> Option<Ordering> {
140 match self.elements.len().cmp(&other.elements.len()) {
141 Greater => {
142 if other.elements.iter().all(|tup| self.elements.contains(tup)) {
143 Some(Greater)
144 } else {
145 None
146 }
147 }
148 Equal => {
149 if self
150 .elements
151 .iter()
152 .all(|head| other.elements.contains(head))
153 {
154 Some(Equal)
155 } else {
156 None
157 }
158 }
159 Less => {
160 if self
161 .elements
162 .iter()
163 .all(|head| other.elements.contains(head))
164 {
165 Some(Less)
166 } else {
167 None
168 }
169 }
170 }
171 }
172}
173
174impl<Head, Node> LatticeOrd<GhtInner<Head, Node>> for GhtInner<Head, Node>
175where
176 Self: PartialOrd<GhtInner<Head, Node>>,
177 Head: Clone,
178 Node: GeneralizedHashTrieNode,
179 Node::Storage: VariadicSet<Schema = Node::Schema>, {
181}
182impl<Schema, SuffixSchema, Storage> LatticeOrd<GhtLeaf<Schema, SuffixSchema, Storage>>
183 for GhtLeaf<Schema, SuffixSchema, Storage>
184where
185 Schema: Eq + Hash + PartialEqVariadic,
186 SuffixSchema: Eq + Hash,
187 Storage: VariadicSet<Schema = Schema> + PartialEq,
188{
189}
190
191impl<Head, Node> IsBot for GhtInner<Head, Node>
192where
193 Head: Clone,
194 Node: GeneralizedHashTrieNode + IsBot,
195{
196 fn is_bot(&self) -> bool {
197 #[expect(
198 clippy::disallowed_methods,
199 reason = "nondeterministic iteration order, TODO(mingwei)"
200 )]
201 self.children.iter().all(|(_, v)| v.is_bot())
202 }
203}
204
205impl<Schema, SuffixSchema, Storage> IsBot for GhtLeaf<Schema, SuffixSchema, Storage>
206where
207 Schema: Eq + Hash,
208 SuffixSchema: Eq + Hash,
209 Storage: VariadicSet<Schema = Schema>,
210{
211 fn is_bot(&self) -> bool {
212 self.elements.is_empty()
213 }
214}
215
216impl<Head, Node> IsTop for GhtInner<Head, Node>
217where
218 Head: Clone,
219 Node: GeneralizedHashTrieNode,
220 Node::Storage: VariadicSet<Schema = Node::Schema>, {
222 fn is_top(&self) -> bool {
223 false
224 }
225}
226
227impl<Schema, SuffixSchema, Storage> IsTop for GhtLeaf<Schema, SuffixSchema, Storage>
228where
229 Schema: Eq + Hash,
230 SuffixSchema: Eq + Hash,
231 Storage: VariadicSet<Schema = Schema>,
232{
233 fn is_top(&self) -> bool {
234 false
235 }
236}
237
238pub struct GhtCartesianProductBimorphism<GhtOut> {
249 _phantom: std::marker::PhantomData<fn() -> GhtOut>,
250}
251impl<GhtOut> Default for GhtCartesianProductBimorphism<GhtOut> {
252 fn default() -> Self {
253 Self {
254 _phantom: Default::default(),
255 }
256 }
257}
258impl<'a, 'b, GhtA, GhtB, GhtOut> LatticeBimorphism<&'a GhtA, &'b GhtB>
259 for GhtCartesianProductBimorphism<GhtOut>
260where
261 GhtA: GeneralizedHashTrieNode,
262 GhtA::Storage: VariadicSet<Schema = GhtA::Schema>, GhtB: GeneralizedHashTrieNode,
264 GhtB::Storage: VariadicSet<Schema = GhtB::Schema>, GhtOut: FromIterator<var_type!(...GhtA::SuffixSchema, ...GhtB::SuffixSchema)>,
266 GhtA::SuffixSchema: CloneVariadic,
267 GhtB::SuffixSchema: CloneVariadic,
268{
269 type Output = GhtOut;
270
271 fn call(&mut self, ght_a: &'a GhtA, ght_b: &'b GhtB) -> Self::Output {
272 ght_a.recursive_iter().flat_map(|a| {
273 let (_a_prefix, a_suffix) = <GhtA::Schema as SplitBySuffix<GhtA::SuffixSchema>>::split_by_suffix_ref(a);
274 ght_b
275 .recursive_iter()
276 .map(move |b| {
277 let (_b_prefix, b_suffix) = <GhtB::Schema as SplitBySuffix<GhtB::SuffixSchema>>::split_by_suffix_ref(b);
278 var_expr!(...<GhtA::SuffixSchema as CloneVariadic>::clone_ref_var(a_suffix), ...<GhtB::SuffixSchema as CloneVariadic>::clone_ref_var(b_suffix))
279 })
280 }).collect()
281 }
282}
283
284pub struct GhtValTypeProductBimorphism<GhtOut> {
287 _phantom: std::marker::PhantomData<fn() -> GhtOut>,
288}
289impl<GhtOut> Default for GhtValTypeProductBimorphism<GhtOut> {
290 fn default() -> Self {
291 Self {
292 _phantom: Default::default(),
293 }
294 }
295}
296impl<'a, 'b, GhtA, GhtB, GhtOut> LatticeBimorphism<&'a GhtA, &'b GhtB>
297 for GhtValTypeProductBimorphism<GhtOut>
298where
299 GhtA: GeneralizedHashTrieNode,
300 GhtA::Storage: VariadicSet<Schema = GhtA::Schema>, GhtB: GeneralizedHashTrieNode,
302 GhtB::Storage: VariadicSet<Schema = GhtB::Schema>, GhtOut: FromIterator<var_type!(...GhtA::Schema, ...GhtB::ValType)>,
304 GhtA::Schema: Eq + Hash + CloneVariadic,
305 GhtB::Schema: Eq + Hash + SplitBySuffix<GhtB::ValType>,
306 GhtB::ValType: CloneVariadic,
307{
308 type Output = GhtOut;
309
310 fn call(&mut self, ght_a: &'a GhtA, ght_b: &'b GhtB) -> Self::Output {
311 ght_a.recursive_iter().flat_map(|a| {
312 ght_b
313 .recursive_iter()
314 .map(move |b| {
315 let (_prefix_b, suffix_b)
316 = <GhtB::Schema as SplitBySuffix<GhtB::ValType>>::split_by_suffix_ref(b);
317 var_expr!(...<GhtA::Schema as CloneVariadic>::clone_ref_var(a), ...<GhtB::ValType as CloneVariadic>::clone_ref_var(suffix_b))
318 }
319 )
320 }).collect()
321 }
322}
323
324#[derive(Default)]
328pub struct GhtBimorphism<Bimorphism> {
329 bimorphism: Bimorphism,
330 }
332impl<Bimorphism> GhtBimorphism<Bimorphism> {
333 pub fn new(bimorphism: Bimorphism) -> Self {
335 Self {
336 bimorphism,
337 }
339 }
340}
341
342impl<GhtA, GhtB, ValFunc, GhtOut> LatticeBimorphism<GhtA, GhtB> for GhtBimorphism<ValFunc>
343where
344 GhtA: GeneralizedHashTrieNode,
345 GhtA::Storage: VariadicSet<Schema = GhtA::Schema>, GhtB: GeneralizedHashTrieNode,
347 GhtB::Storage: VariadicSet<Schema = GhtB::Schema>, GhtOut: GeneralizedHashTrieNode, for<'a, 'b> ValFunc: LatticeBimorphism<&'a GhtA, &'b GhtB, Output = GhtOut>,
350{
351 type Output = GhtOut;
352
353 fn call(&mut self, ght_a: GhtA, ght_b: GhtB) -> Self::Output {
354 let node_bim = &mut self.bimorphism; node_bim.call(&ght_a, &ght_b)
356 }
357}
358
359#[derive(Default)]
360pub struct GhtNodeKeyedBimorphism<Bimorphism> {
362 bimorphism: Bimorphism,
363}
364impl<Bimorphism> GhtNodeKeyedBimorphism<Bimorphism> {
366 pub fn new(bimorphism: Bimorphism) -> Self {
368 Self { bimorphism }
369 }
370}
371impl<'a, 'b, Head, GhtA, GhtB, ValFunc> LatticeBimorphism<&'a GhtA, &'b GhtB>
373 for GhtNodeKeyedBimorphism<ValFunc>
374where
375 Head: Clone + Hash + Eq,
376 ValFunc: LatticeBimorphism<&'a GhtA::Get, &'b GhtB::Get>,
377 ValFunc::Output: GeneralizedHashTrieNode,
378 GhtA: GeneralizedHashTrieNode<Head = Head> + GhtGet,
379 GhtB: GeneralizedHashTrieNode<Head = Head, Schema = GhtA::Schema> + GhtGet,
380 GhtA::Storage: VariadicSet<Schema = GhtA::Schema>, GhtB::Storage: VariadicSet<Schema = GhtB::Schema>, <GhtA::SuffixSchema as VariadicExt>::AsRefVar<'a>: CloneVariadic,
383 <GhtB::SuffixSchema as VariadicExt>::AsRefVar<'b>: CloneVariadic,
384{
385 type Output = GhtInner<Head, ValFunc::Output>; fn call(&mut self, ght_a: &'a GhtA, ght_b: &'b GhtB) -> Self::Output {
388 let mut children = HashMap::<Head, ValFunc::Output>::new();
389 for head in ght_b.iter() {
391 if let Some(get_a) = ght_a.get(&head) {
392 let get_b = ght_b.get(&head).unwrap();
393 let val = self.bimorphism.call(get_a, get_b);
394 children.insert(head.clone(), val);
395 }
396 }
397 GhtInner { children }
398 }
399}
400
401pub trait DeepJoinLatticeBimorphism<Storage> {
403 type DeepJoinLatticeBimorphism;
405}
406impl<Head, NodeA, NodeB, Storage> DeepJoinLatticeBimorphism<Storage>
408 for (GhtInner<Head, NodeA>, GhtInner<Head, NodeB>)
409where
410 Head: 'static + Hash + Eq + Clone,
411 NodeA: 'static + GeneralizedHashTrieNode,
412 NodeB: 'static + GeneralizedHashTrieNode,
413 NodeA::Storage: VariadicSet<Schema = NodeA::Schema>, NodeB::Storage: VariadicSet<Schema = NodeB::Schema>, (NodeA, NodeB): DeepJoinLatticeBimorphism<Storage>,
416 Storage: VariadicSet<Schema = var_type!(...NodeA::Schema, ...NodeB::ValType)>,
417{
418 type DeepJoinLatticeBimorphism = GhtNodeKeyedBimorphism<
419 <(NodeA, NodeB) as DeepJoinLatticeBimorphism<Storage>>::DeepJoinLatticeBimorphism,
420 >;
421}
422impl<SchemaA, ValTypeA, StorageA, SchemaB, ValTypeB, StorageB, StorageOut>
423 DeepJoinLatticeBimorphism<StorageOut>
424 for (
425 GhtLeaf<SchemaA, ValTypeA, StorageA>,
426 GhtLeaf<SchemaB, ValTypeB, StorageB>,
427 )
428where
429 SchemaA: 'static + VariadicExt + Eq + Hash + SplitBySuffix<ValTypeA>, ValTypeA: 'static + VariadicExt + Eq + Hash, SchemaB: 'static + VariadicExt + Eq + Hash + SplitBySuffix<ValTypeB>, ValTypeB: 'static + VariadicExt + Eq + Hash, StorageA: VariadicSet<Schema = SchemaA>,
434 StorageB: VariadicSet<Schema = SchemaB>,
435 StorageOut: VariadicSet<Schema = var_type!(...SchemaA, ...ValTypeB)>,
436 for<'x> SchemaA::AsRefVar<'x>: CloneVariadic,
437 for<'x> SchemaB::AsRefVar<'x>: CloneVariadic,
438 var_type!(...SchemaA, ...ValTypeB): Eq + Hash,
439{
440 type DeepJoinLatticeBimorphism = GhtValTypeProductBimorphism<
441 GhtLeaf<
442 var_type!(...SchemaA, ...ValTypeB),
443 var_type!(...ValTypeA, ...ValTypeB),
444 StorageOut,
445 >,
446 >;
447}