1#![feature(lint_reasons)]
4#![warn(
5 missing_docs,
6 unused_crate_dependencies,
7 unused_macro_rules,
8 variant_size_differences,
9 clippy::allow_attributes,
10 clippy::allow_attributes_without_reason,
11 clippy::expect_used,
12 clippy::indexing_slicing,
13 clippy::missing_docs_in_private_items,
14 clippy::multiple_inherent_impl,
15 clippy::panic,
16 clippy::pedantic,
17 clippy::str_to_string,
18 clippy::unreachable,
19 clippy::unwrap_used,
20 clippy::use_debug
21)]
22
23pub mod transparent;
24pub use transparent::Transparent;
25
26pub mod error;
27pub use error::*; pub type Span = Transparent<proc_macro2::Span>;
32
33#[macro_export]
35macro_rules! repo {
36 () => {
37 "https://github.com/Vanille-N/chandeliers"
38 };
39}
40
41#[macro_export]
43macro_rules! here {
44 () => {
45 concat!(file!(), ":", line!(), ":", column!())
46 };
47}
48
49#[macro_export]
51macro_rules! abort {
52 ($($err:tt)*) => {{
53 std::panic!("
54Chandeliers panicked: \x1b[1;31m{}.\x1b[0m
55This error occured in \x1b[1;35m{}\x1b[0m
56
57If you are not a developper of Chandeliers and you see this message then this is a bug.
58I'd be grateful if you could report this error at \x1b[33m{}\x1b[0m
59with the code that produced it and the version of Chandeliers you are using.
60",
61 format!($($err)*),
62 $crate::here!(),
63 $crate::repo!(),
64 );
65 }};
66}
67
68#[macro_export]
70macro_rules! malformed {
71 () => {{
72 ::chandeliers_err::abort!("Entered unreachable code");
73 }};
74}
75
76#[macro_export]
78macro_rules! consistency {
79 ($cond:expr, $($msg:tt)*) => {{
80 if !$cond {
81 ::chandeliers_err::abort!($($msg)*);
82 }
83 }};
84}
85
86#[derive(Default)]
90pub struct EAccum {
91 err: Vec<Error>,
93 warn: Vec<Error>,
95}
96
97pub struct EAccumScope<'a> {
112 acc: &'a mut EAccum,
114 fatal: bool,
118}
119
120impl EAccum {
121 pub fn error<T, E: IntoError>(&mut self, e: E) -> Option<T> {
125 self.err.push(e.into_err());
126 None
127 }
128
129 pub fn warning<E: IntoError>(&mut self, e: E) {
131 self.warn.push(e.into_err());
132 }
133
134 #[must_use]
136 pub fn is_fatal(&self) -> bool {
137 !self.err.is_empty()
138 }
139
140 #[must_use]
142 pub fn fetch(self) -> (Vec<Error>, Vec<Error>) {
143 (self.err, self.warn)
144 }
145
146 pub fn scope(&mut self) -> EAccumScope {
148 EAccumScope {
149 acc: self,
150 fatal: false,
151 }
152 }
153}
154
155impl<'a> EAccumScope<'a> {
156 pub fn compute<F>(&mut self, f: F)
158 where
159 F: FnOnce(&mut EAccum) -> Option<()>,
160 {
161 let e = f(&mut *self.acc);
162 if e.is_none() {
163 self.fatal = true;
164 }
165 }
166
167 #[must_use]
170 pub fn close(self) -> Option<()> {
171 if self.fatal {
172 None
173 } else {
174 Some(())
175 }
176 }
177
178 pub fn error<E: IntoError>(&mut self, e: E) {
180 self.compute(|acc| acc.error(e));
181 }
182
183 pub fn warning<E: IntoError>(&mut self, e: E) {
185 self.compute(|acc| {
186 acc.warning(e);
187 Some(())
188 });
189 }
190}