use core::fmt;
use std::{rc::Rc, path::{PathBuf, Path}};
use crate::{lexer::lexer_error::LexerError, LexerInfo, static_scheme::scheme::{Procedure, ForegnProc}, Serializator, DynEnvironment};
use super::environment::DynValue;
pub enum DynamicSchemeErrorType
{
DynUnknownSerializator
{
ser_name: String
},
DynNotEnoughArgs
{
li: LexerInfo,
missing_arg_name: Rc<String>,
proc: Rc<Procedure>,
},
DynLexerError
{
err: LexerError,
},
DynArgResolveError
{
path: Vec<String>,
missing_item: String,
proc: Rc<Procedure>,
},
DynProcResolveError
{
path: Vec<String>,
missing_item: String,
proc: Rc<Procedure>,
},
DynDuplicateItem
{
scheme: Rc<Serializator>,
key: Rc<String>,
val: String,
},
DynRootProcNotDefined
{
scheme: Rc<Serializator>
},
DynUnknownProcedure
{
li: LexerInfo,
root_proc_name: Rc<Procedure>,
unkn_proc_name: Rc<Procedure>,
scheme: Rc<Serializator>
},
DynRepeatedProcedure
{
li: LexerInfo,
root_proc_name: Rc<Procedure>,
unkn_proc_name: Rc<Procedure>,
scheme: Rc<Serializator>
},
DynUnexpectedItem
{
li: LexerInfo,
trace: DynValue,
scheme: Rc<Serializator>
},
DynProcedureError
{
li: LexerInfo,
root_proc_name: Rc<Procedure>,
proc: Rc<ForegnProc>,
scheme: Rc<Serializator>
},
DynSymbolNotFound
{
symb_name: String,
li: LexerInfo,
trace: DynValue,
env: Rc<DynEnvironment>
},
DynListEmpty
{
li: LexerInfo,
trace: Option<DynValue>,
env: Rc<DynEnvironment>
},
DynArgsProblem
{
li: LexerInfo,
trace: Option<DynValue>,
env: Rc<DynEnvironment>
},
DynUnexpectedType
{
li: LexerInfo,
trace: DynValue,
},
DynNotAnItemEnum
{
li: LexerInfo,
trace: DynValue,
symb_dyn_val: DynValue,
proc_name: Rc<String>,
define: String,
},
DynEnumMismatch
{
li: LexerInfo,
trace: DynValue,
symb_dyn_val: DynValue,
proc_name: Rc<String>,
define: String,
},
DynIncorrectRange
{
li: LexerInfo,
proc_name: Rc<String>,
},
DynDefineNotInProcScope
{
li: LexerInfo,
proc_name: Rc<String>,
trace: DynValue,
},
DynAutoArgIncompType
{
li: LexerInfo,
proc_name: Rc<String>,
trace: DynValue,
},
DynDefineDataTypeMismatch
{
li: LexerInfo,
proc_name: Rc<String>,
trace: DynValue,
},
DynSymbolDatatypeMismatch
{
li: LexerInfo,
trace: DynValue,
proc_name: Rc<String>,
},
DynIncorrectArgDataType
{
li: LexerInfo,
trace: DynValue,
proc_name: Rc<String>,
},
DynNonEmptyProc
{
li: LexerInfo,
proc: Rc<Procedure>,
env: Rc<DynEnvironment>,
trace: DynValue
}
}
impl fmt::Display for DynamicSchemeErrorType
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
match self
{
Self::DynUnknownSerializator{ ser_name } =>
{
write!(f, "[DynUnknownSerializator] serializator: '{}'", ser_name)
},
Self::DynNotEnoughArgs
{ li, missing_arg_name, proc } =>
{
write!(f, "[DynNotEnoughArgs] near: '{}', argument name: '{}', in procedure: '{}'",
li, missing_arg_name, proc.get_name())
},
Self::DynLexerError { err } =>
{
write!(f, "[lexer error intercepted]: '{}'", err)
},
Self::DynArgResolveError { path, missing_item, proc } =>
{
write!(f, "[DynArgResolveError] a path to item: '{}', path item: '{}', in procedure: '{}'",
path.join("::"), missing_item, proc.get_name())
},
Self::DynProcResolveError { path, missing_item, proc } =>
{
write!(f, "[DynProcResolveError] a path to item: '{}', path item: '{}', in procedure: '{}'",
path.join("::"), missing_item, proc.get_name())
},
Self::DynDuplicateItem{ scheme, key, val } =>
{
write!(f, "[DynDuplicateItem] in scheme: '{}', key: '{}', value: '{}'",
scheme.get_name(), key, val)
},
Self::DynRootProcNotDefined{ scheme } =>
{
write!(f, "[DynRootProcNotDefined] in scheme: '{}'",
scheme.get_name())
},
Self::DynUnknownProcedure{ li, root_proc_name, unkn_proc_name, scheme } =>
{
write!(f, "[DynUnknownProcedure] in scheme: '{}', root procedure: '{}', unknown procedure: '{}', near: '{}'",
scheme.get_name(), root_proc_name.get_name(), unkn_proc_name.get_name(), li)
},
Self::DynRepeatedProcedure{ li, root_proc_name, unkn_proc_name, scheme } =>
{
write!(f, "[DynRepeatedProcedure] in scheme: '{}', root procedure: '{}', repeated procedure: '{}', near: '{}'",
scheme.get_name(), root_proc_name.get_name(), unkn_proc_name.get_name(), li)
},
Self::DynUnexpectedItem{ li, trace, scheme } =>
{
write!(f, "[DynUnexpectedItem] in scheme: '{}', near: '{}', trace: '{}'",
scheme.get_name(), li, trace)
},
Self::DynProcedureError { li, root_proc_name, proc, scheme } =>
{
write!(f, "[DynProcedureError] in scheme: '{}', root procedure: '{}', missing non-optional proc: '{}', near: '{}'",
scheme.get_name(), root_proc_name.get_name(), proc.get_label(), li)
},
Self::DynSymbolNotFound{ symb_name, li, trace, env } =>
{
write!(f, "[DynSymbolNotFound] in environment: '{}', symbol name: '{}', near: '{}', trace: {}",
env.get_scheme().get_name(), symb_name, li, trace)
},
Self::DynListEmpty{ li, trace, env } =>
{
write!(f, "[DynListEmpty] in environment: '{}', near: '{}', trace: {}",
env.get_scheme().get_name(), li, trace.as_ref().map_or("N/A".to_string(), |f| f.to_string()))
},
Self::DynArgsProblem { li, trace, env } =>
{
write!(f, "[DynArgsProblem] in environment: '{}', near: '{}', trace: {}",
env.get_scheme().get_name(), li, trace.as_ref().map_or("N/A".to_string(), |f| f.to_string()))
},
Self::DynUnexpectedType{ li, trace } =>
{
write!(f, "[DynUnexpectedType] near: '{}', trace: {}",
li, trace)
},
Self::DynNotAnItemEnum{ li, trace, symb_dyn_val, proc_name, define } =>
{
write!(f, "[DynNotAnItemEnum] near: '{}', proc name: '{}', symbol val: '{}', define item: '{}', trace: '{}'",
li, proc_name, symb_dyn_val, define, trace)
},
Self::DynEnumMismatch{ li, trace, symb_dyn_val, proc_name, define } =>
{
write!(f, "[DynEnumMismatch] near: '{}', proc name: '{}', symbol val: '{}', define item: '{}', trace: '{}'",
li, proc_name, symb_dyn_val, define, trace)
},
Self::DynIncorrectRange{ li, proc_name } =>
{
write!(f, "[DynIncorrectRange] near: '{}', proc name: '{}'",
li, proc_name)
},
Self::DynDefineNotInProcScope{ li, proc_name, trace } =>
{
write!(f, "[DynDefineNotInProcScope] near: '{}', proc name: '{}', trace: {}",
li, proc_name, trace)
},
Self::DynAutoArgIncompType{ li, proc_name, trace } =>
{
write!(f, "[DynAutoArgIncompType] near: '{}', proc name: '{}', trace: {}",
li, proc_name, trace)
},
Self::DynDefineDataTypeMismatch{ li, proc_name, trace } =>
{
write!(f, "[DynDefineDataTypeMismatch] near: '{}', proc name: '{}', trace: {}",
li, proc_name, trace)
},
Self::DynSymbolDatatypeMismatch{ li, trace, proc_name } =>
{
write!(f, "[DynSymbolDatatypeMismatch] near: '{}', proc name: '{}', trace: '{}'",
li, proc_name, trace)
},
Self::DynIncorrectArgDataType{ li, trace, proc_name } =>
{
write!(f, "[DynIncorrectArgDataType] near: '{}', proc name: '{}', trace: '{}'",
li, proc_name, trace)
},
Self::DynNonEmptyProc{ li, proc, env, trace } =>
{
write!(f, "[DynNonEmptyProc] near: '{}', proc name: '{}', trace: '{}', env: '{}'",
li, proc.get_name(), trace, env.get_scheme().get_name())
}
}
}
}
pub struct DynamicSchemeError
{
filename: Option<PathBuf>,
err_type: DynamicSchemeErrorType,
msg: String,
}
impl DynamicSchemeError
{
pub
fn new(filename: Option<PathBuf>, err_type: DynamicSchemeErrorType, msg: String) -> Self
{
return
Self
{
filename,
err_type,
msg
};
}
pub
fn new_lexer(err: LexerError) -> Self
{
return
Self
{
filename: None,
err_type: DynamicSchemeErrorType::DynLexerError{ err },
msg: String::new()
};
}
pub
fn concat_error_msg(&mut self, msg: String)
{
self.msg = [self.msg.as_str(), " ", msg.as_str()].concat();
}
pub
fn set_filename<P>(&mut self, filename: P)
where P: AsRef<Path>
{
self.filename = Some(filename.as_ref().to_path_buf());
}
}
impl From<LexerError> for DynamicSchemeError
{
fn from(err: LexerError) -> DynamicSchemeError
{
return
DynamicSchemeError::new_lexer(err);
}
}
impl fmt::Display for DynamicSchemeError
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
{
write!(f, "[dynamic_scheme] file: '{}', error: '{}', ",
self.filename.as_ref().map_or("unknown".to_string(), |f| f.display().to_string()), self.err_type)?;
write!(f, "{}", self.msg)
}
}
impl fmt::Debug for DynamicSchemeError
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
{
write!(f, "[dynamic_scheme] file: '{}', error: '{}', ",
self.filename.as_ref().map_or("unknown".to_string(), |f| f.display().to_string()), self.err_type)?;
write!(f, "{}", self.msg)
}
}
pub type DynamicSchemeRes<T> = Result<T, DynamicSchemeError>;
#[macro_export]
macro_rules! dyn_error_return
{
($err_type:expr, $($arg:tt)*) =>
{
return Err($crate::dynamic_scheme::error::DynamicSchemeError::new(None, $err_type, format!($($arg)*)));
};
}
#[macro_export]
macro_rules! dyn_error_map
{
($err_type:expr, $($arg:tt)*) =>
{
$crate::dynamic_scheme::error::DynamicSchemeError::new(None, $err_type, format!($($arg)*))
};
}