use ariadne::Fmt;
use cas_attrs::ErrorKind;
use cas_error::EXPR;
use cas_parser::parser::token::op::{BinOpKind, UnaryOpKind};
#[derive(Debug, Clone, ErrorKind, PartialEq)]
#[error(
message = format!("cannot apply the `{:?}` operator to these operands", self.op),
labels = [
format!("this operand has type `{}`", self.left),
format!("this {}operator", if self.implicit { "(implicit) " } else { "" }),
format!("this operand has type `{}`", self.right),
],
)]
pub struct InvalidBinaryOperation {
pub op: BinOpKind,
pub implicit: bool,
pub left: &'static str,
pub right: &'static str,
}
#[derive(Debug, Clone, ErrorKind, PartialEq)]
#[error(
message = format!("cannot apply the `{:?}` operator to this operand", self.op),
labels = [
format!("this operand has type `{}`", self.expr_type),
"this operator".to_string(),
],
)]
pub struct InvalidUnaryOperation {
pub op: UnaryOpKind,
pub expr_type: &'static str,
}
#[derive(Debug, Clone, ErrorKind, PartialEq)]
#[error(
message = "maximum bitshift amount exceeded",
labels = ["this expression", "", "too many bits to shift by"],
help = "the maximum number of bits you can shift an integer by is equal to: `2^64 - 1`"
)]
pub struct BitshiftOverflow;
#[derive(Debug, Clone, ErrorKind, PartialEq)]
#[error(
message = format!("`{}` is not defined", self.name),
labels = ["this variable"],
help = format!("to define it, type: {} = {}", (&self.name).fg(EXPR), "<expression>".fg(EXPR)),
)]
pub struct UndefinedVariable {
pub name: String,
}
#[derive(Debug, Clone, ErrorKind, PartialEq)]
#[error(
message = format!("the `{}` function does not exist", self.name),
labels = ["this function"],
help = if self.suggestions.is_empty() {
"see the documentation for a list of available functions".to_string()
} else if self.suggestions.len() == 1 {
format!("did you mean the `{}` function?", (&*self.suggestions[0]).fg(EXPR))
} else {
format!(
"did you mean one of these functions? {}",
self.suggestions
.iter()
.map(|s| format!("`{}`", s.fg(EXPR)))
.collect::<Vec<_>>()
.join(", ")
)
}
)]
pub struct UndefinedFunction {
pub name: String,
pub suggestions: Vec<String>,
}
#[derive(Debug, Clone, ErrorKind, PartialEq)]
#[error(
message = format!("too many arguments were given to the `{}` function", self.name),
labels = ["this function call", ""],
help = format!(
"the `{}` function takes {} argument(s); there are {} argument(s) provided here",
(&self.name).fg(EXPR),
self.expected,
self.given
),
note = format!("function signature: {}", self.signature),
)]
pub struct TooManyArguments {
pub name: String,
pub expected: usize,
pub given: usize,
pub signature: String,
}
#[derive(Debug, Clone, ErrorKind, PartialEq)]
#[error(
message = format!("missing argument #{} for the `{}` function", self.index + 1, self.name),
labels = ["this function call", ""],
help = format!(
"the `{}` function takes {} argument(s); there are {} argument(s) provided here",
(&self.name).fg(EXPR),
self.expected,
self.given
),
note = format!("function signature: {}", self.signature),
)]
pub struct MissingArgument {
pub name: String,
pub index: usize,
pub expected: usize,
pub given: usize,
pub signature: String,
}
#[derive(Debug, Clone, ErrorKind, PartialEq)]
#[error(
message = format!(
"incorrect type for argument #{} for the `{}` function",
self.index + 1,
self.name
),
labels = [
"this function call".to_string(),
"".to_string(),
format!("this argument has type `{}`", self.given),
],
help = format!("should be of type `{}`", self.expected),
note = format!("function signature: {}", self.signature),
)]
pub struct TypeMismatch {
pub name: String,
pub index: usize,
pub expected: &'static str,
pub given: &'static str,
pub signature: String,
}
#[derive(Debug, Clone, ErrorKind, PartialEq)]
#[error(
message = "maximum stack depth exceeded",
labels = ["this function called itself too many times", ""],
help = "the maximum stack depth is equal to: `2^11`"
)]
pub struct StackOverflow;
#[derive(Debug, Clone, ErrorKind, PartialEq)]
#[error(
message = format!(
"the `{}` function does not have a single parameter",
self.name
),
labels = ["this function call", ""],
help = "only functions with a single parameter can be differentiated using prime notation"
)]
pub struct InvalidDerivativeArguments {
pub name: String,
}
#[derive(Debug, Clone, ErrorKind, PartialEq)]
#[error(
message = "encountered a non-numeric type while differentiating this function",
labels = [
format!("this function call evaluated to `{}`", self.expr_type),
"".to_string(),
],
help = "derivatives are evaluated numerically using the limit definition of a derivative"
)]
pub struct NonNumericDerivative {
pub expr_type: &'static str,
}