use crate::prelude::*;
use std::fmt;
#[derive(Debug)]
pub enum RuntimeError {
ArithmeticError(RuntimeErrorStruct),
NewFactError(RuntimeErrorStruct),
StoreFactError(RuntimeErrorStruct),
ParseError(RuntimeErrorStruct),
ExecStmtError(RuntimeErrorStruct),
WellDefinedError(RuntimeErrorStruct),
VerifyError(RuntimeErrorStruct),
UnknownError(RuntimeErrorStruct),
InferError(RuntimeErrorStruct),
NameAlreadyUsedError(RuntimeErrorStruct),
DefineParamsError(RuntimeErrorStruct),
InstantiateError(RuntimeErrorStruct),
}
#[derive(Debug)]
pub struct RuntimeErrorStruct {
pub statement: Option<Stmt>,
pub msg: String,
pub line_file: LineFile,
pub previous_error: Option<Box<RuntimeError>>,
pub inside_results: Vec<StmtResult>,
}
macro_rules! runtime_error_wrapper {
($($wrapper:ident => $variant:ident),* $(,)?) => {
$(
#[derive(Debug)]
pub struct $wrapper(pub RuntimeErrorStruct);
impl From<$wrapper> for RuntimeError {
fn from(w: $wrapper) -> Self {
RuntimeError::$variant(w.0)
}
}
)*
};
}
runtime_error_wrapper! {
ArithmeticRuntimeError => ArithmeticError,
NewFactRuntimeError => NewFactError,
StoreFactRuntimeError => StoreFactError,
ParseRuntimeError => ParseError,
WellDefinedRuntimeError => WellDefinedError,
VerifyRuntimeError => VerifyError,
UnknownRuntimeError => UnknownError,
InferRuntimeError => InferError,
NameAlreadyUsedRuntimeError => NameAlreadyUsedError,
DefineParamsRuntimeError => DefineParamsError,
InstantiateRuntimeError => InstantiateError,
}
impl RuntimeErrorStruct {
pub fn new(
statement: Option<Stmt>,
msg: String,
line_file: LineFile,
previous_error: Option<RuntimeError>,
inside_results: Vec<StmtResult>,
) -> Self {
RuntimeErrorStruct {
statement,
msg,
line_file,
previous_error: previous_error.map(Box::new),
inside_results,
}
}
}
pub fn short_exec_error(
stmt: Stmt,
message: impl Into<String>,
cause: Option<RuntimeError>,
inside_results: Vec<StmtResult>,
) -> RuntimeError {
let message = message.into();
let line_file = stmt.line_file();
RuntimeError::ExecStmtError(RuntimeErrorStruct::new(
Some(stmt.clone()),
message,
line_file.clone(),
cause,
inside_results,
))
}
impl std::error::Error for RuntimeError {}
impl RuntimeError {
pub fn wrap_new_fact_as_store_conflict(e: RuntimeError) -> RuntimeError {
match e {
RuntimeError::NewFactError(s) => NewFactRuntimeError(RuntimeErrorStruct::new(
s.statement.clone(),
s.msg.clone(),
s.line_file.clone(),
Some(NewFactRuntimeError(s).into()),
vec![],
))
.into(),
_ => e,
}
}
pub fn line_file(&self) -> LineFile {
match self {
RuntimeError::ArithmeticError(e) => e.line_file.clone(),
RuntimeError::NewFactError(e) => e.line_file.clone(),
RuntimeError::StoreFactError(e) => e.line_file.clone(),
RuntimeError::ParseError(e) => e.line_file.clone(),
RuntimeError::ExecStmtError(e) => e.line_file.clone(),
RuntimeError::WellDefinedError(e) => e.line_file.clone(),
RuntimeError::VerifyError(e) => e.line_file.clone(),
RuntimeError::UnknownError(e) => e.line_file.clone(),
RuntimeError::InferError(e) => e.line_file.clone(),
RuntimeError::NameAlreadyUsedError(e) => e.line_file.clone(),
RuntimeError::DefineParamsError(e) => e.line_file.clone(),
RuntimeError::InstantiateError(e) => e.line_file.clone(),
}
}
pub fn display_label(&self) -> &'static str {
match self {
RuntimeError::ArithmeticError(_) => "ArithmeticError",
RuntimeError::NewFactError(_) => "NewFactError",
RuntimeError::StoreFactError(_) => "StoreFactError",
RuntimeError::ParseError(_) => "ParseError",
RuntimeError::ExecStmtError(_) => "ExecStmtError",
RuntimeError::WellDefinedError(_) => "WellDefinedError",
RuntimeError::VerifyError(_) => "VerifyError",
RuntimeError::UnknownError(_) => "UnknownError",
RuntimeError::InferError(_) => "InferError",
RuntimeError::NameAlreadyUsedError(_) => "NameAlreadyUsedError",
RuntimeError::DefineParamsError(_) => "DefineParamsError",
RuntimeError::InstantiateError(_) => "InstantiateError",
}
}
}
impl fmt::Display for RuntimeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", "error")
}
}
impl fmt::Display for RuntimeErrorStruct {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.msg)
}
}
impl std::error::Error for RuntimeErrorStruct {}
impl RuntimeErrorStruct {
pub fn new_with_just_msg(msg: String) -> Self {
Self::new(None, msg, default_line_file(), None, vec![])
}
pub fn new_with_msg_and_line_file(msg: String, line_file: LineFile) -> Self {
Self::new(None, msg, line_file, None, vec![])
}
pub fn new_with_msg_and_cause(msg: String, cause: RuntimeError) -> Self {
Self::new(None, msg, default_line_file(), Some(cause), vec![])
}
}