use std::error::Error;
use std::fmt::{Display, Formatter};
use anyhow::anyhow;
use thiserror::Error;
use crate::types::Type;
#[derive(Error, Debug)]
#[error("This function def cannot bind its arguments: {0}")]
pub struct MatchTestFailure(pub Box<dyn Error + Send + Sync + 'static>);
impl MatchTestFailure {
pub fn msg(msg: &str) -> Self {
Self(anyhow!(msg.to_string()).into())
}
pub fn wrap(e: impl Error + Send + Sync + 'static) -> Self {
Self(Box::new(e))
}
}
#[derive(Error, Debug)]
pub enum FunctionParameterBindingFailure {
#[error("Attempted to bind a named parameter not present in the function def: {0}")]
UnknownNamedParameter(String),
#[error("Attempted to bind {got} positional arguments; expected only {expected}")]
TooManyPositionalArguments { expected: usize, got: usize },
#[error("Missing required argument: {0}")]
MissingRequiredArgument(String),
#[error("Type mismatch for {name}: expected {expected}, got {got}")]
TypeCheckFailure {
name: String,
expected: String,
got: Type,
},
#[error("Type mismatch for varargs: expected {expected}, got {got}")]
TypeCheckFailureForVarargs { expected: String, got: Type },
#[error("{0}")]
DoesNotMatch(Box<dyn Error + Send + Sync>),
}
#[derive(Error, Debug)]
pub struct FunctionParameterBindingFailures(pub Vec<FunctionParameterBindingFailure>);
impl Display for FunctionParameterBindingFailures {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
for failure in &self.0 {
write!(f, " - {}\n", failure)?;
}
Ok(())
}
}
#[derive(Error, Debug)]
pub enum FunctionBindFailure {
#[error(transparent)]
ParameterBindingFailures(FunctionParameterBindingFailures),
#[error("Fatal failure during type matching: {0}")]
Fatal(Box<dyn Error + Send + Sync + 'static>),
}
#[derive(Error, Debug)]
pub enum FunctionTranslationFailure {
#[error("Fatal failure during type matching: {0}")]
Fatal(Box<dyn Error + Send + Sync + 'static>),
}
#[derive(Error, Debug)]
#[error("Attempted {function_def}\n{binding_failures}")]
pub struct ApplyAttempt {
pub function_def: String,
pub binding_failures: FunctionParameterBindingFailures,
}
#[derive(Error, Debug)]
pub struct ApplyFailure(pub Vec<ApplyAttempt>);
impl Display for ApplyFailure {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
for attempt in self.0.iter() {
write!(f, "{}\n", attempt)?;
}
Ok(())
}
}
#[derive(Error, Debug)]
#[error(
r#"No binding for parameter {name}
This is likely a bug in a FunctionDef implementation. When accessing this class in a lambda
passed to `return_type`, you should only access the parameters defined in `parameters()`.
"#
)]
pub struct NoBindingError {
pub name: String,
}