calyx_opt/traversal/
diagnostics.rs

1use calyx_utils::{CalyxResult, Error};
2
3use super::{Action, VisResult};
4
5/// A pass that implements reporting Diagnostics
6pub trait DiagnosticPass {
7    /// Return an iterator of the diagnostics gathered by this pass.
8    fn diagnostics(&self) -> &DiagnosticContext;
9}
10
11/// A type for accumulating multiple errors
12#[derive(Default, Debug)]
13pub struct DiagnosticContext {
14    errors: Vec<Error>,
15    warnings: Vec<Error>,
16}
17
18impl DiagnosticContext {
19    /// Report an `error`
20    pub fn err(&mut self, error: Error) {
21        self.errors.push(error);
22    }
23
24    /// Report a `warning`
25    pub fn warning(&mut self, warning: Error) {
26        self.warnings.push(warning)
27    }
28
29    /// Accumulates `error` into the context, and returns `Ok(Action::Continue)`.
30    /// This is useful for when we need to raise an Error because we couldn't
31    /// construct some value that we needed to continue the computation.
32    pub fn early_return_err(&mut self, error: Error) -> VisResult {
33        self.err(error);
34        Ok(Action::Continue)
35    }
36
37    pub fn warning_iter(&self) -> impl Iterator<Item = &Error> {
38        self.warnings.iter()
39    }
40
41    pub fn errors_iter(&self) -> impl Iterator<Item = &Error> {
42        self.errors.iter()
43    }
44}
45
46/// Accumuate the error in a [`Result`] type into the [`DiagnosticContext`].
47pub trait DiagnosticResult {
48    fn accumulate_err(self, diag: &mut DiagnosticContext) -> Self;
49}
50
51impl<T> DiagnosticResult for CalyxResult<T>
52where
53    T: Default,
54{
55    fn accumulate_err(self, diag: &mut DiagnosticContext) -> Self {
56        match self {
57            Ok(act) => Ok(act),
58            Err(err) => {
59                diag.err(err);
60                Ok(T::default())
61            }
62        }
63    }
64}
65
66impl DiagnosticResult for VisResult {
67    fn accumulate_err(self, diag: &mut DiagnosticContext) -> Self {
68        match self {
69            Ok(act) => Ok(act),
70            Err(err) => {
71                diag.err(err);
72                Ok(Action::Continue)
73            }
74        }
75    }
76}