use crate::ast::*;
use smol_str::SmolStr;
use std::sync::Arc;
use thiserror::Error;
#[derive(Debug, PartialEq, Clone, Error)]
pub enum EvaluationError {
#[error("entity does not exist: {0}")]
EntityDoesNotExist(Arc<EntityUID>),
#[error("{} does not have the required attribute: {}", &.entity, &.attr)]
EntityAttrDoesNotExist {
entity: Arc<EntityUID>,
attr: SmolStr,
},
#[error("cannot access attribute of unspecified entity: {0}")]
UnspecifiedEntityAccess(SmolStr),
#[error("record does not have the required attribute: {0}")]
RecordAttrDoesNotExist(SmolStr),
#[error(transparent)]
ExtensionsError(#[from] crate::extensions::ExtensionsError),
#[error("{}", pretty_type_error(expected, actual))]
TypeError {
expected: Vec<Type>,
actual: Type,
},
#[error("wrong number of arguments to {op}: expected {expected}, got {actual}")]
WrongNumArguments {
op: ExtensionFunctionOp,
expected: usize,
actual: usize,
},
#[error(transparent)]
IntegerOverflow(#[from] IntegerOverflowError),
#[error(transparent)]
InvalidRestrictedExpression(#[from] RestrictedExpressionError),
#[error("Template slot {0} was not instantiated")]
TemplateInstantiationError(SlotId),
#[error("error from {extension_name} extension: {msg}")]
ExtensionError {
extension_name: Name,
msg: String,
},
#[error("The expression evaluated to a residual: {0}")]
NonValue(Expr),
#[error("Recursion Limit Reached")]
RecursionLimit,
}
fn pretty_type_error(expected: &[Type], actual: &Type) -> String {
match expected.len() {
0 => panic!("should expect at least one type"),
1 => format!("type error: expected {}, got {}", expected[0], actual),
_ => {
use itertools::Itertools;
format!(
"type error: expected one of [{}], got {actual}",
expected.iter().join(", ")
)
}
}
}
#[derive(Debug, PartialEq, Clone, Error)]
pub enum IntegerOverflowError {
#[error("integer overflow while attempting to {} the values {arg1} and {arg2}", match .op { BinaryOp::Add => "add", BinaryOp::Sub => "subtract", _ => "perform an operation on" })]
BinaryOp {
op: BinaryOp,
arg1: Value,
arg2: Value,
},
#[error("integer overflow while attempting to multiply {arg} by {constant}")]
Multiplication {
arg: Value,
constant: i64,
},
#[error("integer overflow while attempting to {} the value {arg}", match .op { UnaryOp::Neg => "negate", _ => "perform an operation on" })]
UnaryOp {
op: UnaryOp,
arg: Value,
},
}
pub type Result<T> = std::result::Result<T, EvaluationError>;