cas_compute/numerical/builtin/error/
func_specific.rs

1use cas_attrs::ErrorKind;
2use cas_error::ErrorKind;
3use cas_parser::parser::ast::call::Call;
4use crate::numerical::builtin::BuiltinError;
5use std::ops::Range;
6
7/// Represents an error specific to a builtin function.
8#[derive(Debug)]
9pub enum FunctionSpecific {
10    /// Errors for the `ncr` and `npr` builtin function.
11    Ncpr(NcprError),
12}
13
14impl FunctionSpecific {
15    /// Get the spans for the error.
16    pub fn spans(&self, call: &Call) -> Vec<Range<usize>> {
17        match self {
18            FunctionSpecific::Ncpr(e) => e.spans(call),
19        }
20    }
21
22    /// Convert the [`FunctionSpecific`] into an [`ErrorKind`].
23    pub fn into_kind(self) -> Box<dyn ErrorKind> {
24        match self {
25            FunctionSpecific::Ncpr(e) => Box::new(e),
26        }
27    }
28}
29
30/// Errors for the `ncr` and `npr` builtin function.
31#[derive(Debug, Clone, Copy, ErrorKind, PartialEq, Eq)]
32#[error(
33    message = format!("incorrect arguments for the `{}` function", self.function_name),
34    labels = if self.error == NcprErrorKind::NLessThanK {
35        [
36            "this function call",
37            "",
38            "(1) argument `n`...",
39            "(2) ...must be less than or equal to argument `k`",
40        ].iter()
41    } else {
42        [
43            "this function call",
44            "",
45            "argument `k` must be positive",
46        ].iter()
47    }
48)]
49pub struct NcprError {
50    /// The specific function name.
51    pub function_name: &'static str,
52
53    /// The error that occurred.
54    pub error: NcprErrorKind,
55}
56
57impl NcprError {
58    pub fn new(function_name: &'static str, error: NcprErrorKind) -> Self {
59        Self { function_name, error }
60    }
61}
62
63#[derive(Debug, Clone, Copy, PartialEq, Eq)]
64pub enum NcprErrorKind {
65    /// The first argument is less than the second.
66    NLessThanK,
67
68    /// One or both of the arguments is negative.
69    NegativeArgs,
70}
71
72impl NcprError {
73    fn spans(&self, call: &Call) -> Vec<Range<usize>> {
74        let mut this_function_call = call.outer_span().to_vec();
75        match self.error {
76            NcprErrorKind::NLessThanK => {
77                this_function_call.extend(call.args.iter().map(|arg| arg.span()));
78            },
79            NcprErrorKind::NegativeArgs => {
80                this_function_call.push(call.args[1].span());
81            },
82        };
83        this_function_call
84    }
85}
86
87impl From<NcprError> for BuiltinError {
88    fn from(e: NcprError) -> Self {
89        BuiltinError::FunctionSpecific(FunctionSpecific::Ncpr(e))
90    }
91}