use probl_syntax::{Diagnostic, Span};
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum ErrorKind {
Language,
Unsupported,
Limit,
Internal,
}
#[derive(Clone, Debug, PartialEq)]
pub struct OpError {
pub message: String,
pub help: Option<String>,
pub kind: ErrorKind,
}
impl OpError {
pub fn new(message: impl Into<String>) -> OpError {
OpError {
message: message.into(),
help: None,
kind: ErrorKind::Language,
}
}
pub fn unsupported(message: impl Into<String>) -> OpError {
OpError {
kind: ErrorKind::Unsupported,
..OpError::new(message)
}
}
pub fn limit(message: impl Into<String>) -> OpError {
OpError {
kind: ErrorKind::Limit,
..OpError::new(message)
}
}
pub fn internal(message: impl Into<String>) -> OpError {
OpError {
kind: ErrorKind::Internal,
..OpError::new(message)
}
.help("this is a bug in Probl; please report it with the program that caused it")
}
pub fn help(mut self, help: impl Into<String>) -> OpError {
self.help = Some(help.into());
self
}
pub fn at(self, span: Span) -> RuntimeError {
RuntimeError {
message: self.message,
span,
notes: Vec::new(),
help: self.help,
kind: self.kind,
}
}
}
pub type OpResult<T> = std::result::Result<T, OpError>;
impl From<probl_number::IntError> for OpError {
fn from(error: probl_number::IntError) -> Self {
match error {
probl_number::IntError::TooLarge => Self::limit(error.to_string()),
_ => Self::new(error.to_string()),
}
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct RuntimeError {
pub message: String,
pub span: Span,
pub notes: Vec<String>,
pub help: Option<String>,
pub kind: ErrorKind,
}
impl RuntimeError {
pub fn new(span: Span, message: impl Into<String>) -> RuntimeError {
OpError::new(message).at(span)
}
pub fn limit(span: Span, message: impl Into<String>) -> RuntimeError {
OpError::limit(message).at(span)
}
pub fn with_note(mut self, note: impl Into<String>) -> RuntimeError {
self.notes.push(note.into());
self
}
pub fn with_help(mut self, help: impl Into<String>) -> RuntimeError {
self.help = Some(help.into());
self
}
pub fn to_diagnostic(&self) -> Diagnostic {
let mut d = Diagnostic::error(self.span, &self.message);
d.notes = self.notes.clone();
d.help = self.help.clone();
d
}
}
pub type Result<T> = std::result::Result<T, RuntimeError>;