1use crate::{GPosIdx, Id, WithPos};
3
4pub type CalyxResult<T> = std::result::Result<T, Error>;
6
7pub struct Error {
9 kind: Box<ErrorKind>,
10 pos: GPosIdx,
11 post_msg: Option<String>,
12}
13
14impl std::fmt::Debug for Error {
15 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
16 if self.pos == GPosIdx::UNKNOWN {
17 write!(f, "{}", self.kind)?
18 } else {
19 write!(f, "{}", self.pos.format(self.kind.to_string()))?
20 }
21 if let Some(post) = &self.post_msg {
22 write!(f, "\n{}", post)?;
23 }
24 Ok(())
25 }
26}
27
28impl Error {
29 pub fn with_pos<T: WithPos>(mut self, pos: &T) -> Self {
30 self.pos = pos.copy_span();
31 self
32 }
33
34 pub fn with_post_msg(mut self, msg: Option<String>) -> Self {
35 self.post_msg = msg;
36 self
37 }
38
39 pub fn reserved_name(name: Id) -> Self {
40 Self {
41 kind: Box::new(ErrorKind::ReservedName(name)),
42 pos: GPosIdx::UNKNOWN,
43 post_msg: None,
44 }
45 }
46 pub fn malformed_control<S: ToString>(msg: S) -> Self {
47 Self {
48 kind: Box::new(ErrorKind::MalformedControl(msg.to_string())),
49 pos: GPosIdx::UNKNOWN,
50 post_msg: None,
51 }
52 }
53 pub fn malformed_structure<S: ToString>(msg: S) -> Self {
54 Self {
55 kind: Box::new(ErrorKind::MalformedStructure(msg.to_string())),
56 pos: GPosIdx::UNKNOWN,
57 post_msg: None,
58 }
59 }
60 pub fn pass_assumption<S: ToString, M: ToString>(pass: S, msg: M) -> Self {
61 Self {
62 kind: Box::new(ErrorKind::PassAssumption(
63 pass.to_string(),
64 msg.to_string(),
65 )),
66 pos: GPosIdx::UNKNOWN,
67 post_msg: None,
68 }
69 }
70 pub fn undefined<S: ToString>(name: Id, typ: S) -> Self {
71 Self {
72 kind: Box::new(ErrorKind::Undefined(name, typ.to_string())),
73 pos: GPosIdx::UNKNOWN,
74 post_msg: None,
75 }
76 }
77 pub fn already_bound<S: ToString>(name: Id, typ: S) -> Self {
78 Self {
79 kind: Box::new(ErrorKind::AlreadyBound(name, typ.to_string())),
80 pos: GPosIdx::UNKNOWN,
81 post_msg: None,
82 }
83 }
84 pub fn unused<S: ToString>(group: Id, typ: S) -> Self {
85 Self {
86 kind: Box::new(ErrorKind::Unused(group, typ.to_string())),
87 pos: GPosIdx::UNKNOWN,
88 post_msg: None,
89 }
90 }
91 pub fn papercut<S: ToString>(msg: S) -> Self {
92 Self {
93 kind: Box::new(ErrorKind::Papercut(msg.to_string())),
94 pos: GPosIdx::UNKNOWN,
95 post_msg: None,
96 }
97 }
98 pub fn misc<S: ToString>(msg: S) -> Self {
99 Self {
100 kind: Box::new(ErrorKind::Misc(msg.to_string())),
101 pos: GPosIdx::UNKNOWN,
102 post_msg: None,
103 }
104 }
105 pub fn invalid_file<S: ToString>(msg: S) -> Self {
106 Self {
107 kind: Box::new(ErrorKind::InvalidFile(msg.to_string())),
108 pos: GPosIdx::UNKNOWN,
109 post_msg: None,
110 }
111 }
112 pub fn write_error<S: ToString>(msg: S) -> Self {
113 Self {
114 kind: Box::new(ErrorKind::WriteError(msg.to_string())),
115 pos: GPosIdx::UNKNOWN,
116 post_msg: None,
117 }
118 }
119 pub fn location(&self) -> (&str, usize, usize) {
120 self.pos.get_location()
121 }
122 pub fn message(&self) -> String {
123 self.kind.to_string()
124 }
125}
126
127enum ErrorKind {
129 ReservedName(Id),
131
132 MalformedControl(String),
134 MalformedStructure(String),
136
137 PassAssumption(String, String),
139
140 Undefined(Id, String),
142 AlreadyBound(Id, String),
144
145 Unused(Id, String),
147
148 Papercut(String),
150
151 Misc(String),
154 InvalidFile(String),
156 WriteError(String),
158}
159
160impl std::fmt::Display for ErrorKind {
161 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
162 use ErrorKind::*;
163 match self {
164 Papercut(msg) => {
165 write!(f, "[Papercut] {}", msg)
166 }
167 Unused(name, typ) => {
168 write!(f, "Unused {typ} `{name}'")
169 }
170 AlreadyBound(name, bound_by) => {
171 write!(f, "Name `{name}' already bound by {bound_by}")
172 }
173 ReservedName(name) => {
174 write!(f, "Use of reserved keyword: {name}")
175 }
176 Undefined(name, typ) => {
177 write!(f, "Undefined {typ} name: {name}")
178 }
179 MalformedControl(msg) => write!(f, "Malformed Control: {msg}"),
180 PassAssumption(pass, msg) => {
181 write!(f, "Pass `{pass}` assumption violated: {msg}")
182 }
183 MalformedStructure(msg) => {
184 write!(f, "Malformed Structure: {msg}")
185 }
186 InvalidFile(msg) | WriteError(msg) | Misc(msg) => {
187 write!(f, "{msg}")
188 }
189 }
190 }
191}
192
193impl From<std::str::Utf8Error> for Error {
196 fn from(err: std::str::Utf8Error) -> Self {
197 Error::invalid_file(err.to_string())
198 }
199}
200
201impl From<std::io::Error> for Error {
202 fn from(e: std::io::Error) -> Self {
203 Error::write_error(format!("IO Error: {}", e))
204 }
205}
206
207impl From<serde_json::Error> for Error {
208 fn from(e: serde_json::Error) -> Self {
209 Error::write_error(format!("serde_json Error: {}", e))
210 }
211}