wolfram_error/errors/
mod.rs

1use diagnostic::{Diagnostic, FileID, FileSpan, ReportKind};
2use std::{
3    error::Error,
4    fmt::{Debug, Display, Formatter},
5    ops::Range,
6};
7
8pub type Result<T = ()> = std::result::Result<T, WolframError>;
9
10pub type Validation<T> = validatus::Validation<T, WolframError>;
11
12pub struct WolframError {
13    kind: Box<WolframErrorKind>,
14}
15
16impl WolframError {
17    /// Get the kind of the error
18    pub fn kind(&self) -> &WolframErrorKind {
19        &*self.kind
20    }
21
22    pub fn as_report(&self) -> Diagnostic {
23        match self.kind() {
24            WolframErrorKind::RuntimeError { message } => Diagnostic::new(ReportKind::Error).with_message(message).finish(),
25            WolframErrorKind::SyntaxError { message, location } => Diagnostic::new(ReportKind::Error)
26                .with_message(message)
27                .with_location(location.get_file(), Some(location.get_start()))
28                .finish(),
29        }
30    }
31}
32
33#[derive(Debug)]
34pub enum WolframErrorKind {
35    RuntimeError { message: String },
36    SyntaxError { message: String, location: FileSpan },
37}
38impl Error for WolframError {}
39
40impl Error for WolframErrorKind {}
41impl Debug for WolframError {
42    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
43        Debug::fmt(&self.kind, f)
44    }
45}
46
47impl Display for WolframError {
48    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
49        Display::fmt(&self.kind, f)
50    }
51}
52impl Display for WolframErrorKind {
53    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
54        match self {
55            WolframErrorKind::RuntimeError { message } => {
56                f.write_str("Runtime Error: ")?;
57                f.write_str(message)
58            }
59            WolframErrorKind::SyntaxError { message, location } => {
60                f.write_str("Syntax Error: ")?;
61                f.write_str(message)?;
62                f.write_str(" at ")?;
63                Debug::fmt(location, f)
64            }
65        }
66    }
67}
68
69impl From<WolframErrorKind> for WolframError {
70    fn from(value: WolframErrorKind) -> Self {
71        WolframError { kind: Box::new(value) }
72    }
73}
74
75impl WolframError {
76    /// Define a runtime error
77    pub fn runtime_error<S>(message: S) -> Self
78    where
79        S: ToString,
80    {
81        Self { kind: Box::new(WolframErrorKind::RuntimeError { message: message.to_string() }) }
82    }
83    /// Define a syntax error
84    pub fn syntax_error<S>(message: S) -> Self
85    where
86        S: ToString,
87    {
88        Self { kind: Box::new(WolframErrorKind::SyntaxError { message: message.to_string(), location: Default::default() }) }
89    }
90    /// Set the file where the error occurred
91    pub fn set_file(&mut self, file: FileID) {
92        self.kind.set_file(file)
93    }
94    /// Set the file where the error occurred
95    pub fn with_file(mut self, file: FileID) -> Self {
96        self.set_file(file);
97        self
98    }
99    /// Set the location where the error occurs
100    pub fn set_span(&mut self, range: Range<usize>) {
101        self.kind.set_span(range)
102    }
103    /// Set the location where the error occurs
104    pub fn with_span(mut self, range: Range<usize>) -> Self {
105        self.set_span(range);
106        self
107    }
108    /// Set the file and location where the error occurred
109    pub fn set_file_span(&mut self, span: FileSpan) {
110        self.kind.set_file_span(span)
111    }
112    /// Set the file and location where the error occurred
113    pub fn with_file_span(mut self, span: FileSpan) -> Self {
114        self.set_file_span(span);
115        self
116    }
117}
118
119impl WolframErrorKind {
120    /// Set the file where the error occurred
121
122    pub fn set_file(&mut self, file: FileID) {
123        match self {
124            Self::RuntimeError { .. } => {}
125            Self::SyntaxError { location: span, .. } => span.set_file(file),
126        }
127    }
128    /// Set the location where the error occurs
129
130    pub fn set_span(&mut self, range: Range<usize>) {
131        match self {
132            Self::RuntimeError { .. } => {}
133            Self::SyntaxError { location: span, .. } => span.set_range(range),
134        }
135    }
136    /// Set the file and location where the error occurred
137    pub fn set_file_span(&mut self, span: FileSpan) {
138        match self {
139            Self::RuntimeError { .. } => {}
140            Self::SyntaxError { location, .. } => *location = span,
141        }
142    }
143}