Skip to main content

oxilean_codegen/chapel_backend/
types.rs

1//! Auto-generated module
2//!
3//! 🤖 Generated with [SplitRS](https://github.com/cool-japan/splitrs)
4
5use std::collections::HashMap;
6
7use std::collections::{HashSet, VecDeque};
8
9#[allow(dead_code)]
10#[derive(Debug, Clone)]
11pub struct ChplDepGraph {
12    pub(super) nodes: Vec<u32>,
13    pub(super) edges: Vec<(u32, u32)>,
14}
15impl ChplDepGraph {
16    #[allow(dead_code)]
17    pub fn new() -> Self {
18        ChplDepGraph {
19            nodes: Vec::new(),
20            edges: Vec::new(),
21        }
22    }
23    #[allow(dead_code)]
24    pub fn add_node(&mut self, id: u32) {
25        if !self.nodes.contains(&id) {
26            self.nodes.push(id);
27        }
28    }
29    #[allow(dead_code)]
30    pub fn add_dep(&mut self, dep: u32, dependent: u32) {
31        self.add_node(dep);
32        self.add_node(dependent);
33        self.edges.push((dep, dependent));
34    }
35    #[allow(dead_code)]
36    pub fn dependents_of(&self, node: u32) -> Vec<u32> {
37        self.edges
38            .iter()
39            .filter(|(d, _)| *d == node)
40            .map(|(_, dep)| *dep)
41            .collect()
42    }
43    #[allow(dead_code)]
44    pub fn dependencies_of(&self, node: u32) -> Vec<u32> {
45        self.edges
46            .iter()
47            .filter(|(_, dep)| *dep == node)
48            .map(|(d, _)| *d)
49            .collect()
50    }
51    #[allow(dead_code)]
52    pub fn topological_sort(&self) -> Vec<u32> {
53        let mut in_degree: std::collections::HashMap<u32, u32> = std::collections::HashMap::new();
54        for &n in &self.nodes {
55            in_degree.insert(n, 0);
56        }
57        for (_, dep) in &self.edges {
58            *in_degree.entry(*dep).or_insert(0) += 1;
59        }
60        let mut queue: std::collections::VecDeque<u32> = self
61            .nodes
62            .iter()
63            .filter(|&&n| in_degree[&n] == 0)
64            .copied()
65            .collect();
66        let mut result = Vec::new();
67        while let Some(node) = queue.pop_front() {
68            result.push(node);
69            for dep in self.dependents_of(node) {
70                let cnt = in_degree.entry(dep).or_insert(0);
71                *cnt = cnt.saturating_sub(1);
72                if *cnt == 0 {
73                    queue.push_back(dep);
74                }
75            }
76        }
77        result
78    }
79    #[allow(dead_code)]
80    pub fn has_cycle(&self) -> bool {
81        self.topological_sort().len() < self.nodes.len()
82    }
83}
84#[allow(dead_code)]
85pub struct ChplConstantFoldingHelper;
86impl ChplConstantFoldingHelper {
87    #[allow(dead_code)]
88    pub fn fold_add_i64(a: i64, b: i64) -> Option<i64> {
89        a.checked_add(b)
90    }
91    #[allow(dead_code)]
92    pub fn fold_sub_i64(a: i64, b: i64) -> Option<i64> {
93        a.checked_sub(b)
94    }
95    #[allow(dead_code)]
96    pub fn fold_mul_i64(a: i64, b: i64) -> Option<i64> {
97        a.checked_mul(b)
98    }
99    #[allow(dead_code)]
100    pub fn fold_div_i64(a: i64, b: i64) -> Option<i64> {
101        if b == 0 {
102            None
103        } else {
104            a.checked_div(b)
105        }
106    }
107    #[allow(dead_code)]
108    pub fn fold_add_f64(a: f64, b: f64) -> f64 {
109        a + b
110    }
111    #[allow(dead_code)]
112    pub fn fold_mul_f64(a: f64, b: f64) -> f64 {
113        a * b
114    }
115    #[allow(dead_code)]
116    pub fn fold_neg_i64(a: i64) -> Option<i64> {
117        a.checked_neg()
118    }
119    #[allow(dead_code)]
120    pub fn fold_not_bool(a: bool) -> bool {
121        !a
122    }
123    #[allow(dead_code)]
124    pub fn fold_and_bool(a: bool, b: bool) -> bool {
125        a && b
126    }
127    #[allow(dead_code)]
128    pub fn fold_or_bool(a: bool, b: bool) -> bool {
129        a || b
130    }
131    #[allow(dead_code)]
132    pub fn fold_shl_i64(a: i64, b: u32) -> Option<i64> {
133        a.checked_shl(b)
134    }
135    #[allow(dead_code)]
136    pub fn fold_shr_i64(a: i64, b: u32) -> Option<i64> {
137        a.checked_shr(b)
138    }
139    #[allow(dead_code)]
140    pub fn fold_rem_i64(a: i64, b: i64) -> Option<i64> {
141        if b == 0 {
142            None
143        } else {
144            Some(a % b)
145        }
146    }
147    #[allow(dead_code)]
148    pub fn fold_bitand_i64(a: i64, b: i64) -> i64 {
149        a & b
150    }
151    #[allow(dead_code)]
152    pub fn fold_bitor_i64(a: i64, b: i64) -> i64 {
153        a | b
154    }
155    #[allow(dead_code)]
156    pub fn fold_bitxor_i64(a: i64, b: i64) -> i64 {
157        a ^ b
158    }
159    #[allow(dead_code)]
160    pub fn fold_bitnot_i64(a: i64) -> i64 {
161        !a
162    }
163}
164/// Backend state for emitting Chapel source code.
165pub struct ChapelBackend {
166    /// Output buffer
167    pub(super) buf: String,
168    /// Current indentation level
169    pub(super) indent: usize,
170    /// Indentation string (spaces per level)
171    pub(super) indent_str: String,
172    /// Configuration
173    pub(super) config: ChapelConfig,
174    /// String interning for deduplication
175    pub(super) _intern: HashMap<String, u32>,
176}
177impl ChapelBackend {
178    /// Create a new backend with default configuration.
179    pub fn new() -> Self {
180        ChapelBackend::with_config(ChapelConfig::default())
181    }
182    /// Create a new backend with custom configuration.
183    pub fn with_config(config: ChapelConfig) -> Self {
184        let indent_str = " ".repeat(config.indent_width);
185        ChapelBackend {
186            buf: String::new(),
187            indent: 0,
188            indent_str,
189            config,
190            _intern: HashMap::new(),
191        }
192    }
193    pub(super) fn push(&mut self, s: &str) {
194        self.buf.push_str(s);
195    }
196    pub(super) fn push_char(&mut self, c: char) {
197        self.buf.push(c);
198    }
199    pub(super) fn newline(&mut self) {
200        self.buf.push('\n');
201    }
202    pub(super) fn emit_indent(&mut self) {
203        for _ in 0..self.indent {
204            self.buf.push_str(&self.indent_str.clone());
205        }
206    }
207    pub(super) fn emit_line(&mut self, s: &str) {
208        self.emit_indent();
209        self.push(s);
210        self.newline();
211    }
212    pub(super) fn indent_in(&mut self) {
213        self.indent += 1;
214    }
215    pub(super) fn indent_out(&mut self) {
216        if self.indent > 0 {
217            self.indent -= 1;
218        }
219    }
220    /// Emit a Chapel expression.
221    pub fn emit_expr(&mut self, expr: &ChapelExpr) {
222        match expr {
223            ChapelExpr::IntLit(n) => self.push(&n.to_string()),
224            ChapelExpr::RealLit(v) => self.push(&format!("{v}")),
225            ChapelExpr::BoolLit(b) => self.push(if *b { "true" } else { "false" }),
226            ChapelExpr::StrLit(s) => {
227                self.push_char('"');
228                self.push(s);
229                self.push_char('"');
230            }
231            ChapelExpr::Var(name) => self.push(name),
232            ChapelExpr::Apply(f, args) => {
233                self.emit_expr(f);
234                self.push("(");
235                for (i, arg) in args.iter().enumerate() {
236                    if i > 0 {
237                        self.push(", ");
238                    }
239                    self.emit_expr(arg);
240                }
241                self.push(")");
242            }
243            ChapelExpr::Index(arr, idx) => {
244                self.emit_expr(arr);
245                self.push("[");
246                self.emit_expr(idx);
247                self.push("]");
248            }
249            ChapelExpr::FieldAccess(obj, field) => {
250                self.emit_expr_paren(obj);
251                self.push(".");
252                self.push(field);
253            }
254            ChapelExpr::BinOp(op, lhs, rhs) => {
255                self.emit_expr_paren(lhs);
256                self.push(" ");
257                self.push(op);
258                self.push(" ");
259                self.emit_expr_paren(rhs);
260            }
261            ChapelExpr::UnOp(op, e) => {
262                self.push(op);
263                self.emit_expr_paren(e);
264            }
265            ChapelExpr::RangeLit(lo, hi, count_based) => {
266                self.emit_expr(lo);
267                if *count_based {
268                    self.push("..#");
269                } else {
270                    self.push("..");
271                }
272                self.emit_expr(hi);
273            }
274            ChapelExpr::ReduceExpr(op, arr) => {
275                self.push(op);
276                self.push(" reduce ");
277                self.emit_expr_paren(arr);
278            }
279            ChapelExpr::ForallExpr(idx, domain, body) => {
280                self.push("[");
281                self.push(idx);
282                self.push(" in ");
283                self.emit_expr(domain);
284                self.push("] ");
285                self.emit_expr(body);
286            }
287            ChapelExpr::CoforallExpr(idx, domain, body) => {
288                self.push("coforall ");
289                self.push(idx);
290                self.push(" in ");
291                self.emit_expr(domain);
292                self.push(" { ");
293                self.emit_expr(body);
294                self.push(" }");
295            }
296            ChapelExpr::TupleLit(elems) => {
297                self.push("(");
298                for (i, e) in elems.iter().enumerate() {
299                    if i > 0 {
300                        self.push(", ");
301                    }
302                    self.emit_expr(e);
303                }
304                self.push(")");
305            }
306            ChapelExpr::ArrayLit(elems) => {
307                self.push("[");
308                for (i, e) in elems.iter().enumerate() {
309                    if i > 0 {
310                        self.push(", ");
311                    }
312                    self.emit_expr(e);
313                }
314                self.push("]");
315            }
316            ChapelExpr::Cast(e, ty) => {
317                self.emit_expr_paren(e);
318                self.push(": ");
319                self.push(&ty.to_string());
320            }
321            ChapelExpr::IfExpr(cond, t, e) => {
322                self.push("if ");
323                self.emit_expr(cond);
324                self.push(" then ");
325                self.emit_expr(t);
326                self.push(" else ");
327                self.emit_expr(e);
328            }
329            ChapelExpr::New(ty, args) => {
330                self.push("new ");
331                self.push(&ty.to_string());
332                self.push("(");
333                for (i, arg) in args.iter().enumerate() {
334                    if i > 0 {
335                        self.push(", ");
336                    }
337                    self.emit_expr(arg);
338                }
339                self.push(")");
340            }
341            ChapelExpr::Nil => self.push("nil"),
342            ChapelExpr::Here => self.push("here"),
343            ChapelExpr::NumLocales => self.push("numLocales"),
344            ChapelExpr::This => self.push("this"),
345            ChapelExpr::TypeOf(e) => {
346                self.emit_expr(e);
347                self.push(".type");
348            }
349            ChapelExpr::DomainLit(dims) => {
350                self.push("{");
351                for (i, d) in dims.iter().enumerate() {
352                    if i > 0 {
353                        self.push(", ");
354                    }
355                    self.emit_expr(d);
356                }
357                self.push("}");
358            }
359        }
360    }
361    /// Emit an expression, adding parentheses for complex forms.
362    pub(super) fn emit_expr_paren(&mut self, expr: &ChapelExpr) {
363        let needs_paren = matches!(
364            expr,
365            ChapelExpr::BinOp(..)
366                | ChapelExpr::IfExpr(..)
367                | ChapelExpr::ForallExpr(..)
368                | ChapelExpr::CoforallExpr(..)
369                | ChapelExpr::Cast(..)
370        );
371        if needs_paren {
372            self.push("(");
373            self.emit_expr(expr);
374            self.push(")");
375        } else {
376            self.emit_expr(expr);
377        }
378    }
379    pub(super) fn emit_param(&mut self, param: &ChapelParam) {
380        if let Some(intent) = &param.intent {
381            self.push(&intent.to_string());
382            self.push(" ");
383        }
384        self.push(&param.name);
385        if let Some(ty) = &param.ty {
386            self.push(": ");
387            self.push(&ty.to_string());
388        }
389        if let Some(def) = &param.default {
390            self.push(" = ");
391            let def = def.clone();
392            self.emit_expr(&def);
393        }
394    }
395    /// Emit a single Chapel statement.
396    pub fn emit_stmt(&mut self, stmt: &ChapelStmt) {
397        match stmt {
398            ChapelStmt::VarDecl(name, ty, init) => {
399                self.emit_indent();
400                self.push("var ");
401                self.push(name);
402                if let Some(t) = ty {
403                    if self.config.annotate_vars {
404                        self.push(": ");
405                        self.push(&t.to_string());
406                    }
407                }
408                if let Some(e) = init {
409                    self.push(" = ");
410                    let e = e.clone();
411                    self.emit_expr(&e);
412                }
413                self.push(";");
414                self.newline();
415            }
416            ChapelStmt::ConstDecl(name, ty, expr) => {
417                self.emit_indent();
418                self.push("const ");
419                self.push(name);
420                if let Some(t) = ty {
421                    if self.config.annotate_vars {
422                        self.push(": ");
423                        self.push(&t.to_string());
424                    }
425                }
426                self.push(" = ");
427                let expr = expr.clone();
428                self.emit_expr(&expr);
429                self.push(";");
430                self.newline();
431            }
432            ChapelStmt::Assign(lhs, rhs) => {
433                self.emit_indent();
434                let lhs = lhs.clone();
435                let rhs = rhs.clone();
436                self.emit_expr(&lhs);
437                self.push(" = ");
438                self.emit_expr(&rhs);
439                self.push(";");
440                self.newline();
441            }
442            ChapelStmt::CompoundAssign(op, lhs, rhs) => {
443                self.emit_indent();
444                let lhs = lhs.clone();
445                let rhs = rhs.clone();
446                self.emit_expr(&lhs);
447                self.push(" ");
448                self.push(op);
449                self.push("= ");
450                self.emit_expr(&rhs);
451                self.push(";");
452                self.newline();
453            }
454            ChapelStmt::IfElse(cond, then_body, else_body) => {
455                self.emit_indent();
456                self.push("if ");
457                let cond = cond.clone();
458                self.emit_expr(&cond);
459                self.push(" {");
460                self.newline();
461                self.indent_in();
462                let then_body = then_body.clone();
463                for s in &then_body {
464                    self.emit_stmt(s);
465                }
466                self.indent_out();
467                if let Some(eb) = else_body {
468                    self.emit_indent();
469                    self.push("} else {");
470                    self.newline();
471                    self.indent_in();
472                    let eb = eb.clone();
473                    for s in &eb {
474                        self.emit_stmt(s);
475                    }
476                    self.indent_out();
477                }
478                self.emit_line("}");
479            }
480            ChapelStmt::ForLoop(idx, domain, body) => {
481                self.emit_indent();
482                self.push("for ");
483                self.push(idx);
484                self.push(" in ");
485                let domain = domain.clone();
486                self.emit_expr(&domain);
487                self.push(" {");
488                self.newline();
489                self.indent_in();
490                let body = body.clone();
491                for s in &body {
492                    self.emit_stmt(s);
493                }
494                self.indent_out();
495                self.emit_line("}");
496            }
497            ChapelStmt::ForallLoop(idx, domain, body) => {
498                self.emit_indent();
499                self.push("forall ");
500                self.push(idx);
501                self.push(" in ");
502                let domain = domain.clone();
503                self.emit_expr(&domain);
504                self.push(" {");
505                self.newline();
506                self.indent_in();
507                let body = body.clone();
508                for s in &body {
509                    self.emit_stmt(s);
510                }
511                self.indent_out();
512                self.emit_line("}");
513            }
514            ChapelStmt::ForallReduce(idx, domain, op, acc, body) => {
515                self.emit_indent();
516                self.push("forall ");
517                self.push(idx);
518                self.push(" in ");
519                let domain = domain.clone();
520                self.emit_expr(&domain);
521                self.push(" with (");
522                self.push(op);
523                self.push(" reduce ");
524                self.push(acc);
525                self.push(") {");
526                self.newline();
527                self.indent_in();
528                let body = body.clone();
529                for s in &body {
530                    self.emit_stmt(s);
531                }
532                self.indent_out();
533                self.emit_line("}");
534            }
535            ChapelStmt::CoforallLoop(idx, domain, body) => {
536                self.emit_indent();
537                self.push("coforall ");
538                self.push(idx);
539                self.push(" in ");
540                let domain = domain.clone();
541                self.emit_expr(&domain);
542                self.push(" {");
543                self.newline();
544                self.indent_in();
545                let body = body.clone();
546                for s in &body {
547                    self.emit_stmt(s);
548                }
549                self.indent_out();
550                self.emit_line("}");
551            }
552            ChapelStmt::WhileLoop(cond, body) => {
553                self.emit_indent();
554                self.push("while ");
555                let cond = cond.clone();
556                self.emit_expr(&cond);
557                self.push(" {");
558                self.newline();
559                self.indent_in();
560                let body = body.clone();
561                for s in &body {
562                    self.emit_stmt(s);
563                }
564                self.indent_out();
565                self.emit_line("}");
566            }
567            ChapelStmt::DoWhileLoop(body, cond) => {
568                self.emit_line("do {");
569                self.indent_in();
570                let body = body.clone();
571                for s in &body {
572                    self.emit_stmt(s);
573                }
574                self.indent_out();
575                self.emit_indent();
576                self.push("} while ");
577                let cond = cond.clone();
578                self.emit_expr(&cond);
579                self.push(";");
580                self.newline();
581            }
582            ChapelStmt::ReturnStmt(e) => {
583                self.emit_indent();
584                self.push("return");
585                if let Some(expr) = e {
586                    self.push(" ");
587                    let expr = expr.clone();
588                    self.emit_expr(&expr);
589                }
590                self.push(";");
591                self.newline();
592            }
593            ChapelStmt::ProcDef(proc) => {
594                self.emit_proc(proc);
595            }
596            ChapelStmt::RecordDef(rec) => {
597                self.emit_record(rec);
598            }
599            ChapelStmt::ClassDef(cls) => {
600                self.emit_class(cls);
601            }
602            ChapelStmt::ExprStmt(e) => {
603                self.emit_indent();
604                let e = e.clone();
605                self.emit_expr(&e);
606                self.push(";");
607                self.newline();
608            }
609            ChapelStmt::Writeln(args) => {
610                self.emit_indent();
611                self.push("writeln(");
612                let args = args.clone();
613                for (i, arg) in args.iter().enumerate() {
614                    if i > 0 {
615                        self.push(", ");
616                    }
617                    self.emit_expr(arg);
618                }
619                self.push(");");
620                self.newline();
621            }
622            ChapelStmt::Write(args) => {
623                self.emit_indent();
624                self.push("write(");
625                let args = args.clone();
626                for (i, arg) in args.iter().enumerate() {
627                    if i > 0 {
628                        self.push(", ");
629                    }
630                    self.emit_expr(arg);
631                }
632                self.push(");");
633                self.newline();
634            }
635            ChapelStmt::Break => {
636                self.emit_line("break;");
637            }
638            ChapelStmt::Continue => {
639                self.emit_line("continue;");
640            }
641            ChapelStmt::Halt(msg) => {
642                self.emit_indent();
643                self.push("halt(\"");
644                self.push(msg);
645                self.push("\");");
646                self.newline();
647            }
648            ChapelStmt::On(locale, body) => {
649                self.emit_indent();
650                self.push("on ");
651                let locale = locale.clone();
652                self.emit_expr(&locale);
653                self.push(" {");
654                self.newline();
655                self.indent_in();
656                let body = body.clone();
657                for s in &body {
658                    self.emit_stmt(s);
659                }
660                self.indent_out();
661                self.emit_line("}");
662            }
663            ChapelStmt::Begin(body) => {
664                self.emit_line("begin {");
665                self.indent_in();
666                let body = body.clone();
667                for s in &body {
668                    self.emit_stmt(s);
669                }
670                self.indent_out();
671                self.emit_line("}");
672            }
673            ChapelStmt::SyncBlock(body) => {
674                self.emit_line("sync {");
675                self.indent_in();
676                let body = body.clone();
677                for s in &body {
678                    self.emit_stmt(s);
679                }
680                self.indent_out();
681                self.emit_line("}");
682            }
683            ChapelStmt::Comment(text) => {
684                self.emit_indent();
685                self.push("// ");
686                self.push(text);
687                self.newline();
688            }
689            ChapelStmt::Blank => {
690                self.newline();
691            }
692        }
693    }
694    /// Emit a Chapel procedure definition.
695    pub fn emit_proc(&mut self, proc: &ChapelProc) {
696        self.emit_indent();
697        if proc.is_inline {
698            self.push("inline ");
699        }
700        if proc.is_override {
701            self.push("override ");
702        }
703        if proc.is_iter {
704            self.push("iter ");
705        } else if proc.is_operator {
706            self.push("operator ");
707        } else {
708            self.push("proc ");
709        }
710        self.push(&proc.name);
711        self.push("(");
712        let params = proc.params.clone();
713        for (i, param) in params.iter().enumerate() {
714            if i > 0 {
715                self.push(", ");
716            }
717            self.emit_param(param);
718        }
719        self.push(")");
720        if let Some(ret) = &proc.return_type {
721            self.push(": ");
722            self.push(&ret.to_string());
723        }
724        if let Some(wh) = &proc.where_clause {
725            self.push(" where ");
726            self.push(wh);
727        }
728        self.push(" {");
729        self.newline();
730        self.indent_in();
731        let body = proc.body.clone();
732        for stmt in &body {
733            self.emit_stmt(stmt);
734        }
735        self.indent_out();
736        self.emit_line("}");
737        self.newline();
738    }
739    /// Emit a Chapel record definition.
740    pub fn emit_record(&mut self, rec: &ChapelRecord) {
741        self.emit_indent();
742        self.push("record ");
743        self.push(&rec.name);
744        if !rec.type_params.is_empty() {
745            self.push("(");
746            for (i, tp) in rec.type_params.iter().enumerate() {
747                if i > 0 {
748                    self.push(", ");
749                }
750                self.push("type ");
751                self.push(tp);
752            }
753            self.push(")");
754        }
755        self.push(" {");
756        self.newline();
757        self.indent_in();
758        let fields = rec.fields.clone();
759        for field in &fields {
760            self.emit_indent();
761            if field.is_const {
762                self.push("const ");
763            } else {
764                self.push("var ");
765            }
766            self.push(&field.name);
767            self.push(": ");
768            self.push(&field.ty.to_string());
769            if let Some(def) = &field.default {
770                self.push(" = ");
771                let def = def.clone();
772                self.emit_expr(&def);
773            }
774            self.push(";");
775            self.newline();
776        }
777        let methods = rec.methods.clone();
778        for method in &methods {
779            self.emit_proc(method);
780        }
781        self.indent_out();
782        self.emit_line("}");
783        self.newline();
784    }
785    /// Emit a Chapel class definition.
786    pub fn emit_class(&mut self, cls: &ChapelClass) {
787        self.emit_indent();
788        self.push("class ");
789        self.push(&cls.name);
790        if !cls.type_params.is_empty() {
791            self.push("(");
792            for (i, tp) in cls.type_params.iter().enumerate() {
793                if i > 0 {
794                    self.push(", ");
795                }
796                self.push("type ");
797                self.push(tp);
798            }
799            self.push(")");
800        }
801        if let Some(parent) = &cls.parent {
802            self.push(" : ");
803            self.push(parent);
804        }
805        self.push(" {");
806        self.newline();
807        self.indent_in();
808        let fields = cls.fields.clone();
809        for field in &fields {
810            self.emit_indent();
811            if field.is_const {
812                self.push("const ");
813            } else {
814                self.push("var ");
815            }
816            self.push(&field.name);
817            self.push(": ");
818            self.push(&field.ty.to_string());
819            if let Some(def) = &field.default {
820                self.push(" = ");
821                let def = def.clone();
822                self.emit_expr(&def);
823            }
824            self.push(";");
825            self.newline();
826        }
827        let methods = cls.methods.clone();
828        for method in &methods {
829            self.emit_proc(method);
830        }
831        self.indent_out();
832        self.emit_line("}");
833        self.newline();
834    }
835    /// Emit a complete Chapel module.
836    pub fn emit_module(&mut self, module: &ChapelModule) {
837        if let Some(doc) = &module.doc.clone() {
838            for line in doc.lines() {
839                self.push("// ");
840                self.push(line);
841                self.newline();
842            }
843            self.newline();
844        }
845        let has_name = module.name.is_some();
846        if let Some(name) = &module.name.clone() {
847            self.emit_line(&format!("module {name} {{"));
848            self.indent_in();
849        }
850        for u in &module.uses.clone() {
851            self.emit_line(&format!("use {u};"));
852        }
853        if !module.uses.is_empty() {
854            self.newline();
855        }
856        for r in &module.requires.clone() {
857            self.emit_line(&format!("require \"{r}\";"));
858        }
859        if !module.requires.is_empty() {
860            self.newline();
861        }
862        for (name, ty, def) in &module.configs.clone() {
863            self.emit_indent();
864            self.push("config var ");
865            self.push(name);
866            self.push(": ");
867            self.push(&ty.to_string());
868            if let Some(d) = def {
869                self.push(" = ");
870                let d = d.clone();
871                self.emit_expr(&d);
872            }
873            self.push(";");
874            self.newline();
875        }
876        if !module.configs.is_empty() {
877            self.newline();
878        }
879        for (name, ty, expr) in &module.globals.clone() {
880            self.emit_indent();
881            self.push("const ");
882            self.push(name);
883            self.push(": ");
884            self.push(&ty.to_string());
885            self.push(" = ");
886            let expr = expr.clone();
887            self.emit_expr(&expr);
888            self.push(";");
889            self.newline();
890        }
891        if !module.globals.is_empty() {
892            self.newline();
893        }
894        for rec in &module.records.clone() {
895            self.emit_record(rec);
896        }
897        for cls in &module.classes.clone() {
898            self.emit_class(cls);
899        }
900        for proc in &module.procs.clone() {
901            self.emit_proc(proc);
902        }
903        for sub in &module.submodules.clone() {
904            self.emit_module(sub);
905        }
906        if has_name {
907            self.indent_out();
908            self.emit_line("}");
909        }
910    }
911    /// Return the generated source and reset the buffer.
912    pub fn finish(&mut self) -> String {
913        std::mem::take(&mut self.buf)
914    }
915    /// Generate a complete `.chpl` file from a module.
916    pub fn generate(module: &ChapelModule) -> String {
917        let mut backend = ChapelBackend::new();
918        backend.emit_module(module);
919        backend.finish()
920    }
921    /// Generate with custom configuration.
922    pub fn generate_with_config(module: &ChapelModule, config: ChapelConfig) -> String {
923        let mut backend = ChapelBackend::with_config(config);
924        backend.emit_module(module);
925        backend.finish()
926    }
927}
928/// Intent for procedure parameters.
929#[derive(Debug, Clone, PartialEq)]
930pub enum ChapelIntent {
931    In,
932    Out,
933    InOut,
934    Ref,
935    Const,
936    ConstRef,
937    Param,
938    Type,
939}
940#[allow(dead_code)]
941pub struct ChplPassRegistry {
942    pub(super) configs: Vec<ChplPassConfig>,
943    pub(super) stats: std::collections::HashMap<String, ChplPassStats>,
944}
945impl ChplPassRegistry {
946    #[allow(dead_code)]
947    pub fn new() -> Self {
948        ChplPassRegistry {
949            configs: Vec::new(),
950            stats: std::collections::HashMap::new(),
951        }
952    }
953    #[allow(dead_code)]
954    pub fn register(&mut self, config: ChplPassConfig) {
955        self.stats
956            .insert(config.pass_name.clone(), ChplPassStats::new());
957        self.configs.push(config);
958    }
959    #[allow(dead_code)]
960    pub fn enabled_passes(&self) -> Vec<&ChplPassConfig> {
961        self.configs.iter().filter(|c| c.enabled).collect()
962    }
963    #[allow(dead_code)]
964    pub fn get_stats(&self, name: &str) -> Option<&ChplPassStats> {
965        self.stats.get(name)
966    }
967    #[allow(dead_code)]
968    pub fn total_passes(&self) -> usize {
969        self.configs.len()
970    }
971    #[allow(dead_code)]
972    pub fn enabled_count(&self) -> usize {
973        self.enabled_passes().len()
974    }
975    #[allow(dead_code)]
976    pub fn update_stats(&mut self, name: &str, changes: u64, time_ms: u64, iter: u32) {
977        if let Some(stats) = self.stats.get_mut(name) {
978            stats.record_run(changes, time_ms, iter);
979        }
980    }
981}
982/// Constant folding helper for ChapelExt.
983#[allow(dead_code)]
984#[derive(Debug, Clone, Default)]
985pub struct ChapelExtConstFolder {
986    pub(super) folds: usize,
987    pub(super) failures: usize,
988    pub(super) enabled: bool,
989}
990impl ChapelExtConstFolder {
991    #[allow(dead_code)]
992    pub fn new() -> Self {
993        Self {
994            folds: 0,
995            failures: 0,
996            enabled: true,
997        }
998    }
999    #[allow(dead_code)]
1000    pub fn add_i64(&mut self, a: i64, b: i64) -> Option<i64> {
1001        self.folds += 1;
1002        a.checked_add(b)
1003    }
1004    #[allow(dead_code)]
1005    pub fn sub_i64(&mut self, a: i64, b: i64) -> Option<i64> {
1006        self.folds += 1;
1007        a.checked_sub(b)
1008    }
1009    #[allow(dead_code)]
1010    pub fn mul_i64(&mut self, a: i64, b: i64) -> Option<i64> {
1011        self.folds += 1;
1012        a.checked_mul(b)
1013    }
1014    #[allow(dead_code)]
1015    pub fn div_i64(&mut self, a: i64, b: i64) -> Option<i64> {
1016        if b == 0 {
1017            self.failures += 1;
1018            None
1019        } else {
1020            self.folds += 1;
1021            a.checked_div(b)
1022        }
1023    }
1024    #[allow(dead_code)]
1025    pub fn rem_i64(&mut self, a: i64, b: i64) -> Option<i64> {
1026        if b == 0 {
1027            self.failures += 1;
1028            None
1029        } else {
1030            self.folds += 1;
1031            a.checked_rem(b)
1032        }
1033    }
1034    #[allow(dead_code)]
1035    pub fn neg_i64(&mut self, a: i64) -> Option<i64> {
1036        self.folds += 1;
1037        a.checked_neg()
1038    }
1039    #[allow(dead_code)]
1040    pub fn shl_i64(&mut self, a: i64, s: u32) -> Option<i64> {
1041        if s >= 64 {
1042            self.failures += 1;
1043            None
1044        } else {
1045            self.folds += 1;
1046            a.checked_shl(s)
1047        }
1048    }
1049    #[allow(dead_code)]
1050    pub fn shr_i64(&mut self, a: i64, s: u32) -> Option<i64> {
1051        if s >= 64 {
1052            self.failures += 1;
1053            None
1054        } else {
1055            self.folds += 1;
1056            a.checked_shr(s)
1057        }
1058    }
1059    #[allow(dead_code)]
1060    pub fn and_i64(&mut self, a: i64, b: i64) -> i64 {
1061        self.folds += 1;
1062        a & b
1063    }
1064    #[allow(dead_code)]
1065    pub fn or_i64(&mut self, a: i64, b: i64) -> i64 {
1066        self.folds += 1;
1067        a | b
1068    }
1069    #[allow(dead_code)]
1070    pub fn xor_i64(&mut self, a: i64, b: i64) -> i64 {
1071        self.folds += 1;
1072        a ^ b
1073    }
1074    #[allow(dead_code)]
1075    pub fn not_i64(&mut self, a: i64) -> i64 {
1076        self.folds += 1;
1077        !a
1078    }
1079    #[allow(dead_code)]
1080    pub fn fold_count(&self) -> usize {
1081        self.folds
1082    }
1083    #[allow(dead_code)]
1084    pub fn failure_count(&self) -> usize {
1085        self.failures
1086    }
1087    #[allow(dead_code)]
1088    pub fn enable(&mut self) {
1089        self.enabled = true;
1090    }
1091    #[allow(dead_code)]
1092    pub fn disable(&mut self) {
1093        self.enabled = false;
1094    }
1095    #[allow(dead_code)]
1096    pub fn is_enabled(&self) -> bool {
1097        self.enabled
1098    }
1099}
1100#[allow(dead_code)]
1101#[derive(Debug, Clone)]
1102pub struct ChplPassConfig {
1103    pub phase: ChplPassPhase,
1104    pub enabled: bool,
1105    pub max_iterations: u32,
1106    pub debug_output: bool,
1107    pub pass_name: String,
1108}
1109impl ChplPassConfig {
1110    #[allow(dead_code)]
1111    pub fn new(name: impl Into<String>, phase: ChplPassPhase) -> Self {
1112        ChplPassConfig {
1113            phase,
1114            enabled: true,
1115            max_iterations: 10,
1116            debug_output: false,
1117            pass_name: name.into(),
1118        }
1119    }
1120    #[allow(dead_code)]
1121    pub fn disabled(mut self) -> Self {
1122        self.enabled = false;
1123        self
1124    }
1125    #[allow(dead_code)]
1126    pub fn with_debug(mut self) -> Self {
1127        self.debug_output = true;
1128        self
1129    }
1130    #[allow(dead_code)]
1131    pub fn max_iter(mut self, n: u32) -> Self {
1132        self.max_iterations = n;
1133        self
1134    }
1135}
1136/// Chapel type representation.
1137#[derive(Debug, Clone, PartialEq)]
1138pub enum ChapelType {
1139    /// `int(8)` / `int(16)` / `int(32)` / `int(64)` (default `int`)
1140    Int(Option<u32>),
1141    /// `uint(8)` / `uint(16)` / `uint(32)` / `uint(64)` (default `uint`)
1142    UInt(Option<u32>),
1143    /// `real(32)` / `real(64)` (default `real`)
1144    Real(Option<u32>),
1145    /// `imag(32)` / `imag(64)` (default `imag`)
1146    Imag(Option<u32>),
1147    /// `complex(64)` / `complex(128)` (default `complex`)
1148    Complex(Option<u32>),
1149    /// `bool`
1150    Bool,
1151    /// `string`
1152    String,
1153    /// `bytes`
1154    Bytes,
1155    /// `range(idxType)` — e.g. `1..n`
1156    Range(Box<ChapelType>),
1157    /// `domain(rank, idxType)` — multi-dimensional index set
1158    Domain(u32, Box<ChapelType>),
1159    /// `[D] eltType` — array over a domain
1160    Array(Box<ChapelType>, Box<ChapelType>),
1161    /// Record type: `record R { ... }`
1162    Record(String),
1163    /// Class type: `class C { ... }`
1164    Class(String),
1165    /// Union type: `union U { ... }`
1166    Union(String),
1167    /// Enum type: `enum E { ... }`
1168    EnumType(String),
1169    /// Procedure/function type: `proc(argTypes) : retType`
1170    ProcType(Vec<ChapelType>, Box<ChapelType>),
1171    /// Tuple type: `(t1, t2, ...)`
1172    Tuple(Vec<ChapelType>),
1173    /// Named / user-defined type
1174    Named(String),
1175    /// `void` (no return)
1176    Void,
1177    /// Type variable / generic
1178    TypeVar(String),
1179    /// `atomic T`
1180    Atomic(Box<ChapelType>),
1181    /// `sync T`
1182    Sync(Box<ChapelType>),
1183    /// `single T`
1184    Single(Box<ChapelType>),
1185    /// Pointer to owned object: `owned C`
1186    Owned(Box<ChapelType>),
1187    /// Shared: `shared C`
1188    Shared(Box<ChapelType>),
1189    /// Unmanaged: `unmanaged C`
1190    Unmanaged(Box<ChapelType>),
1191}
1192/// Pass execution phase for ChapelExt.
1193#[allow(dead_code)]
1194#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1195pub enum ChapelExtPassPhase {
1196    Early,
1197    Middle,
1198    Late,
1199    Finalize,
1200}
1201impl ChapelExtPassPhase {
1202    #[allow(dead_code)]
1203    pub fn is_early(&self) -> bool {
1204        matches!(self, Self::Early)
1205    }
1206    #[allow(dead_code)]
1207    pub fn is_middle(&self) -> bool {
1208        matches!(self, Self::Middle)
1209    }
1210    #[allow(dead_code)]
1211    pub fn is_late(&self) -> bool {
1212        matches!(self, Self::Late)
1213    }
1214    #[allow(dead_code)]
1215    pub fn is_finalize(&self) -> bool {
1216        matches!(self, Self::Finalize)
1217    }
1218    #[allow(dead_code)]
1219    pub fn order(&self) -> u32 {
1220        match self {
1221            Self::Early => 0,
1222            Self::Middle => 1,
1223            Self::Late => 2,
1224            Self::Finalize => 3,
1225        }
1226    }
1227    #[allow(dead_code)]
1228    pub fn from_order(n: u32) -> Option<Self> {
1229        match n {
1230            0 => Some(Self::Early),
1231            1 => Some(Self::Middle),
1232            2 => Some(Self::Late),
1233            3 => Some(Self::Finalize),
1234            _ => None,
1235        }
1236    }
1237}
1238/// Configuration for the Chapel backend emitter.
1239#[derive(Debug, Clone)]
1240pub struct ChapelConfig {
1241    /// Spaces per indentation level
1242    pub indent_width: usize,
1243    /// Emit type annotations on var declarations when available
1244    pub annotate_vars: bool,
1245    /// Use `writeln` for print calls
1246    pub use_writeln: bool,
1247}
1248/// Chapel expression representation.
1249#[derive(Debug, Clone)]
1250pub enum ChapelExpr {
1251    /// Integer literal: `42`
1252    IntLit(i64),
1253    /// Real literal: `3.14`
1254    RealLit(f64),
1255    /// Bool literal: `true` / `false`
1256    BoolLit(bool),
1257    /// String literal: `"hello"`
1258    StrLit(String),
1259    /// Variable reference: `x`
1260    Var(String),
1261    /// Function/procedure application: `f(a, b, ...)`
1262    Apply(Box<ChapelExpr>, Vec<ChapelExpr>),
1263    /// Array index: `a[i]`
1264    Index(Box<ChapelExpr>, Box<ChapelExpr>),
1265    /// Field/member access: `r.field`
1266    FieldAccess(Box<ChapelExpr>, String),
1267    /// Binary operation: `lhs op rhs`
1268    BinOp(String, Box<ChapelExpr>, Box<ChapelExpr>),
1269    /// Unary operation: `op e`
1270    UnOp(String, Box<ChapelExpr>),
1271    /// Range: `lo..hi` or `lo..#n`
1272    RangeLit(Box<ChapelExpr>, Box<ChapelExpr>, bool),
1273    /// Reduce expression: `+ reduce arr`
1274    ReduceExpr(String, Box<ChapelExpr>),
1275    /// Forall expression: `[i in D] f(i)`
1276    ForallExpr(String, Box<ChapelExpr>, Box<ChapelExpr>),
1277    /// Coforall expression body reference
1278    CoforallExpr(String, Box<ChapelExpr>, Box<ChapelExpr>),
1279    /// Tuple literal: `(e1, e2, ...)`
1280    TupleLit(Vec<ChapelExpr>),
1281    /// Array literal: `[e1, e2, ...]`
1282    ArrayLit(Vec<ChapelExpr>),
1283    /// Cast: `e : t`
1284    Cast(Box<ChapelExpr>, ChapelType),
1285    /// Conditional (ternary): `if cond then t else e`
1286    IfExpr(Box<ChapelExpr>, Box<ChapelExpr>, Box<ChapelExpr>),
1287    /// New object: `new C(args...)`
1288    New(ChapelType, Vec<ChapelExpr>),
1289    /// `nil`
1290    Nil,
1291    /// `here` locale
1292    Here,
1293    /// `numLocales`
1294    NumLocales,
1295    /// `this` reference
1296    This,
1297    /// Type query: `e.type`
1298    TypeOf(Box<ChapelExpr>),
1299    /// Domain literal: `{e1, e2, ...}` or `{lo..hi}`
1300    DomainLit(Vec<ChapelExpr>),
1301}
1302#[allow(dead_code)]
1303#[derive(Debug, Clone)]
1304pub struct ChplAnalysisCache {
1305    pub(super) entries: std::collections::HashMap<String, ChplCacheEntry>,
1306    pub(super) max_size: usize,
1307    pub(super) hits: u64,
1308    pub(super) misses: u64,
1309}
1310impl ChplAnalysisCache {
1311    #[allow(dead_code)]
1312    pub fn new(max_size: usize) -> Self {
1313        ChplAnalysisCache {
1314            entries: std::collections::HashMap::new(),
1315            max_size,
1316            hits: 0,
1317            misses: 0,
1318        }
1319    }
1320    #[allow(dead_code)]
1321    pub fn get(&mut self, key: &str) -> Option<&ChplCacheEntry> {
1322        if self.entries.contains_key(key) {
1323            self.hits += 1;
1324            self.entries.get(key)
1325        } else {
1326            self.misses += 1;
1327            None
1328        }
1329    }
1330    #[allow(dead_code)]
1331    pub fn insert(&mut self, key: String, data: Vec<u8>) {
1332        if self.entries.len() >= self.max_size {
1333            if let Some(oldest) = self.entries.keys().next().cloned() {
1334                self.entries.remove(&oldest);
1335            }
1336        }
1337        self.entries.insert(
1338            key.clone(),
1339            ChplCacheEntry {
1340                key,
1341                data,
1342                timestamp: 0,
1343                valid: true,
1344            },
1345        );
1346    }
1347    #[allow(dead_code)]
1348    pub fn invalidate(&mut self, key: &str) {
1349        if let Some(entry) = self.entries.get_mut(key) {
1350            entry.valid = false;
1351        }
1352    }
1353    #[allow(dead_code)]
1354    pub fn clear(&mut self) {
1355        self.entries.clear();
1356    }
1357    #[allow(dead_code)]
1358    pub fn hit_rate(&self) -> f64 {
1359        let total = self.hits + self.misses;
1360        if total == 0 {
1361            return 0.0;
1362        }
1363        self.hits as f64 / total as f64
1364    }
1365    #[allow(dead_code)]
1366    pub fn size(&self) -> usize {
1367        self.entries.len()
1368    }
1369}
1370/// Chapel statement representation.
1371#[derive(Debug, Clone)]
1372pub enum ChapelStmt {
1373    /// `var name: type = expr;`
1374    VarDecl(String, Option<ChapelType>, Option<ChapelExpr>),
1375    /// `const name: type = expr;`
1376    ConstDecl(String, Option<ChapelType>, ChapelExpr),
1377    /// `name = expr;`
1378    Assign(ChapelExpr, ChapelExpr),
1379    /// Compound assign: `name op= expr;`
1380    CompoundAssign(String, ChapelExpr, ChapelExpr),
1381    /// `if cond { ... } else { ... }`
1382    IfElse(ChapelExpr, Vec<ChapelStmt>, Option<Vec<ChapelStmt>>),
1383    /// `for idx in domain { ... }`
1384    ForLoop(String, ChapelExpr, Vec<ChapelStmt>),
1385    /// `forall idx in domain { ... }`
1386    ForallLoop(String, ChapelExpr, Vec<ChapelStmt>),
1387    /// `forall idx in domain with (op reduce acc) { ... }`
1388    ForallReduce(String, ChapelExpr, String, String, Vec<ChapelStmt>),
1389    /// `coforall idx in domain { ... }`
1390    CoforallLoop(String, ChapelExpr, Vec<ChapelStmt>),
1391    /// `while cond { ... }`
1392    WhileLoop(ChapelExpr, Vec<ChapelStmt>),
1393    /// `do { ... } while cond;`
1394    DoWhileLoop(Vec<ChapelStmt>, ChapelExpr),
1395    /// `return expr;`
1396    ReturnStmt(Option<ChapelExpr>),
1397    /// Procedure definition (nested or top-level)
1398    ProcDef(ChapelProc),
1399    /// Record definition
1400    RecordDef(ChapelRecord),
1401    /// Class definition
1402    ClassDef(ChapelClass),
1403    /// Expression statement: `expr;`
1404    ExprStmt(ChapelExpr),
1405    /// `writeln(args...);`
1406    Writeln(Vec<ChapelExpr>),
1407    /// `write(args...);`
1408    Write(Vec<ChapelExpr>),
1409    /// `break;`
1410    Break,
1411    /// `continue;`
1412    Continue,
1413    /// `halt(msg);`
1414    Halt(String),
1415    /// `on locale { ... }`
1416    On(ChapelExpr, Vec<ChapelStmt>),
1417    /// `begin { ... }` — async task
1418    Begin(Vec<ChapelStmt>),
1419    /// `sync { ... }` — synchronisation block
1420    SyncBlock(Vec<ChapelStmt>),
1421    /// Block comment
1422    Comment(String),
1423    /// Blank line separator
1424    Blank,
1425}
1426/// Analysis cache for ChapelExt.
1427#[allow(dead_code)]
1428#[derive(Debug)]
1429pub struct ChapelExtCache {
1430    pub(super) entries: Vec<(u64, Vec<u8>, bool, u32)>,
1431    pub(super) cap: usize,
1432    pub(super) total_hits: u64,
1433    pub(super) total_misses: u64,
1434}
1435impl ChapelExtCache {
1436    #[allow(dead_code)]
1437    pub fn new(cap: usize) -> Self {
1438        Self {
1439            entries: Vec::new(),
1440            cap,
1441            total_hits: 0,
1442            total_misses: 0,
1443        }
1444    }
1445    #[allow(dead_code)]
1446    pub fn get(&mut self, key: u64) -> Option<&[u8]> {
1447        for e in self.entries.iter_mut() {
1448            if e.0 == key && e.2 {
1449                e.3 += 1;
1450                self.total_hits += 1;
1451                return Some(&e.1);
1452            }
1453        }
1454        self.total_misses += 1;
1455        None
1456    }
1457    #[allow(dead_code)]
1458    pub fn put(&mut self, key: u64, data: Vec<u8>) {
1459        if self.entries.len() >= self.cap {
1460            self.entries.retain(|e| e.2);
1461            if self.entries.len() >= self.cap {
1462                self.entries.remove(0);
1463            }
1464        }
1465        self.entries.push((key, data, true, 0));
1466    }
1467    #[allow(dead_code)]
1468    pub fn invalidate(&mut self) {
1469        for e in self.entries.iter_mut() {
1470            e.2 = false;
1471        }
1472    }
1473    #[allow(dead_code)]
1474    pub fn hit_rate(&self) -> f64 {
1475        let t = self.total_hits + self.total_misses;
1476        if t == 0 {
1477            0.0
1478        } else {
1479            self.total_hits as f64 / t as f64
1480        }
1481    }
1482    #[allow(dead_code)]
1483    pub fn live_count(&self) -> usize {
1484        self.entries.iter().filter(|e| e.2).count()
1485    }
1486}
1487/// A Chapel record definition.
1488#[derive(Debug, Clone)]
1489pub struct ChapelRecord {
1490    /// Record name
1491    pub name: String,
1492    /// Fields
1493    pub fields: Vec<ChapelField>,
1494    /// Methods
1495    pub methods: Vec<ChapelProc>,
1496    /// Optional generic type parameters
1497    pub type_params: Vec<String>,
1498}
1499impl ChapelRecord {
1500    /// Create an empty record.
1501    pub fn new(name: impl Into<String>) -> Self {
1502        ChapelRecord {
1503            name: name.into(),
1504            fields: vec![],
1505            methods: vec![],
1506            type_params: vec![],
1507        }
1508    }
1509    /// Add a field.
1510    pub fn add_field(&mut self, field: ChapelField) {
1511        self.fields.push(field);
1512    }
1513    /// Add a method.
1514    pub fn add_method(&mut self, method: ChapelProc) {
1515        self.methods.push(method);
1516    }
1517}
1518#[allow(dead_code)]
1519#[derive(Debug, Clone)]
1520pub struct ChplLivenessInfo {
1521    pub live_in: Vec<std::collections::HashSet<u32>>,
1522    pub live_out: Vec<std::collections::HashSet<u32>>,
1523    pub defs: Vec<std::collections::HashSet<u32>>,
1524    pub uses: Vec<std::collections::HashSet<u32>>,
1525}
1526impl ChplLivenessInfo {
1527    #[allow(dead_code)]
1528    pub fn new(block_count: usize) -> Self {
1529        ChplLivenessInfo {
1530            live_in: vec![std::collections::HashSet::new(); block_count],
1531            live_out: vec![std::collections::HashSet::new(); block_count],
1532            defs: vec![std::collections::HashSet::new(); block_count],
1533            uses: vec![std::collections::HashSet::new(); block_count],
1534        }
1535    }
1536    #[allow(dead_code)]
1537    pub fn add_def(&mut self, block: usize, var: u32) {
1538        if block < self.defs.len() {
1539            self.defs[block].insert(var);
1540        }
1541    }
1542    #[allow(dead_code)]
1543    pub fn add_use(&mut self, block: usize, var: u32) {
1544        if block < self.uses.len() {
1545            self.uses[block].insert(var);
1546        }
1547    }
1548    #[allow(dead_code)]
1549    pub fn is_live_in(&self, block: usize, var: u32) -> bool {
1550        self.live_in
1551            .get(block)
1552            .map(|s| s.contains(&var))
1553            .unwrap_or(false)
1554    }
1555    #[allow(dead_code)]
1556    pub fn is_live_out(&self, block: usize, var: u32) -> bool {
1557        self.live_out
1558            .get(block)
1559            .map(|s| s.contains(&var))
1560            .unwrap_or(false)
1561    }
1562}
1563#[allow(dead_code)]
1564#[derive(Debug, Clone)]
1565pub struct ChplDominatorTree {
1566    pub idom: Vec<Option<u32>>,
1567    pub dom_children: Vec<Vec<u32>>,
1568    pub dom_depth: Vec<u32>,
1569}
1570impl ChplDominatorTree {
1571    #[allow(dead_code)]
1572    pub fn new(size: usize) -> Self {
1573        ChplDominatorTree {
1574            idom: vec![None; size],
1575            dom_children: vec![Vec::new(); size],
1576            dom_depth: vec![0; size],
1577        }
1578    }
1579    #[allow(dead_code)]
1580    pub fn set_idom(&mut self, node: usize, idom: u32) {
1581        self.idom[node] = Some(idom);
1582    }
1583    #[allow(dead_code)]
1584    pub fn dominates(&self, a: usize, b: usize) -> bool {
1585        if a == b {
1586            return true;
1587        }
1588        let mut cur = b;
1589        loop {
1590            match self.idom[cur] {
1591                Some(parent) if parent as usize == a => return true,
1592                Some(parent) if parent as usize == cur => return false,
1593                Some(parent) => cur = parent as usize,
1594                None => return false,
1595            }
1596        }
1597    }
1598    #[allow(dead_code)]
1599    pub fn depth(&self, node: usize) -> u32 {
1600        self.dom_depth.get(node).copied().unwrap_or(0)
1601    }
1602}
1603/// A Chapel procedure parameter.
1604#[derive(Debug, Clone)]
1605pub struct ChapelParam {
1606    /// Parameter name
1607    pub name: String,
1608    /// Optional type annotation
1609    pub ty: Option<ChapelType>,
1610    /// Optional intent
1611    pub intent: Option<ChapelIntent>,
1612    /// Optional default value
1613    pub default: Option<ChapelExpr>,
1614}
1615impl ChapelParam {
1616    /// Simple parameter: `name: type`
1617    pub fn simple(name: impl Into<String>, ty: ChapelType) -> Self {
1618        ChapelParam {
1619            name: name.into(),
1620            ty: Some(ty),
1621            intent: None,
1622            default: None,
1623        }
1624    }
1625    /// Parameter with intent: `intent name: type`
1626    pub fn with_intent(name: impl Into<String>, ty: ChapelType, intent: ChapelIntent) -> Self {
1627        ChapelParam {
1628            name: name.into(),
1629            ty: Some(ty),
1630            intent: Some(intent),
1631            default: None,
1632        }
1633    }
1634}
1635#[allow(dead_code)]
1636#[derive(Debug, Clone, Default)]
1637pub struct ChplPassStats {
1638    pub total_runs: u32,
1639    pub successful_runs: u32,
1640    pub total_changes: u64,
1641    pub time_ms: u64,
1642    pub iterations_used: u32,
1643}
1644impl ChplPassStats {
1645    #[allow(dead_code)]
1646    pub fn new() -> Self {
1647        Self::default()
1648    }
1649    #[allow(dead_code)]
1650    pub fn record_run(&mut self, changes: u64, time_ms: u64, iterations: u32) {
1651        self.total_runs += 1;
1652        self.successful_runs += 1;
1653        self.total_changes += changes;
1654        self.time_ms += time_ms;
1655        self.iterations_used = iterations;
1656    }
1657    #[allow(dead_code)]
1658    pub fn average_changes_per_run(&self) -> f64 {
1659        if self.total_runs == 0 {
1660            return 0.0;
1661        }
1662        self.total_changes as f64 / self.total_runs as f64
1663    }
1664    #[allow(dead_code)]
1665    pub fn success_rate(&self) -> f64 {
1666        if self.total_runs == 0 {
1667            return 0.0;
1668        }
1669        self.successful_runs as f64 / self.total_runs as f64
1670    }
1671    #[allow(dead_code)]
1672    pub fn format_summary(&self) -> String {
1673        format!(
1674            "Runs: {}/{}, Changes: {}, Time: {}ms",
1675            self.successful_runs, self.total_runs, self.total_changes, self.time_ms
1676        )
1677    }
1678}
1679/// Liveness analysis for ChapelExt.
1680#[allow(dead_code)]
1681#[derive(Debug, Clone, Default)]
1682pub struct ChapelExtLiveness {
1683    pub live_in: Vec<Vec<usize>>,
1684    pub live_out: Vec<Vec<usize>>,
1685    pub defs: Vec<Vec<usize>>,
1686    pub uses: Vec<Vec<usize>>,
1687}
1688impl ChapelExtLiveness {
1689    #[allow(dead_code)]
1690    pub fn new(n: usize) -> Self {
1691        Self {
1692            live_in: vec![Vec::new(); n],
1693            live_out: vec![Vec::new(); n],
1694            defs: vec![Vec::new(); n],
1695            uses: vec![Vec::new(); n],
1696        }
1697    }
1698    #[allow(dead_code)]
1699    pub fn live_in(&self, b: usize, v: usize) -> bool {
1700        self.live_in.get(b).map(|s| s.contains(&v)).unwrap_or(false)
1701    }
1702    #[allow(dead_code)]
1703    pub fn live_out(&self, b: usize, v: usize) -> bool {
1704        self.live_out
1705            .get(b)
1706            .map(|s| s.contains(&v))
1707            .unwrap_or(false)
1708    }
1709    #[allow(dead_code)]
1710    pub fn add_def(&mut self, b: usize, v: usize) {
1711        if let Some(s) = self.defs.get_mut(b) {
1712            if !s.contains(&v) {
1713                s.push(v);
1714            }
1715        }
1716    }
1717    #[allow(dead_code)]
1718    pub fn add_use(&mut self, b: usize, v: usize) {
1719        if let Some(s) = self.uses.get_mut(b) {
1720            if !s.contains(&v) {
1721                s.push(v);
1722            }
1723        }
1724    }
1725    #[allow(dead_code)]
1726    pub fn var_is_used_in_block(&self, b: usize, v: usize) -> bool {
1727        self.uses.get(b).map(|s| s.contains(&v)).unwrap_or(false)
1728    }
1729    #[allow(dead_code)]
1730    pub fn var_is_def_in_block(&self, b: usize, v: usize) -> bool {
1731        self.defs.get(b).map(|s| s.contains(&v)).unwrap_or(false)
1732    }
1733}
1734/// A Chapel procedure (function).
1735#[derive(Debug, Clone)]
1736pub struct ChapelProc {
1737    /// Procedure name
1738    pub name: String,
1739    /// Parameters
1740    pub params: Vec<ChapelParam>,
1741    /// Return type (None = void)
1742    pub return_type: Option<ChapelType>,
1743    /// Body statements
1744    pub body: Vec<ChapelStmt>,
1745    /// Whether this is a parallel iterator (`iter` keyword)
1746    pub is_iter: bool,
1747    /// Whether the proc is `inline`
1748    pub is_inline: bool,
1749    /// Whether the proc is `override`
1750    pub is_override: bool,
1751    /// Whether the proc is `operator`
1752    pub is_operator: bool,
1753    /// `where` clause expression
1754    pub where_clause: Option<String>,
1755}
1756impl ChapelProc {
1757    /// Create a simple procedure.
1758    pub fn new(
1759        name: impl Into<String>,
1760        params: Vec<ChapelParam>,
1761        return_type: Option<ChapelType>,
1762        body: Vec<ChapelStmt>,
1763    ) -> Self {
1764        ChapelProc {
1765            name: name.into(),
1766            params,
1767            return_type,
1768            body,
1769            is_iter: false,
1770            is_inline: false,
1771            is_override: false,
1772            is_operator: false,
1773            where_clause: None,
1774        }
1775    }
1776    /// Mark as parallel iterator.
1777    pub fn as_iter(mut self) -> Self {
1778        self.is_iter = true;
1779        self
1780    }
1781    /// Mark as inline.
1782    pub fn as_inline(mut self) -> Self {
1783        self.is_inline = true;
1784        self
1785    }
1786    /// Add a `where` clause.
1787    pub fn with_where(mut self, clause: impl Into<String>) -> Self {
1788        self.where_clause = Some(clause.into());
1789        self
1790    }
1791}
1792/// A field/member of a record or class.
1793#[derive(Debug, Clone)]
1794pub struct ChapelField {
1795    /// Field name
1796    pub name: String,
1797    /// Field type
1798    pub ty: ChapelType,
1799    /// Whether the field is `var` or `const`
1800    pub is_const: bool,
1801    /// Optional default value
1802    pub default: Option<ChapelExpr>,
1803}
1804#[allow(dead_code)]
1805#[derive(Debug, Clone)]
1806pub struct ChplCacheEntry {
1807    pub key: String,
1808    pub data: Vec<u8>,
1809    pub timestamp: u64,
1810    pub valid: bool,
1811}
1812/// Dominator tree for ChapelExt.
1813#[allow(dead_code)]
1814#[derive(Debug, Clone)]
1815pub struct ChapelExtDomTree {
1816    pub(super) idom: Vec<Option<usize>>,
1817    pub(super) children: Vec<Vec<usize>>,
1818    pub(super) depth: Vec<usize>,
1819}
1820impl ChapelExtDomTree {
1821    #[allow(dead_code)]
1822    pub fn new(n: usize) -> Self {
1823        Self {
1824            idom: vec![None; n],
1825            children: vec![Vec::new(); n],
1826            depth: vec![0; n],
1827        }
1828    }
1829    #[allow(dead_code)]
1830    pub fn set_idom(&mut self, node: usize, dom: usize) {
1831        if node < self.idom.len() {
1832            self.idom[node] = Some(dom);
1833            if dom < self.children.len() {
1834                self.children[dom].push(node);
1835            }
1836            self.depth[node] = if dom < self.depth.len() {
1837                self.depth[dom] + 1
1838            } else {
1839                1
1840            };
1841        }
1842    }
1843    #[allow(dead_code)]
1844    pub fn dominates(&self, a: usize, mut b: usize) -> bool {
1845        if a == b {
1846            return true;
1847        }
1848        let n = self.idom.len();
1849        for _ in 0..n {
1850            match self.idom.get(b).copied().flatten() {
1851                None => return false,
1852                Some(p) if p == a => return true,
1853                Some(p) if p == b => return false,
1854                Some(p) => b = p,
1855            }
1856        }
1857        false
1858    }
1859    #[allow(dead_code)]
1860    pub fn children_of(&self, n: usize) -> &[usize] {
1861        self.children.get(n).map(|v| v.as_slice()).unwrap_or(&[])
1862    }
1863    #[allow(dead_code)]
1864    pub fn depth_of(&self, n: usize) -> usize {
1865        self.depth.get(n).copied().unwrap_or(0)
1866    }
1867    #[allow(dead_code)]
1868    pub fn lca(&self, mut a: usize, mut b: usize) -> usize {
1869        let n = self.idom.len();
1870        for _ in 0..(2 * n) {
1871            if a == b {
1872                return a;
1873            }
1874            if self.depth_of(a) > self.depth_of(b) {
1875                a = self.idom.get(a).and_then(|x| *x).unwrap_or(a);
1876            } else {
1877                b = self.idom.get(b).and_then(|x| *x).unwrap_or(b);
1878            }
1879        }
1880        0
1881    }
1882}
1883#[allow(dead_code)]
1884#[derive(Debug, Clone)]
1885pub struct ChplWorklist {
1886    pub(super) items: std::collections::VecDeque<u32>,
1887    pub(super) in_worklist: std::collections::HashSet<u32>,
1888}
1889impl ChplWorklist {
1890    #[allow(dead_code)]
1891    pub fn new() -> Self {
1892        ChplWorklist {
1893            items: std::collections::VecDeque::new(),
1894            in_worklist: std::collections::HashSet::new(),
1895        }
1896    }
1897    #[allow(dead_code)]
1898    pub fn push(&mut self, item: u32) -> bool {
1899        if self.in_worklist.insert(item) {
1900            self.items.push_back(item);
1901            true
1902        } else {
1903            false
1904        }
1905    }
1906    #[allow(dead_code)]
1907    pub fn pop(&mut self) -> Option<u32> {
1908        let item = self.items.pop_front()?;
1909        self.in_worklist.remove(&item);
1910        Some(item)
1911    }
1912    #[allow(dead_code)]
1913    pub fn is_empty(&self) -> bool {
1914        self.items.is_empty()
1915    }
1916    #[allow(dead_code)]
1917    pub fn len(&self) -> usize {
1918        self.items.len()
1919    }
1920    #[allow(dead_code)]
1921    pub fn contains(&self, item: u32) -> bool {
1922        self.in_worklist.contains(&item)
1923    }
1924}
1925/// Statistics for ChapelExt passes.
1926#[allow(dead_code)]
1927#[derive(Debug, Clone, Default)]
1928pub struct ChapelExtPassStats {
1929    pub iterations: usize,
1930    pub changed: bool,
1931    pub nodes_visited: usize,
1932    pub nodes_modified: usize,
1933    pub time_ms: u64,
1934    pub memory_bytes: usize,
1935    pub errors: usize,
1936}
1937impl ChapelExtPassStats {
1938    #[allow(dead_code)]
1939    pub fn new() -> Self {
1940        Self::default()
1941    }
1942    #[allow(dead_code)]
1943    pub fn visit(&mut self) {
1944        self.nodes_visited += 1;
1945    }
1946    #[allow(dead_code)]
1947    pub fn modify(&mut self) {
1948        self.nodes_modified += 1;
1949        self.changed = true;
1950    }
1951    #[allow(dead_code)]
1952    pub fn iterate(&mut self) {
1953        self.iterations += 1;
1954    }
1955    #[allow(dead_code)]
1956    pub fn error(&mut self) {
1957        self.errors += 1;
1958    }
1959    #[allow(dead_code)]
1960    pub fn efficiency(&self) -> f64 {
1961        if self.nodes_visited == 0 {
1962            0.0
1963        } else {
1964            self.nodes_modified as f64 / self.nodes_visited as f64
1965        }
1966    }
1967    #[allow(dead_code)]
1968    pub fn merge(&mut self, o: &ChapelExtPassStats) {
1969        self.iterations += o.iterations;
1970        self.changed |= o.changed;
1971        self.nodes_visited += o.nodes_visited;
1972        self.nodes_modified += o.nodes_modified;
1973        self.time_ms += o.time_ms;
1974        self.memory_bytes = self.memory_bytes.max(o.memory_bytes);
1975        self.errors += o.errors;
1976    }
1977}
1978/// A Chapel class definition.
1979#[derive(Debug, Clone)]
1980pub struct ChapelClass {
1981    /// Class name
1982    pub name: String,
1983    /// Optional parent class
1984    pub parent: Option<String>,
1985    /// Fields
1986    pub fields: Vec<ChapelField>,
1987    /// Methods
1988    pub methods: Vec<ChapelProc>,
1989    /// Optional generic type parameters
1990    pub type_params: Vec<String>,
1991}
1992impl ChapelClass {
1993    /// Create an empty class.
1994    pub fn new(name: impl Into<String>) -> Self {
1995        ChapelClass {
1996            name: name.into(),
1997            parent: None,
1998            fields: vec![],
1999            methods: vec![],
2000            type_params: vec![],
2001        }
2002    }
2003    /// Set the parent class.
2004    pub fn with_parent(mut self, parent: impl Into<String>) -> Self {
2005        self.parent = Some(parent.into());
2006        self
2007    }
2008    /// Add a field.
2009    pub fn add_field(&mut self, field: ChapelField) {
2010        self.fields.push(field);
2011    }
2012    /// Add a method.
2013    pub fn add_method(&mut self, method: ChapelProc) {
2014        self.methods.push(method);
2015    }
2016}
2017/// Configuration for ChapelExt passes.
2018#[allow(dead_code)]
2019#[derive(Debug, Clone)]
2020pub struct ChapelExtPassConfig {
2021    pub name: String,
2022    pub phase: ChapelExtPassPhase,
2023    pub enabled: bool,
2024    pub max_iterations: usize,
2025    pub debug: u32,
2026    pub timeout_ms: Option<u64>,
2027}
2028impl ChapelExtPassConfig {
2029    #[allow(dead_code)]
2030    pub fn new(name: impl Into<String>) -> Self {
2031        Self {
2032            name: name.into(),
2033            phase: ChapelExtPassPhase::Middle,
2034            enabled: true,
2035            max_iterations: 100,
2036            debug: 0,
2037            timeout_ms: None,
2038        }
2039    }
2040    #[allow(dead_code)]
2041    pub fn with_phase(mut self, phase: ChapelExtPassPhase) -> Self {
2042        self.phase = phase;
2043        self
2044    }
2045    #[allow(dead_code)]
2046    pub fn with_max_iter(mut self, n: usize) -> Self {
2047        self.max_iterations = n;
2048        self
2049    }
2050    #[allow(dead_code)]
2051    pub fn with_debug(mut self, d: u32) -> Self {
2052        self.debug = d;
2053        self
2054    }
2055    #[allow(dead_code)]
2056    pub fn disabled(mut self) -> Self {
2057        self.enabled = false;
2058        self
2059    }
2060    #[allow(dead_code)]
2061    pub fn with_timeout(mut self, ms: u64) -> Self {
2062        self.timeout_ms = Some(ms);
2063        self
2064    }
2065    #[allow(dead_code)]
2066    pub fn is_debug_enabled(&self) -> bool {
2067        self.debug > 0
2068    }
2069}
2070#[allow(dead_code)]
2071#[derive(Debug, Clone, PartialEq)]
2072pub enum ChplPassPhase {
2073    Analysis,
2074    Transformation,
2075    Verification,
2076    Cleanup,
2077}
2078impl ChplPassPhase {
2079    #[allow(dead_code)]
2080    pub fn name(&self) -> &str {
2081        match self {
2082            ChplPassPhase::Analysis => "analysis",
2083            ChplPassPhase::Transformation => "transformation",
2084            ChplPassPhase::Verification => "verification",
2085            ChplPassPhase::Cleanup => "cleanup",
2086        }
2087    }
2088    #[allow(dead_code)]
2089    pub fn is_modifying(&self) -> bool {
2090        matches!(self, ChplPassPhase::Transformation | ChplPassPhase::Cleanup)
2091    }
2092}
2093/// A Chapel source module (single `.chpl` file).
2094#[derive(Debug, Clone)]
2095pub struct ChapelModule {
2096    /// Module name (None = implicit top-level)
2097    pub name: Option<String>,
2098    /// `use` imports
2099    pub uses: Vec<String>,
2100    /// `require` directives
2101    pub requires: Vec<String>,
2102    /// Top-level constant declarations
2103    pub globals: Vec<(String, ChapelType, ChapelExpr)>,
2104    /// Top-level config variable declarations
2105    pub configs: Vec<(String, ChapelType, Option<ChapelExpr>)>,
2106    /// Top-level procedures
2107    pub procs: Vec<ChapelProc>,
2108    /// Top-level record definitions
2109    pub records: Vec<ChapelRecord>,
2110    /// Top-level class definitions
2111    pub classes: Vec<ChapelClass>,
2112    /// Sub-modules
2113    pub submodules: Vec<ChapelModule>,
2114    /// Module-level doc comment
2115    pub doc: Option<String>,
2116}
2117impl ChapelModule {
2118    /// Create an empty unnamed module.
2119    pub fn new() -> Self {
2120        ChapelModule {
2121            name: None,
2122            uses: vec![],
2123            requires: vec![],
2124            globals: vec![],
2125            configs: vec![],
2126            procs: vec![],
2127            records: vec![],
2128            classes: vec![],
2129            submodules: vec![],
2130            doc: None,
2131        }
2132    }
2133    /// Create a named module.
2134    pub fn named(name: impl Into<String>) -> Self {
2135        let mut m = ChapelModule::new();
2136        m.name = Some(name.into());
2137        m
2138    }
2139    /// Add a `use` directive.
2140    pub fn add_use(&mut self, name: impl Into<String>) {
2141        self.uses.push(name.into());
2142    }
2143    /// Add a `require` directive.
2144    pub fn add_require(&mut self, path: impl Into<String>) {
2145        self.requires.push(path.into());
2146    }
2147    /// Add a top-level constant.
2148    pub fn add_global(&mut self, name: impl Into<String>, ty: ChapelType, expr: ChapelExpr) {
2149        self.globals.push((name.into(), ty, expr));
2150    }
2151    /// Add a config variable.
2152    pub fn add_config(
2153        &mut self,
2154        name: impl Into<String>,
2155        ty: ChapelType,
2156        default: Option<ChapelExpr>,
2157    ) {
2158        self.configs.push((name.into(), ty, default));
2159    }
2160    /// Add a procedure.
2161    pub fn add_proc(&mut self, proc: ChapelProc) {
2162        self.procs.push(proc);
2163    }
2164    /// Add a record.
2165    pub fn add_record(&mut self, rec: ChapelRecord) {
2166        self.records.push(rec);
2167    }
2168    /// Add a class.
2169    pub fn add_class(&mut self, cls: ChapelClass) {
2170        self.classes.push(cls);
2171    }
2172    /// Set the doc comment.
2173    pub fn set_doc(&mut self, doc: impl Into<String>) {
2174        self.doc = Some(doc.into());
2175    }
2176}
2177/// Worklist for ChapelExt.
2178#[allow(dead_code)]
2179#[derive(Debug, Clone)]
2180pub struct ChapelExtWorklist {
2181    pub(super) items: std::collections::VecDeque<usize>,
2182    pub(super) present: Vec<bool>,
2183}
2184impl ChapelExtWorklist {
2185    #[allow(dead_code)]
2186    pub fn new(capacity: usize) -> Self {
2187        Self {
2188            items: std::collections::VecDeque::new(),
2189            present: vec![false; capacity],
2190        }
2191    }
2192    #[allow(dead_code)]
2193    pub fn push(&mut self, id: usize) {
2194        if id < self.present.len() && !self.present[id] {
2195            self.present[id] = true;
2196            self.items.push_back(id);
2197        }
2198    }
2199    #[allow(dead_code)]
2200    pub fn push_front(&mut self, id: usize) {
2201        if id < self.present.len() && !self.present[id] {
2202            self.present[id] = true;
2203            self.items.push_front(id);
2204        }
2205    }
2206    #[allow(dead_code)]
2207    pub fn pop(&mut self) -> Option<usize> {
2208        let id = self.items.pop_front()?;
2209        if id < self.present.len() {
2210            self.present[id] = false;
2211        }
2212        Some(id)
2213    }
2214    #[allow(dead_code)]
2215    pub fn is_empty(&self) -> bool {
2216        self.items.is_empty()
2217    }
2218    #[allow(dead_code)]
2219    pub fn len(&self) -> usize {
2220        self.items.len()
2221    }
2222    #[allow(dead_code)]
2223    pub fn contains(&self, id: usize) -> bool {
2224        id < self.present.len() && self.present[id]
2225    }
2226    #[allow(dead_code)]
2227    pub fn drain_all(&mut self) -> Vec<usize> {
2228        let v: Vec<usize> = self.items.drain(..).collect();
2229        for &id in &v {
2230            if id < self.present.len() {
2231                self.present[id] = false;
2232            }
2233        }
2234        v
2235    }
2236}
2237/// Dependency graph for ChapelExt.
2238#[allow(dead_code)]
2239#[derive(Debug, Clone)]
2240pub struct ChapelExtDepGraph {
2241    pub(super) n: usize,
2242    pub(super) adj: Vec<Vec<usize>>,
2243    pub(super) rev: Vec<Vec<usize>>,
2244    pub(super) edge_count: usize,
2245}
2246impl ChapelExtDepGraph {
2247    #[allow(dead_code)]
2248    pub fn new(n: usize) -> Self {
2249        Self {
2250            n,
2251            adj: vec![Vec::new(); n],
2252            rev: vec![Vec::new(); n],
2253            edge_count: 0,
2254        }
2255    }
2256    #[allow(dead_code)]
2257    pub fn add_edge(&mut self, from: usize, to: usize) {
2258        if from < self.n && to < self.n {
2259            if !self.adj[from].contains(&to) {
2260                self.adj[from].push(to);
2261                self.rev[to].push(from);
2262                self.edge_count += 1;
2263            }
2264        }
2265    }
2266    #[allow(dead_code)]
2267    pub fn succs(&self, n: usize) -> &[usize] {
2268        self.adj.get(n).map(|v| v.as_slice()).unwrap_or(&[])
2269    }
2270    #[allow(dead_code)]
2271    pub fn preds(&self, n: usize) -> &[usize] {
2272        self.rev.get(n).map(|v| v.as_slice()).unwrap_or(&[])
2273    }
2274    #[allow(dead_code)]
2275    pub fn topo_sort(&self) -> Option<Vec<usize>> {
2276        let mut deg: Vec<usize> = (0..self.n).map(|i| self.rev[i].len()).collect();
2277        let mut q: std::collections::VecDeque<usize> =
2278            (0..self.n).filter(|&i| deg[i] == 0).collect();
2279        let mut out = Vec::with_capacity(self.n);
2280        while let Some(u) = q.pop_front() {
2281            out.push(u);
2282            for &v in &self.adj[u] {
2283                deg[v] -= 1;
2284                if deg[v] == 0 {
2285                    q.push_back(v);
2286                }
2287            }
2288        }
2289        if out.len() == self.n {
2290            Some(out)
2291        } else {
2292            None
2293        }
2294    }
2295    #[allow(dead_code)]
2296    pub fn has_cycle(&self) -> bool {
2297        self.topo_sort().is_none()
2298    }
2299    #[allow(dead_code)]
2300    pub fn reachable(&self, start: usize) -> Vec<usize> {
2301        let mut vis = vec![false; self.n];
2302        let mut stk = vec![start];
2303        let mut out = Vec::new();
2304        while let Some(u) = stk.pop() {
2305            if u < self.n && !vis[u] {
2306                vis[u] = true;
2307                out.push(u);
2308                for &v in &self.adj[u] {
2309                    if !vis[v] {
2310                        stk.push(v);
2311                    }
2312                }
2313            }
2314        }
2315        out
2316    }
2317    #[allow(dead_code)]
2318    pub fn scc(&self) -> Vec<Vec<usize>> {
2319        let mut visited = vec![false; self.n];
2320        let mut order = Vec::new();
2321        for i in 0..self.n {
2322            if !visited[i] {
2323                let mut stk = vec![(i, 0usize)];
2324                while let Some((u, idx)) = stk.last_mut() {
2325                    if !visited[*u] {
2326                        visited[*u] = true;
2327                    }
2328                    if *idx < self.adj[*u].len() {
2329                        let v = self.adj[*u][*idx];
2330                        *idx += 1;
2331                        if !visited[v] {
2332                            stk.push((v, 0));
2333                        }
2334                    } else {
2335                        order.push(*u);
2336                        stk.pop();
2337                    }
2338                }
2339            }
2340        }
2341        let mut comp = vec![usize::MAX; self.n];
2342        let mut components: Vec<Vec<usize>> = Vec::new();
2343        for &start in order.iter().rev() {
2344            if comp[start] == usize::MAX {
2345                let cid = components.len();
2346                let mut component = Vec::new();
2347                let mut stk = vec![start];
2348                while let Some(u) = stk.pop() {
2349                    if comp[u] == usize::MAX {
2350                        comp[u] = cid;
2351                        component.push(u);
2352                        for &v in &self.rev[u] {
2353                            if comp[v] == usize::MAX {
2354                                stk.push(v);
2355                            }
2356                        }
2357                    }
2358                }
2359                components.push(component);
2360            }
2361        }
2362        components
2363    }
2364    #[allow(dead_code)]
2365    pub fn node_count(&self) -> usize {
2366        self.n
2367    }
2368    #[allow(dead_code)]
2369    pub fn edge_count(&self) -> usize {
2370        self.edge_count
2371    }
2372}
2373/// Pass registry for ChapelExt.
2374#[allow(dead_code)]
2375#[derive(Debug, Default)]
2376pub struct ChapelExtPassRegistry {
2377    pub(super) configs: Vec<ChapelExtPassConfig>,
2378    pub(super) stats: Vec<ChapelExtPassStats>,
2379}
2380impl ChapelExtPassRegistry {
2381    #[allow(dead_code)]
2382    pub fn new() -> Self {
2383        Self::default()
2384    }
2385    #[allow(dead_code)]
2386    pub fn register(&mut self, c: ChapelExtPassConfig) {
2387        self.stats.push(ChapelExtPassStats::new());
2388        self.configs.push(c);
2389    }
2390    #[allow(dead_code)]
2391    pub fn len(&self) -> usize {
2392        self.configs.len()
2393    }
2394    #[allow(dead_code)]
2395    pub fn is_empty(&self) -> bool {
2396        self.configs.is_empty()
2397    }
2398    #[allow(dead_code)]
2399    pub fn get(&self, i: usize) -> Option<&ChapelExtPassConfig> {
2400        self.configs.get(i)
2401    }
2402    #[allow(dead_code)]
2403    pub fn get_stats(&self, i: usize) -> Option<&ChapelExtPassStats> {
2404        self.stats.get(i)
2405    }
2406    #[allow(dead_code)]
2407    pub fn enabled_passes(&self) -> Vec<&ChapelExtPassConfig> {
2408        self.configs.iter().filter(|c| c.enabled).collect()
2409    }
2410    #[allow(dead_code)]
2411    pub fn passes_in_phase(&self, ph: &ChapelExtPassPhase) -> Vec<&ChapelExtPassConfig> {
2412        self.configs
2413            .iter()
2414            .filter(|c| c.enabled && &c.phase == ph)
2415            .collect()
2416    }
2417    #[allow(dead_code)]
2418    pub fn total_nodes_visited(&self) -> usize {
2419        self.stats.iter().map(|s| s.nodes_visited).sum()
2420    }
2421    #[allow(dead_code)]
2422    pub fn any_changed(&self) -> bool {
2423        self.stats.iter().any(|s| s.changed)
2424    }
2425}