1use crate::{
4 diagnostics::{Diagnostic, Validation},
5 groups::IRGroup,
6 printer::{IRPrintable, IRPrinter},
7 traits::{Canonicalize, ConstantFolding, Validatable},
8};
9
10#[derive(Debug)]
15pub struct IRCircuit<E, C> {
16 body: Vec<IRGroup<E>>,
17 context: C,
18}
19
20impl<E, C> IRCircuit<E, C> {
21 pub fn new(body: Vec<IRGroup<E>>, context: C) -> Self {
23 Self { body, context }
24 }
25
26 pub fn context(&self) -> &C {
28 &self.context
29 }
30
31 pub fn body(&self) -> &[IRGroup<E>] {
33 &self.body
34 }
35
36 pub fn body_mut(&mut self) -> &mut [IRGroup<E>] {
38 &mut self.body
39 }
40
41 pub fn take_body(self) -> Vec<IRGroup<E>> {
43 self.body
44 }
45
46 pub fn display(&self) -> IRPrinter<'_>
48 where
49 Self: IRPrintable,
50 {
51 IRPrinter::from(self)
52 }
53
54 pub fn main(&self) -> &IRGroup<E> {
58 self.body
60 .iter()
61 .rev()
62 .find(|g| g.is_main())
63 .expect("A main group is required")
64 }
65
66 }
97
98impl<E, C, D> Validatable for IRCircuit<E, C>
99where
100 IRGroup<E>: Validatable<Diagnostic = D, Context = [IRGroup<E>]>,
101 D: Diagnostic,
102{
103 type Diagnostic = D;
104
105 type Context = ();
106
107 fn validate_with_context(
108 &self,
109 _: &Self::Context,
110 ) -> Result<Vec<Self::Diagnostic>, Vec<Self::Diagnostic>> {
111 let mut validation = Validation::new();
112
113 for group in &self.body {
114 let header = format!("in group \"{}\"", group.name());
115 let result = group.validate_with_context(&self.body);
116 validation.append_from_result(result, &header);
117 }
118 validation.into()
119 }
120}
121
122impl<E, C, Err> ConstantFolding for IRCircuit<E, C>
123where
124 IRGroup<E>: ConstantFolding<Error = Err>,
125{
126 type Error = Err;
127
128 type T = ();
129
130 fn constant_fold(&mut self) -> Result<(), Self::Error> {
131 self.body.constant_fold()
132 }
133}
134
135impl<E, C> Canonicalize for IRCircuit<E, C>
136where
137 IRGroup<E>: Canonicalize,
138{
139 fn canonicalize(&mut self) {
140 self.body.canonicalize()
141 }
142}
143
144impl<E: IRPrintable, C: IRPrintable> IRPrintable for IRCircuit<E, C> {
145 fn fmt(&self, ctx: &mut crate::printer::IRPrinterCtx<'_, '_>) -> crate::printer::Result {
146 self.context().fmt(ctx)?;
147 for group in self.body() {
148 ctx.nl()?;
149 group.fmt(ctx)?;
150 }
151 Ok(())
152 }
153}