Skip to main content

oxilean_meta/match_basic/
types.rs

1//! Auto-generated module
2//!
3//! 🤖 Generated with [SplitRS](https://github.com/cool-japan/splitrs)
4
5use oxilean_kernel::{Expr, Literal, Name};
6
7/// A typed slot for MatchBasic configuration.
8#[allow(dead_code)]
9#[derive(Debug, Clone)]
10pub enum MatchBasicConfigValue {
11    Bool(bool),
12    Int(i64),
13    Float(f64),
14    Str(String),
15    List(Vec<String>),
16}
17#[allow(dead_code)]
18impl MatchBasicConfigValue {
19    pub fn as_bool(&self) -> Option<bool> {
20        match self {
21            MatchBasicConfigValue::Bool(b) => Some(*b),
22            _ => None,
23        }
24    }
25    pub fn as_int(&self) -> Option<i64> {
26        match self {
27            MatchBasicConfigValue::Int(i) => Some(*i),
28            _ => None,
29        }
30    }
31    pub fn as_float(&self) -> Option<f64> {
32        match self {
33            MatchBasicConfigValue::Float(f) => Some(*f),
34            _ => None,
35        }
36    }
37    pub fn as_str(&self) -> Option<&str> {
38        match self {
39            MatchBasicConfigValue::Str(s) => Some(s),
40            _ => None,
41        }
42    }
43    pub fn as_list(&self) -> Option<&[String]> {
44        match self {
45            MatchBasicConfigValue::List(v) => Some(v),
46            _ => None,
47        }
48    }
49    pub fn type_name(&self) -> &'static str {
50        match self {
51            MatchBasicConfigValue::Bool(_) => "bool",
52            MatchBasicConfigValue::Int(_) => "int",
53            MatchBasicConfigValue::Float(_) => "float",
54            MatchBasicConfigValue::Str(_) => "str",
55            MatchBasicConfigValue::List(_) => "list",
56        }
57    }
58}
59/// A utility type for MatchBasic (index 12).
60#[allow(dead_code)]
61#[derive(Debug, Clone, Default)]
62pub struct MatchBasicUtil12 {
63    pub id: usize,
64    pub name: String,
65    pub value: i64,
66    pub enabled: bool,
67    pub tags: Vec<String>,
68}
69#[allow(dead_code)]
70impl MatchBasicUtil12 {
71    pub fn new(id: usize, name: &str, value: i64) -> Self {
72        MatchBasicUtil12 {
73            id,
74            name: name.to_string(),
75            value,
76            enabled: true,
77            tags: Vec::new(),
78        }
79    }
80    pub fn with_tag(mut self, tag: &str) -> Self {
81        self.tags.push(tag.to_string());
82        self
83    }
84    pub fn disable(mut self) -> Self {
85        self.enabled = false;
86        self
87    }
88    pub fn is_active(&self) -> bool {
89        self.enabled
90    }
91    pub fn score(&self) -> i64 {
92        if self.enabled {
93            self.value
94        } else {
95            0
96        }
97    }
98    pub fn tag_count(&self) -> usize {
99        self.tags.len()
100    }
101    pub fn has_tag(&self, tag: &str) -> bool {
102        self.tags.iter().any(|t| t == tag)
103    }
104}
105#[allow(dead_code)]
106pub struct MatchBasicExtPass4100 {
107    pub name: String,
108    pub total_runs: usize,
109    pub successes: usize,
110    pub errors: usize,
111    pub enabled: bool,
112    pub results: Vec<MatchBasicExtResult4100>,
113}
114impl MatchBasicExtPass4100 {
115    #[allow(dead_code)]
116    pub fn new(name: &str) -> Self {
117        Self {
118            name: name.to_string(),
119            total_runs: 0,
120            successes: 0,
121            errors: 0,
122            enabled: true,
123            results: Vec::new(),
124        }
125    }
126    #[allow(dead_code)]
127    pub fn run(&mut self, input: &str) -> MatchBasicExtResult4100 {
128        if !self.enabled {
129            return MatchBasicExtResult4100::Skipped;
130        }
131        self.total_runs += 1;
132        let result = if input.is_empty() {
133            self.errors += 1;
134            MatchBasicExtResult4100::Err(format!("empty input in pass '{}'", self.name))
135        } else {
136            self.successes += 1;
137            MatchBasicExtResult4100::Ok(format!(
138                "processed {} chars in pass '{}'",
139                input.len(),
140                self.name
141            ))
142        };
143        self.results.push(result.clone());
144        result
145    }
146    #[allow(dead_code)]
147    pub fn success_count(&self) -> usize {
148        self.successes
149    }
150    #[allow(dead_code)]
151    pub fn error_count(&self) -> usize {
152        self.errors
153    }
154    #[allow(dead_code)]
155    pub fn success_rate(&self) -> f64 {
156        if self.total_runs == 0 {
157            0.0
158        } else {
159            self.successes as f64 / self.total_runs as f64
160        }
161    }
162    #[allow(dead_code)]
163    pub fn disable(&mut self) {
164        self.enabled = false;
165    }
166    #[allow(dead_code)]
167    pub fn enable(&mut self) {
168        self.enabled = true;
169    }
170    #[allow(dead_code)]
171    pub fn clear_results(&mut self) {
172        self.results.clear();
173    }
174}
175#[allow(dead_code)]
176#[derive(Debug, Clone)]
177pub enum MatchBasicExtConfigVal4100 {
178    Bool(bool),
179    Int(i64),
180    Float(f64),
181    Str(String),
182    List(Vec<String>),
183}
184impl MatchBasicExtConfigVal4100 {
185    #[allow(dead_code)]
186    pub fn as_bool(&self) -> Option<bool> {
187        if let MatchBasicExtConfigVal4100::Bool(b) = self {
188            Some(*b)
189        } else {
190            None
191        }
192    }
193    #[allow(dead_code)]
194    pub fn as_int(&self) -> Option<i64> {
195        if let MatchBasicExtConfigVal4100::Int(i) = self {
196            Some(*i)
197        } else {
198            None
199        }
200    }
201    #[allow(dead_code)]
202    pub fn as_float(&self) -> Option<f64> {
203        if let MatchBasicExtConfigVal4100::Float(f) = self {
204            Some(*f)
205        } else {
206            None
207        }
208    }
209    #[allow(dead_code)]
210    pub fn as_str(&self) -> Option<&str> {
211        if let MatchBasicExtConfigVal4100::Str(s) = self {
212            Some(s)
213        } else {
214            None
215        }
216    }
217    #[allow(dead_code)]
218    pub fn as_list(&self) -> Option<&[String]> {
219        if let MatchBasicExtConfigVal4100::List(l) = self {
220            Some(l)
221        } else {
222            None
223        }
224    }
225    #[allow(dead_code)]
226    pub fn type_name(&self) -> &'static str {
227        match self {
228            MatchBasicExtConfigVal4100::Bool(_) => "bool",
229            MatchBasicExtConfigVal4100::Int(_) => "int",
230            MatchBasicExtConfigVal4100::Float(_) => "float",
231            MatchBasicExtConfigVal4100::Str(_) => "str",
232            MatchBasicExtConfigVal4100::List(_) => "list",
233        }
234    }
235}
236/// A diagnostic reporter for MatchBasic.
237#[allow(dead_code)]
238pub struct MatchBasicDiagnostics {
239    pub errors: Vec<String>,
240    pub warnings: Vec<String>,
241    pub notes: Vec<String>,
242    pub max_errors: usize,
243}
244#[allow(dead_code)]
245impl MatchBasicDiagnostics {
246    pub fn new(max_errors: usize) -> Self {
247        MatchBasicDiagnostics {
248            errors: Vec::new(),
249            warnings: Vec::new(),
250            notes: Vec::new(),
251            max_errors,
252        }
253    }
254    pub fn error(&mut self, msg: &str) {
255        if self.errors.len() < self.max_errors {
256            self.errors.push(msg.to_string());
257        }
258    }
259    pub fn warning(&mut self, msg: &str) {
260        self.warnings.push(msg.to_string());
261    }
262    pub fn note(&mut self, msg: &str) {
263        self.notes.push(msg.to_string());
264    }
265    pub fn has_errors(&self) -> bool {
266        !self.errors.is_empty()
267    }
268    pub fn num_errors(&self) -> usize {
269        self.errors.len()
270    }
271    pub fn num_warnings(&self) -> usize {
272        self.warnings.len()
273    }
274    pub fn is_clean(&self) -> bool {
275        self.errors.is_empty() && self.warnings.is_empty()
276    }
277    pub fn at_error_limit(&self) -> bool {
278        self.errors.len() >= self.max_errors
279    }
280    pub fn clear(&mut self) {
281        self.errors.clear();
282        self.warnings.clear();
283        self.notes.clear();
284    }
285    pub fn summary(&self) -> String {
286        format!(
287            "{} error(s), {} warning(s)",
288            self.errors.len(),
289            self.warnings.len()
290        )
291    }
292}
293/// A configuration store for MatchBasic.
294#[allow(dead_code)]
295pub struct MatchBasicConfig {
296    pub values: std::collections::HashMap<String, MatchBasicConfigValue>,
297    pub read_only: bool,
298}
299#[allow(dead_code)]
300impl MatchBasicConfig {
301    pub fn new() -> Self {
302        MatchBasicConfig {
303            values: std::collections::HashMap::new(),
304            read_only: false,
305        }
306    }
307    pub fn set(&mut self, key: &str, value: MatchBasicConfigValue) -> bool {
308        if self.read_only {
309            return false;
310        }
311        self.values.insert(key.to_string(), value);
312        true
313    }
314    pub fn get(&self, key: &str) -> Option<&MatchBasicConfigValue> {
315        self.values.get(key)
316    }
317    pub fn get_bool(&self, key: &str) -> Option<bool> {
318        self.get(key)?.as_bool()
319    }
320    pub fn get_int(&self, key: &str) -> Option<i64> {
321        self.get(key)?.as_int()
322    }
323    pub fn get_str(&self, key: &str) -> Option<&str> {
324        self.get(key)?.as_str()
325    }
326    pub fn set_bool(&mut self, key: &str, v: bool) -> bool {
327        self.set(key, MatchBasicConfigValue::Bool(v))
328    }
329    pub fn set_int(&mut self, key: &str, v: i64) -> bool {
330        self.set(key, MatchBasicConfigValue::Int(v))
331    }
332    pub fn set_str(&mut self, key: &str, v: &str) -> bool {
333        self.set(key, MatchBasicConfigValue::Str(v.to_string()))
334    }
335    pub fn lock(&mut self) {
336        self.read_only = true;
337    }
338    pub fn unlock(&mut self) {
339        self.read_only = false;
340    }
341    pub fn size(&self) -> usize {
342        self.values.len()
343    }
344    pub fn has(&self, key: &str) -> bool {
345        self.values.contains_key(key)
346    }
347    pub fn remove(&mut self, key: &str) -> bool {
348        self.values.remove(key).is_some()
349    }
350}
351/// A utility type for MatchBasic (index 3).
352#[allow(dead_code)]
353#[derive(Debug, Clone, Default)]
354pub struct MatchBasicUtil3 {
355    pub id: usize,
356    pub name: String,
357    pub value: i64,
358    pub enabled: bool,
359    pub tags: Vec<String>,
360}
361#[allow(dead_code)]
362impl MatchBasicUtil3 {
363    pub fn new(id: usize, name: &str, value: i64) -> Self {
364        MatchBasicUtil3 {
365            id,
366            name: name.to_string(),
367            value,
368            enabled: true,
369            tags: Vec::new(),
370        }
371    }
372    pub fn with_tag(mut self, tag: &str) -> Self {
373        self.tags.push(tag.to_string());
374        self
375    }
376    pub fn disable(mut self) -> Self {
377        self.enabled = false;
378        self
379    }
380    pub fn is_active(&self) -> bool {
381        self.enabled
382    }
383    pub fn score(&self) -> i64 {
384        if self.enabled {
385            self.value
386        } else {
387            0
388        }
389    }
390    pub fn tag_count(&self) -> usize {
391        self.tags.len()
392    }
393    pub fn has_tag(&self, tag: &str) -> bool {
394        self.tags.iter().any(|t| t == tag)
395    }
396}
397/// A pattern in a match expression.
398#[derive(Clone, Debug, PartialEq)]
399pub enum MetaPattern {
400    /// Wildcard pattern: matches anything, binds nothing.
401    Wildcard,
402    /// Variable pattern: matches anything, binds the value.
403    Var(Name),
404    /// Constructor pattern: matches if head is this constructor.
405    Constructor(Name, Vec<MetaPattern>),
406    /// Literal pattern: matches exact literal value.
407    Literal(Literal),
408    /// As-pattern: `p as x` matches p and also binds x.
409    As(Box<MetaPattern>, Name),
410    /// Or-pattern: matches if either sub-pattern matches.
411    Or(Box<MetaPattern>, Box<MetaPattern>),
412    /// Inaccessible pattern (dot pattern): `.e`.
413    Inaccessible(Expr),
414}
415impl MetaPattern {
416    /// Check if this pattern is a wildcard or variable.
417    pub fn is_irrefutable(&self) -> bool {
418        matches!(self, MetaPattern::Wildcard | MetaPattern::Var(_))
419    }
420    /// Check if this pattern is a constructor pattern.
421    pub fn is_constructor(&self) -> bool {
422        matches!(self, MetaPattern::Constructor(_, _))
423    }
424    /// Check if this pattern is a literal.
425    pub fn is_literal(&self) -> bool {
426        matches!(self, MetaPattern::Literal(_))
427    }
428    /// Get the constructor name (if this is a constructor pattern).
429    pub fn ctor_name(&self) -> Option<&Name> {
430        match self {
431            MetaPattern::Constructor(name, _) => Some(name),
432            _ => None,
433        }
434    }
435    /// Get the subpatterns (for constructor patterns).
436    pub fn subpatterns(&self) -> &[MetaPattern] {
437        match self {
438            MetaPattern::Constructor(_, pats) => pats,
439            _ => &[],
440        }
441    }
442    /// Count the number of variables bound by this pattern.
443    pub fn num_bindings(&self) -> usize {
444        match self {
445            MetaPattern::Wildcard | MetaPattern::Inaccessible(_) => 0,
446            MetaPattern::Var(_) => 1,
447            MetaPattern::Literal(_) => 0,
448            MetaPattern::Constructor(_, pats) => pats.iter().map(|p| p.num_bindings()).sum(),
449            MetaPattern::As(inner, _) => 1 + inner.num_bindings(),
450            MetaPattern::Or(left, _right) => left.num_bindings(),
451        }
452    }
453    /// Collect all variable names bound by this pattern.
454    pub fn bound_vars(&self) -> Vec<Name> {
455        let mut vars = Vec::new();
456        self.collect_vars(&mut vars);
457        vars
458    }
459    fn collect_vars(&self, vars: &mut Vec<Name>) {
460        match self {
461            MetaPattern::Var(name) => vars.push(name.clone()),
462            MetaPattern::Constructor(_, pats) => {
463                for p in pats {
464                    p.collect_vars(vars);
465                }
466            }
467            MetaPattern::As(inner, name) => {
468                vars.push(name.clone());
469                inner.collect_vars(vars);
470            }
471            MetaPattern::Or(left, _) => {
472                left.collect_vars(vars);
473            }
474            _ => {}
475        }
476    }
477    /// Get the depth of nesting.
478    pub fn depth(&self) -> usize {
479        match self {
480            MetaPattern::Constructor(_, pats) => {
481                1 + pats.iter().map(|p| p.depth()).max().unwrap_or(0)
482            }
483            MetaPattern::As(inner, _) => 1 + inner.depth(),
484            MetaPattern::Or(left, right) => 1 + left.depth().max(right.depth()),
485            _ => 0,
486        }
487    }
488}
489/// A pattern matrix: a list of rows.
490#[derive(Clone, Debug, Default)]
491pub struct PatternMatrix {
492    /// Rows, one per match arm.
493    pub rows: Vec<PatternRow>,
494    /// Number of discriminants (columns).
495    pub num_discriminants: usize,
496}
497impl PatternMatrix {
498    /// Create an empty matrix.
499    pub fn new(num_discriminants: usize) -> Self {
500        Self {
501            rows: Vec::new(),
502            num_discriminants,
503        }
504    }
505    /// Add a row.
506    pub fn add_row(&mut self, row: PatternRow) {
507        self.rows.push(row);
508    }
509    /// Return the number of rows (arms).
510    pub fn num_rows(&self) -> usize {
511        self.rows.len()
512    }
513    /// Check if the matrix is empty.
514    pub fn is_empty(&self) -> bool {
515        self.rows.is_empty()
516    }
517    /// Check if the first row is all irrefutable (catch-all).
518    pub fn first_row_is_catchall(&self) -> bool {
519        self.rows
520            .first()
521            .map(|r| r.is_all_irrefutable())
522            .unwrap_or(false)
523    }
524    /// Specialize the matrix for a constructor.
525    ///
526    /// Keep only rows where the first column matches `ctor_name` (or is irrefutable).
527    /// Expand constructor sub-patterns into the row.
528    pub fn specialize(&self, col: usize, ctor_name: &Name, arity: usize) -> PatternMatrix {
529        let mut result = PatternMatrix::new(self.num_discriminants - 1 + arity);
530        for row in &self.rows {
531            match &row.patterns[col] {
532                MetaPattern::Constructor(name, sub) if name == ctor_name => {
533                    let mut new_pats = row.patterns.clone();
534                    new_pats.remove(col);
535                    for (i, s) in sub.iter().enumerate().rev() {
536                        new_pats.insert(col + arity - 1 - i, s.clone());
537                    }
538                    result.add_row(PatternRow {
539                        patterns: new_pats,
540                        ..row.clone()
541                    });
542                }
543                MetaPattern::Wildcard | MetaPattern::Var(_) => {
544                    let mut new_pats = row.patterns.clone();
545                    new_pats.remove(col);
546                    for _ in 0..arity {
547                        new_pats.insert(col, MetaPattern::Wildcard);
548                    }
549                    result.add_row(PatternRow {
550                        patterns: new_pats,
551                        ..row.clone()
552                    });
553                }
554                _ => {}
555            }
556        }
557        result
558    }
559    /// Default matrix: keep only rows where column `col` is irrefutable.
560    pub fn default_matrix(&self, col: usize) -> PatternMatrix {
561        let mut result = PatternMatrix::new(self.num_discriminants - 1);
562        for row in &self.rows {
563            if row.patterns[col].is_irrefutable() {
564                let mut new_pats = row.patterns.clone();
565                new_pats.remove(col);
566                result.add_row(PatternRow {
567                    patterns: new_pats,
568                    ..row.clone()
569                });
570            }
571        }
572        result
573    }
574}
575/// A pipeline of MatchBasic analysis passes.
576#[allow(dead_code)]
577pub struct MatchBasicPipeline {
578    pub passes: Vec<MatchBasicAnalysisPass>,
579    pub name: String,
580    pub total_inputs_processed: usize,
581}
582#[allow(dead_code)]
583impl MatchBasicPipeline {
584    pub fn new(name: &str) -> Self {
585        MatchBasicPipeline {
586            passes: Vec::new(),
587            name: name.to_string(),
588            total_inputs_processed: 0,
589        }
590    }
591    pub fn add_pass(&mut self, pass: MatchBasicAnalysisPass) {
592        self.passes.push(pass);
593    }
594    pub fn run_all(&mut self, input: &str) -> Vec<MatchBasicResult> {
595        self.total_inputs_processed += 1;
596        self.passes
597            .iter_mut()
598            .filter(|p| p.enabled)
599            .map(|p| p.run(input))
600            .collect()
601    }
602    pub fn num_passes(&self) -> usize {
603        self.passes.len()
604    }
605    pub fn num_enabled_passes(&self) -> usize {
606        self.passes.iter().filter(|p| p.enabled).count()
607    }
608    pub fn total_success_rate(&self) -> f64 {
609        if self.passes.is_empty() {
610            0.0
611        } else {
612            let total_rate: f64 = self.passes.iter().map(|p| p.success_rate()).sum();
613            total_rate / self.passes.len() as f64
614        }
615    }
616}
617/// The result of trying to match a pattern against an expression.
618#[derive(Debug, Clone, PartialEq)]
619pub enum MatchResult {
620    /// The match definitely succeeds; bindings maps variable names to expressions.
621    Success(Vec<(oxilean_kernel::Name, Expr)>),
622    /// The match definitely fails.
623    Failure,
624    /// The match is undetermined (e.g., scrutinee not in WHNF yet).
625    Undetermined,
626}
627impl MatchResult {
628    /// Check if the match succeeded.
629    pub fn is_success(&self) -> bool {
630        matches!(self, MatchResult::Success(_))
631    }
632    /// Check if the match failed.
633    pub fn is_failure(&self) -> bool {
634        matches!(self, MatchResult::Failure)
635    }
636    /// Get the bindings produced by a successful match.
637    pub fn bindings(&self) -> &[(oxilean_kernel::Name, Expr)] {
638        match self {
639            MatchResult::Success(b) => b,
640            _ => &[],
641        }
642    }
643}
644#[allow(dead_code)]
645pub struct MatchBasicExtDiff4100 {
646    pub added: Vec<String>,
647    pub removed: Vec<String>,
648    pub unchanged: Vec<String>,
649}
650impl MatchBasicExtDiff4100 {
651    #[allow(dead_code)]
652    pub fn new() -> Self {
653        Self {
654            added: Vec::new(),
655            removed: Vec::new(),
656            unchanged: Vec::new(),
657        }
658    }
659    #[allow(dead_code)]
660    pub fn add(&mut self, s: &str) {
661        self.added.push(s.to_string());
662    }
663    #[allow(dead_code)]
664    pub fn remove(&mut self, s: &str) {
665        self.removed.push(s.to_string());
666    }
667    #[allow(dead_code)]
668    pub fn keep(&mut self, s: &str) {
669        self.unchanged.push(s.to_string());
670    }
671    #[allow(dead_code)]
672    pub fn is_empty(&self) -> bool {
673        self.added.is_empty() && self.removed.is_empty()
674    }
675    #[allow(dead_code)]
676    pub fn total_changes(&self) -> usize {
677        self.added.len() + self.removed.len()
678    }
679    #[allow(dead_code)]
680    pub fn net_additions(&self) -> i64 {
681        self.added.len() as i64 - self.removed.len() as i64
682    }
683    #[allow(dead_code)]
684    pub fn summary(&self) -> String {
685        format!(
686            "+{} -{} =={}",
687            self.added.len(),
688            self.removed.len(),
689            self.unchanged.len()
690        )
691    }
692}
693/// A utility type for MatchBasic (index 9).
694#[allow(dead_code)]
695#[derive(Debug, Clone, Default)]
696pub struct MatchBasicUtil9 {
697    pub id: usize,
698    pub name: String,
699    pub value: i64,
700    pub enabled: bool,
701    pub tags: Vec<String>,
702}
703#[allow(dead_code)]
704impl MatchBasicUtil9 {
705    pub fn new(id: usize, name: &str, value: i64) -> Self {
706        MatchBasicUtil9 {
707            id,
708            name: name.to_string(),
709            value,
710            enabled: true,
711            tags: Vec::new(),
712        }
713    }
714    pub fn with_tag(mut self, tag: &str) -> Self {
715        self.tags.push(tag.to_string());
716        self
717    }
718    pub fn disable(mut self) -> Self {
719        self.enabled = false;
720        self
721    }
722    pub fn is_active(&self) -> bool {
723        self.enabled
724    }
725    pub fn score(&self) -> i64 {
726        if self.enabled {
727            self.value
728        } else {
729            0
730        }
731    }
732    pub fn tag_count(&self) -> usize {
733        self.tags.len()
734    }
735    pub fn has_tag(&self, tag: &str) -> bool {
736        self.tags.iter().any(|t| t == tag)
737    }
738}
739/// A priority queue for MatchBasic items.
740#[allow(dead_code)]
741pub struct MatchBasicPriorityQueue {
742    pub items: Vec<(MatchBasicUtil0, i64)>,
743}
744#[allow(dead_code)]
745impl MatchBasicPriorityQueue {
746    pub fn new() -> Self {
747        MatchBasicPriorityQueue { items: Vec::new() }
748    }
749    pub fn push(&mut self, item: MatchBasicUtil0, priority: i64) {
750        self.items.push((item, priority));
751        self.items.sort_by_key(|(_, p)| -p);
752    }
753    pub fn pop(&mut self) -> Option<(MatchBasicUtil0, i64)> {
754        if self.items.is_empty() {
755            None
756        } else {
757            Some(self.items.remove(0))
758        }
759    }
760    pub fn peek(&self) -> Option<&(MatchBasicUtil0, i64)> {
761        self.items.first()
762    }
763    pub fn is_empty(&self) -> bool {
764        self.items.is_empty()
765    }
766    pub fn len(&self) -> usize {
767        self.items.len()
768    }
769}
770#[allow(dead_code)]
771#[derive(Debug, Clone)]
772pub enum MatchBasicExtResult4100 {
773    /// Operation completed successfully.
774    Ok(String),
775    /// Operation encountered an error.
776    Err(String),
777    /// Operation partially completed.
778    Partial { done: usize, total: usize },
779    /// Operation was skipped.
780    Skipped,
781}
782impl MatchBasicExtResult4100 {
783    #[allow(dead_code)]
784    pub fn is_ok(&self) -> bool {
785        matches!(self, MatchBasicExtResult4100::Ok(_))
786    }
787    #[allow(dead_code)]
788    pub fn is_err(&self) -> bool {
789        matches!(self, MatchBasicExtResult4100::Err(_))
790    }
791    #[allow(dead_code)]
792    pub fn is_partial(&self) -> bool {
793        matches!(self, MatchBasicExtResult4100::Partial { .. })
794    }
795    #[allow(dead_code)]
796    pub fn is_skipped(&self) -> bool {
797        matches!(self, MatchBasicExtResult4100::Skipped)
798    }
799    #[allow(dead_code)]
800    pub fn ok_msg(&self) -> Option<&str> {
801        if let MatchBasicExtResult4100::Ok(s) = self {
802            Some(s)
803        } else {
804            None
805        }
806    }
807    #[allow(dead_code)]
808    pub fn err_msg(&self) -> Option<&str> {
809        if let MatchBasicExtResult4100::Err(s) = self {
810            Some(s)
811        } else {
812            None
813        }
814    }
815    #[allow(dead_code)]
816    pub fn progress(&self) -> f64 {
817        match self {
818            MatchBasicExtResult4100::Ok(_) => 1.0,
819            MatchBasicExtResult4100::Err(_) => 0.0,
820            MatchBasicExtResult4100::Partial { done, total } => {
821                if *total == 0 {
822                    0.0
823                } else {
824                    *done as f64 / *total as f64
825                }
826            }
827            MatchBasicExtResult4100::Skipped => 0.5,
828        }
829    }
830}
831#[allow(dead_code)]
832pub struct MatchBasicExtDiag4100 {
833    pub errors: Vec<String>,
834    pub warnings: Vec<String>,
835    pub notes: Vec<String>,
836    pub max_errors: usize,
837}
838impl MatchBasicExtDiag4100 {
839    #[allow(dead_code)]
840    pub fn new(max_errors: usize) -> Self {
841        Self {
842            errors: Vec::new(),
843            warnings: Vec::new(),
844            notes: Vec::new(),
845            max_errors,
846        }
847    }
848    #[allow(dead_code)]
849    pub fn error(&mut self, msg: &str) {
850        if self.errors.len() < self.max_errors {
851            self.errors.push(msg.to_string());
852        }
853    }
854    #[allow(dead_code)]
855    pub fn warning(&mut self, msg: &str) {
856        self.warnings.push(msg.to_string());
857    }
858    #[allow(dead_code)]
859    pub fn note(&mut self, msg: &str) {
860        self.notes.push(msg.to_string());
861    }
862    #[allow(dead_code)]
863    pub fn has_errors(&self) -> bool {
864        !self.errors.is_empty()
865    }
866    #[allow(dead_code)]
867    pub fn num_errors(&self) -> usize {
868        self.errors.len()
869    }
870    #[allow(dead_code)]
871    pub fn num_warnings(&self) -> usize {
872        self.warnings.len()
873    }
874    #[allow(dead_code)]
875    pub fn is_clean(&self) -> bool {
876        self.errors.is_empty() && self.warnings.is_empty()
877    }
878    #[allow(dead_code)]
879    pub fn at_error_limit(&self) -> bool {
880        self.errors.len() >= self.max_errors
881    }
882    #[allow(dead_code)]
883    pub fn clear(&mut self) {
884        self.errors.clear();
885        self.warnings.clear();
886        self.notes.clear();
887    }
888    #[allow(dead_code)]
889    pub fn summary(&self) -> String {
890        format!(
891            "{} error(s), {} warning(s)",
892            self.errors.len(),
893            self.warnings.len()
894        )
895    }
896}
897/// A row in a pattern matrix.
898#[derive(Clone, Debug)]
899pub struct PatternRow {
900    /// The patterns in this row (one per discriminant).
901    pub patterns: Vec<MetaPattern>,
902    /// Index of the match arm this row corresponds to.
903    pub arm_index: usize,
904    /// Optional guard.
905    pub guard: Option<Expr>,
906}
907impl PatternRow {
908    /// Create a new pattern row.
909    pub fn new(patterns: Vec<MetaPattern>, arm_index: usize) -> Self {
910        Self {
911            patterns,
912            arm_index,
913            guard: None,
914        }
915    }
916    /// Check if all patterns in this row are irrefutable.
917    pub fn is_all_irrefutable(&self) -> bool {
918        self.patterns.iter().all(|p| p.is_irrefutable())
919    }
920    /// Return the first non-wildcard pattern (if any).
921    pub fn first_refutable(&self) -> Option<(usize, &MetaPattern)> {
922        self.patterns
923            .iter()
924            .enumerate()
925            .find(|(_, p)| !p.is_irrefutable())
926    }
927}
928/// A utility type for MatchBasic (index 7).
929#[allow(dead_code)]
930#[derive(Debug, Clone, Default)]
931pub struct MatchBasicUtil7 {
932    pub id: usize,
933    pub name: String,
934    pub value: i64,
935    pub enabled: bool,
936    pub tags: Vec<String>,
937}
938#[allow(dead_code)]
939impl MatchBasicUtil7 {
940    pub fn new(id: usize, name: &str, value: i64) -> Self {
941        MatchBasicUtil7 {
942            id,
943            name: name.to_string(),
944            value,
945            enabled: true,
946            tags: Vec::new(),
947        }
948    }
949    pub fn with_tag(mut self, tag: &str) -> Self {
950        self.tags.push(tag.to_string());
951        self
952    }
953    pub fn disable(mut self) -> Self {
954        self.enabled = false;
955        self
956    }
957    pub fn is_active(&self) -> bool {
958        self.enabled
959    }
960    pub fn score(&self) -> i64 {
961        if self.enabled {
962            self.value
963        } else {
964            0
965        }
966    }
967    pub fn tag_count(&self) -> usize {
968        self.tags.len()
969    }
970    pub fn has_tag(&self, tag: &str) -> bool {
971        self.tags.iter().any(|t| t == tag)
972    }
973}
974/// A utility type for MatchBasic (index 4).
975#[allow(dead_code)]
976#[derive(Debug, Clone, Default)]
977pub struct MatchBasicUtil4 {
978    pub id: usize,
979    pub name: String,
980    pub value: i64,
981    pub enabled: bool,
982    pub tags: Vec<String>,
983}
984#[allow(dead_code)]
985impl MatchBasicUtil4 {
986    pub fn new(id: usize, name: &str, value: i64) -> Self {
987        MatchBasicUtil4 {
988            id,
989            name: name.to_string(),
990            value,
991            enabled: true,
992            tags: Vec::new(),
993        }
994    }
995    pub fn with_tag(mut self, tag: &str) -> Self {
996        self.tags.push(tag.to_string());
997        self
998    }
999    pub fn disable(mut self) -> Self {
1000        self.enabled = false;
1001        self
1002    }
1003    pub fn is_active(&self) -> bool {
1004        self.enabled
1005    }
1006    pub fn score(&self) -> i64 {
1007        if self.enabled {
1008            self.value
1009        } else {
1010            0
1011        }
1012    }
1013    pub fn tag_count(&self) -> usize {
1014        self.tags.len()
1015    }
1016    pub fn has_tag(&self, tag: &str) -> bool {
1017        self.tags.iter().any(|t| t == tag)
1018    }
1019}
1020/// A simple cache for MatchBasic computations.
1021#[allow(dead_code)]
1022pub struct MatchBasicCache {
1023    pub data: std::collections::HashMap<String, i64>,
1024    pub hits: usize,
1025    pub misses: usize,
1026}
1027#[allow(dead_code)]
1028impl MatchBasicCache {
1029    pub fn new() -> Self {
1030        MatchBasicCache {
1031            data: std::collections::HashMap::new(),
1032            hits: 0,
1033            misses: 0,
1034        }
1035    }
1036    pub fn get(&mut self, key: &str) -> Option<i64> {
1037        if let Some(&v) = self.data.get(key) {
1038            self.hits += 1;
1039            Some(v)
1040        } else {
1041            self.misses += 1;
1042            None
1043        }
1044    }
1045    pub fn insert(&mut self, key: &str, value: i64) {
1046        self.data.insert(key.to_string(), value);
1047    }
1048    pub fn hit_rate(&self) -> f64 {
1049        let t = self.hits + self.misses;
1050        if t == 0 {
1051            0.0
1052        } else {
1053            self.hits as f64 / t as f64
1054        }
1055    }
1056    pub fn size(&self) -> usize {
1057        self.data.len()
1058    }
1059    pub fn clear(&mut self) {
1060        self.data.clear();
1061        self.hits = 0;
1062        self.misses = 0;
1063    }
1064}
1065/// A diff for MatchBasic analysis results.
1066#[allow(dead_code)]
1067#[derive(Debug, Clone)]
1068pub struct MatchBasicDiff {
1069    pub added: Vec<String>,
1070    pub removed: Vec<String>,
1071    pub unchanged: Vec<String>,
1072}
1073#[allow(dead_code)]
1074impl MatchBasicDiff {
1075    pub fn new() -> Self {
1076        MatchBasicDiff {
1077            added: Vec::new(),
1078            removed: Vec::new(),
1079            unchanged: Vec::new(),
1080        }
1081    }
1082    pub fn add(&mut self, s: &str) {
1083        self.added.push(s.to_string());
1084    }
1085    pub fn remove(&mut self, s: &str) {
1086        self.removed.push(s.to_string());
1087    }
1088    pub fn keep(&mut self, s: &str) {
1089        self.unchanged.push(s.to_string());
1090    }
1091    pub fn is_empty(&self) -> bool {
1092        self.added.is_empty() && self.removed.is_empty()
1093    }
1094    pub fn total_changes(&self) -> usize {
1095        self.added.len() + self.removed.len()
1096    }
1097    pub fn net_additions(&self) -> i64 {
1098        self.added.len() as i64 - self.removed.len() as i64
1099    }
1100    pub fn summary(&self) -> String {
1101        format!(
1102            "+{} -{} =={}",
1103            self.added.len(),
1104            self.removed.len(),
1105            self.unchanged.len()
1106        )
1107    }
1108}
1109/// A registry for MatchBasic utilities.
1110#[allow(dead_code)]
1111pub struct MatchBasicRegistry {
1112    pub entries: Vec<MatchBasicUtil0>,
1113    pub capacity: usize,
1114}
1115#[allow(dead_code)]
1116impl MatchBasicRegistry {
1117    pub fn new(capacity: usize) -> Self {
1118        MatchBasicRegistry {
1119            entries: Vec::new(),
1120            capacity,
1121        }
1122    }
1123    pub fn register(&mut self, entry: MatchBasicUtil0) -> bool {
1124        if self.entries.len() >= self.capacity {
1125            return false;
1126        }
1127        self.entries.push(entry);
1128        true
1129    }
1130    pub fn lookup(&self, id: usize) -> Option<&MatchBasicUtil0> {
1131        self.entries.iter().find(|e| e.id == id)
1132    }
1133    pub fn remove(&mut self, id: usize) -> bool {
1134        let before = self.entries.len();
1135        self.entries.retain(|e| e.id != id);
1136        self.entries.len() < before
1137    }
1138    pub fn active_entries(&self) -> Vec<&MatchBasicUtil0> {
1139        self.entries.iter().filter(|e| e.is_active()).collect()
1140    }
1141    pub fn total_score(&self) -> i64 {
1142        self.entries.iter().map(|e| e.score()).sum()
1143    }
1144    pub fn count(&self) -> usize {
1145        self.entries.len()
1146    }
1147    pub fn is_full(&self) -> bool {
1148        self.entries.len() >= self.capacity
1149    }
1150    pub fn is_empty(&self) -> bool {
1151        self.entries.is_empty()
1152    }
1153}
1154/// A utility type for MatchBasic (index 0).
1155#[allow(dead_code)]
1156#[derive(Debug, Clone, Default)]
1157pub struct MatchBasicUtil0 {
1158    pub id: usize,
1159    pub name: String,
1160    pub value: i64,
1161    pub enabled: bool,
1162    pub tags: Vec<String>,
1163}
1164#[allow(dead_code)]
1165impl MatchBasicUtil0 {
1166    pub fn new(id: usize, name: &str, value: i64) -> Self {
1167        MatchBasicUtil0 {
1168            id,
1169            name: name.to_string(),
1170            value,
1171            enabled: true,
1172            tags: Vec::new(),
1173        }
1174    }
1175    pub fn with_tag(mut self, tag: &str) -> Self {
1176        self.tags.push(tag.to_string());
1177        self
1178    }
1179    pub fn disable(mut self) -> Self {
1180        self.enabled = false;
1181        self
1182    }
1183    pub fn is_active(&self) -> bool {
1184        self.enabled
1185    }
1186    pub fn score(&self) -> i64 {
1187        if self.enabled {
1188            self.value
1189        } else {
1190            0
1191        }
1192    }
1193    pub fn tag_count(&self) -> usize {
1194        self.tags.len()
1195    }
1196    pub fn has_tag(&self, tag: &str) -> bool {
1197        self.tags.iter().any(|t| t == tag)
1198    }
1199}
1200/// A utility type for MatchBasic (index 6).
1201#[allow(dead_code)]
1202#[derive(Debug, Clone, Default)]
1203pub struct MatchBasicUtil6 {
1204    pub id: usize,
1205    pub name: String,
1206    pub value: i64,
1207    pub enabled: bool,
1208    pub tags: Vec<String>,
1209}
1210#[allow(dead_code)]
1211impl MatchBasicUtil6 {
1212    pub fn new(id: usize, name: &str, value: i64) -> Self {
1213        MatchBasicUtil6 {
1214            id,
1215            name: name.to_string(),
1216            value,
1217            enabled: true,
1218            tags: Vec::new(),
1219        }
1220    }
1221    pub fn with_tag(mut self, tag: &str) -> Self {
1222        self.tags.push(tag.to_string());
1223        self
1224    }
1225    pub fn disable(mut self) -> Self {
1226        self.enabled = false;
1227        self
1228    }
1229    pub fn is_active(&self) -> bool {
1230        self.enabled
1231    }
1232    pub fn score(&self) -> i64 {
1233        if self.enabled {
1234            self.value
1235        } else {
1236            0
1237        }
1238    }
1239    pub fn tag_count(&self) -> usize {
1240        self.tags.len()
1241    }
1242    pub fn has_tag(&self, tag: &str) -> bool {
1243        self.tags.iter().any(|t| t == tag)
1244    }
1245}
1246/// A utility type for MatchBasic (index 11).
1247#[allow(dead_code)]
1248#[derive(Debug, Clone, Default)]
1249pub struct MatchBasicUtil11 {
1250    pub id: usize,
1251    pub name: String,
1252    pub value: i64,
1253    pub enabled: bool,
1254    pub tags: Vec<String>,
1255}
1256#[allow(dead_code)]
1257impl MatchBasicUtil11 {
1258    pub fn new(id: usize, name: &str, value: i64) -> Self {
1259        MatchBasicUtil11 {
1260            id,
1261            name: name.to_string(),
1262            value,
1263            enabled: true,
1264            tags: Vec::new(),
1265        }
1266    }
1267    pub fn with_tag(mut self, tag: &str) -> Self {
1268        self.tags.push(tag.to_string());
1269        self
1270    }
1271    pub fn disable(mut self) -> Self {
1272        self.enabled = false;
1273        self
1274    }
1275    pub fn is_active(&self) -> bool {
1276        self.enabled
1277    }
1278    pub fn score(&self) -> i64 {
1279        if self.enabled {
1280            self.value
1281        } else {
1282            0
1283        }
1284    }
1285    pub fn tag_count(&self) -> usize {
1286        self.tags.len()
1287    }
1288    pub fn has_tag(&self, tag: &str) -> bool {
1289        self.tags.iter().any(|t| t == tag)
1290    }
1291}
1292/// A result type for MatchBasic analysis.
1293#[allow(dead_code)]
1294#[derive(Debug, Clone, PartialEq)]
1295pub enum MatchBasicResult {
1296    Ok(String),
1297    Err(String),
1298    Partial { done: usize, total: usize },
1299    Skipped,
1300}
1301#[allow(dead_code)]
1302impl MatchBasicResult {
1303    pub fn is_ok(&self) -> bool {
1304        matches!(self, MatchBasicResult::Ok(_))
1305    }
1306    pub fn is_err(&self) -> bool {
1307        matches!(self, MatchBasicResult::Err(_))
1308    }
1309    pub fn is_partial(&self) -> bool {
1310        matches!(self, MatchBasicResult::Partial { .. })
1311    }
1312    pub fn is_skipped(&self) -> bool {
1313        matches!(self, MatchBasicResult::Skipped)
1314    }
1315    pub fn ok_msg(&self) -> Option<&str> {
1316        match self {
1317            MatchBasicResult::Ok(s) => Some(s),
1318            _ => None,
1319        }
1320    }
1321    pub fn err_msg(&self) -> Option<&str> {
1322        match self {
1323            MatchBasicResult::Err(s) => Some(s),
1324            _ => None,
1325        }
1326    }
1327    pub fn progress(&self) -> f64 {
1328        match self {
1329            MatchBasicResult::Ok(_) => 1.0,
1330            MatchBasicResult::Err(_) => 0.0,
1331            MatchBasicResult::Skipped => 0.0,
1332            MatchBasicResult::Partial { done, total } => {
1333                if *total == 0 {
1334                    0.0
1335                } else {
1336                    *done as f64 / *total as f64
1337                }
1338            }
1339        }
1340    }
1341}
1342/// A utility type for MatchBasic (index 10).
1343#[allow(dead_code)]
1344#[derive(Debug, Clone, Default)]
1345pub struct MatchBasicUtil10 {
1346    pub id: usize,
1347    pub name: String,
1348    pub value: i64,
1349    pub enabled: bool,
1350    pub tags: Vec<String>,
1351}
1352#[allow(dead_code)]
1353impl MatchBasicUtil10 {
1354    pub fn new(id: usize, name: &str, value: i64) -> Self {
1355        MatchBasicUtil10 {
1356            id,
1357            name: name.to_string(),
1358            value,
1359            enabled: true,
1360            tags: Vec::new(),
1361        }
1362    }
1363    pub fn with_tag(mut self, tag: &str) -> Self {
1364        self.tags.push(tag.to_string());
1365        self
1366    }
1367    pub fn disable(mut self) -> Self {
1368        self.enabled = false;
1369        self
1370    }
1371    pub fn is_active(&self) -> bool {
1372        self.enabled
1373    }
1374    pub fn score(&self) -> i64 {
1375        if self.enabled {
1376            self.value
1377        } else {
1378            0
1379        }
1380    }
1381    pub fn tag_count(&self) -> usize {
1382        self.tags.len()
1383    }
1384    pub fn has_tag(&self, tag: &str) -> bool {
1385        self.tags.iter().any(|t| t == tag)
1386    }
1387}
1388/// A match expression being elaborated.
1389#[derive(Clone, Debug)]
1390pub struct MetaMatchExpr {
1391    /// Discriminant expressions.
1392    pub discriminants: Vec<Expr>,
1393    /// Types of discriminants.
1394    pub discr_types: Vec<Expr>,
1395    /// Match arms.
1396    pub arms: Vec<MetaMatchArm>,
1397    /// Expected result type.
1398    pub expected_type: Option<Expr>,
1399}
1400impl MetaMatchExpr {
1401    /// Create a new match expression.
1402    pub fn new(discriminants: Vec<Expr>, discr_types: Vec<Expr>) -> Self {
1403        Self {
1404            discriminants,
1405            discr_types,
1406            arms: Vec::new(),
1407            expected_type: None,
1408        }
1409    }
1410    /// Add a match arm.
1411    pub fn add_arm(&mut self, arm: MetaMatchArm) {
1412        self.arms.push(arm);
1413    }
1414    /// Set the expected result type.
1415    pub fn set_expected_type(&mut self, ty: Expr) {
1416        self.expected_type = Some(ty);
1417    }
1418    /// Get the number of discriminants.
1419    pub fn num_discriminants(&self) -> usize {
1420        self.discriminants.len()
1421    }
1422    /// Get the number of arms.
1423    pub fn num_arms(&self) -> usize {
1424        self.arms.len()
1425    }
1426    /// Check if all arms have the correct number of patterns.
1427    pub fn validate_patterns(&self) -> Result<(), String> {
1428        let expected = self.num_discriminants();
1429        for (i, arm) in self.arms.iter().enumerate() {
1430            if arm.patterns.len() != expected {
1431                return Err(format!(
1432                    "Arm {} has {} patterns, expected {}",
1433                    i,
1434                    arm.patterns.len(),
1435                    expected
1436                ));
1437            }
1438        }
1439        Ok(())
1440    }
1441}
1442/// A node in a match decision tree.
1443///
1444/// Decision trees are a compiled form of pattern matching that avoid
1445/// repeatedly testing the same sub-expression.
1446#[derive(Debug, Clone)]
1447pub enum DecisionTree {
1448    /// Leaf: all patterns exhausted; execute this arm index.
1449    Leaf(usize),
1450    /// Failure: no arm matches.
1451    Fail,
1452    /// Switch on the constructor of a sub-expression.
1453    Switch {
1454        /// Index of the discriminant to examine (in the match clause).
1455        discr_idx: usize,
1456        /// Cases keyed by constructor name.
1457        cases: Vec<(oxilean_kernel::Name, Box<DecisionTree>)>,
1458        /// Default case (wildcard/variable patterns).
1459        default: Option<Box<DecisionTree>>,
1460    },
1461    /// Guard: check a boolean expression before proceeding.
1462    Guard {
1463        /// The guard expression to evaluate.
1464        condition: Expr,
1465        /// Sub-tree for when the guard holds.
1466        success: Box<DecisionTree>,
1467        /// Sub-tree for when the guard fails.
1468        failure: Box<DecisionTree>,
1469    },
1470}
1471impl DecisionTree {
1472    /// Check if this is a leaf node.
1473    pub fn is_leaf(&self) -> bool {
1474        matches!(self, DecisionTree::Leaf(_))
1475    }
1476    /// Check if this is a fail node.
1477    pub fn is_fail(&self) -> bool {
1478        matches!(self, DecisionTree::Fail)
1479    }
1480    /// Count the number of leaf nodes (reachable arms).
1481    pub fn num_reachable_arms(&self) -> usize {
1482        match self {
1483            DecisionTree::Leaf(_) => 1,
1484            DecisionTree::Fail => 0,
1485            DecisionTree::Switch { cases, default, .. } => {
1486                let case_count: usize = cases.iter().map(|(_, sub)| sub.num_reachable_arms()).sum();
1487                let default_count = default
1488                    .as_ref()
1489                    .map(|d| d.num_reachable_arms())
1490                    .unwrap_or(0);
1491                case_count + default_count
1492            }
1493            DecisionTree::Guard {
1494                success, failure, ..
1495            } => success.num_reachable_arms() + failure.num_reachable_arms(),
1496        }
1497    }
1498    /// Compute the maximum depth of this decision tree.
1499    pub fn depth(&self) -> usize {
1500        match self {
1501            DecisionTree::Leaf(_) | DecisionTree::Fail => 0,
1502            DecisionTree::Switch { cases, default, .. } => {
1503                let case_depth = cases.iter().map(|(_, sub)| sub.depth()).max().unwrap_or(0);
1504                let default_depth = default.as_ref().map(|d| d.depth()).unwrap_or(0);
1505                1 + case_depth.max(default_depth)
1506            }
1507            DecisionTree::Guard {
1508                success, failure, ..
1509            } => 1 + success.depth().max(failure.depth()),
1510        }
1511    }
1512}
1513/// A utility type for MatchBasic (index 13).
1514#[allow(dead_code)]
1515#[derive(Debug, Clone, Default)]
1516pub struct MatchBasicUtil13 {
1517    pub id: usize,
1518    pub name: String,
1519    pub value: i64,
1520    pub enabled: bool,
1521    pub tags: Vec<String>,
1522}
1523#[allow(dead_code)]
1524impl MatchBasicUtil13 {
1525    pub fn new(id: usize, name: &str, value: i64) -> Self {
1526        MatchBasicUtil13 {
1527            id,
1528            name: name.to_string(),
1529            value,
1530            enabled: true,
1531            tags: Vec::new(),
1532        }
1533    }
1534    pub fn with_tag(mut self, tag: &str) -> Self {
1535        self.tags.push(tag.to_string());
1536        self
1537    }
1538    pub fn disable(mut self) -> Self {
1539        self.enabled = false;
1540        self
1541    }
1542    pub fn is_active(&self) -> bool {
1543        self.enabled
1544    }
1545    pub fn score(&self) -> i64 {
1546        if self.enabled {
1547            self.value
1548        } else {
1549            0
1550        }
1551    }
1552    pub fn tag_count(&self) -> usize {
1553        self.tags.len()
1554    }
1555    pub fn has_tag(&self, tag: &str) -> bool {
1556        self.tags.iter().any(|t| t == tag)
1557    }
1558}
1559/// An analysis pass for MatchBasic.
1560#[allow(dead_code)]
1561pub struct MatchBasicAnalysisPass {
1562    pub name: String,
1563    pub enabled: bool,
1564    pub results: Vec<MatchBasicResult>,
1565    pub total_runs: usize,
1566}
1567#[allow(dead_code)]
1568impl MatchBasicAnalysisPass {
1569    pub fn new(name: &str) -> Self {
1570        MatchBasicAnalysisPass {
1571            name: name.to_string(),
1572            enabled: true,
1573            results: Vec::new(),
1574            total_runs: 0,
1575        }
1576    }
1577    pub fn run(&mut self, input: &str) -> MatchBasicResult {
1578        self.total_runs += 1;
1579        let result = if input.is_empty() {
1580            MatchBasicResult::Err("empty input".to_string())
1581        } else {
1582            MatchBasicResult::Ok(format!("processed: {}", input))
1583        };
1584        self.results.push(result.clone());
1585        result
1586    }
1587    pub fn success_count(&self) -> usize {
1588        self.results.iter().filter(|r| r.is_ok()).count()
1589    }
1590    pub fn error_count(&self) -> usize {
1591        self.results.iter().filter(|r| r.is_err()).count()
1592    }
1593    pub fn success_rate(&self) -> f64 {
1594        if self.total_runs == 0 {
1595            0.0
1596        } else {
1597            self.success_count() as f64 / self.total_runs as f64
1598        }
1599    }
1600    pub fn disable(&mut self) {
1601        self.enabled = false;
1602    }
1603    pub fn enable(&mut self) {
1604        self.enabled = true;
1605    }
1606    pub fn clear_results(&mut self) {
1607        self.results.clear();
1608    }
1609}
1610/// A match arm (clause) in a match expression.
1611#[derive(Clone, Debug)]
1612pub struct MetaMatchArm {
1613    /// Patterns for each discriminant.
1614    pub patterns: Vec<MetaPattern>,
1615    /// Optional guard expression.
1616    pub guard: Option<Expr>,
1617    /// Right-hand side (body).
1618    pub rhs: Expr,
1619}
1620/// A utility type for MatchBasic (index 1).
1621#[allow(dead_code)]
1622#[derive(Debug, Clone, Default)]
1623pub struct MatchBasicUtil1 {
1624    pub id: usize,
1625    pub name: String,
1626    pub value: i64,
1627    pub enabled: bool,
1628    pub tags: Vec<String>,
1629}
1630#[allow(dead_code)]
1631impl MatchBasicUtil1 {
1632    pub fn new(id: usize, name: &str, value: i64) -> Self {
1633        MatchBasicUtil1 {
1634            id,
1635            name: name.to_string(),
1636            value,
1637            enabled: true,
1638            tags: Vec::new(),
1639        }
1640    }
1641    pub fn with_tag(mut self, tag: &str) -> Self {
1642        self.tags.push(tag.to_string());
1643        self
1644    }
1645    pub fn disable(mut self) -> Self {
1646        self.enabled = false;
1647        self
1648    }
1649    pub fn is_active(&self) -> bool {
1650        self.enabled
1651    }
1652    pub fn score(&self) -> i64 {
1653        if self.enabled {
1654            self.value
1655        } else {
1656            0
1657        }
1658    }
1659    pub fn tag_count(&self) -> usize {
1660        self.tags.len()
1661    }
1662    pub fn has_tag(&self, tag: &str) -> bool {
1663        self.tags.iter().any(|t| t == tag)
1664    }
1665}
1666/// Statistics for MatchBasic operations.
1667#[allow(dead_code)]
1668#[derive(Debug, Clone, Default)]
1669pub struct MatchBasicStats {
1670    pub total_ops: usize,
1671    pub successful_ops: usize,
1672    pub failed_ops: usize,
1673    pub total_time_ns: u64,
1674    pub max_time_ns: u64,
1675}
1676#[allow(dead_code)]
1677impl MatchBasicStats {
1678    pub fn new() -> Self {
1679        MatchBasicStats::default()
1680    }
1681    pub fn record_success(&mut self, time_ns: u64) {
1682        self.total_ops += 1;
1683        self.successful_ops += 1;
1684        self.total_time_ns += time_ns;
1685        if time_ns > self.max_time_ns {
1686            self.max_time_ns = time_ns;
1687        }
1688    }
1689    pub fn record_failure(&mut self) {
1690        self.total_ops += 1;
1691        self.failed_ops += 1;
1692    }
1693    pub fn success_rate(&self) -> f64 {
1694        if self.total_ops == 0 {
1695            0.0
1696        } else {
1697            self.successful_ops as f64 / self.total_ops as f64
1698        }
1699    }
1700    pub fn avg_time_ns(&self) -> f64 {
1701        if self.successful_ops == 0 {
1702            0.0
1703        } else {
1704            self.total_time_ns as f64 / self.successful_ops as f64
1705        }
1706    }
1707    pub fn merge(&mut self, other: &Self) {
1708        self.total_ops += other.total_ops;
1709        self.successful_ops += other.successful_ops;
1710        self.failed_ops += other.failed_ops;
1711        self.total_time_ns += other.total_time_ns;
1712        if other.max_time_ns > self.max_time_ns {
1713            self.max_time_ns = other.max_time_ns;
1714        }
1715    }
1716}
1717#[allow(dead_code)]
1718pub struct MatchBasicExtConfig4100 {
1719    pub(super) values: std::collections::HashMap<String, MatchBasicExtConfigVal4100>,
1720    pub(super) read_only: bool,
1721    pub(super) name: String,
1722}
1723impl MatchBasicExtConfig4100 {
1724    #[allow(dead_code)]
1725    pub fn new() -> Self {
1726        Self {
1727            values: std::collections::HashMap::new(),
1728            read_only: false,
1729            name: String::new(),
1730        }
1731    }
1732    #[allow(dead_code)]
1733    pub fn named(name: &str) -> Self {
1734        Self {
1735            values: std::collections::HashMap::new(),
1736            read_only: false,
1737            name: name.to_string(),
1738        }
1739    }
1740    #[allow(dead_code)]
1741    pub fn set(&mut self, key: &str, value: MatchBasicExtConfigVal4100) -> bool {
1742        if self.read_only {
1743            return false;
1744        }
1745        self.values.insert(key.to_string(), value);
1746        true
1747    }
1748    #[allow(dead_code)]
1749    pub fn get(&self, key: &str) -> Option<&MatchBasicExtConfigVal4100> {
1750        self.values.get(key)
1751    }
1752    #[allow(dead_code)]
1753    pub fn get_bool(&self, key: &str) -> Option<bool> {
1754        self.get(key)?.as_bool()
1755    }
1756    #[allow(dead_code)]
1757    pub fn get_int(&self, key: &str) -> Option<i64> {
1758        self.get(key)?.as_int()
1759    }
1760    #[allow(dead_code)]
1761    pub fn get_str(&self, key: &str) -> Option<&str> {
1762        self.get(key)?.as_str()
1763    }
1764    #[allow(dead_code)]
1765    pub fn set_bool(&mut self, key: &str, v: bool) -> bool {
1766        self.set(key, MatchBasicExtConfigVal4100::Bool(v))
1767    }
1768    #[allow(dead_code)]
1769    pub fn set_int(&mut self, key: &str, v: i64) -> bool {
1770        self.set(key, MatchBasicExtConfigVal4100::Int(v))
1771    }
1772    #[allow(dead_code)]
1773    pub fn set_str(&mut self, key: &str, v: &str) -> bool {
1774        self.set(key, MatchBasicExtConfigVal4100::Str(v.to_string()))
1775    }
1776    #[allow(dead_code)]
1777    pub fn lock(&mut self) {
1778        self.read_only = true;
1779    }
1780    #[allow(dead_code)]
1781    pub fn unlock(&mut self) {
1782        self.read_only = false;
1783    }
1784    #[allow(dead_code)]
1785    pub fn size(&self) -> usize {
1786        self.values.len()
1787    }
1788    #[allow(dead_code)]
1789    pub fn has(&self, key: &str) -> bool {
1790        self.values.contains_key(key)
1791    }
1792    #[allow(dead_code)]
1793    pub fn remove(&mut self, key: &str) -> bool {
1794        self.values.remove(key).is_some()
1795    }
1796}
1797/// A utility type for MatchBasic (index 2).
1798#[allow(dead_code)]
1799#[derive(Debug, Clone, Default)]
1800pub struct MatchBasicUtil2 {
1801    pub id: usize,
1802    pub name: String,
1803    pub value: i64,
1804    pub enabled: bool,
1805    pub tags: Vec<String>,
1806}
1807#[allow(dead_code)]
1808impl MatchBasicUtil2 {
1809    pub fn new(id: usize, name: &str, value: i64) -> Self {
1810        MatchBasicUtil2 {
1811            id,
1812            name: name.to_string(),
1813            value,
1814            enabled: true,
1815            tags: Vec::new(),
1816        }
1817    }
1818    pub fn with_tag(mut self, tag: &str) -> Self {
1819        self.tags.push(tag.to_string());
1820        self
1821    }
1822    pub fn disable(mut self) -> Self {
1823        self.enabled = false;
1824        self
1825    }
1826    pub fn is_active(&self) -> bool {
1827        self.enabled
1828    }
1829    pub fn score(&self) -> i64 {
1830        if self.enabled {
1831            self.value
1832        } else {
1833            0
1834        }
1835    }
1836    pub fn tag_count(&self) -> usize {
1837        self.tags.len()
1838    }
1839    pub fn has_tag(&self, tag: &str) -> bool {
1840        self.tags.iter().any(|t| t == tag)
1841    }
1842}
1843/// A utility type for MatchBasic (index 5).
1844#[allow(dead_code)]
1845#[derive(Debug, Clone, Default)]
1846pub struct MatchBasicUtil5 {
1847    pub id: usize,
1848    pub name: String,
1849    pub value: i64,
1850    pub enabled: bool,
1851    pub tags: Vec<String>,
1852}
1853#[allow(dead_code)]
1854impl MatchBasicUtil5 {
1855    pub fn new(id: usize, name: &str, value: i64) -> Self {
1856        MatchBasicUtil5 {
1857            id,
1858            name: name.to_string(),
1859            value,
1860            enabled: true,
1861            tags: Vec::new(),
1862        }
1863    }
1864    pub fn with_tag(mut self, tag: &str) -> Self {
1865        self.tags.push(tag.to_string());
1866        self
1867    }
1868    pub fn disable(mut self) -> Self {
1869        self.enabled = false;
1870        self
1871    }
1872    pub fn is_active(&self) -> bool {
1873        self.enabled
1874    }
1875    pub fn score(&self) -> i64 {
1876        if self.enabled {
1877            self.value
1878        } else {
1879            0
1880        }
1881    }
1882    pub fn tag_count(&self) -> usize {
1883        self.tags.len()
1884    }
1885    pub fn has_tag(&self, tag: &str) -> bool {
1886        self.tags.iter().any(|t| t == tag)
1887    }
1888}
1889/// A logger for MatchBasic operations.
1890#[allow(dead_code)]
1891pub struct MatchBasicLogger {
1892    pub entries: Vec<String>,
1893    pub max_entries: usize,
1894    pub verbose: bool,
1895}
1896#[allow(dead_code)]
1897impl MatchBasicLogger {
1898    pub fn new(max_entries: usize) -> Self {
1899        MatchBasicLogger {
1900            entries: Vec::new(),
1901            max_entries,
1902            verbose: false,
1903        }
1904    }
1905    pub fn log(&mut self, msg: &str) {
1906        if self.entries.len() < self.max_entries {
1907            self.entries.push(msg.to_string());
1908        }
1909    }
1910    pub fn verbose(&mut self, msg: &str) {
1911        if self.verbose {
1912            self.log(msg);
1913        }
1914    }
1915    pub fn clear(&mut self) {
1916        self.entries.clear();
1917    }
1918    pub fn count(&self) -> usize {
1919        self.entries.len()
1920    }
1921    pub fn last(&self) -> Option<&str> {
1922        self.entries.last().map(|s| s.as_str())
1923    }
1924    pub fn enable_verbose(&mut self) {
1925        self.verbose = true;
1926    }
1927    pub fn disable_verbose(&mut self) {
1928        self.verbose = false;
1929    }
1930}
1931/// A utility type for MatchBasic (index 8).
1932#[allow(dead_code)]
1933#[derive(Debug, Clone, Default)]
1934pub struct MatchBasicUtil8 {
1935    pub id: usize,
1936    pub name: String,
1937    pub value: i64,
1938    pub enabled: bool,
1939    pub tags: Vec<String>,
1940}
1941#[allow(dead_code)]
1942impl MatchBasicUtil8 {
1943    pub fn new(id: usize, name: &str, value: i64) -> Self {
1944        MatchBasicUtil8 {
1945            id,
1946            name: name.to_string(),
1947            value,
1948            enabled: true,
1949            tags: Vec::new(),
1950        }
1951    }
1952    pub fn with_tag(mut self, tag: &str) -> Self {
1953        self.tags.push(tag.to_string());
1954        self
1955    }
1956    pub fn disable(mut self) -> Self {
1957        self.enabled = false;
1958        self
1959    }
1960    pub fn is_active(&self) -> bool {
1961        self.enabled
1962    }
1963    pub fn score(&self) -> i64 {
1964        if self.enabled {
1965            self.value
1966        } else {
1967            0
1968        }
1969    }
1970    pub fn tag_count(&self) -> usize {
1971        self.tags.len()
1972    }
1973    pub fn has_tag(&self, tag: &str) -> bool {
1974        self.tags.iter().any(|t| t == tag)
1975    }
1976}
1977#[allow(dead_code)]
1978pub struct MatchBasicExtPipeline4100 {
1979    pub name: String,
1980    pub passes: Vec<MatchBasicExtPass4100>,
1981    pub run_count: usize,
1982}
1983impl MatchBasicExtPipeline4100 {
1984    #[allow(dead_code)]
1985    pub fn new(name: &str) -> Self {
1986        Self {
1987            name: name.to_string(),
1988            passes: Vec::new(),
1989            run_count: 0,
1990        }
1991    }
1992    #[allow(dead_code)]
1993    pub fn add_pass(&mut self, pass: MatchBasicExtPass4100) {
1994        self.passes.push(pass);
1995    }
1996    #[allow(dead_code)]
1997    pub fn run_all(&mut self, input: &str) -> Vec<MatchBasicExtResult4100> {
1998        self.run_count += 1;
1999        self.passes
2000            .iter_mut()
2001            .filter(|p| p.enabled)
2002            .map(|p| p.run(input))
2003            .collect()
2004    }
2005    #[allow(dead_code)]
2006    pub fn num_passes(&self) -> usize {
2007        self.passes.len()
2008    }
2009    #[allow(dead_code)]
2010    pub fn num_enabled_passes(&self) -> usize {
2011        self.passes.iter().filter(|p| p.enabled).count()
2012    }
2013    #[allow(dead_code)]
2014    pub fn total_success_rate(&self) -> f64 {
2015        let total: usize = self.passes.iter().map(|p| p.total_runs).sum();
2016        let ok: usize = self.passes.iter().map(|p| p.successes).sum();
2017        if total == 0 {
2018            0.0
2019        } else {
2020            ok as f64 / total as f64
2021        }
2022    }
2023}