pattern_core/pattern/core.rs
1//! Pattern type definition
2//!
3//! This module provides the core `Pattern<V>` type, a recursive, nested structure
4//! (s-expression-like) that is generic over value type `V`.
5//!
6//! # Construction Functions
7//!
8//! - [`Pattern::point`] - Creates an atomic pattern from a value (special case, matches gram-hs API)
9//! - [`Pattern::pattern`] - Creates a pattern with elements (primary constructor, matches gram-hs API)
10//! - [`Pattern::from_list`] - Creates a pattern from a list of values
11//!
12//! # Accessor Methods
13//!
14//! - [`Pattern::value`] - Returns a reference to the pattern's value
15//! - [`Pattern::elements`] - Returns a slice of the pattern's elements
16//!
17//! # Inspection Utilities
18//!
19//! - [`Pattern::length`] - Returns the number of direct elements
20//! - [`Pattern::size`] - Returns the total number of nodes
21//! - [`Pattern::depth`] - Returns the maximum nesting depth
22//! - [`Pattern::is_atomic`] - Checks if a pattern is atomic
23//! - [`Pattern::values`] - Extracts all values as a flat list (pre-order)
24//!
25//! # Query Functions
26//!
27//! - [`Pattern::any_value`] - Checks if at least one value satisfies a predicate (short-circuits)
28//! - [`Pattern::all_values`] - Checks if all values satisfy a predicate (short-circuits)
29//! - [`Pattern::filter`] - Extracts subpatterns that satisfy a pattern predicate
30//! - [`Pattern::find_first`] - Finds the first subpattern that satisfies a pattern predicate (short-circuits)
31//! - [`Pattern::matches`] - Checks if two patterns have identical structure
32//! - [`Pattern::contains`] - Checks if a pattern contains another as a subpattern
33//!
34//! # Combination Operations
35//!
36//! - [`Pattern::combine`] - Combines two patterns associatively (value combination + element concatenation)
37
38use std::cmp::Ordering;
39use std::fmt;
40use std::hash::{Hash, Hasher};
41
42/// A recursive, nested structure (s-expression-like) that is generic over value type `V`.
43///
44/// The value provides "information about the elements" - they form an intimate pairing.
45/// Elements are themselves patterns, creating the recursive structure.
46///
47/// Patterns are s-expression-like structures, not trees, though they may appear tree-like
48/// and accept tree-like operations.
49///
50/// # Examples
51///
52/// ## Creating a simple pattern
53///
54/// ```rust
55/// use pattern_core::Pattern;
56///
57/// let pattern = Pattern {
58/// value: "hello".to_string(),
59/// elements: vec![],
60/// };
61/// ```
62///
63/// ## Creating a nested pattern
64///
65/// ```rust
66/// use pattern_core::Pattern;
67///
68/// let nested = Pattern {
69/// value: "parent".to_string(),
70/// elements: vec![
71/// Pattern {
72/// value: "child1".to_string(),
73/// elements: vec![],
74/// },
75/// Pattern {
76/// value: "child2".to_string(),
77/// elements: vec![],
78/// },
79/// ],
80/// };
81/// ```
82///
83/// ## Using with Subject type
84///
85/// ```rust
86/// use pattern_core::{Pattern, Subject, Symbol};
87/// use std::collections::HashSet;
88///
89/// let subject = Subject {
90/// identity: Symbol("n".to_string()),
91/// labels: HashSet::new(),
92/// properties: std::collections::HashMap::new(),
93/// };
94///
95/// let pattern: Pattern<Subject> = Pattern {
96/// value: subject,
97/// elements: vec![],
98/// };
99/// ```
100///
101/// # Trait Implementations
102///
103/// - `Clone`: Patterns can be cloned when `V: Clone`
104/// - `PartialEq`, `Eq`: Patterns can be compared for equality when `V: PartialEq` (or `Eq`)
105/// - `PartialOrd`, `Ord`: Patterns can be ordered when `V: PartialOrd` (or `Ord`)
106/// - Uses value-first lexicographic ordering: compares values, then elements
107/// - Enables sorting, min/max operations, and use in ordered collections (BTreeSet, BTreeMap)
108/// - `Hash`: Patterns can be hashed when `V: Hash` for use in HashMap/HashSet
109/// - Enables pattern deduplication and caching
110/// - Structure-preserving: different structures produce different hashes
111/// - Note: `Pattern<Subject>` is NOT hashable (Subject contains f64)
112/// - `Debug`: Structured representation for debugging (with truncation for deep nesting)
113/// - `Display`: Human-readable representation
114///
115/// # Performance
116///
117/// Patterns support:
118/// - At least 100 nesting levels without stack overflow
119/// - At least 10,000 elements efficiently
120/// - WASM compilation for web applications
121#[derive(Clone, PartialEq, Eq)]
122pub struct Pattern<V> {
123 /// The value component, which provides information about the elements.
124 ///
125 /// The value and elements form an intimate pairing where the value provides
126 /// "information about the elements".
127 pub value: V,
128
129 /// The nested collection of patterns that form the recursive structure.
130 ///
131 /// Elements are themselves `Pattern<V>`, creating the recursive nested structure.
132 /// An empty vector represents an atomic pattern (a pattern with no nested elements).
133 pub elements: Vec<Pattern<V>>,
134}
135
136/// Configurable validation rules for pattern structure.
137///
138/// Rules can specify limits on nesting depth, element counts, or other structural properties.
139/// Rules are optional (None means no limit).
140///
141/// # Examples
142///
143/// ```
144/// use pattern_core::ValidationRules;
145///
146/// // No constraints (all patterns valid)
147/// let rules = ValidationRules::default();
148///
149/// // Maximum depth constraint
150/// let rules = ValidationRules {
151/// max_depth: Some(10),
152/// ..Default::default()
153/// };
154/// ```
155#[derive(Debug, Clone, Default)]
156pub struct ValidationRules {
157 /// Maximum nesting depth allowed (None = no limit)
158 pub max_depth: Option<usize>,
159 /// Maximum element count allowed (None = no limit)
160 pub max_elements: Option<usize>,
161 /// Required fields (reserved for future value-specific validation)
162 pub required_fields: Vec<String>,
163}
164
165/// Error type for pattern validation failures.
166///
167/// Provides detailed information about what rule was violated and where
168/// in the pattern structure the violation occurred.
169///
170/// # Examples
171///
172/// ```
173/// use pattern_core::ValidationError;
174///
175/// let error = ValidationError {
176/// message: "Pattern depth exceeds maximum".to_string(),
177/// rule_violated: "max_depth".to_string(),
178/// location: vec!["elements".to_string(), "0".to_string()],
179/// };
180/// ```
181#[derive(Debug, Clone, PartialEq, Eq)]
182pub struct ValidationError {
183 /// Human-readable error message
184 pub message: String,
185 /// Name of violated rule (e.g., "max_depth", "max_elements")
186 pub rule_violated: String,
187 /// Path to violating node in pattern structure
188 pub location: Vec<String>,
189}
190
191/// Results from structure analysis utilities.
192///
193/// Provides detailed information about pattern structural characteristics
194/// including depth distribution, element counts, nesting patterns, and summaries.
195///
196/// # Examples
197///
198/// ```
199/// use pattern_core::{Pattern, StructureAnalysis};
200///
201/// let pattern = Pattern::pattern("root".to_string(), vec![/* ... */]);
202/// let analysis = pattern.analyze_structure();
203///
204/// println!("Depth distribution: {:?}", analysis.depth_distribution);
205/// println!("Summary: {}", analysis.summary);
206/// ```
207#[derive(Debug, Clone)]
208pub struct StructureAnalysis {
209 /// Count of nodes at each depth level (index = depth, value = count)
210 pub depth_distribution: Vec<usize>,
211 /// Element counts at each level (index = level, value = count)
212 pub element_counts: Vec<usize>,
213 /// Identified structural patterns (e.g., "linear", "tree", "balanced")
214 pub nesting_patterns: Vec<String>,
215 /// Human-readable summary of structure
216 pub summary: String,
217}
218
219impl<V: fmt::Debug> Pattern<V> {
220 fn fmt_debug_with_depth(
221 &self,
222 f: &mut fmt::Formatter<'_>,
223 depth: usize,
224 max_depth: usize,
225 ) -> fmt::Result {
226 if depth > max_depth {
227 return write!(f, "...");
228 }
229
230 f.debug_struct("Pattern")
231 .field("value", &self.value)
232 .field(
233 "elements",
234 &DebugElements {
235 elements: &self.elements,
236 depth,
237 max_depth,
238 },
239 )
240 .finish()
241 }
242}
243
244impl<V: fmt::Debug> fmt::Debug for Pattern<V> {
245 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
246 self.fmt_debug_with_depth(f, 0, 10) // Max depth of 10 for truncation
247 }
248}
249
250struct DebugElements<'a, V> {
251 elements: &'a Vec<Pattern<V>>,
252 depth: usize,
253 max_depth: usize,
254}
255
256impl<'a, V: fmt::Debug> fmt::Debug for DebugElements<'a, V> {
257 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
258 if self.depth > self.max_depth {
259 return write!(f, "[...]");
260 }
261
262 let mut list = f.debug_list();
263 for (i, elem) in self.elements.iter().enumerate() {
264 if i >= 5 && self.elements.len() > 10 {
265 // Truncate if more than 10 elements
266 list.entry(&format_args!("... ({} more)", self.elements.len() - 5));
267 break;
268 }
269 list.entry(&DebugPattern {
270 pattern: elem,
271 depth: self.depth + 1,
272 max_depth: self.max_depth,
273 });
274 }
275 list.finish()
276 }
277}
278
279struct DebugPattern<'a, V> {
280 pattern: &'a Pattern<V>,
281 depth: usize,
282 max_depth: usize,
283}
284
285impl<'a, V: fmt::Debug> fmt::Debug for DebugPattern<'a, V> {
286 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
287 self.pattern
288 .fmt_debug_with_depth(f, self.depth, self.max_depth)
289 }
290}
291
292impl<V: fmt::Display> Pattern<V> {
293 fn fmt_display_with_depth(
294 &self,
295 f: &mut fmt::Formatter<'_>,
296 depth: usize,
297 max_depth: usize,
298 ) -> fmt::Result {
299 if depth > max_depth {
300 return write!(f, "...");
301 }
302
303 write!(f, "(")?;
304 write!(f, "{}", self.value)?;
305
306 if !self.elements.is_empty() {
307 write!(f, " ")?;
308 for (i, elem) in self.elements.iter().enumerate() {
309 if i > 0 {
310 write!(f, " ")?;
311 }
312 if i >= 5 && self.elements.len() > 10 {
313 write!(f, "... ({} more)", self.elements.len() - 5)?;
314 break;
315 }
316 elem.fmt_display_with_depth(f, depth + 1, max_depth)?;
317 }
318 }
319
320 write!(f, ")")
321 }
322}
323
324impl<V: fmt::Display> fmt::Display for Pattern<V> {
325 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
326 self.fmt_display_with_depth(f, 0, 10) // Max depth of 10 for truncation
327 }
328}
329
330// Construction Functions
331
332impl<V> Pattern<V> {
333 /// Creates an atomic pattern (a pattern with no elements) from a value.
334 ///
335 /// This is the special case constructor for atomic patterns.
336 /// Equivalent to gram-hs `point :: v -> Pattern v`.
337 ///
338 /// # Arguments
339 ///
340 /// * `value` - The value component of the pattern
341 ///
342 /// # Returns
343 ///
344 /// A new atomic `Pattern<V>` instance with the specified value and empty elements.
345 ///
346 /// # Examples
347 ///
348 /// ```
349 /// use pattern_core::Pattern;
350 ///
351 /// let atomic = Pattern::point("atom".to_string());
352 /// assert_eq!(atomic.value, "atom");
353 /// assert_eq!(atomic.elements.len(), 0);
354 /// ```
355 pub fn point(value: V) -> Self {
356 Pattern {
357 value,
358 elements: vec![],
359 }
360 }
361
362 /// Creates a pattern with a value and elements.
363 ///
364 /// This is the primary constructor for creating patterns. Takes a decoration value
365 /// and a list of pattern elements. The elements form the pattern itself; the value
366 /// provides decoration about that pattern.
367 ///
368 /// Equivalent to gram-hs `pattern :: v -> [Pattern v] -> Pattern v`.
369 ///
370 /// # Arguments
371 ///
372 /// * `value` - The value component of the pattern
373 /// * `elements` - The nested collection of patterns
374 ///
375 /// # Returns
376 ///
377 /// A new `Pattern<V>` instance with the specified value and elements.
378 ///
379 /// # Examples
380 ///
381 /// ```
382 /// use pattern_core::Pattern;
383 ///
384 /// let pattern = Pattern::pattern("root".to_string(), vec![
385 /// Pattern::point("child".to_string()),
386 /// ]);
387 /// assert_eq!(pattern.value, "root");
388 /// assert_eq!(pattern.elements.len(), 1);
389 /// ```
390 #[allow(clippy::self_named_constructors)]
391 pub fn pattern(value: V, elements: Vec<Pattern<V>>) -> Self {
392 Pattern { value, elements }
393 }
394
395 /// Creates a pattern from a list of values.
396 ///
397 /// Creates a pattern where the first argument is the decoration value,
398 /// and the list of values are converted to atomic patterns and used as elements.
399 /// Equivalent to gram-hs `fromList :: v -> [v] -> Pattern v`.
400 ///
401 /// # Arguments
402 ///
403 /// * `value` - The decoration value for the pattern
404 /// * `values` - List of values to convert to atomic patterns as elements
405 ///
406 /// # Returns
407 ///
408 /// A new `Pattern<V>` instance with value as decoration and values converted to atomic patterns as elements.
409 ///
410 /// # Examples
411 ///
412 /// ```
413 /// use pattern_core::Pattern;
414 ///
415 /// let pattern = Pattern::from_list("root".to_string(), vec![
416 /// "a".to_string(),
417 /// "b".to_string(),
418 /// "c".to_string(),
419 /// ]);
420 /// assert_eq!(pattern.value, "root");
421 /// assert_eq!(pattern.elements.len(), 3);
422 /// ```
423 pub fn from_list(value: V, values: Vec<V>) -> Self {
424 Pattern {
425 value,
426 elements: values.into_iter().map(Pattern::point).collect(),
427 }
428 }
429
430 /// Returns a reference to the pattern's value component.
431 ///
432 /// Equivalent to gram-hs `value :: Pattern v -> v` (record field accessor).
433 ///
434 /// # Returns
435 ///
436 /// An immutable reference to the pattern's value.
437 ///
438 /// # Examples
439 ///
440 /// ```
441 /// use pattern_core::Pattern;
442 ///
443 /// let pattern = Pattern::point("hello".to_string());
444 /// let value = pattern.value(); // &String
445 /// assert_eq!(value, "hello");
446 /// ```
447 pub fn value(&self) -> &V {
448 &self.value
449 }
450
451 /// Returns a slice of the pattern's elements.
452 ///
453 /// Equivalent to gram-hs `elements :: Pattern v -> [Pattern v]` (record field accessor).
454 ///
455 /// # Returns
456 ///
457 /// An immutable slice of the pattern's nested elements.
458 ///
459 /// # Examples
460 ///
461 /// ```
462 /// use pattern_core::Pattern;
463 ///
464 /// let pattern = Pattern::pattern("parent".to_string(), vec![
465 /// Pattern::point("child1".to_string()),
466 /// Pattern::point("child2".to_string()),
467 /// ]);
468 /// let elements = pattern.elements();
469 /// assert_eq!(elements.len(), 2);
470 /// ```
471 pub fn elements(&self) -> &[Pattern<V>] {
472 &self.elements
473 }
474
475 /// Returns the number of direct elements in a pattern's sequence.
476 ///
477 /// Equivalent to gram-hs `length :: Pattern v -> Int`.
478 ///
479 /// # Returns
480 ///
481 /// The number of direct elements (not nested).
482 ///
483 /// # Examples
484 ///
485 /// ```
486 /// use pattern_core::Pattern;
487 ///
488 /// let pattern = Pattern::pattern("parent".to_string(), vec![
489 /// Pattern::point("child1".to_string()),
490 /// Pattern::point("child2".to_string()),
491 /// ]);
492 /// assert_eq!(pattern.length(), 2);
493 /// ```
494 pub fn length(&self) -> usize {
495 self.elements.len()
496 }
497
498 /// Returns the total number of nodes in a pattern structure, including all nested patterns.
499 ///
500 /// Equivalent to gram-hs `size :: Pattern v -> Int`.
501 ///
502 /// # Returns
503 ///
504 /// The total number of nodes (root + all nested nodes).
505 ///
506 /// # Examples
507 ///
508 /// ```
509 /// use pattern_core::Pattern;
510 ///
511 /// let atomic = Pattern::point("atom".to_string());
512 /// assert_eq!(atomic.size(), 1);
513 ///
514 /// let pattern = Pattern::pattern("root".to_string(), vec![
515 /// Pattern::point("child1".to_string()),
516 /// Pattern::point("child2".to_string()),
517 /// ]);
518 /// assert_eq!(pattern.size(), 3); // root + 2 children
519 /// ```
520 pub fn size(&self) -> usize {
521 1 + self.elements.iter().map(|e| e.size()).sum::<usize>()
522 }
523
524 /// Returns the maximum nesting depth of a pattern structure.
525 ///
526 /// Equivalent to gram-hs `depth :: Pattern v -> Int`.
527 ///
528 /// # Returns
529 ///
530 /// The maximum nesting depth. Atomic patterns (patterns with no elements) have depth 0.
531 ///
532 /// # Examples
533 ///
534 /// ```
535 /// use pattern_core::Pattern;
536 ///
537 /// let atomic = Pattern::point("hello".to_string());
538 /// assert_eq!(atomic.depth(), 0); // Atomic patterns have depth 0
539 ///
540 /// let nested = Pattern::pattern("parent".to_string(), vec![
541 /// Pattern::pattern("child".to_string(), vec![
542 /// Pattern::point("grandchild".to_string()),
543 /// ]),
544 /// ]);
545 /// assert_eq!(nested.depth(), 2);
546 /// ```
547 pub fn depth(&self) -> usize {
548 if self.elements.is_empty() {
549 0
550 } else {
551 1 + self.elements.iter().map(|e| e.depth()).max().unwrap_or(0)
552 }
553 }
554
555 /// Checks if a pattern is atomic (has no elements).
556 ///
557 /// This is a convenience helper for pattern classification.
558 ///
559 /// # Returns
560 ///
561 /// `true` if the pattern has no elements, `false` otherwise.
562 ///
563 /// # Examples
564 ///
565 /// ```
566 /// use pattern_core::Pattern;
567 ///
568 /// let atomic = Pattern::point("hello".to_string());
569 /// assert!(atomic.is_atomic());
570 ///
571 /// let nested = Pattern::pattern("parent".to_string(), vec![
572 /// Pattern::point("child".to_string()),
573 /// ]);
574 /// assert!(!nested.is_atomic());
575 /// ```
576 pub fn is_atomic(&self) -> bool {
577 self.elements.is_empty()
578 }
579
580 /// Checks if at least one value in the pattern satisfies the given predicate.
581 ///
582 /// This operation traverses the pattern structure in pre-order (root first, then elements)
583 /// and applies the predicate to each value. Returns `true` as soon as a value satisfies
584 /// the predicate (short-circuit evaluation - both predicate evaluation AND traversal stop),
585 /// or `false` if no values match.
586 ///
587 /// Equivalent to Haskell's `anyValue :: (v -> Bool) -> Pattern v -> Bool`.
588 ///
589 /// # Type Parameters
590 ///
591 /// * `F` - A function that takes a reference to a value and returns a boolean
592 ///
593 /// # Arguments
594 ///
595 /// * `predicate` - A function to test each value
596 ///
597 /// # Returns
598 ///
599 /// * `true` if at least one value satisfies the predicate
600 /// * `false` if no values satisfy the predicate (including empty patterns)
601 ///
602 /// # Complexity
603 ///
604 /// * Time: O(n) worst case, O(1) to O(n) average (short-circuits on first match)
605 /// * Space: O(1) heap, O(d) stack where d = maximum depth
606 ///
607 /// # Examples
608 ///
609 /// ```
610 /// use pattern_core::Pattern;
611 ///
612 /// let pattern = Pattern::pattern(5, vec![
613 /// Pattern::point(10),
614 /// Pattern::point(3),
615 /// ]);
616 ///
617 /// // Check if any value is greater than 8
618 /// assert!(pattern.any_value(|v| *v > 8)); // true (10 > 8)
619 ///
620 /// // Check if any value is negative
621 /// assert!(!pattern.any_value(|v| *v < 0)); // false (all positive)
622 /// ```
623 ///
624 /// # Short-Circuit Behavior
625 ///
626 /// The operation stops traversal as soon as a matching value is found:
627 ///
628 /// ```
629 /// use pattern_core::Pattern;
630 ///
631 /// let pattern = Pattern::pattern(1, vec![
632 /// Pattern::point(2),
633 /// Pattern::point(5), // Matches here - stops traversal
634 /// Pattern::point(3), // Not visited
635 /// ]);
636 ///
637 /// assert!(pattern.any_value(|v| *v == 5));
638 /// ```
639 pub fn any_value<F>(&self, predicate: F) -> bool
640 where
641 F: Fn(&V) -> bool,
642 {
643 self.any_value_recursive(&predicate)
644 }
645
646 /// Helper function for any_value with early termination.
647 fn any_value_recursive<F>(&self, predicate: &F) -> bool
648 where
649 F: Fn(&V) -> bool,
650 {
651 // Check current value (pre-order)
652 if predicate(&self.value) {
653 return true;
654 }
655
656 // Check elements recursively, stop on first match
657 for element in &self.elements {
658 if element.any_value_recursive(predicate) {
659 return true;
660 }
661 }
662
663 false
664 }
665
666 /// Checks if all values in the pattern satisfy the given predicate.
667 ///
668 /// This operation traverses the pattern structure in pre-order (root first, then elements)
669 /// and applies the predicate to each value. Returns `false` as soon as a value is found
670 /// that does not satisfy the predicate (short-circuit evaluation - both predicate evaluation
671 /// AND traversal stop), or `true` if all values satisfy the predicate.
672 ///
673 /// Equivalent to Haskell's `allValues :: (v -> Bool) -> Pattern v -> Bool`.
674 ///
675 /// # Type Parameters
676 ///
677 /// * `F` - A function that takes a reference to a value and returns a boolean
678 ///
679 /// # Arguments
680 ///
681 /// * `predicate` - A function to test each value
682 ///
683 /// # Returns
684 ///
685 /// * `true` if all values satisfy the predicate (vacuous truth for patterns with no values)
686 /// * `false` if at least one value does not satisfy the predicate
687 ///
688 /// # Complexity
689 ///
690 /// * Time: O(n) worst case, O(1) to O(n) average (short-circuits on first failure)
691 /// * Space: O(1) heap, O(d) stack where d = maximum depth
692 ///
693 /// # Examples
694 ///
695 /// ```
696 /// use pattern_core::Pattern;
697 ///
698 /// let pattern = Pattern::pattern(5, vec![
699 /// Pattern::point(10),
700 /// Pattern::point(3),
701 /// ]);
702 ///
703 /// // Check if all values are positive
704 /// assert!(pattern.all_values(|v| *v > 0)); // true (all > 0)
705 ///
706 /// // Check if all values are greater than 8
707 /// assert!(!pattern.all_values(|v| *v > 8)); // false (5 and 3 fail)
708 /// ```
709 ///
710 /// # Short-Circuit Behavior
711 ///
712 /// The operation stops traversal as soon as a non-matching value is found:
713 ///
714 /// ```
715 /// use pattern_core::Pattern;
716 ///
717 /// let pattern = Pattern::pattern(1, vec![
718 /// Pattern::point(2),
719 /// Pattern::point(-5), // Fails here - stops traversal
720 /// Pattern::point(3), // Not visited
721 /// ]);
722 ///
723 /// assert!(!pattern.all_values(|v| *v > 0));
724 /// ```
725 ///
726 /// # Relationship to any_value
727 ///
728 /// The following equivalence holds: `all_values(p) ≡ !any_value(!p)`
729 ///
730 /// ```
731 /// use pattern_core::Pattern;
732 ///
733 /// let pattern = Pattern::pattern(5, vec![Pattern::point(10)]);
734 /// let predicate = |v: &i32| *v > 0;
735 ///
736 /// assert_eq!(
737 /// pattern.all_values(predicate),
738 /// !pattern.any_value(|v| !predicate(v))
739 /// );
740 /// ```
741 pub fn all_values<F>(&self, predicate: F) -> bool
742 where
743 F: Fn(&V) -> bool,
744 {
745 self.all_values_recursive(&predicate)
746 }
747
748 /// Helper function for all_values with early termination.
749 fn all_values_recursive<F>(&self, predicate: &F) -> bool
750 where
751 F: Fn(&V) -> bool,
752 {
753 // Check current value (pre-order)
754 if !predicate(&self.value) {
755 return false;
756 }
757
758 // Check elements recursively, stop on first failure
759 for element in &self.elements {
760 if !element.all_values_recursive(predicate) {
761 return false;
762 }
763 }
764
765 true
766 }
767
768 /// Filters subpatterns that satisfy the given pattern predicate.
769 ///
770 /// This operation traverses the pattern structure in pre-order (root first, then elements)
771 /// and collects references to all patterns that satisfy the predicate. Unlike `any_value`
772 /// and `all_values` which operate on values, this method operates on entire patterns,
773 /// allowing predicates to test structural properties (length, depth, etc.) as well as values.
774 ///
775 /// Equivalent to Haskell's `filterPatterns :: (Pattern v -> Bool) -> Pattern v -> [Pattern v]`.
776 ///
777 /// # Type Parameters
778 ///
779 /// * `F` - A function that takes a reference to a pattern and returns a boolean
780 ///
781 /// # Arguments
782 ///
783 /// * `predicate` - A function to test each pattern (including the root)
784 ///
785 /// # Returns
786 ///
787 /// A vector of immutable references to patterns that satisfy the predicate, in pre-order
788 /// traversal order. Returns an empty vector if no patterns match.
789 ///
790 /// # Complexity
791 ///
792 /// * Time: O(n) where n is the number of nodes (must visit all patterns)
793 /// * Space: O(m) heap where m is the number of matches, O(d) stack where d = maximum depth
794 ///
795 /// # Examples
796 ///
797 /// ```
798 /// use pattern_core::Pattern;
799 ///
800 /// let pattern = Pattern::pattern(
801 /// "root",
802 /// vec![
803 /// Pattern::point("leaf1"),
804 /// Pattern::pattern("branch", vec![
805 /// Pattern::point("leaf2"),
806 /// ]),
807 /// ],
808 /// );
809 ///
810 /// // Find all atomic (leaf) patterns
811 /// let leaves = pattern.filter(|p| p.is_atomic());
812 /// assert_eq!(leaves.len(), 2); // leaf1, leaf2
813 ///
814 /// // Find all patterns with specific value
815 /// let roots = pattern.filter(|p| p.value == "root");
816 /// assert_eq!(roots.len(), 1);
817 ///
818 /// // Find patterns with elements (non-atomic)
819 /// let branches = pattern.filter(|p| p.length() > 0);
820 /// assert_eq!(branches.len(), 2); // root, branch
821 /// ```
822 ///
823 /// # Pre-Order Traversal
824 ///
825 /// Results are returned in pre-order traversal order (root first, then elements in order):
826 ///
827 /// ```
828 /// use pattern_core::Pattern;
829 ///
830 /// let pattern = Pattern::pattern(1, vec![
831 /// Pattern::point(2),
832 /// Pattern::pattern(3, vec![Pattern::point(4)]),
833 /// Pattern::point(5),
834 /// ]);
835 ///
836 /// let all = pattern.filter(|_| true);
837 /// assert_eq!(all.len(), 5);
838 /// assert_eq!(all[0].value, 1); // root
839 /// assert_eq!(all[1].value, 2); // first element
840 /// assert_eq!(all[2].value, 3); // second element
841 /// assert_eq!(all[3].value, 4); // nested in second element
842 /// assert_eq!(all[4].value, 5); // third element
843 /// ```
844 ///
845 /// # Combining with Other Operations
846 ///
847 /// Filter can be combined with value predicates:
848 ///
849 /// ```
850 /// use pattern_core::Pattern;
851 ///
852 /// let pattern = Pattern::pattern(5, vec![
853 /// Pattern::point(10),
854 /// Pattern::pattern(3, vec![]),
855 /// ]);
856 ///
857 /// // Find patterns with large values
858 /// let large = pattern.filter(|p| p.value > 8);
859 /// assert_eq!(large.len(), 1); // Only point(10)
860 ///
861 /// // Find non-empty patterns with all values positive
862 /// let branches = pattern.filter(|p| {
863 /// p.length() > 0 && p.all_values(|v| *v > 0)
864 /// });
865 /// ```
866 ///
867 /// # Lifetime and References
868 ///
869 /// The returned references borrow from the source pattern and have the same lifetime:
870 ///
871 /// ```
872 /// use pattern_core::Pattern;
873 ///
874 /// let pattern = Pattern::pattern("a", vec![Pattern::point("b")]);
875 /// let matches = pattern.filter(|_| true);
876 /// // matches[0] and matches[1] borrow from pattern
877 /// // Cannot move or drop pattern while matches exist
878 /// ```
879 pub fn filter<F>(&self, predicate: F) -> Vec<&Pattern<V>>
880 where
881 F: Fn(&Pattern<V>) -> bool,
882 {
883 let mut result = Vec::new();
884 self.filter_recursive(&predicate, &mut result);
885 result
886 }
887
888 /// Helper function for recursive filter implementation.
889 ///
890 /// This performs a pre-order traversal, checking the current pattern first,
891 /// then recursively filtering elements.
892 fn filter_recursive<'a, F>(&'a self, predicate: &F, result: &mut Vec<&'a Pattern<V>>)
893 where
894 F: Fn(&Pattern<V>) -> bool,
895 {
896 // Check current pattern (pre-order: root first)
897 if predicate(self) {
898 result.push(self);
899 }
900
901 // Recursively filter elements
902 for element in &self.elements {
903 element.filter_recursive(predicate, result);
904 }
905 }
906
907 /// Finds the first subpattern (including self) that satisfies a predicate.
908 ///
909 /// This method performs a depth-first pre-order traversal of the pattern structure
910 /// (checking the root first, then elements recursively from left to right) and
911 /// returns the first pattern that satisfies the predicate.
912 ///
913 /// # Arguments
914 ///
915 /// * `predicate` - A function that takes a pattern reference and returns `true`
916 /// if it matches the search criteria. The predicate can examine both the
917 /// pattern's value and its structure (element count, depth, etc.).
918 ///
919 /// # Returns
920 ///
921 /// * `Some(&Pattern<V>)` - A reference to the first matching pattern
922 /// * `None` - If no pattern in the structure satisfies the predicate
923 ///
924 /// # Traversal Order
925 ///
926 /// The method uses depth-first pre-order traversal:
927 /// 1. Check the root pattern first
928 /// 2. Then check elements from left to right
929 /// 3. For each element, recursively apply the same order
930 ///
931 /// This ensures consistent, predictable ordering and matches the behavior
932 /// of other pattern traversal methods (`filter`, `fold`, `map`).
933 ///
934 /// # Short-Circuit Evaluation
935 ///
936 /// Unlike `filter`, which collects all matches, `find_first` stops immediately
937 /// upon finding the first match. This makes it more efficient when you only
938 /// need to know if a match exists or when you want the first occurrence.
939 ///
940 /// # Time Complexity
941 ///
942 /// * Best case: O(1) - if root matches
943 /// * Average case: O(k) - where k is position of first match
944 /// * Worst case: O(n) - if no match exists or match is last
945 ///
946 /// # Space Complexity
947 ///
948 /// O(d) where d is the maximum nesting depth (recursion stack)
949 ///
950 /// # Examples
951 ///
952 /// ## Finding by value
953 ///
954 /// ```
955 /// use pattern_core::Pattern;
956 ///
957 /// let pattern = Pattern::pattern("root", vec![
958 /// Pattern::point("child1"),
959 /// Pattern::point("target"),
960 /// ]);
961 ///
962 /// let result = pattern.find_first(|p| p.value == "target");
963 /// assert!(result.is_some());
964 /// assert_eq!(result.unwrap().value, "target");
965 /// ```
966 ///
967 /// ## Finding by structure
968 ///
969 /// ```
970 /// use pattern_core::Pattern;
971 ///
972 /// let pattern = Pattern::pattern("root", vec![
973 /// Pattern::pattern("branch", vec![
974 /// Pattern::point("leaf"),
975 /// ]),
976 /// Pattern::point("leaf2"),
977 /// ]);
978 ///
979 /// // Find first atomic pattern (no elements)
980 /// let leaf = pattern.find_first(|p| p.is_atomic());
981 /// assert!(leaf.is_some());
982 /// assert_eq!(leaf.unwrap().value, "leaf"); // First in pre-order
983 /// ```
984 ///
985 /// ## No match returns None
986 ///
987 /// ```
988 /// use pattern_core::Pattern;
989 ///
990 /// let pattern = Pattern::point("single");
991 /// let result = pattern.find_first(|p| p.value == "other");
992 /// assert!(result.is_none());
993 /// ```
994 ///
995 /// ## Combining value and structural predicates
996 ///
997 /// ```
998 /// use pattern_core::Pattern;
999 ///
1000 /// let pattern = Pattern::pattern(5, vec![
1001 /// Pattern::pattern(10, vec![
1002 /// Pattern::point(3),
1003 /// Pattern::point(7),
1004 /// ]),
1005 /// Pattern::point(15),
1006 /// ]);
1007 ///
1008 /// // Find first pattern with value > 8 AND has elements
1009 /// let result = pattern.find_first(|p| p.value > 8 && p.length() > 0);
1010 /// assert!(result.is_some());
1011 /// assert_eq!(result.unwrap().value, 10);
1012 /// ```
1013 ///
1014 /// ## Pre-order traversal demonstration
1015 ///
1016 /// ```
1017 /// use pattern_core::Pattern;
1018 ///
1019 /// let pattern = Pattern::pattern(1, vec![
1020 /// Pattern::pattern(2, vec![
1021 /// Pattern::point(3),
1022 /// ]),
1023 /// Pattern::point(4),
1024 /// ]);
1025 ///
1026 /// // Traversal order: 1 (root), 2, 3, 4
1027 /// // First pattern with value > 1 is 2 (not 3)
1028 /// let result = pattern.find_first(|p| p.value > 1);
1029 /// assert_eq!(result.unwrap().value, 2);
1030 /// ```
1031 ///
1032 /// ## Integration with other methods
1033 ///
1034 /// ```
1035 /// use pattern_core::Pattern;
1036 ///
1037 /// let pattern = Pattern::pattern(5, vec![
1038 /// Pattern::pattern(10, vec![
1039 /// Pattern::point(-3),
1040 /// Pattern::point(7),
1041 /// ]),
1042 /// Pattern::pattern(2, vec![
1043 /// Pattern::point(1),
1044 /// Pattern::point(4),
1045 /// ]),
1046 /// ]);
1047 ///
1048 /// // Find first pattern where all values are positive
1049 /// let result = pattern.find_first(|p| p.all_values(|v| *v > 0));
1050 /// assert!(result.is_some());
1051 /// assert_eq!(result.unwrap().value, 7); // First point with all positive values
1052 /// ```
1053 ///
1054 /// # Panics
1055 ///
1056 /// This method does not panic. All inputs are valid:
1057 /// - Works with atomic patterns (no elements)
1058 /// - Works with patterns with empty elements
1059 /// - Works with deeply nested structures (limited only by stack size)
1060 /// - Handles all predicate results gracefully
1061 ///
1062 /// # Relationship to Other Methods
1063 ///
1064 /// * `filter` - Returns all matches, `find_first` returns only the first
1065 /// * `any_value` - Operates on values only, `find_first` operates on whole patterns
1066 /// * Consistency: `find_first(p).is_some()` implies `filter(p).len() > 0`
1067 /// * Consistency: If `find_first(p) == Some(x)`, then `filter(p)[0] == x`
1068 pub fn find_first<F>(&self, predicate: F) -> Option<&Pattern<V>>
1069 where
1070 F: Fn(&Pattern<V>) -> bool,
1071 {
1072 self.find_first_recursive(&predicate)
1073 }
1074
1075 /// Helper function for recursive find_first implementation.
1076 ///
1077 /// This performs a pre-order traversal with early termination.
1078 /// Checks the current pattern first, then recursively searches elements.
1079 ///
1080 /// Returns `Some(&Pattern<V>)` on first match, `None` if no match found.
1081 fn find_first_recursive<'a, F>(&'a self, predicate: &F) -> Option<&'a Pattern<V>>
1082 where
1083 F: Fn(&Pattern<V>) -> bool,
1084 {
1085 // Check current pattern first (pre-order: root first)
1086 if predicate(self) {
1087 return Some(self);
1088 }
1089
1090 // Recursively search elements (with early termination)
1091 for element in &self.elements {
1092 if let Some(found) = element.find_first_recursive(predicate) {
1093 return Some(found);
1094 }
1095 }
1096
1097 // No match found
1098 None
1099 }
1100
1101 /// Checks if two patterns have identical structure.
1102 ///
1103 /// This method performs structural equality checking, comparing both values and
1104 /// element arrangement recursively. Two patterns match if and only if:
1105 /// - Their values are equal (using `PartialEq`)
1106 /// - They have the same number of elements
1107 /// - All corresponding elements match recursively
1108 ///
1109 /// This is distinct from the `Eq` trait implementation and is intended for
1110 /// structural pattern matching operations. While currently equivalent to `==`
1111 /// for patterns where `V: Eq`, this method may diverge in the future to support
1112 /// wildcards, partial matching, or other pattern matching semantics.
1113 ///
1114 /// # Type Constraints
1115 ///
1116 /// Requires `V: PartialEq` so that values can be compared for equality.
1117 ///
1118 /// # Mathematical Properties
1119 ///
1120 /// * **Reflexive**: `p.matches(&p)` is always `true`
1121 /// * **Symmetric**: `p.matches(&q) == q.matches(&p)`
1122 /// * **Structural**: Distinguishes patterns with same values but different structures
1123 ///
1124 /// # Time Complexity
1125 ///
1126 /// * Best case: O(1) - if root values differ
1127 /// * Average case: O(min(n, m) / 2) - short-circuits on first mismatch
1128 /// * Worst case: O(min(n, m)) - if patterns are identical or differ only at end
1129 ///
1130 /// Where n and m are the number of nodes in each pattern.
1131 ///
1132 /// # Space Complexity
1133 ///
1134 /// O(min(d1, d2)) where d1 and d2 are the maximum nesting depths
1135 /// (recursion stack usage).
1136 ///
1137 /// # Examples
1138 ///
1139 /// ## Identical patterns match
1140 ///
1141 /// ```
1142 /// use pattern_core::Pattern;
1143 ///
1144 /// let p1 = Pattern::pattern("root", vec![
1145 /// Pattern::point("a"),
1146 /// Pattern::point("b"),
1147 /// ]);
1148 /// let p2 = Pattern::pattern("root", vec![
1149 /// Pattern::point("a"),
1150 /// Pattern::point("b"),
1151 /// ]);
1152 ///
1153 /// assert!(p1.matches(&p2));
1154 /// ```
1155 ///
1156 /// ## Self-matching (reflexive)
1157 ///
1158 /// ```
1159 /// use pattern_core::Pattern;
1160 ///
1161 /// let pattern = Pattern::point("a");
1162 /// assert!(pattern.matches(&pattern));
1163 /// ```
1164 ///
1165 /// ## Different values don't match
1166 ///
1167 /// ```
1168 /// use pattern_core::Pattern;
1169 ///
1170 /// let p1 = Pattern::point("a");
1171 /// let p2 = Pattern::point("b");
1172 /// assert!(!p1.matches(&p2));
1173 /// ```
1174 ///
1175 /// ## Different structures don't match
1176 ///
1177 /// ```
1178 /// use pattern_core::Pattern;
1179 ///
1180 /// let p1 = Pattern::pattern("a", vec![
1181 /// Pattern::point("b"),
1182 /// Pattern::point("c"),
1183 /// ]);
1184 /// let p2 = Pattern::pattern("a", vec![
1185 /// Pattern::pattern("b", vec![
1186 /// Pattern::point("c"),
1187 /// ]),
1188 /// ]);
1189 ///
1190 /// // Same flattened values ["a", "b", "c"] but different structure
1191 /// assert!(!p1.matches(&p2));
1192 /// ```
1193 ///
1194 /// ## Symmetry property
1195 ///
1196 /// ```
1197 /// use pattern_core::Pattern;
1198 ///
1199 /// let p1 = Pattern::point(42);
1200 /// let p2 = Pattern::point(99);
1201 ///
1202 /// // p1.matches(&p2) == p2.matches(&p1)
1203 /// assert_eq!(p1.matches(&p2), p2.matches(&p1));
1204 /// ```
1205 ///
1206 /// # Panics
1207 ///
1208 /// This method does not panic. All inputs are valid:
1209 /// - Works with atomic patterns
1210 /// - Works with patterns with empty elements
1211 /// - Works with deeply nested structures (limited only by stack size)
1212 ///
1213 /// # Relationship to Other Methods
1214 ///
1215 /// * **Eq trait**: Currently equivalent for `V: Eq`, may diverge in future
1216 /// * **contains**: `p.matches(&q)` implies `p.contains(&q)` (equality implies containment)
1217 pub fn matches(&self, other: &Pattern<V>) -> bool
1218 where
1219 V: PartialEq,
1220 {
1221 // Values must match
1222 if self.value != other.value {
1223 return false;
1224 }
1225
1226 // Element counts must match
1227 if self.elements.len() != other.elements.len() {
1228 return false;
1229 }
1230
1231 // All corresponding elements must match recursively
1232 self.elements
1233 .iter()
1234 .zip(other.elements.iter())
1235 .all(|(e1, e2)| e1.matches(e2))
1236 }
1237
1238 /// Checks if this pattern contains another pattern as a subpattern.
1239 ///
1240 /// This method searches the entire pattern structure to determine if the given
1241 /// subpattern appears anywhere within it. A pattern contains a subpattern if:
1242 /// - The pattern matches the subpattern (using `matches`), OR
1243 /// - Any of its elements contains the subpattern (recursive search)
1244 ///
1245 /// This provides a structural containment check that goes beyond simple equality,
1246 /// allowing you to test whether a pattern appears as part of a larger structure.
1247 ///
1248 /// # Type Constraints
1249 ///
1250 /// Requires `V: PartialEq` because it uses `matches` internally for comparison.
1251 ///
1252 /// # Mathematical Properties
1253 ///
1254 /// * **Reflexive**: `p.contains(&p)` is always `true` (self-containment)
1255 /// * **Transitive**: If `a.contains(&b)` and `b.contains(&c)`, then `a.contains(&c)`
1256 /// * **Weaker than matches**: `p.matches(&q)` implies `p.contains(&q)`, but not vice versa
1257 /// * **Not symmetric**: `p.contains(&q)` does NOT imply `q.contains(&p)`
1258 ///
1259 /// # Time Complexity
1260 ///
1261 /// * Best case: O(1) - if root matches subpattern
1262 /// * Average case: O(n * m / 2) - where n = container size, m = subpattern size
1263 /// * Worst case: O(n * m) - if subpattern not found or found at end
1264 ///
1265 /// # Space Complexity
1266 ///
1267 /// O(d) where d is the maximum nesting depth (recursion stack usage).
1268 ///
1269 /// # Examples
1270 ///
1271 /// ## Self-containment
1272 ///
1273 /// ```
1274 /// use pattern_core::Pattern;
1275 ///
1276 /// let pattern = Pattern::pattern("root", vec![
1277 /// Pattern::point("child"),
1278 /// ]);
1279 ///
1280 /// // Every pattern contains itself
1281 /// assert!(pattern.contains(&pattern));
1282 /// ```
1283 ///
1284 /// ## Direct element containment
1285 ///
1286 /// ```
1287 /// use pattern_core::Pattern;
1288 ///
1289 /// let pattern = Pattern::pattern("root", vec![
1290 /// Pattern::point("a"),
1291 /// Pattern::point("b"),
1292 /// ]);
1293 ///
1294 /// let subpattern = Pattern::point("a");
1295 /// assert!(pattern.contains(&subpattern));
1296 /// ```
1297 ///
1298 /// ## Nested descendant containment
1299 ///
1300 /// ```
1301 /// use pattern_core::Pattern;
1302 ///
1303 /// let pattern = Pattern::pattern("root", vec![
1304 /// Pattern::pattern("branch", vec![
1305 /// Pattern::point("leaf"),
1306 /// ]),
1307 /// ]);
1308 ///
1309 /// let subpattern = Pattern::point("leaf");
1310 /// assert!(pattern.contains(&subpattern));
1311 /// ```
1312 ///
1313 /// ## Non-existent subpattern
1314 ///
1315 /// ```
1316 /// use pattern_core::Pattern;
1317 ///
1318 /// let pattern = Pattern::pattern("root", vec![
1319 /// Pattern::point("a"),
1320 /// ]);
1321 ///
1322 /// let subpattern = Pattern::point("b");
1323 /// assert!(!pattern.contains(&subpattern));
1324 /// ```
1325 ///
1326 /// ## Transitivity
1327 ///
1328 /// ```
1329 /// use pattern_core::Pattern;
1330 ///
1331 /// let a = Pattern::pattern("a", vec![
1332 /// Pattern::pattern("b", vec![
1333 /// Pattern::point("c"),
1334 /// ]),
1335 /// ]);
1336 /// let b = Pattern::pattern("b", vec![
1337 /// Pattern::point("c"),
1338 /// ]);
1339 /// let c = Pattern::point("c");
1340 ///
1341 /// // If a contains b and b contains c, then a contains c
1342 /// assert!(a.contains(&b));
1343 /// assert!(b.contains(&c));
1344 /// assert!(a.contains(&c)); // Transitive
1345 /// ```
1346 ///
1347 /// ## Contains is weaker than matches
1348 ///
1349 /// ```
1350 /// use pattern_core::Pattern;
1351 ///
1352 /// let pattern = Pattern::pattern("root", vec![
1353 /// Pattern::pattern("branch", vec![
1354 /// Pattern::point("leaf"),
1355 /// ]),
1356 /// ]);
1357 /// let subpattern = Pattern::point("leaf");
1358 ///
1359 /// // pattern contains subpattern, but they don't match
1360 /// assert!(pattern.contains(&subpattern));
1361 /// assert!(!pattern.matches(&subpattern));
1362 /// ```
1363 ///
1364 /// # Panics
1365 ///
1366 /// This method does not panic. All inputs are valid:
1367 /// - Works with atomic patterns
1368 /// - Works with patterns with empty elements
1369 /// - Works with deeply nested structures (limited only by stack size)
1370 /// - Handles multiple occurrences correctly
1371 ///
1372 /// # Relationship to Other Methods
1373 ///
1374 /// * **matches**: `p.matches(&q)` implies `p.contains(&q)`, but not vice versa
1375 /// * **Short-circuit**: Returns `true` as soon as a match is found
1376 pub fn contains(&self, subpattern: &Pattern<V>) -> bool
1377 where
1378 V: PartialEq,
1379 {
1380 // Check if this pattern matches the subpattern
1381 if self.matches(subpattern) {
1382 return true;
1383 }
1384
1385 // Recursively check if any element contains the subpattern
1386 self.elements
1387 .iter()
1388 .any(|element| element.contains(subpattern))
1389 }
1390
1391 /// Maps a function over all values in the pattern, preserving structure.
1392 ///
1393 /// This is equivalent to Haskell's `fmap` for the Functor typeclass,
1394 /// but follows Rust naming conventions. The transformation applies to
1395 /// all values recursively while preserving the pattern structure
1396 /// (number of elements, nesting depth, element order).
1397 ///
1398 /// # Functor Laws
1399 ///
1400 /// This implementation satisfies the functor laws:
1401 /// - **Identity**: `pattern.map(|x| x.clone()) == pattern`
1402 /// - **Composition**: `pattern.map(|x| g(&f(x))) == pattern.map(f).map(g)`
1403 ///
1404 /// # Type Parameters
1405 ///
1406 /// * `W` - The output value type (can be different from `V`)
1407 /// * `F` - The transformation function type
1408 ///
1409 /// # Arguments
1410 ///
1411 /// * `f` - Transformation function that takes a reference to a value (`&V`)
1412 /// and returns a new value (`W`)
1413 ///
1414 /// # Returns
1415 ///
1416 /// A new `Pattern<W>` with the same structure but transformed values
1417 ///
1418 /// # Examples
1419 ///
1420 /// ## String transformation
1421 ///
1422 /// ```
1423 /// use pattern_core::Pattern;
1424 ///
1425 /// let pattern = Pattern::point("hello");
1426 /// let upper = pattern.map(|s| s.to_uppercase());
1427 /// assert_eq!(upper.value, "HELLO");
1428 /// ```
1429 ///
1430 /// ## Type conversion
1431 ///
1432 /// ```
1433 /// use pattern_core::Pattern;
1434 ///
1435 /// let numbers = Pattern::point(42);
1436 /// let strings = numbers.map(|n| n.to_string());
1437 /// assert_eq!(strings.value, "42");
1438 /// ```
1439 ///
1440 /// ## Nested patterns
1441 ///
1442 /// ```
1443 /// use pattern_core::Pattern;
1444 ///
1445 /// let pattern = Pattern::pattern("root", vec![
1446 /// Pattern::point("child1"),
1447 /// Pattern::point("child2"),
1448 /// ]);
1449 /// let upper = pattern.map(|s| s.to_uppercase());
1450 /// assert_eq!(upper.value, "ROOT");
1451 /// assert_eq!(upper.elements[0].value, "CHILD1");
1452 /// assert_eq!(upper.elements[1].value, "CHILD2");
1453 /// ```
1454 ///
1455 /// ## Composition
1456 ///
1457 /// ```
1458 /// use pattern_core::Pattern;
1459 ///
1460 /// let result = Pattern::point(5)
1461 /// .map(|n| n * 2)
1462 /// .map(|n| n + 1);
1463 /// assert_eq!(result.value, 11);
1464 /// ```
1465 ///
1466 /// # Performance
1467 ///
1468 /// - Time complexity: O(n) where n is the total number of nodes
1469 /// - Space complexity: O(n) for the new pattern + O(d) for recursion stack
1470 /// where d is the maximum nesting depth
1471 /// - Handles patterns with 100+ nesting levels without stack overflow
1472 /// - Handles patterns with 10,000+ nodes efficiently
1473 pub fn map<W, F>(self, f: F) -> Pattern<W>
1474 where
1475 F: Fn(&V) -> W,
1476 {
1477 self.map_with(&f)
1478 }
1479
1480 /// Internal helper for map that takes function by reference.
1481 /// This enables efficient recursion without cloning the closure.
1482 fn map_with<W, F>(self, f: &F) -> Pattern<W>
1483 where
1484 F: Fn(&V) -> W,
1485 {
1486 Pattern {
1487 value: f(&self.value),
1488 elements: self
1489 .elements
1490 .into_iter()
1491 .map(|elem| elem.map_with(f))
1492 .collect(),
1493 }
1494 }
1495
1496 /// Folds the pattern into a single value by applying a function to each value with an accumulator.
1497 ///
1498 /// Processes values in depth-first, root-first order (pre-order traversal).
1499 /// The root value is processed first, then elements are processed left to right, recursively.
1500 /// Each value in the pattern is processed exactly once, and the accumulator is threaded through
1501 /// all processing steps.
1502 ///
1503 /// # Type Parameters
1504 ///
1505 /// * `B` - The accumulator type (can be different from `V`)
1506 /// * `F` - The folding function type
1507 ///
1508 /// # Arguments
1509 ///
1510 /// * `init` - Initial accumulator value
1511 /// * `f` - Folding function with signature `Fn(B, &V) -> B`
1512 /// - First parameter: Accumulator (passed by value)
1513 /// - Second parameter: Value reference (borrowed from pattern)
1514 /// - Returns: New accumulator value
1515 ///
1516 /// # Returns
1517 ///
1518 /// The final accumulated value of type `B`
1519 ///
1520 /// # Examples
1521 ///
1522 /// ## Sum all integers
1523 ///
1524 /// ```
1525 /// use pattern_core::Pattern;
1526 ///
1527 /// let pattern = Pattern::pattern(10, vec![
1528 /// Pattern::point(20),
1529 /// Pattern::point(30),
1530 /// ]);
1531 /// let sum = pattern.fold(0, |acc, v| acc + v);
1532 /// assert_eq!(sum, 60); // 10 + 20 + 30
1533 /// ```
1534 ///
1535 /// ## Count values
1536 ///
1537 /// ```
1538 /// use pattern_core::Pattern;
1539 ///
1540 /// let pattern = Pattern::pattern("root", vec![
1541 /// Pattern::point("child1"),
1542 /// Pattern::point("child2"),
1543 /// ]);
1544 /// let count = pattern.fold(0, |acc, _| acc + 1);
1545 /// assert_eq!(count, 3); // root + 2 children
1546 /// assert_eq!(count, pattern.size());
1547 /// ```
1548 ///
1549 /// ## Concatenate strings
1550 ///
1551 /// ```
1552 /// use pattern_core::Pattern;
1553 ///
1554 /// let pattern = Pattern::pattern("Hello", vec![
1555 /// Pattern::point(" "),
1556 /// Pattern::point("World"),
1557 /// ]);
1558 /// let result = pattern.fold(String::new(), |acc, s| acc + s);
1559 /// assert_eq!(result, "Hello World");
1560 /// ```
1561 ///
1562 /// ## Type transformation (string lengths to sum)
1563 ///
1564 /// ```
1565 /// use pattern_core::Pattern;
1566 ///
1567 /// let pattern = Pattern::pattern("hello", vec![
1568 /// Pattern::point("world"),
1569 /// Pattern::point("!"),
1570 /// ]);
1571 /// let total_length: usize = pattern.fold(0, |acc, s| acc + s.len());
1572 /// assert_eq!(total_length, 11); // 5 + 5 + 1
1573 /// ```
1574 ///
1575 /// ## Build a vector
1576 ///
1577 /// ```
1578 /// use pattern_core::Pattern;
1579 ///
1580 /// let pattern = Pattern::pattern(1, vec![
1581 /// Pattern::point(2),
1582 /// Pattern::point(3),
1583 /// ]);
1584 /// let values: Vec<i32> = pattern.fold(Vec::new(), |mut acc, v| {
1585 /// acc.push(*v);
1586 /// acc
1587 /// });
1588 /// assert_eq!(values, vec![1, 2, 3]);
1589 /// ```
1590 ///
1591 /// ## Verify traversal order
1592 ///
1593 /// ```
1594 /// use pattern_core::Pattern;
1595 ///
1596 /// let pattern = Pattern::pattern("A", vec![
1597 /// Pattern::point("B"),
1598 /// Pattern::pattern("C", vec![
1599 /// Pattern::point("D"),
1600 /// ]),
1601 /// ]);
1602 /// // Root first, then elements in order, depth-first
1603 /// let result = pattern.fold(String::new(), |acc, s| acc + s);
1604 /// assert_eq!(result, "ABCD");
1605 /// ```
1606 ///
1607 /// # Performance
1608 ///
1609 /// - Time complexity: O(n) where n is the total number of values
1610 /// - Space complexity: O(d) for recursion stack where d is the maximum nesting depth
1611 /// - Handles patterns with 100+ nesting levels without stack overflow
1612 /// - Handles patterns with 10,000+ nodes efficiently
1613 ///
1614 /// # Behavioral Guarantees
1615 ///
1616 /// 1. **Completeness**: Every value in the pattern is processed exactly once
1617 /// 2. **Order**: Values processed in depth-first, root-first order
1618 /// 3. **Non-destructive**: Pattern structure is not modified (borrows only)
1619 /// 4. **Reusability**: Pattern can be folded multiple times
1620 pub fn fold<B, F>(&self, init: B, f: F) -> B
1621 where
1622 F: Fn(B, &V) -> B,
1623 {
1624 self.fold_with(init, &f)
1625 }
1626
1627 /// Internal helper for fold that takes function by reference.
1628 ///
1629 /// This enables efficient recursion without cloning the closure.
1630 /// Public `fold` passes closure by value for ergonomics,
1631 /// internal `fold_with` passes closure by reference for efficiency.
1632 fn fold_with<B, F>(&self, acc: B, f: &F) -> B
1633 where
1634 F: Fn(B, &V) -> B,
1635 {
1636 // Process root value first
1637 let acc = f(acc, &self.value);
1638
1639 // Process elements recursively (left to right)
1640 self.elements
1641 .iter()
1642 .fold(acc, |acc, elem| elem.fold_with(acc, f))
1643 }
1644
1645 /// Collects all values from the pattern into a vector in traversal order.
1646 ///
1647 /// Returns references to all values in the pattern, maintaining depth-first,
1648 /// root-first order (same as `fold`). The root value appears first in the vector,
1649 /// followed by element values in traversal order.
1650 ///
1651 /// This method uses `fold` internally and is a convenience for the common case
1652 /// of collecting all pattern values into a standard collection.
1653 ///
1654 /// # Returns
1655 ///
1656 /// A `Vec<&V>` containing references to all values in traversal order
1657 ///
1658 /// # Examples
1659 ///
1660 /// ## Get all values
1661 ///
1662 /// ```
1663 /// use pattern_core::Pattern;
1664 ///
1665 /// let pattern = Pattern::pattern(1, vec![
1666 /// Pattern::point(2),
1667 /// Pattern::point(3),
1668 /// ]);
1669 /// let values: Vec<&i32> = pattern.values();
1670 /// assert_eq!(values, vec![&1, &2, &3]);
1671 /// assert_eq!(values.len(), pattern.size());
1672 /// ```
1673 ///
1674 /// ## Verify order
1675 ///
1676 /// ```
1677 /// use pattern_core::Pattern;
1678 ///
1679 /// let pattern = Pattern::pattern(1, vec![
1680 /// Pattern::point(2),
1681 /// Pattern::pattern(3, vec![
1682 /// Pattern::point(4),
1683 /// ]),
1684 /// ]);
1685 /// let values = pattern.values();
1686 /// assert_eq!(values, vec![&1, &2, &3, &4]);
1687 /// ```
1688 ///
1689 /// ## Use with Iterator methods
1690 ///
1691 /// ```
1692 /// use pattern_core::Pattern;
1693 ///
1694 /// let pattern = Pattern::pattern(1, vec![
1695 /// Pattern::point(2),
1696 /// Pattern::point(3),
1697 /// Pattern::point(4),
1698 /// ]);
1699 /// let sum: i32 = pattern.values().iter().map(|&&v| v).sum();
1700 /// assert_eq!(sum, 10);
1701 ///
1702 /// let all_positive = pattern.values().iter().all(|&&v| v > 0);
1703 /// assert!(all_positive);
1704 /// ```
1705 ///
1706 /// ## Nested patterns
1707 ///
1708 /// ```
1709 /// use pattern_core::Pattern;
1710 ///
1711 /// let pattern = Pattern::pattern(1, vec![
1712 /// Pattern::pattern(2, vec![
1713 /// Pattern::point(3),
1714 /// ]),
1715 /// ]);
1716 /// let values: Vec<&i32> = pattern.values();
1717 /// assert_eq!(values, vec![&1, &2, &3]);
1718 /// ```
1719 ///
1720 /// # Performance
1721 ///
1722 /// - Time complexity: O(n) where n is the total number of values
1723 /// - Space complexity: O(n) for the result vector
1724 /// - Efficient single-pass collection using fold
1725 pub fn values(&self) -> Vec<&V> {
1726 // Collect all values into a vector using fold
1727 let mut result = Vec::with_capacity(self.size());
1728 self.collect_values(&mut result);
1729 result
1730 }
1731
1732 /// Internal helper to recursively collect values into a vector.
1733 fn collect_values<'a>(&'a self, result: &mut Vec<&'a V>) {
1734 result.push(&self.value);
1735 for elem in &self.elements {
1736 elem.collect_values(result);
1737 }
1738 }
1739
1740 /// Paramorphism: structure-aware folding over patterns.
1741 ///
1742 /// Folds the pattern into a single value using a structure-aware folding function.
1743 /// Unlike `fold` (which only provides values), paramorphism gives the folding function
1744 /// access to the full pattern structure at each position, enabling sophisticated
1745 /// aggregations that consider depth, element count, and nesting level.
1746 ///
1747 /// # Type Parameters
1748 ///
1749 /// * `R` - Result type produced by the folding function (can differ from `V`)
1750 /// * `F` - Folding function type `Fn(&Pattern<V>, &[R]) -> R`
1751 ///
1752 /// # Parameters
1753 ///
1754 /// * `f` - Folding function with signature `Fn(&Pattern<V>, &[R]) -> R`
1755 /// - First parameter: Reference to the current pattern subtree
1756 /// - Second parameter: Slice of results from the pattern's elements (left-to-right order)
1757 /// - Returns: Result for this node (type `R`)
1758 ///
1759 /// # Returns
1760 ///
1761 /// The result produced by applying the folding function at the root after all elements
1762 /// have been processed recursively.
1763 ///
1764 /// # Semantics
1765 ///
1766 /// - **Evaluation order**: Bottom-up. For each node, para is first applied to all
1767 /// elements (left to right); then the folding function is called with the current
1768 /// pattern and the slice of those results.
1769 /// - **Atomic patterns**: If the pattern has no elements, the folding function receives
1770 /// an empty slice `&[]` for the second argument.
1771 /// - **Element order**: The slice of results is in the same order as `self.elements()`.
1772 /// - **Non-destructive**: The pattern is not modified. The pattern can be reused after the call.
1773 /// - **Single traversal**: Each node is visited exactly once.
1774 ///
1775 /// # Complexity
1776 ///
1777 /// - **Time**: O(n) where n = total number of nodes in the pattern
1778 /// - **Space**: O(n) for collecting element results (plus O(d) stack where d = max depth)
1779 ///
1780 /// # Relationship to Other Operations
1781 ///
1782 /// | Operation | Access | Use when |
1783 /// |-----------|--------|----------|
1784 /// | `fold` | Values only | Reducing to a single value without structure (e.g. sum, count) |
1785 /// | `para` | Pattern + element results | Structure-aware aggregation (e.g. depth-weighted sum) |
1786 /// | `extend` | Pattern for transformation | Structure-aware transformation returning new Pattern |
1787 ///
1788 /// # Examples
1789 ///
1790 /// ## Sum all values (equivalent to fold)
1791 ///
1792 /// ```
1793 /// use pattern_core::Pattern;
1794 ///
1795 /// let p = Pattern::pattern(10, vec![Pattern::point(5), Pattern::point(3)]);
1796 /// let sum: i32 = p.para(|pat, rs| *pat.value() + rs.iter().sum::<i32>());
1797 /// assert_eq!(sum, 18); // 10 + 5 + 3
1798 /// ```
1799 ///
1800 /// ## Depth-weighted sum
1801 ///
1802 /// ```
1803 /// use pattern_core::Pattern;
1804 ///
1805 /// let p = Pattern::pattern(10, vec![Pattern::point(5), Pattern::point(3)]);
1806 /// let depth_weighted: i32 = p.para(|pat, rs| {
1807 /// *pat.value() * pat.depth() as i32 + rs.iter().sum::<i32>()
1808 /// });
1809 /// // Root: 10*1 + (0+0) = 10
1810 /// // Elements are atomic (depth 0): 5*0=0, 3*0=0
1811 /// assert_eq!(depth_weighted, 10);
1812 /// ```
1813 ///
1814 /// ## Atomic pattern receives empty slice
1815 ///
1816 /// ```
1817 /// use pattern_core::Pattern;
1818 ///
1819 /// let atom = Pattern::point(42);
1820 /// let result = atom.para(|pat, rs| {
1821 /// assert!(rs.is_empty()); // Atomic pattern has no elements
1822 /// *pat.value()
1823 /// });
1824 /// assert_eq!(result, 42);
1825 /// ```
1826 ///
1827 /// ## Nesting statistics (sum, count, max_depth)
1828 ///
1829 /// ```
1830 /// use pattern_core::Pattern;
1831 ///
1832 /// let p = Pattern::pattern(1, vec![
1833 /// Pattern::pattern(2, vec![Pattern::point(3)]),
1834 /// ]);
1835 ///
1836 /// let (sum, count, max_depth): (i32, usize, usize) = p.para(|pat, rs| {
1837 /// let (child_sum, child_count, child_depth) = rs.iter()
1838 /// .fold((0_i32, 0_usize, 0_usize), |(s, c, d), (s2, c2, d2)| {
1839 /// (s + s2, c + c2, d.max(*d2))
1840 /// });
1841 /// (*pat.value() + child_sum, 1 + child_count, pat.depth().max(child_depth))
1842 /// });
1843 ///
1844 /// assert_eq!(sum, 6); // 1 + 2 + 3
1845 /// assert_eq!(count, 3); // 3 nodes total
1846 /// assert_eq!(max_depth, 2); // Maximum nesting depth (root -> pattern(2) -> point(3))
1847 /// ```
1848 ///
1849 /// # Reference
1850 ///
1851 /// Ported from gram-hs: `../pattern-hs/libs/pattern/src/Pattern/Core.hs` (lines 1188-1190)
1852 pub fn para<R, F>(&self, f: F) -> R
1853 where
1854 F: Fn(&Pattern<V>, &[R]) -> R,
1855 {
1856 self.para_with(&f)
1857 }
1858
1859 /// Internal helper for paramorphism that takes the folding function by reference.
1860 ///
1861 /// This avoids moving the closure on each recursive call, which would require
1862 /// the closure to be `Clone`. By taking `&F` instead of `F`, we can recursively
1863 /// call `para_with` without ownership issues.
1864 fn para_with<R, F>(&self, f: &F) -> R
1865 where
1866 F: Fn(&Pattern<V>, &[R]) -> R,
1867 {
1868 // Recursively compute results for all elements (left to right)
1869 let child_results: Vec<R> = self
1870 .elements
1871 .iter()
1872 .map(|child| child.para_with(f))
1873 .collect();
1874
1875 // Apply folding function to current pattern and element results
1876 f(self, &child_results)
1877 }
1878
1879 /// Validates pattern structure against configurable rules and constraints.
1880 ///
1881 /// Returns `Ok(())` if the pattern is valid according to the rules,
1882 /// or `Err(ValidationError)` if validation fails.
1883 ///
1884 /// # Arguments
1885 ///
1886 /// * `rules` - Validation rules to apply
1887 ///
1888 /// # Returns
1889 ///
1890 /// * `Ok(())` if pattern is valid
1891 /// * `Err(ValidationError)` if validation fails, containing detailed error information
1892 ///
1893 /// # Examples
1894 ///
1895 /// ```
1896 /// use pattern_core::{Pattern, ValidationRules};
1897 ///
1898 /// let pattern = Pattern::pattern("root".to_string(), vec![/* ... */]);
1899 ///
1900 /// let rules = ValidationRules {
1901 /// max_depth: Some(10),
1902 /// ..Default::default()
1903 /// };
1904 ///
1905 /// match pattern.validate(&rules) {
1906 /// Ok(()) => println!("Pattern is valid"),
1907 /// Err(e) => println!("Validation failed: {} at {:?}", e.message, e.location),
1908 /// }
1909 /// ```
1910 ///
1911 /// # Performance
1912 ///
1913 /// This operation is O(n) where n is the number of nodes in the pattern.
1914 /// Must handle at least 100 nesting levels without stack overflow.
1915 pub fn validate(&self, rules: &ValidationRules) -> Result<(), ValidationError> {
1916 self.validate_recursive(rules, 0, &mut Vec::new())
1917 }
1918
1919 /// Internal recursive validation helper
1920 fn validate_recursive(
1921 &self,
1922 rules: &ValidationRules,
1923 current_depth: usize,
1924 location: &mut Vec<String>,
1925 ) -> Result<(), ValidationError> {
1926 // Check max_depth constraint
1927 if let Some(max_depth) = rules.max_depth {
1928 if current_depth > max_depth {
1929 return Err(ValidationError {
1930 message: format!(
1931 "Pattern depth {} exceeds maximum allowed depth {}",
1932 current_depth, max_depth
1933 ),
1934 rule_violated: "max_depth".to_string(),
1935 location: location.clone(),
1936 });
1937 }
1938 }
1939
1940 // Check max_elements constraint at current level
1941 if let Some(max_elements) = rules.max_elements {
1942 if self.elements.len() > max_elements {
1943 return Err(ValidationError {
1944 message: format!(
1945 "Pattern has {} elements, exceeding maximum allowed {}",
1946 self.elements.len(),
1947 max_elements
1948 ),
1949 rule_violated: "max_elements".to_string(),
1950 location: location.clone(),
1951 });
1952 }
1953 }
1954
1955 // Recursively validate all elements
1956 for (index, element) in self.elements.iter().enumerate() {
1957 location.push("elements".to_string());
1958 location.push(index.to_string());
1959
1960 element.validate_recursive(rules, current_depth + 1, location)?;
1961
1962 location.pop(); // Remove index
1963 location.pop(); // Remove "elements"
1964 }
1965
1966 Ok(())
1967 }
1968
1969 /// Analyzes pattern structure and returns detailed information about structural characteristics.
1970 ///
1971 /// Provides comprehensive structural analysis including depth distribution, element counts,
1972 /// nesting patterns, and a human-readable summary.
1973 ///
1974 /// # Returns
1975 ///
1976 /// `StructureAnalysis` containing:
1977 /// - Depth distribution: Count of nodes at each depth level
1978 /// - Element counts: Maximum element count at each level (for pattern identification)
1979 /// - Nesting patterns: Identified structural patterns
1980 /// - Summary: Human-readable text summary
1981 ///
1982 /// # Examples
1983 ///
1984 /// ```
1985 /// use pattern_core::Pattern;
1986 ///
1987 /// let pattern = Pattern::pattern("root".to_string(), vec![/* ... */]);
1988 /// let analysis = pattern.analyze_structure();
1989 ///
1990 /// println!("Depth distribution: {:?}", analysis.depth_distribution);
1991 /// println!("Element counts: {:?}", analysis.element_counts);
1992 /// println!("Nesting patterns: {:?}", analysis.nesting_patterns);
1993 /// println!("Summary: {}", analysis.summary);
1994 /// ```
1995 ///
1996 /// # Performance
1997 ///
1998 /// This operation is O(n) where n is the number of nodes in the pattern.
1999 /// Must handle at least 100 nesting levels without stack overflow.
2000 /// Must handle at least 10,000 elements efficiently.
2001 pub fn analyze_structure(&self) -> StructureAnalysis {
2002 let mut depth_distribution = Vec::new();
2003 let mut element_counts = Vec::new();
2004
2005 self.analyze_recursive(0, &mut depth_distribution, &mut element_counts);
2006
2007 // Trim trailing zeros from element_counts (leaf levels with 0 elements)
2008 // According to spec: atomic pattern should have [], 2-level tree should have [count], not [count, 0]
2009 while let Some(&0) = element_counts.last() {
2010 element_counts.pop();
2011 }
2012
2013 // Identify nesting patterns
2014 let nesting_patterns = self.identify_nesting_patterns(&depth_distribution, &element_counts);
2015
2016 // Generate summary
2017 let summary =
2018 self.generate_summary(&depth_distribution, &element_counts, &nesting_patterns);
2019
2020 StructureAnalysis {
2021 depth_distribution,
2022 element_counts,
2023 nesting_patterns,
2024 summary,
2025 }
2026 }
2027
2028 /// Internal recursive analysis helper
2029 /// Tracks maximum element count at each level for pattern identification
2030 fn analyze_recursive(
2031 &self,
2032 current_depth: usize,
2033 depth_distribution: &mut Vec<usize>,
2034 element_counts: &mut Vec<usize>,
2035 ) {
2036 // Ensure vectors are large enough
2037 while depth_distribution.len() <= current_depth {
2038 depth_distribution.push(0);
2039 }
2040 while element_counts.len() <= current_depth {
2041 element_counts.push(0);
2042 }
2043
2044 // Count this node at current depth
2045 depth_distribution[current_depth] += 1;
2046
2047 // Track maximum element count at current level
2048 // Maximum is used for linear/tree pattern detection (all nodes <= 1 vs any node > 1)
2049 // For balanced patterns, we compare maximums across levels, which works correctly
2050 // with the fixed balanced pattern logic (ratio between 0.5 and 2.0)
2051 let current_count = self.elements.len();
2052 if current_count > element_counts[current_depth] {
2053 element_counts[current_depth] = current_count;
2054 }
2055
2056 // Recursively analyze elements
2057 for element in &self.elements {
2058 element.analyze_recursive(current_depth + 1, depth_distribution, element_counts);
2059 }
2060 }
2061
2062 /// Identify structural patterns from depth distribution and element counts
2063 fn identify_nesting_patterns(
2064 &self,
2065 depth_distribution: &[usize],
2066 element_counts: &[usize],
2067 ) -> Vec<String> {
2068 let mut patterns = Vec::new();
2069
2070 if depth_distribution.len() <= 1 {
2071 patterns.push("atomic".to_string());
2072 return patterns;
2073 }
2074
2075 // Check for linear pattern (one element per level)
2076 let is_linear = element_counts.iter().all(|&count| count <= 1);
2077 if is_linear {
2078 patterns.push("linear".to_string());
2079 }
2080
2081 // Check for tree-like pattern (multiple elements, decreasing with depth)
2082 let has_branching = element_counts.iter().any(|&count| count > 1);
2083 if has_branching {
2084 patterns.push("tree".to_string());
2085 }
2086
2087 // Check for balanced pattern (similar element counts across levels)
2088 // Balanced means counts are within 50% of each other (ratio between 0.5 and 2.0)
2089 // Note: element_counts already has trailing zeros trimmed, so all entries are non-zero
2090 if element_counts.len() >= 2 {
2091 let first_count = element_counts[0];
2092 if first_count > 0 {
2093 // Check all levels (trailing zeros already trimmed)
2094 let similar_counts = element_counts.iter().skip(1).all(|&count| {
2095 let ratio = count as f64 / first_count as f64;
2096 // Balanced if ratio is between 0.5 and 2.0 (within 50% of first_count)
2097 (0.5..=2.0).contains(&ratio)
2098 });
2099 if similar_counts && first_count > 1 {
2100 patterns.push("balanced".to_string());
2101 }
2102 }
2103 }
2104
2105 if patterns.is_empty() {
2106 patterns.push("irregular".to_string());
2107 }
2108
2109 patterns
2110 }
2111
2112 /// Generate human-readable summary of structure
2113 fn generate_summary(
2114 &self,
2115 depth_distribution: &[usize],
2116 _element_counts: &[usize], // Reserved for future use in summary generation
2117 nesting_patterns: &[String],
2118 ) -> String {
2119 let total_nodes: usize = depth_distribution.iter().sum();
2120 let max_depth = depth_distribution.len().saturating_sub(1);
2121 let pattern_desc = if nesting_patterns.is_empty() {
2122 "unknown"
2123 } else {
2124 &nesting_patterns[0]
2125 };
2126
2127 format!(
2128 "Pattern with {} level{}, {} node{}, {}-like structure",
2129 max_depth + 1,
2130 if max_depth == 0 { "" } else { "s" },
2131 total_nodes,
2132 if total_nodes == 1 { "" } else { "s" },
2133 pattern_desc
2134 )
2135 }
2136
2137 // ====================================================================================
2138 // Traversable Operations
2139 // ====================================================================================
2140
2141 /// Applies an effectful function returning `Option` to all values in the pattern.
2142 ///
2143 /// Traverses the pattern in depth-first, root-first order (pre-order traversal).
2144 /// If any transformation returns `None`, the entire operation returns `None`.
2145 /// If all transformations return `Some`, returns `Some(Pattern<W>)` with transformed values.
2146 ///
2147 /// This implements the Traversable pattern for Option, providing:
2148 /// - Structure preservation: Output pattern has same shape as input
2149 /// - Effect sequencing: Short-circuits on first None
2150 /// - All-or-nothing semantics: All values must be Some for success
2151 ///
2152 /// # Type Parameters
2153 ///
2154 /// * `W` - The type of transformed values
2155 /// * `F` - The transformation function type
2156 ///
2157 /// # Arguments
2158 ///
2159 /// * `f` - A function that transforms values of type `&V` to `Option<W>`
2160 ///
2161 /// # Returns
2162 ///
2163 /// * `Some(Pattern<W>)` if all transformations succeed
2164 /// * `None` if any transformation returns None (short-circuit)
2165 ///
2166 /// # Examples
2167 ///
2168 /// ```
2169 /// use pattern_core::Pattern;
2170 ///
2171 /// // Successful traversal - all values parse
2172 /// let pattern = Pattern::pattern("1", vec![Pattern::point("2")]);
2173 /// let result = pattern.traverse_option(|s| s.parse::<i32>().ok());
2174 /// assert!(result.is_some());
2175 /// assert_eq!(result.unwrap().value, 1);
2176 ///
2177 /// // Failed traversal - one value doesn't parse
2178 /// let pattern = Pattern::pattern("1", vec![Pattern::point("invalid")]);
2179 /// let result = pattern.traverse_option(|s| s.parse::<i32>().ok());
2180 /// assert!(result.is_none());
2181 /// ```
2182 ///
2183 /// # Traversable Laws
2184 ///
2185 /// This implementation satisfies the traversable laws:
2186 /// - Identity: `pattern.traverse_option(|v| Some(*v)) == Some(pattern.clone())`
2187 /// - Structure preservation: If successful, output has same size, depth, and length
2188 ///
2189 /// # Performance
2190 ///
2191 /// - Time: O(n) where n is the number of nodes
2192 /// - Space: O(n) for the new pattern + O(d) stack for recursion depth d
2193 /// - Short-circuits on first None without processing remaining values
2194 pub fn traverse_option<W, F>(&self, f: F) -> Option<Pattern<W>>
2195 where
2196 F: Fn(&V) -> Option<W>,
2197 {
2198 self.traverse_option_with(&f)
2199 }
2200
2201 /// Internal helper for `traverse_option` that takes function by reference.
2202 ///
2203 /// This enables efficient recursion without cloning the closure.
2204 /// Public `traverse_option` passes closure by value for ergonomics,
2205 /// internal `traverse_option_with` passes closure by reference for efficiency.
2206 fn traverse_option_with<W, F>(&self, f: &F) -> Option<Pattern<W>>
2207 where
2208 F: Fn(&V) -> Option<W>,
2209 {
2210 // Transform root value first (short-circuits on None via ?)
2211 let new_value = f(&self.value)?;
2212
2213 // Transform elements recursively (left to right)
2214 // Iterator::collect() handles Option sequencing - stops on first None
2215 let new_elements: Option<Vec<Pattern<W>>> = self
2216 .elements
2217 .iter()
2218 .map(|elem| elem.traverse_option_with(f))
2219 .collect();
2220
2221 // Construct new pattern with transformed value and elements
2222 Some(Pattern {
2223 value: new_value,
2224 elements: new_elements?,
2225 })
2226 }
2227
2228 /// Applies an effectful function returning `Result` to all values in the pattern.
2229 ///
2230 /// Traverses the pattern in depth-first, root-first order (pre-order traversal).
2231 /// If any transformation returns `Err`, the entire operation returns `Err` (short-circuits).
2232 /// If all transformations return `Ok`, returns `Ok(Pattern<W>)` with transformed values.
2233 ///
2234 /// This implements the Traversable pattern for Result, providing:
2235 /// - Structure preservation: Output pattern has same shape as input
2236 /// - Effect sequencing: Short-circuits on first Err
2237 /// - All-or-nothing semantics: All values must be Ok for success
2238 /// - Error propagation: First error encountered is returned
2239 ///
2240 /// # Type Parameters
2241 ///
2242 /// * `W` - The type of transformed values
2243 /// * `E` - The error type
2244 /// * `F` - The transformation function type
2245 ///
2246 /// # Arguments
2247 ///
2248 /// * `f` - A function that transforms values of type `&V` to `Result<W, E>`
2249 ///
2250 /// # Returns
2251 ///
2252 /// * `Ok(Pattern<W>)` if all transformations succeed
2253 /// * `Err(E)` with the first error encountered (short-circuit)
2254 ///
2255 /// # Examples
2256 ///
2257 /// ```
2258 /// use pattern_core::Pattern;
2259 ///
2260 /// // Successful traversal - all values parse
2261 /// let pattern = Pattern::pattern("1", vec![Pattern::point("2")]);
2262 /// let result: Result<Pattern<i32>, String> = pattern.traverse_result(|s| {
2263 /// s.parse::<i32>().map_err(|e| format!("parse error: {}", e))
2264 /// });
2265 /// assert!(result.is_ok());
2266 /// assert_eq!(result.unwrap().value, 1);
2267 ///
2268 /// // Failed traversal - one value doesn't parse
2269 /// let pattern = Pattern::pattern("1", vec![Pattern::point("invalid")]);
2270 /// let result: Result<Pattern<i32>, String> = pattern.traverse_result(|s| {
2271 /// s.parse::<i32>().map_err(|e| format!("parse error: {}", e))
2272 /// });
2273 /// assert!(result.is_err());
2274 /// ```
2275 ///
2276 /// # Traversable Laws
2277 ///
2278 /// This implementation satisfies the traversable laws:
2279 /// - Identity: `pattern.traverse_result(|v| Ok(*v)) == Ok(pattern.clone())`
2280 /// - Structure preservation: If successful, output has same size, depth, and length
2281 ///
2282 /// # Short-Circuiting
2283 ///
2284 /// The traversal stops immediately when the first error is encountered:
2285 /// - Root value is checked first
2286 /// - Elements are processed left-to-right
2287 /// - Nested patterns are traversed depth-first
2288 /// - No further values are processed after an error
2289 ///
2290 /// # Performance
2291 ///
2292 /// - Time: O(n) where n is the number of nodes (best case: O(1) if root errors)
2293 /// - Space: O(n) for the new pattern + O(d) stack for recursion depth d
2294 /// - Short-circuits on first Err without processing remaining values
2295 pub fn traverse_result<W, E, F>(&self, f: F) -> Result<Pattern<W>, E>
2296 where
2297 F: Fn(&V) -> Result<W, E>,
2298 {
2299 self.traverse_result_with(&f)
2300 }
2301
2302 /// Internal helper for `traverse_result` that takes function by reference.
2303 ///
2304 /// This enables efficient recursion without cloning the closure.
2305 /// Public `traverse_result` passes closure by value for ergonomics,
2306 /// internal `traverse_result_with` passes closure by reference for efficiency.
2307 fn traverse_result_with<W, E, F>(&self, f: &F) -> Result<Pattern<W>, E>
2308 where
2309 F: Fn(&V) -> Result<W, E>,
2310 {
2311 // Transform root value first (short-circuits on Err via ?)
2312 let new_value = f(&self.value)?;
2313
2314 // Transform elements recursively (left to right)
2315 // Iterator::collect() handles Result sequencing - stops on first Err
2316 let new_elements: Result<Vec<Pattern<W>>, E> = self
2317 .elements
2318 .iter()
2319 .map(|elem| elem.traverse_result_with(f))
2320 .collect();
2321
2322 // Construct new pattern with transformed value and elements
2323 Ok(Pattern {
2324 value: new_value,
2325 elements: new_elements?,
2326 })
2327 }
2328}
2329
2330impl<V: Clone> Pattern<Option<V>> {
2331 /// Flips the layers of structure from `Pattern<Option<V>>` to `Option<Pattern<V>>`.
2332 ///
2333 /// This is the `sequence` operation for Option, which "sequences" or "flips" the
2334 /// nested structure layers. If all values in the pattern are `Some`, returns
2335 /// `Some(Pattern<V>)` with the unwrapped values. If any value is `None`, returns `None`.
2336 ///
2337 /// This operation is equivalent to `traverse_option` with the identity function,
2338 /// and demonstrates the relationship: `sequence = traverse(id)`.
2339 ///
2340 /// # Type Parameters
2341 ///
2342 /// * `V` - The type inside the Option values (must implement Clone)
2343 ///
2344 /// # Returns
2345 ///
2346 /// * `Some(Pattern<V>)` if all values are Some (unwrapped)
2347 /// * `None` if any value in the pattern is None
2348 ///
2349 /// # Examples
2350 ///
2351 /// ```
2352 /// use pattern_core::Pattern;
2353 ///
2354 /// // All Some values → Some(Pattern)
2355 /// let pattern = Pattern::pattern(Some(1), vec![Pattern::point(Some(2))]);
2356 /// let result = pattern.sequence_option();
2357 /// assert!(result.is_some());
2358 /// assert_eq!(result.unwrap().value, 1);
2359 ///
2360 /// // Any None → None
2361 /// let pattern = Pattern::pattern(Some(1), vec![Pattern::point(None)]);
2362 /// let result = pattern.sequence_option();
2363 /// assert!(result.is_none());
2364 /// ```
2365 ///
2366 /// # All-or-Nothing Semantics
2367 ///
2368 /// - If all values are `Some`, returns `Some` with unwrapped pattern
2369 /// - If any value is `None`, returns `None` (short-circuits)
2370 /// - Preserves pattern structure when successful
2371 ///
2372 /// # Use Cases
2373 ///
2374 /// - Converting `Pattern<Option<V>>` from multiple optional lookups into `Option<Pattern<V>>`
2375 /// - Validating that all values in a pattern are present
2376 /// - Implementing all-or-nothing processing for optional data
2377 ///
2378 /// # Performance
2379 ///
2380 /// - Time: O(n) where n is the number of nodes (best case: O(1) if root is None)
2381 /// - Space: O(n) for the new pattern + O(d) stack for recursion depth d
2382 /// - Short-circuits on first None without processing remaining values
2383 pub fn sequence_option(self) -> Option<Pattern<V>> {
2384 self.traverse_option(|opt| opt.as_ref().cloned())
2385 }
2386}
2387
2388impl<V, E> Pattern<Result<V, E>> {
2389 /// Flips the layers of structure from `Pattern<Result<V, E>>` to `Result<Pattern<V>, E>`.
2390 ///
2391 /// This is the `sequence` operation for Result, which "sequences" or "flips" the
2392 /// nested structure layers. If all values in the pattern are `Ok`, returns
2393 /// `Ok(Pattern<V>)` with the unwrapped values. If any value is `Err`, returns that `Err`.
2394 ///
2395 /// This operation is equivalent to `traverse_result` with the identity function,
2396 /// and demonstrates the relationship: `sequence = traverse(id)`.
2397 ///
2398 /// # Type Parameters
2399 ///
2400 /// * `V` - The success type inside the Result values
2401 /// * `E` - The error type
2402 ///
2403 /// # Returns
2404 ///
2405 /// * `Ok(Pattern<V>)` if all values are Ok (unwrapped)
2406 /// * `Err(E)` with the first error encountered
2407 ///
2408 /// # Examples
2409 ///
2410 /// ```
2411 /// use pattern_core::Pattern;
2412 ///
2413 /// // All Ok values → Ok(Pattern)
2414 /// let pattern: Pattern<Result<i32, String>> = Pattern::pattern(
2415 /// Ok(1),
2416 /// vec![Pattern::point(Ok(2))]
2417 /// );
2418 /// let result = pattern.sequence_result();
2419 /// assert!(result.is_ok());
2420 /// assert_eq!(result.unwrap().value, 1);
2421 ///
2422 /// // Any Err → Err
2423 /// let pattern: Pattern<Result<i32, String>> = Pattern::pattern(
2424 /// Ok(1),
2425 /// vec![Pattern::point(Err("error".to_string()))]
2426 /// );
2427 /// let result = pattern.sequence_result();
2428 /// assert!(result.is_err());
2429 /// ```
2430 ///
2431 /// # All-or-Nothing Semantics
2432 ///
2433 /// - If all values are `Ok`, returns `Ok` with unwrapped pattern
2434 /// - If any value is `Err`, returns first `Err` encountered (short-circuits)
2435 /// - Preserves pattern structure when successful
2436 ///
2437 /// # Use Cases
2438 ///
2439 /// - Converting `Pattern<Result<V, E>>` from multiple fallible operations into `Result<Pattern<V>, E>`
2440 /// - Validating that all operations in a pattern succeeded
2441 /// - Implementing all-or-nothing processing for fallible operations
2442 ///
2443 /// # Performance
2444 ///
2445 /// - Time: O(n) where n is the number of nodes (best case: O(1) if root is Err)
2446 /// - Space: O(n) for the new pattern + O(d) stack for recursion depth d
2447 /// - Short-circuits on first Err without processing remaining values
2448 pub fn sequence_result(self) -> Result<Pattern<V>, E>
2449 where
2450 V: Clone,
2451 E: Clone,
2452 {
2453 self.traverse_result(|res| res.clone())
2454 }
2455}
2456
2457impl<V> Pattern<V> {
2458 /// Applies a validation function to all values and collects ALL errors.
2459 ///
2460 /// Unlike `traverse_result` which short-circuits on the first error, `validate_all`
2461 /// processes the entire pattern and collects all errors encountered. This is useful
2462 /// for comprehensive validation where you want to report all issues at once.
2463 ///
2464 /// Traverses in depth-first, root-first order (pre-order). If all validations succeed,
2465 /// returns `Ok(Pattern<W>)` with transformed values. If any validation fails, returns
2466 /// `Err(Vec<E>)` with ALL errors collected in traversal order.
2467 ///
2468 /// # Type Parameters
2469 ///
2470 /// * `W` - The type of transformed values
2471 /// * `E` - The error type
2472 /// * `F` - The validation function type
2473 ///
2474 /// # Arguments
2475 ///
2476 /// * `f` - A function that validates and transforms values of type `&V` to `Result<W, E>`
2477 ///
2478 /// # Returns
2479 ///
2480 /// * `Ok(Pattern<W>)` if all validations succeed
2481 /// * `Err(Vec<E>)` with ALL errors collected in traversal order
2482 ///
2483 /// # Examples
2484 ///
2485 /// ```
2486 /// use pattern_core::Pattern;
2487 ///
2488 /// // All validations succeed
2489 /// let pattern = Pattern::pattern(1, vec![Pattern::point(2), Pattern::point(3)]);
2490 /// let result: Result<Pattern<i32>, Vec<String>> = pattern.validate_all(|v| {
2491 /// if *v > 0 { Ok(*v * 10) } else { Err(format!("negative: {}", v)) }
2492 /// });
2493 /// assert!(result.is_ok());
2494 ///
2495 /// // Multiple validations fail - ALL errors collected
2496 /// let pattern = Pattern::pattern(-1, vec![Pattern::point(2), Pattern::point(-3)]);
2497 /// let result: Result<Pattern<i32>, Vec<String>> = pattern.validate_all(|v| {
2498 /// if *v > 0 { Ok(*v * 10) } else { Err(format!("negative: {}", v)) }
2499 /// });
2500 /// assert!(result.is_err());
2501 /// let errors = result.unwrap_err();
2502 /// assert_eq!(errors.len(), 2); // Both -1 and -3 reported
2503 /// ```
2504 ///
2505 /// # Comparison with traverse_result
2506 ///
2507 /// **traverse_result**: Returns first error (short-circuits)
2508 /// - Use when: You want to fail fast and stop processing
2509 /// - Performance: O(1) to O(n) depending on error location
2510 /// - Behavior: Stops at first error
2511 ///
2512 /// **validate_all**: Returns ALL errors (no short-circuit)
2513 /// - Use when: You want comprehensive error reporting
2514 /// - Performance: Always O(n) - processes entire pattern
2515 /// - Behavior: Collects all errors, then returns
2516 ///
2517 /// # Error Ordering
2518 ///
2519 /// Errors are collected in traversal order (root first, then elements left to right).
2520 /// This provides predictable and consistent error reporting.
2521 ///
2522 /// # Performance
2523 ///
2524 /// - Time: Always O(n) where n is the number of nodes (no short-circuiting)
2525 /// - Space: O(n) for the new pattern + O(e) for error collection + O(d) stack depth
2526 /// - Processes every value regardless of errors
2527 pub fn validate_all<W, E, F>(&self, f: F) -> Result<Pattern<W>, Vec<E>>
2528 where
2529 F: Fn(&V) -> Result<W, E>,
2530 {
2531 self.validate_all_with(&f)
2532 }
2533
2534 /// Internal helper for `validate_all` that takes function by reference.
2535 ///
2536 /// This enables efficient recursion without cloning the closure.
2537 /// Collects errors during traversal and returns them all at the end.
2538 ///
2539 /// Uses a single-pass approach:
2540 /// 1. Apply function to all values once, collecting both successes and errors
2541 /// 2. If no errors: Build the transformed pattern from collected successes
2542 /// 3. If errors: Return all collected errors
2543 fn validate_all_with<W, E, F>(&self, f: &F) -> Result<Pattern<W>, Vec<E>>
2544 where
2545 F: Fn(&V) -> Result<W, E>,
2546 {
2547 // Helper to recursively collect all results in pre-order (root first, then elements)
2548 fn collect_results<V, W, E, F>(
2549 pattern: &Pattern<V>,
2550 f: &F,
2551 successes: &mut Vec<W>,
2552 errors: &mut Vec<E>,
2553 ) where
2554 F: Fn(&V) -> Result<W, E>,
2555 {
2556 // Process root value first
2557 match f(&pattern.value) {
2558 Ok(w) => successes.push(w),
2559 Err(e) => errors.push(e),
2560 }
2561
2562 // Process elements recursively (left to right)
2563 for elem in &pattern.elements {
2564 collect_results(elem, f, successes, errors);
2565 }
2566 }
2567
2568 // Single pass: apply function to all values, collecting results
2569 let mut successes = Vec::new();
2570 let mut errors = Vec::new();
2571 collect_results(self, f, &mut successes, &mut errors);
2572
2573 // If any errors occurred, return them all
2574 if !errors.is_empty() {
2575 return Err(errors);
2576 }
2577
2578 // All validations succeeded - rebuild pattern from collected values
2579 // Values are in pre-order, so we consume them in the same order
2580 fn rebuild<V, W>(pattern: &Pattern<V>, values: &mut impl Iterator<Item = W>) -> Pattern<W> {
2581 // Get root value (next in pre-order sequence)
2582 let value = values
2583 .next()
2584 .expect("validate_all: insufficient transformed values");
2585
2586 // Rebuild elements recursively
2587 let elements = pattern
2588 .elements
2589 .iter()
2590 .map(|elem| rebuild(elem, values))
2591 .collect();
2592
2593 Pattern { value, elements }
2594 }
2595
2596 Ok(rebuild(self, &mut successes.into_iter()))
2597 }
2598}
2599
2600// ============================================================================
2601// Ordering Trait Implementations
2602// ============================================================================
2603
2604/// `PartialOrd` implementation for `Pattern`.
2605///
2606/// Provides lexicographic ordering for patterns based on their structure.
2607/// Patterns are compared by their value first, then by their elements recursively.
2608///
2609/// This implementation follows the same semantics as the Haskell reference implementation
2610/// in `gram-hs/libs/pattern/src/Pattern/Core.hs`.
2611///
2612/// # Ordering Rules
2613///
2614/// 1. **Value-first comparison**: Compare pattern values first using the value type's `PartialOrd` instance
2615/// 2. **Element comparison**: If values are equal, compare element vectors lexicographically
2616/// 3. **Lexicographic elements**: Elements are compared left-to-right, stopping at first difference
2617/// 4. **Length comparison**: If all compared elements are equal, shorter < longer
2618///
2619/// # Examples
2620///
2621/// ```
2622/// use pattern_core::Pattern;
2623///
2624/// // Comparing atomic patterns
2625/// let p1 = Pattern::point(1);
2626/// let p2 = Pattern::point(2);
2627/// assert!(p1 < p2);
2628///
2629/// // Comparing patterns with same value but different elements
2630/// let p3 = Pattern::pattern(5, vec![Pattern::point(1)]);
2631/// let p4 = Pattern::pattern(5, vec![Pattern::point(2)]);
2632/// assert!(p3 < p4); // Values equal, first element 1 < 2
2633///
2634/// // Value takes precedence over elements
2635/// let p5 = Pattern::pattern(3, vec![Pattern::point(100)]);
2636/// let p6 = Pattern::pattern(4, vec![Pattern::point(1)]);
2637/// assert!(p5 < p6); // 3 < 4, elements not compared
2638/// ```
2639///
2640/// # Comparison with Haskell
2641///
2642/// This implementation is behaviorally equivalent to the Haskell `Ord` instance:
2643///
2644/// ```haskell
2645/// instance Ord v => Ord (Pattern v) where
2646/// compare (Pattern v1 es1) (Pattern v2 es2) =
2647/// case compare v1 v2 of
2648/// EQ -> compare es1 es2
2649/// other -> other
2650/// ```
2651impl<V: PartialOrd> PartialOrd for Pattern<V> {
2652 /// Compares two patterns, returning `Some(ordering)` if comparable, `None` otherwise.
2653 ///
2654 /// Uses value-first lexicographic comparison:
2655 /// 1. Compare pattern values using `V::partial_cmp`
2656 /// 2. If equal (or both None), compare element vectors lexicographically
2657 /// 3. If values differ, return that ordering
2658 ///
2659 /// # Returns
2660 ///
2661 /// - `Some(Ordering::Less)` if `self < other`
2662 /// - `Some(Ordering::Equal)` if `self == other`
2663 /// - `Some(Ordering::Greater)` if `self > other`
2664 /// - `None` if values cannot be compared (e.g., NaN in floats)
2665 ///
2666 /// # Performance
2667 ///
2668 /// - **Best case**: O(1) - Values differ, immediate return
2669 /// - **Average case**: O(log n) - Finds difference early in elements
2670 /// - **Worst case**: O(n) - Must compare all nodes where n = total nodes
2671 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
2672 match self.value.partial_cmp(&other.value) {
2673 Some(Ordering::Equal) => self.elements.partial_cmp(&other.elements),
2674 other => other,
2675 }
2676 }
2677}
2678
2679/// `Ord` implementation for `Pattern`.
2680///
2681/// Provides total ordering for patterns where the value type implements `Ord`.
2682/// This enables patterns to be used as keys in ordered data structures like
2683/// `BTreeMap`, `BTreeSet`, and `BinaryHeap`.
2684///
2685/// # Ordering Rules
2686///
2687/// Same as `PartialOrd`:
2688/// 1. Compare values first
2689/// 2. If equal, compare elements lexicographically
2690///
2691/// # Properties
2692///
2693/// This implementation satisfies all `Ord` trait requirements:
2694///
2695/// - **Reflexivity**: `x.cmp(&x) == Ordering::Equal` for all x
2696/// - **Antisymmetry**: if `x.cmp(&y) == Less` then `y.cmp(&x) == Greater`
2697/// - **Transitivity**: if `x < y` and `y < z` then `x < z`
2698/// - **Totality**: For all x, y, exactly one of `x < y`, `x == y`, `x > y` holds
2699/// - **Consistency with Eq**: `x == y` implies `x.cmp(&y) == Equal`
2700///
2701/// These properties are verified through property-based tests.
2702///
2703/// # Examples
2704///
2705/// ```
2706/// use pattern_core::Pattern;
2707/// use std::cmp::Ordering;
2708///
2709/// let p1 = Pattern::point(1);
2710/// let p2 = Pattern::point(2);
2711///
2712/// // Using cmp directly
2713/// assert_eq!(p1.cmp(&p2), Ordering::Less);
2714///
2715/// // Using comparison operators
2716/// assert!(p1 < p2);
2717/// assert!(p1 <= p2);
2718/// assert!(p2 > p1);
2719/// assert!(p2 >= p1);
2720///
2721/// // Sorting collections
2722/// let mut patterns = vec![p2.clone(), p1.clone()];
2723/// patterns.sort();
2724/// assert_eq!(patterns, vec![p1, p2]);
2725/// ```
2726///
2727/// # Usage in Data Structures
2728///
2729/// ```
2730/// use pattern_core::Pattern;
2731/// use std::collections::{BTreeMap, BTreeSet};
2732///
2733/// // As BTreeSet elements
2734/// let mut set = BTreeSet::new();
2735/// set.insert(Pattern::point(3));
2736/// set.insert(Pattern::point(1));
2737/// set.insert(Pattern::point(2));
2738/// // Iteration in sorted order: 1, 2, 3
2739///
2740/// // As BTreeMap keys
2741/// let mut map = BTreeMap::new();
2742/// map.insert(Pattern::point(1), "first");
2743/// map.insert(Pattern::point(2), "second");
2744/// ```
2745impl<V: Ord> Ord for Pattern<V> {
2746 /// Compares two patterns, returning their ordering.
2747 ///
2748 /// Uses value-first lexicographic comparison:
2749 /// 1. Compare pattern values using `V::cmp`
2750 /// 2. If equal, compare element vectors lexicographically
2751 /// 3. If values differ, return that ordering
2752 ///
2753 /// This method always returns a definitive ordering (never None).
2754 ///
2755 /// # Performance
2756 ///
2757 /// - **Best case**: O(1) - Values differ, immediate return
2758 /// - **Average case**: O(log n) - Finds difference early in elements
2759 /// - **Worst case**: O(n) - Must compare all nodes where n = total nodes
2760 ///
2761 /// # Short-Circuit Optimization
2762 ///
2763 /// Comparison stops as soon as a difference is found:
2764 /// - If values differ, elements are never compared
2765 /// - If elements differ, remaining elements are not compared
2766 ///
2767 /// This provides efficient comparison even for large patterns.
2768 fn cmp(&self, other: &Self) -> Ordering {
2769 match self.value.cmp(&other.value) {
2770 Ordering::Equal => self.elements.cmp(&other.elements),
2771 non_equal => non_equal,
2772 }
2773 }
2774}
2775
2776// ============================================================================
2777// Pattern Combination
2778// ============================================================================
2779
2780impl<V: crate::Combinable> Pattern<V> {
2781 /// Combines two patterns associatively.
2782 ///
2783 /// Creates a new pattern by:
2784 /// 1. Combining the values using `V::combine`
2785 /// 2. Concatenating the element vectors (left first, then right)
2786 ///
2787 /// The operation is associative: `(a.combine(b)).combine(c)` equals `a.combine(b.combine(c))`.
2788 ///
2789 /// # Parameters
2790 ///
2791 /// * `self` - The first pattern (consumed)
2792 /// * `other` - The second pattern to combine with (consumed)
2793 ///
2794 /// # Returns
2795 ///
2796 /// A new `Pattern<V>` with:
2797 /// * `value`: Result of `self.value.combine(other.value)`
2798 /// * `elements`: Concatenation of `self.elements` and `other.elements`
2799 ///
2800 /// # Examples
2801 ///
2802 /// ## Atomic Patterns
2803 ///
2804 /// ```rust
2805 /// use pattern_core::Pattern;
2806 ///
2807 /// let p1 = Pattern::point("hello".to_string());
2808 /// let p2 = Pattern::point(" world".to_string());
2809 /// let result = p1.combine(p2);
2810 ///
2811 /// assert_eq!(result.value(), "hello world");
2812 /// assert_eq!(result.length(), 0); // No elements
2813 /// ```
2814 ///
2815 /// ## Patterns with Elements
2816 ///
2817 /// ```rust
2818 /// use pattern_core::Pattern;
2819 ///
2820 /// let p1 = Pattern::pattern("a".to_string(), vec![
2821 /// Pattern::point("b".to_string()),
2822 /// Pattern::point("c".to_string()),
2823 /// ]);
2824 ///
2825 /// let p2 = Pattern::pattern("d".to_string(), vec![
2826 /// Pattern::point("e".to_string()),
2827 /// ]);
2828 ///
2829 /// let result = p1.combine(p2);
2830 ///
2831 /// assert_eq!(result.value(), "ad");
2832 /// assert_eq!(result.length(), 3); // [b, c, e]
2833 /// ```
2834 ///
2835 /// ## Associativity
2836 ///
2837 /// ```rust
2838 /// use pattern_core::Pattern;
2839 ///
2840 /// let a = Pattern::point("a".to_string());
2841 /// let b = Pattern::point("b".to_string());
2842 /// let c = Pattern::point("c".to_string());
2843 ///
2844 /// let left = a.clone().combine(b.clone()).combine(c.clone());
2845 /// let right = a.combine(b.combine(c));
2846 ///
2847 /// assert_eq!(left, right); // Associativity holds
2848 /// ```
2849 ///
2850 /// # Performance
2851 ///
2852 /// * **Time Complexity**: O(|elements1| + |elements2| + value_combine_cost)
2853 /// * **Space Complexity**: O(|elements1| + |elements2|)
2854 ///
2855 /// Element concatenation uses `Vec::extend` for efficiency.
2856 ///
2857 /// **Benchmark Results** (on typical hardware):
2858 /// * Atomic patterns: ~100 ns
2859 /// * 100 elements: ~11 µs
2860 /// * 1000 elements: ~119 µs
2861 /// * 100-pattern fold: ~17 µs
2862 ///
2863 /// All operations complete in microseconds, making combination suitable
2864 /// for performance-critical applications.
2865 pub fn combine(self, other: Self) -> Self {
2866 // Step 1: Combine values using V's Combinable implementation
2867 let combined_value = self.value.combine(other.value);
2868
2869 // Step 2: Concatenate elements (left first, then right)
2870 let mut combined_elements = self.elements;
2871 combined_elements.extend(other.elements);
2872
2873 // Step 3: Return new pattern
2874 Pattern {
2875 value: combined_value,
2876 elements: combined_elements,
2877 }
2878 }
2879
2880 /// Creates patterns by combining three lists pointwise (zipWith3).
2881 ///
2882 /// Takes three lists of equal length and combines them element-wise to create
2883 /// new patterns. Each resulting pattern has:
2884 /// - **value**: From the `values` list
2885 /// - **elements**: A pair `[left, right]` from the corresponding positions
2886 ///
2887 /// This is useful for creating relationship patterns from separate lists of
2888 /// source nodes, target nodes, and relationship values.
2889 ///
2890 /// # Arguments
2891 ///
2892 /// * `left` - First list of patterns (e.g., source nodes)
2893 /// * `right` - Second list of patterns (e.g., target nodes)
2894 /// * `values` - List of values for the new patterns (e.g., relationship types)
2895 ///
2896 /// # Returns
2897 ///
2898 /// A vector of patterns where each pattern has value from `values` and
2899 /// elements `[left[i], right[i]]`.
2900 ///
2901 /// # Behavior
2902 ///
2903 /// - Stops at the length of the shortest input list
2904 /// - Consumes all three input vectors
2905 ///
2906 /// # Examples
2907 ///
2908 /// ```
2909 /// use pattern_core::Pattern;
2910 ///
2911 /// // Create relationship patterns
2912 /// let sources = vec![
2913 /// Pattern::point("Alice".to_string()),
2914 /// Pattern::point("Bob".to_string()),
2915 /// ];
2916 /// let targets = vec![
2917 /// Pattern::point("Company".to_string()),
2918 /// Pattern::point("Project".to_string()),
2919 /// ];
2920 /// let rel_types = vec!["WORKS_FOR".to_string(), "MANAGES".to_string()];
2921 ///
2922 /// let relationships = Pattern::zip3(sources, targets, rel_types);
2923 ///
2924 /// assert_eq!(relationships.len(), 2);
2925 /// assert_eq!(relationships[0].value, "WORKS_FOR");
2926 /// assert_eq!(relationships[0].elements.len(), 2);
2927 /// ```
2928 pub fn zip3(left: Vec<Pattern<V>>, right: Vec<Pattern<V>>, values: Vec<V>) -> Vec<Pattern<V>> {
2929 left.into_iter()
2930 .zip(right)
2931 .zip(values)
2932 .map(|((l, r), v)| Pattern::pattern(v, vec![l, r]))
2933 .collect()
2934 }
2935
2936 /// Creates patterns by applying a function to pairs from two lists (zipWith2).
2937 ///
2938 /// Takes two lists of patterns and applies a function to each pair to compute
2939 /// the value for the resulting pattern. Each resulting pattern has:
2940 /// - **value**: Computed by applying `value_fn` to the pair
2941 /// - **elements**: A pair `[left, right]` from the corresponding positions
2942 ///
2943 /// This is useful when relationship values are derived from the patterns being
2944 /// connected, rather than from a pre-computed list.
2945 ///
2946 /// # Arguments
2947 ///
2948 /// * `left` - First list of patterns (e.g., source nodes)
2949 /// * `right` - Second list of patterns (e.g., target nodes)
2950 /// * `value_fn` - Function that computes the value from each pair
2951 ///
2952 /// # Returns
2953 ///
2954 /// A vector of patterns where each pattern has value computed by `value_fn`
2955 /// and elements `[left[i], right[i]]`.
2956 ///
2957 /// # Behavior
2958 ///
2959 /// - Stops at the length of the shortest input list
2960 /// - Borrows patterns (uses references) to allow inspection without consuming
2961 ///
2962 /// # Examples
2963 ///
2964 /// ```
2965 /// use pattern_core::Pattern;
2966 ///
2967 /// let people = vec![
2968 /// Pattern::point("Alice".to_string()),
2969 /// Pattern::point("Bob".to_string()),
2970 /// ];
2971 /// let companies = vec![
2972 /// Pattern::point("TechCorp".to_string()),
2973 /// Pattern::point("StartupInc".to_string()),
2974 /// ];
2975 ///
2976 /// // Derive relationship type from patterns
2977 /// let relationships = Pattern::zip_with(people, companies, |person, company| {
2978 /// format!("{}_WORKS_AT_{}", person.value, company.value)
2979 /// });
2980 ///
2981 /// assert_eq!(relationships[0].value, "Alice_WORKS_AT_TechCorp");
2982 /// ```
2983 pub fn zip_with<F>(
2984 left: Vec<Pattern<V>>,
2985 right: Vec<Pattern<V>>,
2986 value_fn: F,
2987 ) -> Vec<Pattern<V>>
2988 where
2989 F: Fn(&Pattern<V>, &Pattern<V>) -> V,
2990 {
2991 left.into_iter()
2992 .zip(right)
2993 .map(|(l, r)| {
2994 let value = value_fn(&l, &r);
2995 Pattern::pattern(value, vec![l, r])
2996 })
2997 .collect()
2998 }
2999}
3000
3001// ============================================================================
3002// Default Trait Implementation - Identity Element for Monoid
3003// ============================================================================
3004
3005/// Provides a default (identity) pattern for value types that implement `Default`.
3006///
3007/// The default pattern serves as the identity element for pattern combination,
3008/// completing the monoid algebraic structure (associative operation + identity).
3009/// The default pattern has the default value for type `V` and an empty elements list.
3010///
3011/// # Monoid Laws
3012///
3013/// When combined with the [`Combinable`] trait, patterns form a complete monoid
3014/// satisfying these identity laws:
3015///
3016/// - **Left Identity**: `Pattern::default().combine(p) == p` for all patterns `p`
3017/// - **Right Identity**: `p.combine(Pattern::default()) == p` for all patterns `p`
3018///
3019/// These laws ensure that the default pattern acts as a neutral element: combining
3020/// any pattern with the default pattern (on either side) yields the original pattern
3021/// unchanged.
3022///
3023/// # Implementation
3024///
3025/// The default pattern is created using [`Pattern::point`] with the default value
3026/// for type `V`. This results in:
3027/// ```text
3028/// Pattern {
3029/// value: V::default(),
3030/// elements: vec![]
3031/// }
3032/// ```
3033///
3034/// # Examples
3035///
3036/// ## Basic Usage
3037///
3038/// ```rust
3039/// use pattern_core::Pattern;
3040///
3041/// // Create default pattern for String
3042/// let empty: Pattern<String> = Pattern::default();
3043/// assert_eq!(empty.value(), "");
3044/// assert_eq!(empty.length(), 0);
3045///
3046/// // Create default pattern for Vec<i32>
3047/// let empty: Pattern<Vec<i32>> = Pattern::default();
3048/// let expected: Vec<i32> = vec![];
3049/// assert_eq!(empty.value(), &expected);
3050/// assert_eq!(empty.length(), 0);
3051///
3052/// // Create default pattern for unit type
3053/// let empty: Pattern<()> = Pattern::default();
3054/// assert_eq!(empty.value(), &());
3055/// assert_eq!(empty.length(), 0);
3056/// ```
3057///
3058/// ## Identity Laws
3059///
3060/// ```rust
3061/// use pattern_core::{Pattern, Combinable};
3062///
3063/// let p = Pattern::point("hello".to_string());
3064/// let empty = Pattern::<String>::default();
3065///
3066/// // Left identity: empty.combine(p) == p
3067/// assert_eq!(empty.clone().combine(p.clone()), p);
3068///
3069/// // Right identity: p.combine(empty) == p
3070/// assert_eq!(p.clone().combine(empty.clone()), p);
3071/// ```
3072///
3073/// ## Usage with Iterators
3074///
3075/// ```rust
3076/// use pattern_core::{Pattern, Combinable};
3077///
3078/// let patterns = vec![
3079/// Pattern::point("hello".to_string()),
3080/// Pattern::point(" ".to_string()),
3081/// Pattern::point("world".to_string()),
3082/// ];
3083///
3084/// // Fold with default as initial value
3085/// let result = patterns.into_iter()
3086/// .fold(Pattern::default(), |acc, p| acc.combine(p));
3087///
3088/// assert_eq!(result.value(), "hello world");
3089/// ```
3090///
3091/// ## Handling Empty Collections
3092///
3093/// ```rust
3094/// use pattern_core::{Pattern, Combinable};
3095///
3096/// let empty_vec: Vec<Pattern<String>> = vec![];
3097///
3098/// // Folding empty collection returns default
3099/// let result = empty_vec.into_iter()
3100/// .fold(Pattern::default(), |acc, p| acc.combine(p));
3101///
3102/// assert_eq!(result, Pattern::default());
3103/// ```
3104///
3105/// # See Also
3106///
3107/// - [`Pattern::point`] - Used internally to create the default pattern
3108/// - [`Pattern::combine`] - The associative combination operation
3109/// - [`Combinable`] - Trait for types supporting associative combination
3110///
3111/// [`Combinable`]: crate::Combinable
3112impl<V> Default for Pattern<V>
3113where
3114 V: Default,
3115{
3116 /// Creates a default pattern with the default value and empty elements.
3117 ///
3118 /// This is the identity element for pattern combination operations.
3119 ///
3120 /// # Returns
3121 ///
3122 /// A pattern with `V::default()` as the value and an empty elements vector.
3123 ///
3124 /// # Examples
3125 ///
3126 /// ```rust
3127 /// use pattern_core::Pattern;
3128 ///
3129 /// let empty: Pattern<String> = Pattern::default();
3130 /// assert_eq!(empty.value(), "");
3131 /// assert_eq!(empty.length(), 0);
3132 /// assert!(empty.is_atomic());
3133 /// ```
3134 fn default() -> Self {
3135 Pattern::point(V::default())
3136 }
3137}
3138
3139// ============================================================================
3140// Hash Trait Implementation
3141// ============================================================================
3142
3143/// Provides hashing support for patterns where the value type implements `Hash`.
3144///
3145/// This enables patterns to be used as keys in `HashMap` and elements in `HashSet`,
3146/// enabling efficient pattern deduplication, caching, and set-based operations.
3147///
3148/// # Hash/Eq Consistency
3149///
3150/// This implementation guarantees that equal patterns produce equal hashes:
3151/// - If `p1 == p2`, then `hash(p1) == hash(p2)`
3152/// - This consistency is required for correct HashMap/HashSet behavior
3153///
3154/// # Structure-Preserving Hashing
3155///
3156/// The hash incorporates both the value and the element structure recursively:
3157/// - Different patterns with the same values produce different hashes
3158/// - The nesting structure and element order affect the hash
3159/// - Atomic patterns hash differently from compound patterns
3160///
3161/// # Implementation
3162///
3163/// The implementation hashes both components of a pattern:
3164/// 1. Hash the value using `V::hash`
3165/// 2. Hash the elements vector (which recursively hashes nested patterns)
3166///
3167/// This approach leverages `Vec<T>`'s built-in `Hash` implementation, which
3168/// automatically handles recursive hashing of nested patterns correctly.
3169///
3170/// # Type Constraints
3171///
3172/// Only patterns where `V: Hash` can be hashed. This means:
3173/// - ✅ `Pattern<String>` is hashable (String implements Hash)
3174/// - ✅ `Pattern<Symbol>` is hashable (Symbol implements Hash)
3175/// - ✅ `Pattern<i32>` is hashable (integers implement Hash)
3176/// - ❌ `Pattern<Subject>` is NOT hashable (Subject contains f64)
3177/// - ❌ `Pattern<f64>` is NOT hashable (floats don't implement Hash)
3178///
3179/// This is correct behavior - the type system prevents hashing types that
3180/// shouldn't be hashed due to problematic equality semantics (e.g., NaN != NaN for floats).
3181///
3182/// # Examples
3183///
3184/// ## Using Patterns in HashSet (Deduplication)
3185///
3186/// ```rust
3187/// use pattern_core::Pattern;
3188/// use std::collections::HashSet;
3189///
3190/// let p1 = Pattern::point("hello".to_string());
3191/// let p2 = Pattern::point("world".to_string());
3192/// let p3 = Pattern::point("hello".to_string()); // Duplicate of p1
3193///
3194/// let mut set = HashSet::new();
3195/// set.insert(p1);
3196/// set.insert(p2);
3197/// set.insert(p3); // Automatically deduplicated
3198///
3199/// assert_eq!(set.len(), 2); // Only unique patterns
3200/// ```
3201///
3202/// ## Using Patterns as HashMap Keys (Caching)
3203///
3204/// ```rust
3205/// use pattern_core::Pattern;
3206/// use std::collections::HashMap;
3207///
3208/// let mut cache: HashMap<Pattern<String>, i32> = HashMap::new();
3209///
3210/// let p1 = Pattern::point("key1".to_string());
3211/// let p2 = Pattern::point("key2".to_string());
3212///
3213/// cache.insert(p1.clone(), 42);
3214/// cache.insert(p2.clone(), 100);
3215///
3216/// assert_eq!(cache.get(&p1), Some(&42));
3217/// assert_eq!(cache.get(&p2), Some(&100));
3218/// ```
3219///
3220/// ## Hash Consistency with Equality
3221///
3222/// ```rust
3223/// use pattern_core::Pattern;
3224/// use std::collections::hash_map::DefaultHasher;
3225/// use std::hash::{Hash, Hasher};
3226///
3227/// fn hash_pattern<V: Hash>(p: &Pattern<V>) -> u64 {
3228/// let mut hasher = DefaultHasher::new();
3229/// p.hash(&mut hasher);
3230/// hasher.finish()
3231/// }
3232///
3233/// let p1 = Pattern::point("test".to_string());
3234/// let p2 = Pattern::point("test".to_string());
3235///
3236/// // Equal patterns have equal hashes
3237/// assert_eq!(p1, p2);
3238/// assert_eq!(hash_pattern(&p1), hash_pattern(&p2));
3239/// ```
3240///
3241/// ## Structure Distinguishes Hashes
3242///
3243/// ```rust
3244/// use pattern_core::Pattern;
3245/// use std::collections::hash_map::DefaultHasher;
3246/// use std::hash::{Hash, Hasher};
3247///
3248/// fn hash_pattern<V: Hash>(p: &Pattern<V>) -> u64 {
3249/// let mut hasher = DefaultHasher::new();
3250/// p.hash(&mut hasher);
3251/// hasher.finish()
3252/// }
3253///
3254/// // Same values, different structures
3255/// let atomic = Pattern::point("value".to_string());
3256/// let compound = Pattern::pattern(
3257/// "value".to_string(),
3258/// vec![Pattern::point("child".to_string())]
3259/// );
3260///
3261/// // Different structures produce different hashes
3262/// assert_ne!(atomic, compound);
3263/// // Note: Hash inequality is not guaranteed but expected
3264/// // (hash collisions are possible but rare)
3265/// ```
3266///
3267/// # Performance
3268///
3269/// - **Time Complexity**: O(n) where n is the total number of nodes in the pattern
3270/// - **Space Complexity**: O(1) (hash computation uses constant space)
3271/// - Hashing is typically very fast (microseconds even for large patterns)
3272/// - Results are cached in HashMap/HashSet (computed once per pattern)
3273///
3274/// # Comparison with Haskell
3275///
3276/// This implementation is behaviorally equivalent to the Haskell `Hashable` instance:
3277///
3278/// ```haskell
3279/// instance Hashable v => Hashable (Pattern v) where
3280/// hashWithSalt salt (Pattern v es) =
3281/// salt `hashWithSalt` v `hashWithSalt` es
3282/// ```
3283///
3284/// Both implementations hash the value and elements in the same order, ensuring
3285/// equivalent hash values for equivalent patterns.
3286///
3287/// # See Also
3288///
3289/// - `HashMap` - For using patterns as keys in hash-based maps
3290/// - `HashSet` - For pattern deduplication and set operations
3291/// - [`Pattern::combine`] - Pattern combination (works well with cached patterns)
3292/// - [`Eq`] - Equality trait that Hash must be consistent with
3293impl<V: Hash> Hash for Pattern<V> {
3294 /// Hashes this pattern into the provided hasher.
3295 ///
3296 /// Computes the hash by:
3297 /// 1. Hashing the value component
3298 /// 2. Hashing the elements vector (recursively hashes nested patterns)
3299 ///
3300 /// This ensures that equal patterns produce equal hashes while different
3301 /// structures produce different hashes.
3302 ///
3303 /// # Parameters
3304 ///
3305 /// * `state` - The hasher to write the hash into
3306 ///
3307 /// # Examples
3308 ///
3309 /// ```rust
3310 /// use pattern_core::Pattern;
3311 /// use std::collections::hash_map::DefaultHasher;
3312 /// use std::hash::{Hash, Hasher};
3313 ///
3314 /// let pattern = Pattern::point("test".to_string());
3315 ///
3316 /// let mut hasher = DefaultHasher::new();
3317 /// pattern.hash(&mut hasher);
3318 /// let hash_value = hasher.finish();
3319 /// ```
3320 fn hash<H: Hasher>(&self, state: &mut H) {
3321 self.value.hash(state);
3322 self.elements.hash(state);
3323 }
3324}
3325
3326// ============================================================================
3327// Paramorphism Tests
3328// ============================================================================
3329
3330#[cfg(test)]
3331mod para_tests {
3332 use super::*;
3333
3334 // ========================================================================
3335 // Phase 3: User Story 1 – Pattern-of-Elements Analysis
3336 // ========================================================================
3337
3338 /// T007: Atomic pattern receives empty slice
3339 #[test]
3340 fn para_atomic_pattern_receives_empty_slice() {
3341 let atom = Pattern::point(42);
3342 let result = atom.para(|p, rs| {
3343 // Verify atomic pattern has no elements
3344 assert!(rs.is_empty(), "Atomic pattern should receive empty slice");
3345 assert_eq!(
3346 p.elements().len(),
3347 0,
3348 "Atomic pattern should have no elements"
3349 );
3350 *p.value()
3351 });
3352 assert_eq!(result, 42);
3353 }
3354
3355 /// T008: Pattern with elements receives results in element order
3356 #[test]
3357 fn para_preserves_element_order() {
3358 // Build pattern: root(10) with elements [point(5), point(3), point(7)]
3359 let p = Pattern::pattern(
3360 10,
3361 vec![Pattern::point(5), Pattern::point(3), Pattern::point(7)],
3362 );
3363
3364 // Use para to collect values in pre-order (root first, then elements left-to-right)
3365 let values: Vec<i32> = p.para(|pat, child_results| {
3366 let mut result = vec![*pat.value()];
3367 for child_vec in child_results {
3368 result.extend(child_vec);
3369 }
3370 result
3371 });
3372
3373 // Should be: [10, 5, 3, 7] (root, then elements in order)
3374 assert_eq!(values, vec![10, 5, 3, 7]);
3375 }
3376
3377 /// T008 (additional): Nested pattern preserves element order
3378 #[test]
3379 fn para_preserves_element_order_nested() {
3380 // Build nested pattern:
3381 // root(1) with elements [
3382 // pattern(2) with [point(3), point(4)],
3383 // point(5)
3384 // ]
3385 let p = Pattern::pattern(
3386 1,
3387 vec![
3388 Pattern::pattern(2, vec![Pattern::point(3), Pattern::point(4)]),
3389 Pattern::point(5),
3390 ],
3391 );
3392
3393 // Collect values in pre-order
3394 let values: Vec<i32> = p.para(|pat, child_results| {
3395 let mut result = vec![*pat.value()];
3396 for child_vec in child_results {
3397 result.extend(child_vec);
3398 }
3399 result
3400 });
3401
3402 // Should be: [1, 2, 3, 4, 5] (pre-order traversal)
3403 assert_eq!(values, vec![1, 2, 3, 4, 5]);
3404 }
3405
3406 /// T009: Structure access – para can access pattern structure
3407 #[test]
3408 fn para_provides_structure_access() {
3409 // Build pattern with known structure
3410 // Root(10) with [Pattern(20, [Point(30)]), Point(40)]
3411 // Depth: 2 (root -> pattern(20) -> point(30))
3412 let p = Pattern::pattern(
3413 10,
3414 vec![
3415 Pattern::pattern(20, vec![Pattern::point(30)]),
3416 Pattern::point(40),
3417 ],
3418 );
3419
3420 // Test 1: Access depth at each position
3421 let depth_at_root = p.para(|pat, _| pat.depth());
3422 assert_eq!(depth_at_root, 2, "Root should have depth 2 (max nesting)");
3423
3424 // Test 2: Access element count at each position
3425 let element_count_at_root = p.para(|pat, _| pat.elements().len());
3426 assert_eq!(element_count_at_root, 2, "Root should have 2 elements");
3427
3428 // Test 3: Verify structure access matches direct calls
3429 assert_eq!(p.depth(), depth_at_root);
3430 assert_eq!(p.elements().len(), element_count_at_root);
3431 }
3432
3433 /// T009 (additional): Structure access for nested patterns
3434 #[test]
3435 fn para_structure_access_nested() {
3436 // Pattern structure:
3437 // Root(1) with [Pattern(2, [Point(3), Point(4)]), Point(5)]
3438 // Depth: 2 (root -> pattern(2) -> point(3/4))
3439 let p = Pattern::pattern(
3440 1,
3441 vec![
3442 Pattern::pattern(2, vec![Pattern::point(3), Pattern::point(4)]),
3443 Pattern::point(5),
3444 ],
3445 );
3446
3447 // Collect (value, depth, element_count) at each position
3448 type Info = (i32, usize, usize);
3449 let info: Info = p.para(|pat, child_infos: &[Info]| {
3450 let value = *pat.value();
3451 let depth = pat.depth();
3452 let elem_count = pat.elements().len();
3453
3454 // Verify child infos match expected structure
3455 if value == 1 {
3456 // Root: should have 2 children
3457 assert_eq!(child_infos.len(), 2);
3458 assert_eq!(child_infos[0].0, 2); // First child value
3459 assert_eq!(child_infos[1].0, 5); // Second child value
3460 } else if value == 2 {
3461 // Middle node: should have 2 children
3462 assert_eq!(child_infos.len(), 2);
3463 assert_eq!(child_infos[0].0, 3);
3464 assert_eq!(child_infos[1].0, 4);
3465 } else {
3466 // Leaf nodes: no children
3467 assert_eq!(child_infos.len(), 0);
3468 }
3469
3470 (value, depth, elem_count)
3471 });
3472
3473 assert_eq!(info.0, 1); // Root value
3474 assert_eq!(info.1, 2); // Root depth (max nesting: root -> pattern(2) -> point)
3475 assert_eq!(info.2, 2); // Root has 2 elements
3476 }
3477
3478 // ========================================================================
3479 // Phase 4: User Story 2 – Element-Count-Aware Computation
3480 // ========================================================================
3481
3482 /// T010: Element-count-weighted computation
3483 #[test]
3484 fn para_element_count_weighted_computation() {
3485 // Pattern: root(10) with [point(5), point(3)]
3486 // Formula: value * element_count + sum(element_results)
3487 // Expected: 10*2 + (5*0 + 3*0) = 20 + 0 = 20
3488 let p = Pattern::pattern(10, vec![Pattern::point(5), Pattern::point(3)]);
3489
3490 let result: i32 = p.para(|pat, rs| {
3491 let value = *pat.value();
3492 let elem_count = pat.elements().len() as i32;
3493 let element_sum: i32 = rs.iter().sum();
3494 value * elem_count + element_sum
3495 });
3496
3497 assert_eq!(result, 20, "Root: 10*2 + (0+0) = 20");
3498 }
3499
3500 /// T010 (additional): Element-count-weighted with nested pattern
3501 #[test]
3502 fn para_element_count_weighted_nested() {
3503 // Pattern: root(10) with [pattern(5, [point(2)]), point(3)]
3504 // Root: 10*2 + (middle_result + 0) = 20 + middle_result
3505 // Middle: 5*1 + (0) = 5
3506 // Expected: 20 + 5 = 25
3507 let p = Pattern::pattern(
3508 10,
3509 vec![
3510 Pattern::pattern(5, vec![Pattern::point(2)]),
3511 Pattern::point(3),
3512 ],
3513 );
3514
3515 let result: i32 = p.para(|pat, rs| {
3516 let value = *pat.value();
3517 let elem_count = pat.elements().len() as i32;
3518 let element_sum: i32 = rs.iter().sum();
3519 value * elem_count + element_sum
3520 });
3521
3522 // Root: 10*2 + (5 + 0) = 25
3523 // Middle pattern(5): 5*1 + 0 = 5
3524 // Leaves: 2*0=0, 3*0=0
3525 assert_eq!(result, 25);
3526 }
3527
3528 /// T011: Nested patterns with varying element counts
3529 #[test]
3530 fn para_varying_element_counts() {
3531 // Build pattern with varying element counts at each level:
3532 // root(1) with [
3533 // pattern(2, [point(3), point(4)]), // 2 elements
3534 // pattern(5, [point(6)]), // 1 element
3535 // point(7) // 0 elements
3536 // ]
3537 let p = Pattern::pattern(
3538 1,
3539 vec![
3540 Pattern::pattern(2, vec![Pattern::point(3), Pattern::point(4)]),
3541 Pattern::pattern(5, vec![Pattern::point(6)]),
3542 Pattern::point(7),
3543 ],
3544 );
3545
3546 // Aggregate element counts at each level
3547 type CountInfo = (i32, usize); // (value, total_element_count_in_subtree)
3548 let result: CountInfo = p.para(|pat, rs: &[CountInfo]| {
3549 let value = *pat.value();
3550 let elem_count = pat.elements().len();
3551 let subtree_count: usize = rs.iter().map(|(_, count)| count).sum();
3552 (value, elem_count + subtree_count)
3553 });
3554
3555 // Root has 3 direct elements
3556 // First element has 2 elements
3557 // Second element has 1 element
3558 // Third element has 0 elements
3559 // Total: 3 + 2 + 1 + 0 = 6
3560 assert_eq!(result.0, 1, "Root value should be 1");
3561 assert_eq!(
3562 result.1, 6,
3563 "Total element count across all levels should be 6"
3564 );
3565 }
3566
3567 /// T011 (additional): Element count aggregation with depth
3568 #[test]
3569 fn para_element_count_by_depth() {
3570 // Pattern: root(1) with [pattern(2, [point(3), point(4)]), point(5)]
3571 let p = Pattern::pattern(
3572 1,
3573 vec![
3574 Pattern::pattern(2, vec![Pattern::point(3), Pattern::point(4)]),
3575 Pattern::point(5),
3576 ],
3577 );
3578
3579 // Count elements at each depth level
3580 type DepthCounts = Vec<usize>; // counts[depth] = number of elements at that depth
3581 let result: DepthCounts = p.para(|pat, rs: &[DepthCounts]| {
3582 let elem_count = pat.elements().len();
3583 let max_depth = rs.iter().map(|v| v.len()).max().unwrap_or(0);
3584
3585 let mut counts = vec![0; max_depth + 1];
3586 counts[0] = elem_count; // Current level
3587
3588 // Aggregate from elements
3589 for child_counts in rs {
3590 for (depth, &count) in child_counts.iter().enumerate() {
3591 counts[depth + 1] += count;
3592 }
3593 }
3594
3595 counts
3596 });
3597
3598 // Depth 0 (root level): 2 elements [pattern(2), point(5)]
3599 // Depth 1 (pattern(2) level): 2 elements [point(3), point(4)]
3600 // Depth 2: 0 elements (all leaves)
3601 assert_eq!(result[0], 2, "Root has 2 elements");
3602 assert_eq!(result[1], 2, "Second level has 2 elements");
3603 }
3604
3605 // ========================================================================
3606 // Phase 5: User Story 3 – Nesting Statistics
3607 // ========================================================================
3608
3609 /// T012: Atomic pattern nesting statistics
3610 #[test]
3611 fn para_atomic_nesting_statistics() {
3612 let atom = Pattern::point(42);
3613
3614 // Compute (sum, count, max_depth) for atomic pattern
3615 type Stats = (i32, usize, usize);
3616 let stats: Stats = atom.para(|pat, rs: &[Stats]| {
3617 let value = *pat.value();
3618 let (child_sum, child_count, child_max_depth) = rs
3619 .iter()
3620 .fold((0_i32, 0_usize, 0_usize), |(s, c, d), (s2, c2, d2)| {
3621 (s + s2, c + c2, d.max(*d2))
3622 });
3623
3624 (
3625 value + child_sum,
3626 1 + child_count,
3627 pat.depth().max(child_max_depth),
3628 )
3629 });
3630
3631 assert_eq!(stats.0, 42, "Sum should be the value itself");
3632 assert_eq!(stats.1, 1, "Count should be 1 (single node)");
3633 assert_eq!(stats.2, 0, "Max depth should be 0 (atomic pattern)");
3634 }
3635
3636 /// T013: Nested pattern computing (sum, count, max_depth) in single traversal
3637 #[test]
3638 fn para_nested_nesting_statistics() {
3639 // Pattern: root(1) with [pattern(2, [point(3)]), point(4)]
3640 // Structure:
3641 // 1
3642 // ├─ 2
3643 // │ └─ 3
3644 // └─ 4
3645 let p = Pattern::pattern(
3646 1,
3647 vec![
3648 Pattern::pattern(2, vec![Pattern::point(3)]),
3649 Pattern::point(4),
3650 ],
3651 );
3652
3653 // Compute (sum, count, max_depth) in a single traversal
3654 type Stats = (i32, usize, usize);
3655 let stats: Stats = p.para(|pat, rs: &[Stats]| {
3656 let value = *pat.value();
3657 let (child_sum, child_count, child_max_depth) = rs
3658 .iter()
3659 .fold((0_i32, 0_usize, 0_usize), |(s, c, d), (s2, c2, d2)| {
3660 (s + s2, c + c2, d.max(*d2))
3661 });
3662
3663 (
3664 value + child_sum,
3665 1 + child_count,
3666 pat.depth().max(child_max_depth),
3667 )
3668 });
3669
3670 assert_eq!(stats.0, 10, "Sum: 1 + 2 + 3 + 4 = 10");
3671 assert_eq!(stats.1, 4, "Count: 4 nodes total");
3672 assert_eq!(stats.2, 2, "Max depth: 2 (root -> pattern(2) -> point(3))");
3673 }
3674
3675 /// T013 (additional): Complex nested pattern statistics
3676 #[test]
3677 fn para_complex_nesting_statistics() {
3678 // More complex pattern:
3679 // root(1) with [
3680 // pattern(2, [point(3), point(4)]),
3681 // pattern(5, [pattern(6, [point(7)])]),
3682 // point(8)
3683 // ]
3684 let p = Pattern::pattern(
3685 1,
3686 vec![
3687 Pattern::pattern(2, vec![Pattern::point(3), Pattern::point(4)]),
3688 Pattern::pattern(5, vec![Pattern::pattern(6, vec![Pattern::point(7)])]),
3689 Pattern::point(8),
3690 ],
3691 );
3692
3693 type Stats = (i32, usize, usize);
3694 let stats: Stats = p.para(|pat, rs: &[Stats]| {
3695 let value = *pat.value();
3696 let (child_sum, child_count, child_max_depth) = rs
3697 .iter()
3698 .fold((0_i32, 0_usize, 0_usize), |(s, c, d), (s2, c2, d2)| {
3699 (s + s2, c + c2, d.max(*d2))
3700 });
3701
3702 (
3703 value + child_sum,
3704 1 + child_count,
3705 pat.depth().max(child_max_depth),
3706 )
3707 });
3708
3709 // Sum: 1+2+3+4+5+6+7+8 = 36
3710 assert_eq!(stats.0, 36, "Sum of all values");
3711 // Count: 8 nodes
3712 assert_eq!(stats.1, 8, "Total node count");
3713 // Max depth: 3 (root -> pattern(5) -> pattern(6) -> point(7))
3714 assert_eq!(stats.2, 3, "Maximum nesting depth");
3715 }
3716
3717 /// T013 (additional): Verify single traversal efficiency
3718 #[test]
3719 fn para_single_traversal_statistics() {
3720 let p = Pattern::pattern(
3721 10,
3722 vec![
3723 Pattern::pattern(20, vec![Pattern::point(30), Pattern::point(40)]),
3724 Pattern::point(50),
3725 ],
3726 );
3727
3728 // Use a counter to verify single traversal
3729 use std::cell::RefCell;
3730 let visit_count = RefCell::new(0);
3731
3732 type Stats = (i32, usize, usize);
3733 let stats: Stats = p.para(|pat, rs: &[Stats]| {
3734 *visit_count.borrow_mut() += 1;
3735
3736 let value = *pat.value();
3737 let (child_sum, child_count, child_max_depth) = rs
3738 .iter()
3739 .fold((0_i32, 0_usize, 0_usize), |(s, c, d), (s2, c2, d2)| {
3740 (s + s2, c + c2, d.max(*d2))
3741 });
3742
3743 (
3744 value + child_sum,
3745 1 + child_count,
3746 pat.depth().max(child_max_depth),
3747 )
3748 });
3749
3750 // Verify statistics
3751 assert_eq!(stats.0, 150, "Sum: 10+20+30+40+50");
3752 assert_eq!(stats.1, 5, "Count: 5 nodes");
3753 assert_eq!(stats.2, 2, "Max depth: 2");
3754
3755 // Verify single traversal: each node visited exactly once
3756 assert_eq!(
3757 *visit_count.borrow(),
3758 5,
3759 "Should visit each node exactly once"
3760 );
3761 }
3762
3763 // ========================================================================
3764 // Phase 6: User Story 4 – Custom Structure-Aware Folding
3765 // ========================================================================
3766
3767 /// T014: Para simulates fold – equivalence test
3768 #[test]
3769 fn para_simulates_fold() {
3770 let p = Pattern::pattern(
3771 10,
3772 vec![
3773 Pattern::pattern(20, vec![Pattern::point(30), Pattern::point(40)]),
3774 Pattern::point(50),
3775 ],
3776 );
3777
3778 // Para version: sum all values
3779 let para_sum: i32 = p.para(|pat, rs| *pat.value() + rs.iter().sum::<i32>());
3780
3781 // Fold version: sum all values
3782 let fold_sum: i32 = p.fold(0, |acc, v| acc + v);
3783
3784 assert_eq!(para_sum, fold_sum, "Para should produce same sum as fold");
3785 assert_eq!(para_sum, 150, "Sum: 10+20+30+40+50 = 150");
3786 }
3787
3788 /// T014 (additional): Para simulates fold for different operations
3789 #[test]
3790 fn para_simulates_fold_product() {
3791 let p = Pattern::pattern(
3792 2,
3793 vec![
3794 Pattern::pattern(3, vec![Pattern::point(4)]),
3795 Pattern::point(5),
3796 ],
3797 );
3798
3799 // Para version: product of all values
3800 let para_product: i32 = p.para(|pat, rs| {
3801 let element_product: i32 = rs.iter().product();
3802 if element_product == 0 {
3803 *pat.value() // No elements, just the value
3804 } else {
3805 *pat.value() * element_product
3806 }
3807 });
3808
3809 // Fold version: product of all values
3810 let fold_product: i32 = p.fold(1, |acc, v| acc * v);
3811
3812 assert_eq!(
3813 para_product, fold_product,
3814 "Para should produce same product as fold"
3815 );
3816 assert_eq!(para_product, 120, "Product: 2*3*4*5 = 120");
3817 }
3818
3819 /// T015: Para preserves element order (toList property)
3820 #[test]
3821 fn para_preserves_order_tolist() {
3822 let p = Pattern::pattern(
3823 1,
3824 vec![
3825 Pattern::pattern(2, vec![Pattern::point(3), Pattern::point(4)]),
3826 Pattern::point(5),
3827 ],
3828 );
3829
3830 // Use para to build value list (pre-order: root first, then elements)
3831 let para_values: Vec<i32> = p.para(|pat, rs: &[Vec<i32>]| {
3832 let mut result = vec![*pat.value()];
3833 for child_vec in rs {
3834 result.extend(child_vec);
3835 }
3836 result
3837 });
3838
3839 // Expected pre-order: 1, 2, 3, 4, 5
3840 assert_eq!(
3841 para_values,
3842 vec![1, 2, 3, 4, 5],
3843 "Para should preserve pre-order"
3844 );
3845
3846 // Verify it matches values() method
3847 let values_method: Vec<i32> = p.values().into_iter().copied().collect();
3848 assert_eq!(
3849 para_values, values_method,
3850 "Para toList should match values()"
3851 );
3852 }
3853
3854 /// T015 (additional): Para order preservation with different structures
3855 #[test]
3856 fn para_order_preservation_wide() {
3857 // Wide pattern: many siblings
3858 let p = Pattern::pattern(
3859 0,
3860 vec![
3861 Pattern::point(1),
3862 Pattern::point(2),
3863 Pattern::point(3),
3864 Pattern::point(4),
3865 ],
3866 );
3867
3868 let para_values: Vec<i32> = p.para(|pat, rs: &[Vec<i32>]| {
3869 let mut result = vec![*pat.value()];
3870 for child_vec in rs {
3871 result.extend(child_vec);
3872 }
3873 result
3874 });
3875
3876 assert_eq!(
3877 para_values,
3878 vec![0, 1, 2, 3, 4],
3879 "Should preserve left-to-right order"
3880 );
3881 }
3882
3883 /// T016: Custom folding function with structure access
3884 #[test]
3885 fn para_custom_structure_aware_folding() {
3886 let p = Pattern::pattern(
3887 "root",
3888 vec![
3889 Pattern::pattern(
3890 "branch",
3891 vec![Pattern::point("leaf1"), Pattern::point("leaf2")],
3892 ),
3893 Pattern::point("leaf3"),
3894 ],
3895 );
3896
3897 // Custom folding: build a description of the structure
3898 type Description = String;
3899 let description: Description = p.para(|pat, rs: &[Description]| {
3900 let value = *pat.value();
3901 let elem_count = pat.elements().len();
3902 let depth = pat.depth();
3903
3904 if elem_count == 0 {
3905 // Atomic pattern
3906 format!("Leaf({})", value)
3907 } else {
3908 // Pattern with elements
3909 let children_desc = rs.join(", ");
3910 format!(
3911 "Node({}, depth={}, elements=[{}])",
3912 value, depth, children_desc
3913 )
3914 }
3915 });
3916
3917 // Verify structure description
3918 assert!(description.contains("root"), "Should mention root");
3919 assert!(description.contains("branch"), "Should mention branch");
3920 assert!(description.contains("leaf1"), "Should mention leaf1");
3921 assert!(description.contains("depth="), "Should include depth info");
3922 }
3923
3924 /// T016 (additional): Structure-aware transformation returning Pattern
3925 #[test]
3926 fn para_structure_preserving_transformation() {
3927 let p = Pattern::pattern(
3928 1,
3929 vec![
3930 Pattern::pattern(2, vec![Pattern::point(3)]),
3931 Pattern::point(4),
3932 ],
3933 );
3934
3935 // Use para to transform: multiply each value by its depth + 1
3936 let transformed: Pattern<i32> = p.para(|pat, rs: &[Pattern<i32>]| {
3937 let value = *pat.value();
3938 let depth = pat.depth();
3939 let new_value = value * (depth as i32 + 1);
3940
3941 Pattern::pattern(new_value, rs.to_vec())
3942 });
3943
3944 // Verify structure is preserved
3945 assert_eq!(transformed.size(), p.size(), "Size should be preserved");
3946 assert_eq!(transformed.depth(), p.depth(), "Depth should be preserved");
3947 assert_eq!(
3948 transformed.elements().len(),
3949 p.elements().len(),
3950 "Element count should be preserved"
3951 );
3952
3953 // Verify values are transformed correctly
3954 // Root (depth=2): 1 * 3 = 3
3955 assert_eq!(*transformed.value(), 3);
3956 }
3957
3958 /// T016 (additional): Para with complex custom logic
3959 #[test]
3960 fn para_complex_custom_logic() {
3961 let p = Pattern::pattern(
3962 10,
3963 vec![
3964 Pattern::pattern(20, vec![Pattern::point(30)]),
3965 Pattern::point(40),
3966 ],
3967 );
3968
3969 // Custom logic: compute weighted sum where each value is weighted by
3970 // (1 + number of descendants)
3971 type WeightedSum = (i32, usize); // (weighted_sum, descendant_count)
3972 let result: WeightedSum = p.para(|pat, rs: &[WeightedSum]| {
3973 let value = *pat.value();
3974 let (child_sum, child_descendants): (i32, usize) =
3975 rs.iter().fold((0, 0), |(s, d), (s2, d2)| (s + s2, d + d2));
3976
3977 let my_descendants = child_descendants + pat.elements().len();
3978 let my_weighted_value = value * (1 + my_descendants) as i32;
3979
3980 (my_weighted_value + child_sum, my_descendants)
3981 });
3982
3983 // Verify the computation
3984 // Leaf 30: 30 * 1 = 30, descendants=0
3985 // Leaf 40: 40 * 1 = 40, descendants=0
3986 // Branch 20: 20 * 2 = 40, descendants=1 (point 30)
3987 // Root 10: 10 * 4 = 40, descendants=3 (branch 20, point 30, point 40)
3988 // Total: 30 + 40 + 40 + 40 = 150
3989 assert_eq!(result.0, 150, "Weighted sum should be 150");
3990 assert_eq!(result.1, 3, "Root should have 3 descendants");
3991 }
3992}
3993
3994// ============================================================================
3995// Comonad Operations
3996// ============================================================================