Skip to main content

oxilean_codegen/zig_backend/
types.rs

1//! Auto-generated module
2//!
3//! 🤖 Generated with [SplitRS](https://github.com/cool-japan/splitrs)
4
5use std::collections::{HashMap, HashSet, VecDeque};
6
7#[allow(dead_code)]
8#[derive(Debug, Clone, Default)]
9pub struct ZigPassStats {
10    pub total_runs: u32,
11    pub successful_runs: u32,
12    pub total_changes: u64,
13    pub time_ms: u64,
14    pub iterations_used: u32,
15}
16impl ZigPassStats {
17    #[allow(dead_code)]
18    pub fn new() -> Self {
19        Self::default()
20    }
21    #[allow(dead_code)]
22    pub fn record_run(&mut self, changes: u64, time_ms: u64, iterations: u32) {
23        self.total_runs += 1;
24        self.successful_runs += 1;
25        self.total_changes += changes;
26        self.time_ms += time_ms;
27        self.iterations_used = iterations;
28    }
29    #[allow(dead_code)]
30    pub fn average_changes_per_run(&self) -> f64 {
31        if self.total_runs == 0 {
32            return 0.0;
33        }
34        self.total_changes as f64 / self.total_runs as f64
35    }
36    #[allow(dead_code)]
37    pub fn success_rate(&self) -> f64 {
38        if self.total_runs == 0 {
39            return 0.0;
40        }
41        self.successful_runs as f64 / self.total_runs as f64
42    }
43    #[allow(dead_code)]
44    pub fn format_summary(&self) -> String {
45        format!(
46            "Runs: {}/{}, Changes: {}, Time: {}ms",
47            self.successful_runs, self.total_runs, self.total_changes, self.time_ms
48        )
49    }
50}
51/// Pass registry for ZigExt.
52#[allow(dead_code)]
53#[derive(Debug, Default)]
54pub struct ZigExtPassRegistry {
55    pub(super) configs: Vec<ZigExtPassConfig>,
56    pub(super) stats: Vec<ZigExtPassStats>,
57}
58impl ZigExtPassRegistry {
59    #[allow(dead_code)]
60    pub fn new() -> Self {
61        Self::default()
62    }
63    #[allow(dead_code)]
64    pub fn register(&mut self, c: ZigExtPassConfig) {
65        self.stats.push(ZigExtPassStats::new());
66        self.configs.push(c);
67    }
68    #[allow(dead_code)]
69    pub fn len(&self) -> usize {
70        self.configs.len()
71    }
72    #[allow(dead_code)]
73    pub fn is_empty(&self) -> bool {
74        self.configs.is_empty()
75    }
76    #[allow(dead_code)]
77    pub fn get(&self, i: usize) -> Option<&ZigExtPassConfig> {
78        self.configs.get(i)
79    }
80    #[allow(dead_code)]
81    pub fn get_stats(&self, i: usize) -> Option<&ZigExtPassStats> {
82        self.stats.get(i)
83    }
84    #[allow(dead_code)]
85    pub fn enabled_passes(&self) -> Vec<&ZigExtPassConfig> {
86        self.configs.iter().filter(|c| c.enabled).collect()
87    }
88    #[allow(dead_code)]
89    pub fn passes_in_phase(&self, ph: &ZigExtPassPhase) -> Vec<&ZigExtPassConfig> {
90        self.configs
91            .iter()
92            .filter(|c| c.enabled && &c.phase == ph)
93            .collect()
94    }
95    #[allow(dead_code)]
96    pub fn total_nodes_visited(&self) -> usize {
97        self.stats.iter().map(|s| s.nodes_visited).sum()
98    }
99    #[allow(dead_code)]
100    pub fn any_changed(&self) -> bool {
101        self.stats.iter().any(|s| s.changed)
102    }
103}
104#[allow(dead_code)]
105#[derive(Debug, Clone)]
106pub struct ZigErrorSet {
107    pub name: String,
108    pub errors: Vec<String>,
109}
110impl ZigErrorSet {
111    #[allow(dead_code)]
112    pub fn new(name: impl Into<String>) -> Self {
113        ZigErrorSet {
114            name: name.into(),
115            errors: Vec::new(),
116        }
117    }
118    #[allow(dead_code)]
119    pub fn add_error(&mut self, err: impl Into<String>) {
120        self.errors.push(err.into());
121    }
122    #[allow(dead_code)]
123    pub fn emit(&self) -> String {
124        format!(
125            "const {} = error{{ {} }};",
126            self.name,
127            self.errors.join(", ")
128        )
129    }
130}
131#[allow(dead_code)]
132#[derive(Debug, Clone)]
133pub struct ZigAsyncFn {
134    pub name: String,
135    pub params: Vec<(String, String)>,
136    pub return_type: String,
137    pub frame_size: Option<usize>,
138}
139impl ZigAsyncFn {
140    #[allow(dead_code)]
141    pub fn new(name: impl Into<String>) -> Self {
142        ZigAsyncFn {
143            name: name.into(),
144            params: Vec::new(),
145            return_type: "void".to_string(),
146            frame_size: None,
147        }
148    }
149    #[allow(dead_code)]
150    pub fn param(mut self, name: impl Into<String>, ty: impl Into<String>) -> Self {
151        self.params.push((name.into(), ty.into()));
152        self
153    }
154    #[allow(dead_code)]
155    pub fn emit(&self) -> String {
156        let params: Vec<String> = self
157            .params
158            .iter()
159            .map(|(n, t)| format!("{}: {}", n, t))
160            .collect();
161        format!(
162            "async fn {}({}) {} {{\n    // async body\n}}",
163            self.name,
164            params.join(", "),
165            self.return_type
166        )
167    }
168    #[allow(dead_code)]
169    pub fn emit_await_call(&self, args: &[&str]) -> String {
170        format!("await async {}({})", self.name, args.join(", "))
171    }
172}
173/// Pass execution phase for ZigExt.
174#[allow(dead_code)]
175#[derive(Debug, Clone, PartialEq, Eq, Hash)]
176pub enum ZigExtPassPhase {
177    Early,
178    Middle,
179    Late,
180    Finalize,
181}
182impl ZigExtPassPhase {
183    #[allow(dead_code)]
184    pub fn is_early(&self) -> bool {
185        matches!(self, Self::Early)
186    }
187    #[allow(dead_code)]
188    pub fn is_middle(&self) -> bool {
189        matches!(self, Self::Middle)
190    }
191    #[allow(dead_code)]
192    pub fn is_late(&self) -> bool {
193        matches!(self, Self::Late)
194    }
195    #[allow(dead_code)]
196    pub fn is_finalize(&self) -> bool {
197        matches!(self, Self::Finalize)
198    }
199    #[allow(dead_code)]
200    pub fn order(&self) -> u32 {
201        match self {
202            Self::Early => 0,
203            Self::Middle => 1,
204            Self::Late => 2,
205            Self::Finalize => 3,
206        }
207    }
208    #[allow(dead_code)]
209    pub fn from_order(n: u32) -> Option<Self> {
210        match n {
211            0 => Some(Self::Early),
212            1 => Some(Self::Middle),
213            2 => Some(Self::Late),
214            3 => Some(Self::Finalize),
215            _ => None,
216        }
217    }
218}
219/// Worklist for ZigExt.
220#[allow(dead_code)]
221#[derive(Debug, Clone)]
222pub struct ZigExtWorklist {
223    pub(super) items: std::collections::VecDeque<usize>,
224    pub(super) present: Vec<bool>,
225}
226impl ZigExtWorklist {
227    #[allow(dead_code)]
228    pub fn new(capacity: usize) -> Self {
229        Self {
230            items: std::collections::VecDeque::new(),
231            present: vec![false; capacity],
232        }
233    }
234    #[allow(dead_code)]
235    pub fn push(&mut self, id: usize) {
236        if id < self.present.len() && !self.present[id] {
237            self.present[id] = true;
238            self.items.push_back(id);
239        }
240    }
241    #[allow(dead_code)]
242    pub fn push_front(&mut self, id: usize) {
243        if id < self.present.len() && !self.present[id] {
244            self.present[id] = true;
245            self.items.push_front(id);
246        }
247    }
248    #[allow(dead_code)]
249    pub fn pop(&mut self) -> Option<usize> {
250        let id = self.items.pop_front()?;
251        if id < self.present.len() {
252            self.present[id] = false;
253        }
254        Some(id)
255    }
256    #[allow(dead_code)]
257    pub fn is_empty(&self) -> bool {
258        self.items.is_empty()
259    }
260    #[allow(dead_code)]
261    pub fn len(&self) -> usize {
262        self.items.len()
263    }
264    #[allow(dead_code)]
265    pub fn contains(&self, id: usize) -> bool {
266        id < self.present.len() && self.present[id]
267    }
268    #[allow(dead_code)]
269    pub fn drain_all(&mut self) -> Vec<usize> {
270        let v: Vec<usize> = self.items.drain(..).collect();
271        for &id in &v {
272            if id < self.present.len() {
273                self.present[id] = false;
274            }
275        }
276        v
277    }
278}
279#[allow(dead_code)]
280struct ZigStructField2 {
281    pub name: String,
282    pub ty_name: String,
283}
284#[allow(dead_code)]
285pub struct ZigBuildConfiguration {
286    pub target_os: String,
287    pub target_arch: String,
288    pub optimize_mode: ZigOptimizeMode,
289    pub root_source_file: String,
290    pub dependencies: Vec<String>,
291}
292impl ZigBuildConfiguration {
293    #[allow(dead_code)]
294    pub fn new(root: impl Into<String>) -> Self {
295        ZigBuildConfiguration {
296            target_os: "native".to_string(),
297            target_arch: "native".to_string(),
298            optimize_mode: ZigOptimizeMode::Debug,
299            root_source_file: root.into(),
300            dependencies: Vec::new(),
301        }
302    }
303    #[allow(dead_code)]
304    pub fn optimize(mut self, mode: ZigOptimizeMode) -> Self {
305        self.optimize_mode = mode;
306        self
307    }
308    #[allow(dead_code)]
309    pub fn dep(mut self, name: impl Into<String>) -> Self {
310        self.dependencies.push(name.into());
311        self
312    }
313    #[allow(dead_code)]
314    pub fn emit_build_zig(&self) -> String {
315        let mut out = String::from("const std = @import(\"std\");\n\n");
316        out.push_str("pub fn build(b: *std.Build) void {\n");
317        out.push_str(&format!(
318            "    const target = b.standardTargetOptions(.{{}});\n"
319        ));
320        out.push_str(&format!(
321            "    const optimize = b.standardOptimizeOption(.{{}});\n"
322        ));
323        out.push_str(
324            &format!(
325                "    const exe = b.addExecutable(.{{\n        .name = \"app\",\n        .root_source_file = .{{ .path = \"{}\" }},\n        .target = target,\n        .optimize = optimize,\n    }});\n",
326                self.root_source_file
327            ),
328        );
329        out.push_str("    b.installArtifact(exe);\n");
330        out.push('}');
331        out
332    }
333}
334/// Represents a Zig function definition.
335pub struct ZigFn {
336    pub name: String,
337    pub params: Vec<(String, ZigType)>,
338    pub ret_ty: ZigType,
339    pub body: Vec<ZigStmt>,
340    pub is_pub: bool,
341    pub is_async: bool,
342}
343impl ZigFn {
344    /// Create a new function with the given name and return type.
345    pub fn new(name: &str, ret: ZigType) -> Self {
346        ZigFn {
347            name: name.to_string(),
348            params: Vec::new(),
349            ret_ty: ret,
350            body: Vec::new(),
351            is_pub: false,
352            is_async: false,
353        }
354    }
355    /// Add a parameter to the function.
356    pub fn add_param(&mut self, name: &str, ty: ZigType) {
357        self.params.push((name.to_string(), ty));
358    }
359    /// Add a statement to the function body.
360    pub fn add_stmt(&mut self, stmt: ZigStmt) {
361        self.body.push(stmt);
362    }
363    /// Generate Zig source code for this function.
364    pub fn codegen(&self) -> String {
365        let pub_str = if self.is_pub { "pub " } else { "" };
366        let async_str = if self.is_async { "async " } else { "" };
367        let params_str: Vec<String> = self
368            .params
369            .iter()
370            .map(|(name, ty)| format!("{}: {}", name, ty.codegen()))
371            .collect();
372        let body_str: Vec<String> = self
373            .body
374            .iter()
375            .map(|s| format!("    {}", s.codegen()))
376            .collect();
377        format!(
378            "{}{}fn {}({}) {} {{\n{}\n}}",
379            pub_str,
380            async_str,
381            self.name,
382            params_str.join(", "),
383            self.ret_ty.codegen(),
384            body_str.join("\n")
385        )
386    }
387}
388#[allow(dead_code)]
389pub struct ZigConstantFoldingHelper;
390impl ZigConstantFoldingHelper {
391    #[allow(dead_code)]
392    pub fn fold_add_i64(a: i64, b: i64) -> Option<i64> {
393        a.checked_add(b)
394    }
395    #[allow(dead_code)]
396    pub fn fold_sub_i64(a: i64, b: i64) -> Option<i64> {
397        a.checked_sub(b)
398    }
399    #[allow(dead_code)]
400    pub fn fold_mul_i64(a: i64, b: i64) -> Option<i64> {
401        a.checked_mul(b)
402    }
403    #[allow(dead_code)]
404    pub fn fold_div_i64(a: i64, b: i64) -> Option<i64> {
405        if b == 0 {
406            None
407        } else {
408            a.checked_div(b)
409        }
410    }
411    #[allow(dead_code)]
412    pub fn fold_add_f64(a: f64, b: f64) -> f64 {
413        a + b
414    }
415    #[allow(dead_code)]
416    pub fn fold_mul_f64(a: f64, b: f64) -> f64 {
417        a * b
418    }
419    #[allow(dead_code)]
420    pub fn fold_neg_i64(a: i64) -> Option<i64> {
421        a.checked_neg()
422    }
423    #[allow(dead_code)]
424    pub fn fold_not_bool(a: bool) -> bool {
425        !a
426    }
427    #[allow(dead_code)]
428    pub fn fold_and_bool(a: bool, b: bool) -> bool {
429        a && b
430    }
431    #[allow(dead_code)]
432    pub fn fold_or_bool(a: bool, b: bool) -> bool {
433        a || b
434    }
435    #[allow(dead_code)]
436    pub fn fold_shl_i64(a: i64, b: u32) -> Option<i64> {
437        a.checked_shl(b)
438    }
439    #[allow(dead_code)]
440    pub fn fold_shr_i64(a: i64, b: u32) -> Option<i64> {
441        a.checked_shr(b)
442    }
443    #[allow(dead_code)]
444    pub fn fold_rem_i64(a: i64, b: i64) -> Option<i64> {
445        if b == 0 {
446            None
447        } else {
448            Some(a % b)
449        }
450    }
451    #[allow(dead_code)]
452    pub fn fold_bitand_i64(a: i64, b: i64) -> i64 {
453        a & b
454    }
455    #[allow(dead_code)]
456    pub fn fold_bitor_i64(a: i64, b: i64) -> i64 {
457        a | b
458    }
459    #[allow(dead_code)]
460    pub fn fold_bitxor_i64(a: i64, b: i64) -> i64 {
461        a ^ b
462    }
463    #[allow(dead_code)]
464    pub fn fold_bitnot_i64(a: i64) -> i64 {
465        !a
466    }
467}
468/// Analysis cache for ZigExt.
469#[allow(dead_code)]
470#[derive(Debug)]
471pub struct ZigExtCache {
472    pub(super) entries: Vec<(u64, Vec<u8>, bool, u32)>,
473    pub(super) cap: usize,
474    pub(super) total_hits: u64,
475    pub(super) total_misses: u64,
476}
477impl ZigExtCache {
478    #[allow(dead_code)]
479    pub fn new(cap: usize) -> Self {
480        Self {
481            entries: Vec::new(),
482            cap,
483            total_hits: 0,
484            total_misses: 0,
485        }
486    }
487    #[allow(dead_code)]
488    pub fn get(&mut self, key: u64) -> Option<&[u8]> {
489        for e in self.entries.iter_mut() {
490            if e.0 == key && e.2 {
491                e.3 += 1;
492                self.total_hits += 1;
493                return Some(&e.1);
494            }
495        }
496        self.total_misses += 1;
497        None
498    }
499    #[allow(dead_code)]
500    pub fn put(&mut self, key: u64, data: Vec<u8>) {
501        if self.entries.len() >= self.cap {
502            self.entries.retain(|e| e.2);
503            if self.entries.len() >= self.cap {
504                self.entries.remove(0);
505            }
506        }
507        self.entries.push((key, data, true, 0));
508    }
509    #[allow(dead_code)]
510    pub fn invalidate(&mut self) {
511        for e in self.entries.iter_mut() {
512            e.2 = false;
513        }
514    }
515    #[allow(dead_code)]
516    pub fn hit_rate(&self) -> f64 {
517        let t = self.total_hits + self.total_misses;
518        if t == 0 {
519            0.0
520        } else {
521            self.total_hits as f64 / t as f64
522        }
523    }
524    #[allow(dead_code)]
525    pub fn live_count(&self) -> usize {
526        self.entries.iter().filter(|e| e.2).count()
527    }
528}
529#[allow(dead_code)]
530#[derive(Debug, Clone)]
531pub struct ZigWorklist {
532    pub(super) items: std::collections::VecDeque<u32>,
533    pub(super) in_worklist: std::collections::HashSet<u32>,
534}
535impl ZigWorklist {
536    #[allow(dead_code)]
537    pub fn new() -> Self {
538        ZigWorklist {
539            items: std::collections::VecDeque::new(),
540            in_worklist: std::collections::HashSet::new(),
541        }
542    }
543    #[allow(dead_code)]
544    pub fn push(&mut self, item: u32) -> bool {
545        if self.in_worklist.insert(item) {
546            self.items.push_back(item);
547            true
548        } else {
549            false
550        }
551    }
552    #[allow(dead_code)]
553    pub fn pop(&mut self) -> Option<u32> {
554        let item = self.items.pop_front()?;
555        self.in_worklist.remove(&item);
556        Some(item)
557    }
558    #[allow(dead_code)]
559    pub fn is_empty(&self) -> bool {
560        self.items.is_empty()
561    }
562    #[allow(dead_code)]
563    pub fn len(&self) -> usize {
564        self.items.len()
565    }
566    #[allow(dead_code)]
567    pub fn contains(&self, item: u32) -> bool {
568        self.in_worklist.contains(&item)
569    }
570}
571#[allow(dead_code)]
572#[derive(Debug, Clone)]
573pub struct ZigPassConfig {
574    pub phase: ZigPassPhase,
575    pub enabled: bool,
576    pub max_iterations: u32,
577    pub debug_output: bool,
578    pub pass_name: String,
579}
580impl ZigPassConfig {
581    #[allow(dead_code)]
582    pub fn new(name: impl Into<String>, phase: ZigPassPhase) -> Self {
583        ZigPassConfig {
584            phase,
585            enabled: true,
586            max_iterations: 10,
587            debug_output: false,
588            pass_name: name.into(),
589        }
590    }
591    #[allow(dead_code)]
592    pub fn disabled(mut self) -> Self {
593        self.enabled = false;
594        self
595    }
596    #[allow(dead_code)]
597    pub fn with_debug(mut self) -> Self {
598        self.debug_output = true;
599        self
600    }
601    #[allow(dead_code)]
602    pub fn max_iter(mut self, n: u32) -> Self {
603        self.max_iterations = n;
604        self
605    }
606}
607/// Dependency graph for ZigExt.
608#[allow(dead_code)]
609#[derive(Debug, Clone)]
610pub struct ZigExtDepGraph {
611    pub(super) n: usize,
612    pub(super) adj: Vec<Vec<usize>>,
613    pub(super) rev: Vec<Vec<usize>>,
614    pub(super) edge_count: usize,
615}
616impl ZigExtDepGraph {
617    #[allow(dead_code)]
618    pub fn new(n: usize) -> Self {
619        Self {
620            n,
621            adj: vec![Vec::new(); n],
622            rev: vec![Vec::new(); n],
623            edge_count: 0,
624        }
625    }
626    #[allow(dead_code)]
627    pub fn add_edge(&mut self, from: usize, to: usize) {
628        if from < self.n && to < self.n {
629            if !self.adj[from].contains(&to) {
630                self.adj[from].push(to);
631                self.rev[to].push(from);
632                self.edge_count += 1;
633            }
634        }
635    }
636    #[allow(dead_code)]
637    pub fn succs(&self, n: usize) -> &[usize] {
638        self.adj.get(n).map(|v| v.as_slice()).unwrap_or(&[])
639    }
640    #[allow(dead_code)]
641    pub fn preds(&self, n: usize) -> &[usize] {
642        self.rev.get(n).map(|v| v.as_slice()).unwrap_or(&[])
643    }
644    #[allow(dead_code)]
645    pub fn topo_sort(&self) -> Option<Vec<usize>> {
646        let mut deg: Vec<usize> = (0..self.n).map(|i| self.rev[i].len()).collect();
647        let mut q: std::collections::VecDeque<usize> =
648            (0..self.n).filter(|&i| deg[i] == 0).collect();
649        let mut out = Vec::with_capacity(self.n);
650        while let Some(u) = q.pop_front() {
651            out.push(u);
652            for &v in &self.adj[u] {
653                deg[v] -= 1;
654                if deg[v] == 0 {
655                    q.push_back(v);
656                }
657            }
658        }
659        if out.len() == self.n {
660            Some(out)
661        } else {
662            None
663        }
664    }
665    #[allow(dead_code)]
666    pub fn has_cycle(&self) -> bool {
667        self.topo_sort().is_none()
668    }
669    #[allow(dead_code)]
670    pub fn reachable(&self, start: usize) -> Vec<usize> {
671        let mut vis = vec![false; self.n];
672        let mut stk = vec![start];
673        let mut out = Vec::new();
674        while let Some(u) = stk.pop() {
675            if u < self.n && !vis[u] {
676                vis[u] = true;
677                out.push(u);
678                for &v in &self.adj[u] {
679                    if !vis[v] {
680                        stk.push(v);
681                    }
682                }
683            }
684        }
685        out
686    }
687    #[allow(dead_code)]
688    pub fn scc(&self) -> Vec<Vec<usize>> {
689        let mut visited = vec![false; self.n];
690        let mut order = Vec::new();
691        for i in 0..self.n {
692            if !visited[i] {
693                let mut stk = vec![(i, 0usize)];
694                while let Some((u, idx)) = stk.last_mut() {
695                    if !visited[*u] {
696                        visited[*u] = true;
697                    }
698                    if *idx < self.adj[*u].len() {
699                        let v = self.adj[*u][*idx];
700                        *idx += 1;
701                        if !visited[v] {
702                            stk.push((v, 0));
703                        }
704                    } else {
705                        order.push(*u);
706                        stk.pop();
707                    }
708                }
709            }
710        }
711        let mut comp = vec![usize::MAX; self.n];
712        let mut components: Vec<Vec<usize>> = Vec::new();
713        for &start in order.iter().rev() {
714            if comp[start] == usize::MAX {
715                let cid = components.len();
716                let mut component = Vec::new();
717                let mut stk = vec![start];
718                while let Some(u) = stk.pop() {
719                    if comp[u] == usize::MAX {
720                        comp[u] = cid;
721                        component.push(u);
722                        for &v in &self.rev[u] {
723                            if comp[v] == usize::MAX {
724                                stk.push(v);
725                            }
726                        }
727                    }
728                }
729                components.push(component);
730            }
731        }
732        components
733    }
734    #[allow(dead_code)]
735    pub fn node_count(&self) -> usize {
736        self.n
737    }
738    #[allow(dead_code)]
739    pub fn edge_count(&self) -> usize {
740        self.edge_count
741    }
742}
743/// Zig statement representation.
744#[derive(Debug, Clone, PartialEq)]
745pub enum ZigStmt {
746    VarDecl {
747        name: String,
748        ty: Option<ZigType>,
749        value: ZigExpr,
750    },
751    ConstDecl {
752        name: String,
753        ty: Option<ZigType>,
754        value: ZigExpr,
755    },
756    Assign {
757        target: ZigExpr,
758        value: ZigExpr,
759    },
760    Return(Option<ZigExpr>),
761    Expr(ZigExpr),
762    If {
763        cond: ZigExpr,
764        body: Vec<ZigStmt>,
765        else_: Vec<ZigStmt>,
766    },
767    While {
768        cond: ZigExpr,
769        body: Vec<ZigStmt>,
770    },
771    Defer(ZigExpr),
772}
773impl ZigStmt {
774    /// Emit Zig source for this statement.
775    pub fn codegen(&self) -> String {
776        match self {
777            ZigStmt::VarDecl { name, ty, value } => {
778                let ty_str = ty
779                    .as_ref()
780                    .map(|t| format!(": {}", t.codegen()))
781                    .unwrap_or_default();
782                format!("var {}{} = {};", name, ty_str, value.codegen())
783            }
784            ZigStmt::ConstDecl { name, ty, value } => {
785                let ty_str = ty
786                    .as_ref()
787                    .map(|t| format!(": {}", t.codegen()))
788                    .unwrap_or_default();
789                format!("const {}{} = {};", name, ty_str, value.codegen())
790            }
791            ZigStmt::Assign { target, value } => {
792                format!("{} = {};", target.codegen(), value.codegen())
793            }
794            ZigStmt::Return(None) => "return;".to_string(),
795            ZigStmt::Return(Some(expr)) => format!("return {};", expr.codegen()),
796            ZigStmt::Expr(expr) => format!("{};", expr.codegen()),
797            ZigStmt::If { cond, body, else_ } => {
798                let body_str: Vec<String> = body
799                    .iter()
800                    .map(|s| format!("    {}", s.codegen()))
801                    .collect();
802                let else_str = if else_.is_empty() {
803                    String::new()
804                } else {
805                    let else_body: Vec<String> = else_
806                        .iter()
807                        .map(|s| format!("    {}", s.codegen()))
808                        .collect();
809                    format!(" else {{\n{}\n}}", else_body.join("\n"))
810                };
811                format!(
812                    "if ({}) {{\n{}\n}}{}",
813                    cond.codegen(),
814                    body_str.join("\n"),
815                    else_str
816                )
817            }
818            ZigStmt::While { cond, body } => {
819                let body_str: Vec<String> = body
820                    .iter()
821                    .map(|s| format!("    {}", s.codegen()))
822                    .collect();
823                format!("while ({}) {{\n{}\n}}", cond.codegen(), body_str.join("\n"))
824            }
825            ZigStmt::Defer(expr) => format!("defer {};", expr.codegen()),
826        }
827    }
828}
829/// Constant folding helper for ZigExt.
830#[allow(dead_code)]
831#[derive(Debug, Clone, Default)]
832pub struct ZigExtConstFolder {
833    pub(super) folds: usize,
834    pub(super) failures: usize,
835    pub(super) enabled: bool,
836}
837impl ZigExtConstFolder {
838    #[allow(dead_code)]
839    pub fn new() -> Self {
840        Self {
841            folds: 0,
842            failures: 0,
843            enabled: true,
844        }
845    }
846    #[allow(dead_code)]
847    pub fn add_i64(&mut self, a: i64, b: i64) -> Option<i64> {
848        self.folds += 1;
849        a.checked_add(b)
850    }
851    #[allow(dead_code)]
852    pub fn sub_i64(&mut self, a: i64, b: i64) -> Option<i64> {
853        self.folds += 1;
854        a.checked_sub(b)
855    }
856    #[allow(dead_code)]
857    pub fn mul_i64(&mut self, a: i64, b: i64) -> Option<i64> {
858        self.folds += 1;
859        a.checked_mul(b)
860    }
861    #[allow(dead_code)]
862    pub fn div_i64(&mut self, a: i64, b: i64) -> Option<i64> {
863        if b == 0 {
864            self.failures += 1;
865            None
866        } else {
867            self.folds += 1;
868            a.checked_div(b)
869        }
870    }
871    #[allow(dead_code)]
872    pub fn rem_i64(&mut self, a: i64, b: i64) -> Option<i64> {
873        if b == 0 {
874            self.failures += 1;
875            None
876        } else {
877            self.folds += 1;
878            a.checked_rem(b)
879        }
880    }
881    #[allow(dead_code)]
882    pub fn neg_i64(&mut self, a: i64) -> Option<i64> {
883        self.folds += 1;
884        a.checked_neg()
885    }
886    #[allow(dead_code)]
887    pub fn shl_i64(&mut self, a: i64, s: u32) -> Option<i64> {
888        if s >= 64 {
889            self.failures += 1;
890            None
891        } else {
892            self.folds += 1;
893            a.checked_shl(s)
894        }
895    }
896    #[allow(dead_code)]
897    pub fn shr_i64(&mut self, a: i64, s: u32) -> Option<i64> {
898        if s >= 64 {
899            self.failures += 1;
900            None
901        } else {
902            self.folds += 1;
903            a.checked_shr(s)
904        }
905    }
906    #[allow(dead_code)]
907    pub fn and_i64(&mut self, a: i64, b: i64) -> i64 {
908        self.folds += 1;
909        a & b
910    }
911    #[allow(dead_code)]
912    pub fn or_i64(&mut self, a: i64, b: i64) -> i64 {
913        self.folds += 1;
914        a | b
915    }
916    #[allow(dead_code)]
917    pub fn xor_i64(&mut self, a: i64, b: i64) -> i64 {
918        self.folds += 1;
919        a ^ b
920    }
921    #[allow(dead_code)]
922    pub fn not_i64(&mut self, a: i64) -> i64 {
923        self.folds += 1;
924        !a
925    }
926    #[allow(dead_code)]
927    pub fn fold_count(&self) -> usize {
928        self.folds
929    }
930    #[allow(dead_code)]
931    pub fn failure_count(&self) -> usize {
932        self.failures
933    }
934    #[allow(dead_code)]
935    pub fn enable(&mut self) {
936        self.enabled = true;
937    }
938    #[allow(dead_code)]
939    pub fn disable(&mut self) {
940        self.enabled = false;
941    }
942    #[allow(dead_code)]
943    pub fn is_enabled(&self) -> bool {
944        self.enabled
945    }
946}
947#[allow(dead_code)]
948#[derive(Debug, Clone)]
949pub struct ZigLivenessInfo {
950    pub live_in: Vec<std::collections::HashSet<u32>>,
951    pub live_out: Vec<std::collections::HashSet<u32>>,
952    pub defs: Vec<std::collections::HashSet<u32>>,
953    pub uses: Vec<std::collections::HashSet<u32>>,
954}
955impl ZigLivenessInfo {
956    #[allow(dead_code)]
957    pub fn new(block_count: usize) -> Self {
958        ZigLivenessInfo {
959            live_in: vec![std::collections::HashSet::new(); block_count],
960            live_out: vec![std::collections::HashSet::new(); block_count],
961            defs: vec![std::collections::HashSet::new(); block_count],
962            uses: vec![std::collections::HashSet::new(); block_count],
963        }
964    }
965    #[allow(dead_code)]
966    pub fn add_def(&mut self, block: usize, var: u32) {
967        if block < self.defs.len() {
968            self.defs[block].insert(var);
969        }
970    }
971    #[allow(dead_code)]
972    pub fn add_use(&mut self, block: usize, var: u32) {
973        if block < self.uses.len() {
974            self.uses[block].insert(var);
975        }
976    }
977    #[allow(dead_code)]
978    pub fn is_live_in(&self, block: usize, var: u32) -> bool {
979        self.live_in
980            .get(block)
981            .map(|s| s.contains(&var))
982            .unwrap_or(false)
983    }
984    #[allow(dead_code)]
985    pub fn is_live_out(&self, block: usize, var: u32) -> bool {
986        self.live_out
987            .get(block)
988            .map(|s| s.contains(&var))
989            .unwrap_or(false)
990    }
991}
992#[allow(dead_code)]
993pub struct ZigFile {
994    pub imports: Vec<ZigImport>,
995    pub structs: Vec<ZigStruct>,
996    pub functions: Vec<ZigFn>,
997    pub tests: Vec<ZigTestBlock>,
998}
999impl ZigFile {
1000    #[allow(dead_code)]
1001    pub fn new() -> Self {
1002        ZigFile {
1003            imports: Vec::new(),
1004            structs: Vec::new(),
1005            functions: Vec::new(),
1006            tests: Vec::new(),
1007        }
1008    }
1009    #[allow(dead_code)]
1010    pub fn import(mut self, imp: ZigImport) -> Self {
1011        self.imports.push(imp);
1012        self
1013    }
1014    #[allow(dead_code)]
1015    pub fn add_struct(mut self, s: ZigStruct) -> Self {
1016        self.structs.push(s);
1017        self
1018    }
1019    #[allow(dead_code)]
1020    pub fn add_fn(mut self, f: ZigFn) -> Self {
1021        self.functions.push(f);
1022        self
1023    }
1024    #[allow(dead_code)]
1025    pub fn add_test(mut self, t: ZigTestBlock) -> Self {
1026        self.tests.push(t);
1027        self
1028    }
1029    #[allow(dead_code)]
1030    pub fn emit(&self) -> String {
1031        let mut parts = Vec::new();
1032        for imp in &self.imports {
1033            parts.push(imp.emit());
1034        }
1035        for s in &self.structs {
1036            let mut out = format!("const {} = struct {{\n", s.name);
1037            for f in &s.fields {
1038                out.push_str(&format!("    {}: {},\n", f.0, f.1.codegen()));
1039            }
1040            out.push_str("};");
1041            parts.push(out);
1042        }
1043        for t in &self.tests {
1044            parts.push(t.emit());
1045        }
1046        parts.join("\n\n")
1047    }
1048}
1049#[allow(dead_code)]
1050pub struct ZigSliceOps;
1051impl ZigSliceOps {
1052    #[allow(dead_code)]
1053    pub fn len_expr(slice: &str) -> String {
1054        format!("{}.len", slice)
1055    }
1056    #[allow(dead_code)]
1057    pub fn ptr_expr(slice: &str) -> String {
1058        format!("{}.ptr", slice)
1059    }
1060    #[allow(dead_code)]
1061    pub fn index_expr(slice: &str, idx: &str) -> String {
1062        format!("{}[{}]", slice, idx)
1063    }
1064    #[allow(dead_code)]
1065    pub fn slice_expr(slice: &str, start: &str, end: &str) -> String {
1066        format!("{}[{}..{}]", slice, start, end)
1067    }
1068    #[allow(dead_code)]
1069    pub fn concat_alloc(alloc: &str, a: &str, b: &str) -> String {
1070        format!("try std.mem.concat({}, u8, &.{{ {}, {} }})", alloc, a, b)
1071    }
1072    #[allow(dead_code)]
1073    pub fn copy(dst: &str, src: &str) -> String {
1074        format!("std.mem.copy(u8, {}, {})", dst, src)
1075    }
1076    #[allow(dead_code)]
1077    pub fn eql(a: &str, b: &str) -> String {
1078        format!("std.mem.eql(u8, {}, {})", a, b)
1079    }
1080}
1081#[allow(dead_code)]
1082#[derive(Debug, Clone)]
1083pub struct ZigPackedStruct {
1084    pub name: String,
1085    pub fields: Vec<ZigPackedField>,
1086}
1087impl ZigPackedStruct {
1088    #[allow(dead_code)]
1089    pub fn new(name: impl Into<String>) -> Self {
1090        ZigPackedStruct {
1091            name: name.into(),
1092            fields: Vec::new(),
1093        }
1094    }
1095    #[allow(dead_code)]
1096    pub fn add_field(&mut self, name: impl Into<String>, ty: ZigType, bits: Option<u32>) {
1097        self.fields.push(ZigPackedField {
1098            name: name.into(),
1099            ty,
1100            bit_width: bits,
1101        });
1102    }
1103    #[allow(dead_code)]
1104    pub fn emit(&self) -> String {
1105        let mut out = format!("const {} = packed struct {{\n", self.name);
1106        for f in &self.fields {
1107            match f.bit_width {
1108                Some(bits) => out.push_str(&format!("    {}: u{},\n", f.name, bits)),
1109                None => out.push_str(&format!("    {}: {},\n", f.name, "type")),
1110            }
1111        }
1112        out.push_str("};");
1113        out
1114    }
1115    #[allow(dead_code)]
1116    pub fn total_bits(&self) -> u32 {
1117        self.fields.iter().map(|f| f.bit_width.unwrap_or(8)).sum()
1118    }
1119}
1120/// Dominator tree for ZigExt.
1121#[allow(dead_code)]
1122#[derive(Debug, Clone)]
1123pub struct ZigExtDomTree {
1124    pub(super) idom: Vec<Option<usize>>,
1125    pub(super) children: Vec<Vec<usize>>,
1126    pub(super) depth: Vec<usize>,
1127}
1128impl ZigExtDomTree {
1129    #[allow(dead_code)]
1130    pub fn new(n: usize) -> Self {
1131        Self {
1132            idom: vec![None; n],
1133            children: vec![Vec::new(); n],
1134            depth: vec![0; n],
1135        }
1136    }
1137    #[allow(dead_code)]
1138    pub fn set_idom(&mut self, node: usize, dom: usize) {
1139        if node < self.idom.len() {
1140            self.idom[node] = Some(dom);
1141            if dom < self.children.len() {
1142                self.children[dom].push(node);
1143            }
1144            self.depth[node] = if dom < self.depth.len() {
1145                self.depth[dom] + 1
1146            } else {
1147                1
1148            };
1149        }
1150    }
1151    #[allow(dead_code)]
1152    pub fn dominates(&self, a: usize, mut b: usize) -> bool {
1153        if a == b {
1154            return true;
1155        }
1156        let n = self.idom.len();
1157        for _ in 0..n {
1158            match self.idom.get(b).copied().flatten() {
1159                None => return false,
1160                Some(p) if p == a => return true,
1161                Some(p) if p == b => return false,
1162                Some(p) => b = p,
1163            }
1164        }
1165        false
1166    }
1167    #[allow(dead_code)]
1168    pub fn children_of(&self, n: usize) -> &[usize] {
1169        self.children.get(n).map(|v| v.as_slice()).unwrap_or(&[])
1170    }
1171    #[allow(dead_code)]
1172    pub fn depth_of(&self, n: usize) -> usize {
1173        self.depth.get(n).copied().unwrap_or(0)
1174    }
1175    #[allow(dead_code)]
1176    pub fn lca(&self, mut a: usize, mut b: usize) -> usize {
1177        let n = self.idom.len();
1178        for _ in 0..(2 * n) {
1179            if a == b {
1180                return a;
1181            }
1182            if self.depth_of(a) > self.depth_of(b) {
1183                a = self.idom.get(a).and_then(|x| *x).unwrap_or(a);
1184            } else {
1185                b = self.idom.get(b).and_then(|x| *x).unwrap_or(b);
1186            }
1187        }
1188        0
1189    }
1190}
1191#[allow(dead_code)]
1192#[derive(Debug, Clone)]
1193pub struct ZigCacheEntry {
1194    pub key: String,
1195    pub data: Vec<u8>,
1196    pub timestamp: u64,
1197    pub valid: bool,
1198}
1199/// Represents a complete Zig module (source file).
1200pub struct ZigModule {
1201    pub name: String,
1202    pub imports: Vec<String>,
1203    pub structs: Vec<ZigStruct>,
1204    pub fns: Vec<ZigFn>,
1205    pub consts: Vec<(String, ZigType, ZigExpr)>,
1206}
1207impl ZigModule {
1208    /// Create a new empty module.
1209    pub fn new(name: &str) -> Self {
1210        ZigModule {
1211            name: name.to_string(),
1212            imports: Vec::new(),
1213            structs: Vec::new(),
1214            fns: Vec::new(),
1215            consts: Vec::new(),
1216        }
1217    }
1218    /// Add an import statement (e.g., `@import("std")`).
1219    pub fn add_import(&mut self, path: &str) {
1220        self.imports.push(path.to_string());
1221    }
1222    /// Add a struct definition.
1223    pub fn add_struct(&mut self, s: ZigStruct) {
1224        self.structs.push(s);
1225    }
1226    /// Add a function definition.
1227    pub fn add_fn(&mut self, f: ZigFn) {
1228        self.fns.push(f);
1229    }
1230    /// Generate the complete Zig module source code.
1231    pub fn codegen(&self) -> String {
1232        let mut parts: Vec<String> = Vec::new();
1233        for (i, path) in self.imports.iter().enumerate() {
1234            let binding = format!("_import_{}", i);
1235            parts.push(format!("const {} = @import(\"{}\");", binding, path));
1236        }
1237        for (name, ty, expr) in &self.consts {
1238            parts.push(format!(
1239                "const {}: {} = {};",
1240                name,
1241                ty.codegen(),
1242                expr.codegen()
1243            ));
1244        }
1245        for s in &self.structs {
1246            parts.push(s.codegen());
1247        }
1248        for f in &self.fns {
1249            parts.push(f.codegen());
1250        }
1251        parts.join("\n\n")
1252    }
1253}
1254#[allow(dead_code)]
1255#[derive(Debug, Clone)]
1256pub struct ZigPackedField {
1257    pub name: String,
1258    pub ty: ZigType,
1259    pub bit_width: Option<u32>,
1260}
1261#[allow(dead_code)]
1262#[derive(Debug, Clone)]
1263pub enum ZigAllocatorKind {
1264    GeneralPurpose,
1265    Arena,
1266    Page,
1267    FixedBuffer(usize),
1268    C,
1269    LogToFile,
1270}
1271impl ZigAllocatorKind {
1272    #[allow(dead_code)]
1273    pub fn type_name(&self) -> &str {
1274        match self {
1275            ZigAllocatorKind::GeneralPurpose => "std.heap.GeneralPurposeAllocator(.{})",
1276            ZigAllocatorKind::Arena => "std.heap.ArenaAllocator",
1277            ZigAllocatorKind::Page => "std.heap.page_allocator",
1278            ZigAllocatorKind::FixedBuffer(_) => "std.heap.FixedBufferAllocator",
1279            ZigAllocatorKind::C => "std.heap.c_allocator",
1280            ZigAllocatorKind::LogToFile => "std.heap.LoggingAllocator",
1281        }
1282    }
1283}
1284#[allow(dead_code)]
1285#[derive(Debug, Clone, PartialEq)]
1286pub enum ZigPassPhase {
1287    Analysis,
1288    Transformation,
1289    Verification,
1290    Cleanup,
1291}
1292impl ZigPassPhase {
1293    #[allow(dead_code)]
1294    pub fn name(&self) -> &str {
1295        match self {
1296            ZigPassPhase::Analysis => "analysis",
1297            ZigPassPhase::Transformation => "transformation",
1298            ZigPassPhase::Verification => "verification",
1299            ZigPassPhase::Cleanup => "cleanup",
1300        }
1301    }
1302    #[allow(dead_code)]
1303    pub fn is_modifying(&self) -> bool {
1304        matches!(self, ZigPassPhase::Transformation | ZigPassPhase::Cleanup)
1305    }
1306}
1307#[allow(dead_code)]
1308#[derive(Debug, Clone)]
1309pub struct ZigDepGraph {
1310    pub(super) nodes: Vec<u32>,
1311    pub(super) edges: Vec<(u32, u32)>,
1312}
1313impl ZigDepGraph {
1314    #[allow(dead_code)]
1315    pub fn new() -> Self {
1316        ZigDepGraph {
1317            nodes: Vec::new(),
1318            edges: Vec::new(),
1319        }
1320    }
1321    #[allow(dead_code)]
1322    pub fn add_node(&mut self, id: u32) {
1323        if !self.nodes.contains(&id) {
1324            self.nodes.push(id);
1325        }
1326    }
1327    #[allow(dead_code)]
1328    pub fn add_dep(&mut self, dep: u32, dependent: u32) {
1329        self.add_node(dep);
1330        self.add_node(dependent);
1331        self.edges.push((dep, dependent));
1332    }
1333    #[allow(dead_code)]
1334    pub fn dependents_of(&self, node: u32) -> Vec<u32> {
1335        self.edges
1336            .iter()
1337            .filter(|(d, _)| *d == node)
1338            .map(|(_, dep)| *dep)
1339            .collect()
1340    }
1341    #[allow(dead_code)]
1342    pub fn dependencies_of(&self, node: u32) -> Vec<u32> {
1343        self.edges
1344            .iter()
1345            .filter(|(_, dep)| *dep == node)
1346            .map(|(d, _)| *d)
1347            .collect()
1348    }
1349    #[allow(dead_code)]
1350    pub fn topological_sort(&self) -> Vec<u32> {
1351        let mut in_degree: std::collections::HashMap<u32, u32> = std::collections::HashMap::new();
1352        for &n in &self.nodes {
1353            in_degree.insert(n, 0);
1354        }
1355        for (_, dep) in &self.edges {
1356            *in_degree.entry(*dep).or_insert(0) += 1;
1357        }
1358        let mut queue: std::collections::VecDeque<u32> = self
1359            .nodes
1360            .iter()
1361            .filter(|&&n| in_degree[&n] == 0)
1362            .copied()
1363            .collect();
1364        let mut result = Vec::new();
1365        while let Some(node) = queue.pop_front() {
1366            result.push(node);
1367            for dep in self.dependents_of(node) {
1368                let cnt = in_degree.entry(dep).or_insert(0);
1369                *cnt = cnt.saturating_sub(1);
1370                if *cnt == 0 {
1371                    queue.push_back(dep);
1372                }
1373            }
1374        }
1375        result
1376    }
1377    #[allow(dead_code)]
1378    pub fn has_cycle(&self) -> bool {
1379        self.topological_sort().len() < self.nodes.len()
1380    }
1381}
1382/// Statistics for ZigExt passes.
1383#[allow(dead_code)]
1384#[derive(Debug, Clone, Default)]
1385pub struct ZigExtPassStats {
1386    pub iterations: usize,
1387    pub changed: bool,
1388    pub nodes_visited: usize,
1389    pub nodes_modified: usize,
1390    pub time_ms: u64,
1391    pub memory_bytes: usize,
1392    pub errors: usize,
1393}
1394impl ZigExtPassStats {
1395    #[allow(dead_code)]
1396    pub fn new() -> Self {
1397        Self::default()
1398    }
1399    #[allow(dead_code)]
1400    pub fn visit(&mut self) {
1401        self.nodes_visited += 1;
1402    }
1403    #[allow(dead_code)]
1404    pub fn modify(&mut self) {
1405        self.nodes_modified += 1;
1406        self.changed = true;
1407    }
1408    #[allow(dead_code)]
1409    pub fn iterate(&mut self) {
1410        self.iterations += 1;
1411    }
1412    #[allow(dead_code)]
1413    pub fn error(&mut self) {
1414        self.errors += 1;
1415    }
1416    #[allow(dead_code)]
1417    pub fn efficiency(&self) -> f64 {
1418        if self.nodes_visited == 0 {
1419            0.0
1420        } else {
1421            self.nodes_modified as f64 / self.nodes_visited as f64
1422        }
1423    }
1424    #[allow(dead_code)]
1425    pub fn merge(&mut self, o: &ZigExtPassStats) {
1426        self.iterations += o.iterations;
1427        self.changed |= o.changed;
1428        self.nodes_visited += o.nodes_visited;
1429        self.nodes_modified += o.nodes_modified;
1430        self.time_ms += o.time_ms;
1431        self.memory_bytes = self.memory_bytes.max(o.memory_bytes);
1432        self.errors += o.errors;
1433    }
1434}
1435/// Represents a Zig struct definition.
1436pub struct ZigStruct {
1437    pub name: String,
1438    pub fields: Vec<(String, ZigType)>,
1439    pub is_pub: bool,
1440}
1441impl ZigStruct {
1442    /// Create a new struct with the given name.
1443    pub fn new(name: &str) -> Self {
1444        ZigStruct {
1445            name: name.to_string(),
1446            fields: Vec::new(),
1447            is_pub: false,
1448        }
1449    }
1450    /// Add a field to the struct.
1451    pub fn add_field(&mut self, name: &str, ty: ZigType) {
1452        self.fields.push((name.to_string(), ty));
1453    }
1454    /// Generate Zig source code for this struct.
1455    pub fn codegen(&self) -> String {
1456        let pub_str = if self.is_pub { "pub " } else { "" };
1457        let fields_str: Vec<String> = self
1458            .fields
1459            .iter()
1460            .map(|(name, ty)| format!("    {}: {},", name, ty.codegen()))
1461            .collect();
1462        format!(
1463            "{}const {} = struct {{\n{}\n}};",
1464            pub_str,
1465            self.name,
1466            fields_str.join("\n")
1467        )
1468    }
1469}
1470/// Liveness analysis for ZigExt.
1471#[allow(dead_code)]
1472#[derive(Debug, Clone, Default)]
1473pub struct ZigExtLiveness {
1474    pub live_in: Vec<Vec<usize>>,
1475    pub live_out: Vec<Vec<usize>>,
1476    pub defs: Vec<Vec<usize>>,
1477    pub uses: Vec<Vec<usize>>,
1478}
1479impl ZigExtLiveness {
1480    #[allow(dead_code)]
1481    pub fn new(n: usize) -> Self {
1482        Self {
1483            live_in: vec![Vec::new(); n],
1484            live_out: vec![Vec::new(); n],
1485            defs: vec![Vec::new(); n],
1486            uses: vec![Vec::new(); n],
1487        }
1488    }
1489    #[allow(dead_code)]
1490    pub fn live_in(&self, b: usize, v: usize) -> bool {
1491        self.live_in.get(b).map(|s| s.contains(&v)).unwrap_or(false)
1492    }
1493    #[allow(dead_code)]
1494    pub fn live_out(&self, b: usize, v: usize) -> bool {
1495        self.live_out
1496            .get(b)
1497            .map(|s| s.contains(&v))
1498            .unwrap_or(false)
1499    }
1500    #[allow(dead_code)]
1501    pub fn add_def(&mut self, b: usize, v: usize) {
1502        if let Some(s) = self.defs.get_mut(b) {
1503            if !s.contains(&v) {
1504                s.push(v);
1505            }
1506        }
1507    }
1508    #[allow(dead_code)]
1509    pub fn add_use(&mut self, b: usize, v: usize) {
1510        if let Some(s) = self.uses.get_mut(b) {
1511            if !s.contains(&v) {
1512                s.push(v);
1513            }
1514        }
1515    }
1516    #[allow(dead_code)]
1517    pub fn var_is_used_in_block(&self, b: usize, v: usize) -> bool {
1518        self.uses.get(b).map(|s| s.contains(&v)).unwrap_or(false)
1519    }
1520    #[allow(dead_code)]
1521    pub fn var_is_def_in_block(&self, b: usize, v: usize) -> bool {
1522        self.defs.get(b).map(|s| s.contains(&v)).unwrap_or(false)
1523    }
1524}
1525/// Zig type representation.
1526#[derive(Debug, Clone, PartialEq)]
1527pub enum ZigType {
1528    Void,
1529    Bool,
1530    U8,
1531    U64,
1532    I64,
1533    F64,
1534    /// Generic signed integer type.
1535    Int,
1536    Ptr(Box<ZigType>),
1537    Slice(Box<ZigType>),
1538    Struct(String),
1539    Fn(Vec<ZigType>, Box<ZigType>),
1540    Optional(Box<ZigType>),
1541    ErrorUnion(Box<ZigType>),
1542    Anyopaque,
1543}
1544impl ZigType {
1545    /// Emit Zig source representation of this type.
1546    pub fn codegen(&self) -> String {
1547        match self {
1548            ZigType::Void => "void".to_string(),
1549            ZigType::Bool => "bool".to_string(),
1550            ZigType::U8 => "u8".to_string(),
1551            ZigType::U64 => "u64".to_string(),
1552            ZigType::I64 => "i64".to_string(),
1553            ZigType::F64 => "f64".to_string(),
1554            ZigType::Int => "i64".to_string(),
1555            ZigType::Ptr(inner) => format!("*{}", inner.codegen()),
1556            ZigType::Slice(inner) => format!("[]{}", inner.codegen()),
1557            ZigType::Struct(name) => name.clone(),
1558            ZigType::Fn(params, ret) => {
1559                let params_str: Vec<String> = params.iter().map(|p| p.codegen()).collect();
1560                format!("fn({}) {}", params_str.join(", "), ret.codegen())
1561            }
1562            ZigType::Optional(inner) => format!("?{}", inner.codegen()),
1563            ZigType::ErrorUnion(inner) => format!("!{}", inner.codegen()),
1564            ZigType::Anyopaque => "anyopaque".to_string(),
1565        }
1566    }
1567}
1568#[allow(dead_code)]
1569#[derive(Debug, Clone)]
1570pub struct ZigTestBlock {
1571    pub name: String,
1572    pub body: Vec<String>,
1573}
1574impl ZigTestBlock {
1575    #[allow(dead_code)]
1576    pub fn new(name: impl Into<String>) -> Self {
1577        ZigTestBlock {
1578            name: name.into(),
1579            body: Vec::new(),
1580        }
1581    }
1582    #[allow(dead_code)]
1583    pub fn add_line(&mut self, line: impl Into<String>) {
1584        self.body.push(line.into());
1585    }
1586    #[allow(dead_code)]
1587    pub fn add_expect(mut self, lhs: &str, rhs: &str) -> Self {
1588        self.body
1589            .push(format!("try std.testing.expectEqual({}, {});", lhs, rhs));
1590        self
1591    }
1592    #[allow(dead_code)]
1593    pub fn add_expect_equal_strings(mut self, lhs: &str, rhs: &str) -> Self {
1594        self.body.push(format!(
1595            "try std.testing.expectEqualStrings({}, {});",
1596            lhs, rhs
1597        ));
1598        self
1599    }
1600    #[allow(dead_code)]
1601    pub fn emit(&self) -> String {
1602        let mut out = format!("test \"{}\" {{\n", self.name);
1603        for line in &self.body {
1604            out.push_str(&format!("    {}\n", line));
1605        }
1606        out.push('}');
1607        out
1608    }
1609}
1610#[allow(dead_code)]
1611#[derive(Debug, Clone)]
1612pub struct ZigTaggedUnion {
1613    pub name: String,
1614    pub tag_type: Option<String>,
1615    pub fields: Vec<(String, Option<ZigType>)>,
1616}
1617impl ZigTaggedUnion {
1618    #[allow(dead_code)]
1619    pub fn new(name: impl Into<String>) -> Self {
1620        ZigTaggedUnion {
1621            name: name.into(),
1622            tag_type: None,
1623            fields: Vec::new(),
1624        }
1625    }
1626    #[allow(dead_code)]
1627    pub fn with_tag(mut self, ty: impl Into<String>) -> Self {
1628        self.tag_type = Some(ty.into());
1629        self
1630    }
1631    #[allow(dead_code)]
1632    pub fn add_field(&mut self, name: impl Into<String>, ty: Option<ZigType>) {
1633        self.fields.push((name.into(), ty));
1634    }
1635    #[allow(dead_code)]
1636    pub fn emit(&self) -> String {
1637        let tag_part = if let Some(ref t) = self.tag_type {
1638            format!("union({}) ", t)
1639        } else {
1640            "union ".to_string()
1641        };
1642        let mut out = format!("const {} = {}{{\n", self.name, tag_part);
1643        for (name, ty) in &self.fields {
1644            match ty {
1645                Some(_) => out.push_str(&format!("    {}: {},\n", name, "type")),
1646                None => out.push_str(&format!("    {},\n", name)),
1647            }
1648        }
1649        out.push_str("};");
1650        out
1651    }
1652}
1653#[allow(dead_code)]
1654#[derive(Debug, Clone)]
1655pub struct ZigAnalysisCache {
1656    pub(super) entries: std::collections::HashMap<String, ZigCacheEntry>,
1657    pub(super) max_size: usize,
1658    pub(super) hits: u64,
1659    pub(super) misses: u64,
1660}
1661impl ZigAnalysisCache {
1662    #[allow(dead_code)]
1663    pub fn new(max_size: usize) -> Self {
1664        ZigAnalysisCache {
1665            entries: std::collections::HashMap::new(),
1666            max_size,
1667            hits: 0,
1668            misses: 0,
1669        }
1670    }
1671    #[allow(dead_code)]
1672    pub fn get(&mut self, key: &str) -> Option<&ZigCacheEntry> {
1673        if self.entries.contains_key(key) {
1674            self.hits += 1;
1675            self.entries.get(key)
1676        } else {
1677            self.misses += 1;
1678            None
1679        }
1680    }
1681    #[allow(dead_code)]
1682    pub fn insert(&mut self, key: String, data: Vec<u8>) {
1683        if self.entries.len() >= self.max_size {
1684            if let Some(oldest) = self.entries.keys().next().cloned() {
1685                self.entries.remove(&oldest);
1686            }
1687        }
1688        self.entries.insert(
1689            key.clone(),
1690            ZigCacheEntry {
1691                key,
1692                data,
1693                timestamp: 0,
1694                valid: true,
1695            },
1696        );
1697    }
1698    #[allow(dead_code)]
1699    pub fn invalidate(&mut self, key: &str) {
1700        if let Some(entry) = self.entries.get_mut(key) {
1701            entry.valid = false;
1702        }
1703    }
1704    #[allow(dead_code)]
1705    pub fn clear(&mut self) {
1706        self.entries.clear();
1707    }
1708    #[allow(dead_code)]
1709    pub fn hit_rate(&self) -> f64 {
1710        let total = self.hits + self.misses;
1711        if total == 0 {
1712            return 0.0;
1713        }
1714        self.hits as f64 / total as f64
1715    }
1716    #[allow(dead_code)]
1717    pub fn size(&self) -> usize {
1718        self.entries.len()
1719    }
1720}
1721/// Zig expression representation.
1722#[derive(Debug, Clone, PartialEq)]
1723pub enum ZigExpr {
1724    Ident(String),
1725    IntLit(i64),
1726    FloatLit(f64),
1727    BoolLit(bool),
1728    StringLit(String),
1729    NullLit,
1730    BinOp {
1731        op: String,
1732        lhs: Box<ZigExpr>,
1733        rhs: Box<ZigExpr>,
1734    },
1735    UnaryOp {
1736        op: String,
1737        operand: Box<ZigExpr>,
1738    },
1739    Call {
1740        callee: Box<ZigExpr>,
1741        args: Vec<ZigExpr>,
1742    },
1743    FieldAccess {
1744        base: Box<ZigExpr>,
1745        field: String,
1746    },
1747    Try(Box<ZigExpr>),
1748    Await(Box<ZigExpr>),
1749    Comptime(Box<ZigExpr>),
1750    If {
1751        cond: Box<ZigExpr>,
1752        then: Box<ZigExpr>,
1753        else_: Option<Box<ZigExpr>>,
1754    },
1755    Block(Vec<ZigStmt>),
1756}
1757impl ZigExpr {
1758    /// Emit Zig source for this expression.
1759    pub fn codegen(&self) -> String {
1760        match self {
1761            ZigExpr::Ident(name) => name.clone(),
1762            ZigExpr::IntLit(n) => n.to_string(),
1763            ZigExpr::FloatLit(f) => format!("{}", f),
1764            ZigExpr::BoolLit(b) => b.to_string(),
1765            ZigExpr::StringLit(s) => {
1766                format!("\"{}\"", s.replace('\\', "\\\\").replace('"', "\\\""))
1767            }
1768            ZigExpr::NullLit => "null".to_string(),
1769            ZigExpr::BinOp { op, lhs, rhs } => {
1770                format!("({} {} {})", lhs.codegen(), op, rhs.codegen())
1771            }
1772            ZigExpr::UnaryOp { op, operand } => format!("({}{})", op, operand.codegen()),
1773            ZigExpr::Call { callee, args } => {
1774                let args_str: Vec<String> = args.iter().map(|a| a.codegen()).collect();
1775                format!("{}({})", callee.codegen(), args_str.join(", "))
1776            }
1777            ZigExpr::FieldAccess { base, field } => {
1778                format!("{}.{}", base.codegen(), field)
1779            }
1780            ZigExpr::Try(inner) => format!("try {}", inner.codegen()),
1781            ZigExpr::Await(inner) => format!("await {}", inner.codegen()),
1782            ZigExpr::Comptime(inner) => format!("comptime {}", inner.codegen()),
1783            ZigExpr::If { cond, then, else_ } => {
1784                let else_str = else_
1785                    .as_ref()
1786                    .map(|e| format!(" else {}", e.codegen()))
1787                    .unwrap_or_default();
1788                format!("if ({}) {}{}", cond.codegen(), then.codegen(), else_str)
1789            }
1790            ZigExpr::Block(stmts) => {
1791                let body: Vec<String> = stmts
1792                    .iter()
1793                    .map(|s| format!("    {}", s.codegen()))
1794                    .collect();
1795                format!("{{\n{}\n}}", body.join("\n"))
1796            }
1797        }
1798    }
1799}
1800#[allow(dead_code)]
1801#[derive(Debug, Clone)]
1802pub enum ZigOptimizeMode {
1803    Debug,
1804    ReleaseSafe,
1805    ReleaseFast,
1806    ReleaseSmall,
1807}
1808impl ZigOptimizeMode {
1809    #[allow(dead_code)]
1810    pub fn name(&self) -> &str {
1811        match self {
1812            ZigOptimizeMode::Debug => "Debug",
1813            ZigOptimizeMode::ReleaseSafe => "ReleaseSafe",
1814            ZigOptimizeMode::ReleaseFast => "ReleaseFast",
1815            ZigOptimizeMode::ReleaseSmall => "ReleaseSmall",
1816        }
1817    }
1818}
1819#[allow(dead_code)]
1820#[derive(Debug, Clone)]
1821pub struct ZigDominatorTree {
1822    pub idom: Vec<Option<u32>>,
1823    pub dom_children: Vec<Vec<u32>>,
1824    pub dom_depth: Vec<u32>,
1825}
1826impl ZigDominatorTree {
1827    #[allow(dead_code)]
1828    pub fn new(size: usize) -> Self {
1829        ZigDominatorTree {
1830            idom: vec![None; size],
1831            dom_children: vec![Vec::new(); size],
1832            dom_depth: vec![0; size],
1833        }
1834    }
1835    #[allow(dead_code)]
1836    pub fn set_idom(&mut self, node: usize, idom: u32) {
1837        self.idom[node] = Some(idom);
1838    }
1839    #[allow(dead_code)]
1840    pub fn dominates(&self, a: usize, b: usize) -> bool {
1841        if a == b {
1842            return true;
1843        }
1844        let mut cur = b;
1845        loop {
1846            match self.idom[cur] {
1847                Some(parent) if parent as usize == a => return true,
1848                Some(parent) if parent as usize == cur => return false,
1849                Some(parent) => cur = parent as usize,
1850                None => return false,
1851            }
1852        }
1853    }
1854    #[allow(dead_code)]
1855    pub fn depth(&self, node: usize) -> u32 {
1856        self.dom_depth.get(node).copied().unwrap_or(0)
1857    }
1858}
1859#[allow(dead_code)]
1860#[derive(Debug, Clone)]
1861pub struct ZigImport {
1862    pub module: String,
1863    pub alias: Option<String>,
1864}
1865impl ZigImport {
1866    #[allow(dead_code)]
1867    pub fn std() -> Self {
1868        ZigImport {
1869            module: "std".to_string(),
1870            alias: Some("std".to_string()),
1871        }
1872    }
1873    #[allow(dead_code)]
1874    pub fn module(module: impl Into<String>) -> Self {
1875        let m = module.into();
1876        ZigImport {
1877            module: m.clone(),
1878            alias: Some(m),
1879        }
1880    }
1881    #[allow(dead_code)]
1882    pub fn with_alias(mut self, alias: impl Into<String>) -> Self {
1883        self.alias = Some(alias.into());
1884        self
1885    }
1886    #[allow(dead_code)]
1887    pub fn emit(&self) -> String {
1888        if let Some(ref alias) = self.alias {
1889            format!("const {} = @import(\"{}\");", alias, self.module)
1890        } else {
1891            format!("_ = @import(\"{}\");", self.module)
1892        }
1893    }
1894}
1895#[allow(dead_code)]
1896#[derive(Debug, Clone)]
1897pub struct ZigAllocatorUsage {
1898    pub allocator_type: ZigAllocatorKind,
1899    pub var_name: String,
1900}
1901impl ZigAllocatorUsage {
1902    #[allow(dead_code)]
1903    pub fn new(kind: ZigAllocatorKind, var_name: impl Into<String>) -> Self {
1904        ZigAllocatorUsage {
1905            allocator_type: kind,
1906            var_name: var_name.into(),
1907        }
1908    }
1909    #[allow(dead_code)]
1910    pub fn emit_init(&self) -> String {
1911        match &self.allocator_type {
1912            ZigAllocatorKind::GeneralPurpose => {
1913                format!(
1914                    "var {} = std.heap.GeneralPurposeAllocator(.{{}}){{}};\ndefer _ = {}.deinit();",
1915                    self.var_name, self.var_name
1916                )
1917            }
1918            ZigAllocatorKind::Arena => {
1919                format!(
1920                    "var {} = std.heap.ArenaAllocator.init(std.heap.page_allocator);\ndefer {}.deinit();",
1921                    self.var_name, self.var_name
1922                )
1923            }
1924            ZigAllocatorKind::FixedBuffer(size) => {
1925                format!(
1926                    "var buf: [{}]u8 = undefined;\nvar {} = std.heap.FixedBufferAllocator.init(&buf);",
1927                    size, self.var_name
1928                )
1929            }
1930            _ => format!("// allocator: {}", self.allocator_type.type_name()),
1931        }
1932    }
1933    #[allow(dead_code)]
1934    pub fn emit_interface_call(&self) -> String {
1935        match &self.allocator_type {
1936            ZigAllocatorKind::GeneralPurpose => format!("{}.allocator()", self.var_name),
1937            ZigAllocatorKind::Arena => format!("{}.allocator()", self.var_name),
1938            ZigAllocatorKind::FixedBuffer(_) => format!("{}.allocator()", self.var_name),
1939            ZigAllocatorKind::Page => "std.heap.page_allocator".to_string(),
1940            ZigAllocatorKind::C => "std.heap.c_allocator".to_string(),
1941            _ => format!("{}.allocator()", self.var_name),
1942        }
1943    }
1944}
1945#[allow(dead_code)]
1946#[derive(Debug, Clone)]
1947pub struct ZigComptime {
1948    pub body: Vec<ZigStmt>,
1949    pub is_block: bool,
1950}
1951impl ZigComptime {
1952    #[allow(dead_code)]
1953    pub fn new() -> Self {
1954        ZigComptime {
1955            body: Vec::new(),
1956            is_block: true,
1957        }
1958    }
1959    #[allow(dead_code)]
1960    pub fn add_stmt(&mut self, stmt: ZigStmt) {
1961        self.body.push(stmt);
1962    }
1963    #[allow(dead_code)]
1964    pub fn emit(&self) -> String {
1965        if self.is_block {
1966            format!(
1967                "comptime {{\n{}}}",
1968                self.body
1969                    .iter()
1970                    .map(|_| "    // stmt\n")
1971                    .collect::<String>()
1972            )
1973        } else {
1974            "comptime expr".to_string()
1975        }
1976    }
1977}
1978#[allow(dead_code)]
1979pub struct ZigPassRegistry {
1980    pub(super) configs: Vec<ZigPassConfig>,
1981    pub(super) stats: std::collections::HashMap<String, ZigPassStats>,
1982}
1983impl ZigPassRegistry {
1984    #[allow(dead_code)]
1985    pub fn new() -> Self {
1986        ZigPassRegistry {
1987            configs: Vec::new(),
1988            stats: std::collections::HashMap::new(),
1989        }
1990    }
1991    #[allow(dead_code)]
1992    pub fn register(&mut self, config: ZigPassConfig) {
1993        self.stats
1994            .insert(config.pass_name.clone(), ZigPassStats::new());
1995        self.configs.push(config);
1996    }
1997    #[allow(dead_code)]
1998    pub fn enabled_passes(&self) -> Vec<&ZigPassConfig> {
1999        self.configs.iter().filter(|c| c.enabled).collect()
2000    }
2001    #[allow(dead_code)]
2002    pub fn get_stats(&self, name: &str) -> Option<&ZigPassStats> {
2003        self.stats.get(name)
2004    }
2005    #[allow(dead_code)]
2006    pub fn total_passes(&self) -> usize {
2007        self.configs.len()
2008    }
2009    #[allow(dead_code)]
2010    pub fn enabled_count(&self) -> usize {
2011        self.enabled_passes().len()
2012    }
2013    #[allow(dead_code)]
2014    pub fn update_stats(&mut self, name: &str, changes: u64, time_ms: u64, iter: u32) {
2015        if let Some(stats) = self.stats.get_mut(name) {
2016            stats.record_run(changes, time_ms, iter);
2017        }
2018    }
2019}
2020#[allow(dead_code)]
2021#[derive(Debug, Clone)]
2022pub struct ZigGenericFn {
2023    pub name: String,
2024    pub type_params: Vec<String>,
2025    pub params: Vec<(String, String)>,
2026    pub return_type: String,
2027    pub body: Vec<ZigStmt>,
2028}
2029impl ZigGenericFn {
2030    #[allow(dead_code)]
2031    pub fn new(name: impl Into<String>) -> Self {
2032        ZigGenericFn {
2033            name: name.into(),
2034            type_params: Vec::new(),
2035            params: Vec::new(),
2036            return_type: "void".to_string(),
2037            body: Vec::new(),
2038        }
2039    }
2040    #[allow(dead_code)]
2041    pub fn type_param(mut self, tp: impl Into<String>) -> Self {
2042        self.type_params.push(tp.into());
2043        self
2044    }
2045    #[allow(dead_code)]
2046    pub fn param(mut self, name: impl Into<String>, ty: impl Into<String>) -> Self {
2047        self.params.push((name.into(), ty.into()));
2048        self
2049    }
2050    #[allow(dead_code)]
2051    pub fn returns(mut self, ty: impl Into<String>) -> Self {
2052        self.return_type = ty.into();
2053        self
2054    }
2055    #[allow(dead_code)]
2056    pub fn emit(&self) -> String {
2057        let tp_part = if self.type_params.is_empty() {
2058            String::new()
2059        } else {
2060            format!("comptime {}: type, ", self.type_params.join(", comptime "))
2061        };
2062        let params: Vec<String> = self
2063            .params
2064            .iter()
2065            .map(|(n, t)| format!("{}: {}", n, t))
2066            .collect();
2067        format!(
2068            "fn {}({}{}){} {{\n    // body\n}}",
2069            self.name,
2070            tp_part,
2071            params.join(", "),
2072            self.return_type
2073        )
2074    }
2075}
2076/// The Zig code generation backend.
2077pub struct ZigBackend;
2078impl ZigBackend {
2079    /// Create a new ZigBackend.
2080    pub fn new() -> Self {
2081        ZigBackend
2082    }
2083    /// Emit source code for a complete Zig module.
2084    pub fn emit_module(&self, module: &ZigModule) -> String {
2085        module.codegen()
2086    }
2087    /// Emit source code for a single Zig function.
2088    pub fn emit_fn(&self, f: &ZigFn) -> String {
2089        f.codegen()
2090    }
2091    /// Emit source code for a single Zig struct.
2092    pub fn emit_struct(&self, s: &ZigStruct) -> String {
2093        s.codegen()
2094    }
2095    /// Sanitize an OxiLean name for use as a Zig identifier.
2096    ///
2097    /// Replaces dots and other special characters with underscores,
2098    /// prepends `ox_` if the name starts with a digit or is a Zig keyword.
2099    pub fn compile_name(oxilean_name: &str) -> String {
2100        let sanitized: String = oxilean_name
2101            .chars()
2102            .map(|c| {
2103                if c.is_alphanumeric() || c == '_' {
2104                    c
2105                } else {
2106                    '_'
2107                }
2108            })
2109            .collect();
2110        let result = if sanitized.is_empty() {
2111            "ox_empty".to_string()
2112        } else if sanitized
2113            .chars()
2114            .next()
2115            .map(|c| c.is_ascii_digit())
2116            .unwrap_or(false)
2117        {
2118            format!("ox_{}", sanitized)
2119        } else {
2120            sanitized
2121        };
2122        let zig_keywords = [
2123            "align",
2124            "allowzero",
2125            "and",
2126            "anyframe",
2127            "anytype",
2128            "asm",
2129            "async",
2130            "await",
2131            "break",
2132            "callconv",
2133            "catch",
2134            "comptime",
2135            "const",
2136            "continue",
2137            "defer",
2138            "else",
2139            "enum",
2140            "errdefer",
2141            "error",
2142            "export",
2143            "extern",
2144            "fn",
2145            "for",
2146            "if",
2147            "inline",
2148            "noalias",
2149            "noinline",
2150            "nosuspend",
2151            "opaque",
2152            "or",
2153            "orelse",
2154            "packed",
2155            "pub",
2156            "resume",
2157            "return",
2158            "struct",
2159            "suspend",
2160            "switch",
2161            "test",
2162            "threadlocal",
2163            "try",
2164            "union",
2165            "unreachable",
2166            "usingnamespace",
2167            "var",
2168            "volatile",
2169            "while",
2170        ];
2171        if zig_keywords.contains(&result.as_str()) {
2172            format!("ox_{}", result)
2173        } else {
2174            result
2175        }
2176    }
2177}
2178/// Configuration for ZigExt passes.
2179#[allow(dead_code)]
2180#[derive(Debug, Clone)]
2181pub struct ZigExtPassConfig {
2182    pub name: String,
2183    pub phase: ZigExtPassPhase,
2184    pub enabled: bool,
2185    pub max_iterations: usize,
2186    pub debug: u32,
2187    pub timeout_ms: Option<u64>,
2188}
2189impl ZigExtPassConfig {
2190    #[allow(dead_code)]
2191    pub fn new(name: impl Into<String>) -> Self {
2192        Self {
2193            name: name.into(),
2194            phase: ZigExtPassPhase::Middle,
2195            enabled: true,
2196            max_iterations: 100,
2197            debug: 0,
2198            timeout_ms: None,
2199        }
2200    }
2201    #[allow(dead_code)]
2202    pub fn with_phase(mut self, phase: ZigExtPassPhase) -> Self {
2203        self.phase = phase;
2204        self
2205    }
2206    #[allow(dead_code)]
2207    pub fn with_max_iter(mut self, n: usize) -> Self {
2208        self.max_iterations = n;
2209        self
2210    }
2211    #[allow(dead_code)]
2212    pub fn with_debug(mut self, d: u32) -> Self {
2213        self.debug = d;
2214        self
2215    }
2216    #[allow(dead_code)]
2217    pub fn disabled(mut self) -> Self {
2218        self.enabled = false;
2219        self
2220    }
2221    #[allow(dead_code)]
2222    pub fn with_timeout(mut self, ms: u64) -> Self {
2223        self.timeout_ms = Some(ms);
2224        self
2225    }
2226    #[allow(dead_code)]
2227    pub fn is_debug_enabled(&self) -> bool {
2228        self.debug > 0
2229    }
2230}
2231#[allow(dead_code)]
2232#[derive(Debug, Clone)]
2233pub struct ZigBuiltinFn {
2234    pub name: String,
2235    pub args: Vec<String>,
2236}
2237impl ZigBuiltinFn {
2238    #[allow(dead_code)]
2239    pub fn new(name: impl Into<String>) -> Self {
2240        ZigBuiltinFn {
2241            name: name.into(),
2242            args: Vec::new(),
2243        }
2244    }
2245    #[allow(dead_code)]
2246    pub fn arg(mut self, a: impl Into<String>) -> Self {
2247        self.args.push(a.into());
2248        self
2249    }
2250    #[allow(dead_code)]
2251    pub fn emit(&self) -> String {
2252        format!("@{}({})", self.name, self.args.join(", "))
2253    }
2254}