1use std::{rc::Rc, sync::RwLock};
2
3use spade_codespan_reporting::term::termcolor::Buffer;
4use spade_diagnostics::{diag_list::DiagList, CodeBundle, CompilationError, DiagHandler};
5
6pub struct ErrorHandler<'a> {
7 failed: bool,
8 failed_now: bool,
9 pub error_buffer: &'a mut Buffer,
10 pub diag_handler: DiagHandler,
11 pub code: Rc<RwLock<CodeBundle>>,
14}
15
16impl<'a> ErrorHandler<'a> {
17 pub fn new(
18 error_buffer: &'a mut Buffer,
19 diag_handler: DiagHandler,
20 code: Rc<RwLock<CodeBundle>>,
21 ) -> Self {
22 ErrorHandler {
23 failed: false,
24 failed_now: false,
25 error_buffer,
26 diag_handler,
27 code: Rc::clone(&code),
28 }
29 }
30
31 pub fn set_failed(&mut self) {
32 self.failed = true;
33 self.failed_now = true;
34 }
35
36 pub fn errors_are_recoverable(&mut self) {
37 self.failed_now = false;
38 }
39
40 pub fn failed(&self) -> bool {
41 self.failed
42 }
43
44 pub fn failed_now(&mut self) -> bool {
45 let result = self.failed_now;
46 self.failed_now = false;
47 result
48 }
49
50 pub fn report(&mut self, err: &impl CompilationError) {
51 self.failed = true;
52 self.failed_now = true;
53 err.report(
54 self.error_buffer,
55 &self.code.read().unwrap(),
56 &mut self.diag_handler,
57 );
58 }
59
60 pub fn drain_diag_list(&mut self, diag_list: &mut DiagList) {
61 for diag in diag_list.drain() {
62 self.report(&diag)
63 }
64 }
65}
66
67pub trait Reportable<T> {
68 fn or_report(self, errors: &mut ErrorHandler) -> Option<T>;
70
71 fn report(self, errors: &mut ErrorHandler) -> Self;
73}
74
75impl<T, E> Reportable<T> for Result<T, E>
76where
77 E: CompilationError,
78{
79 fn report(self, errors: &mut ErrorHandler) -> Self {
80 if let Err(e) = &self {
81 errors.report(e);
82 }
83 self
84 }
85
86 fn or_report(self, errors: &mut ErrorHandler) -> Option<T> {
87 self.report(errors).ok()
88 }
89}