clc_engine/
errors.rs

1use std::borrow::Cow;
2use std::fmt;
3use std::fmt::Formatter;
4
5/// Errors in calculation.
6#[derive(Debug, PartialEq)]
7pub enum Error {
8    /// Provided input is invalid.
9    InvalidInput(String),
10    /// Error in eval stage.
11    Eval(EvalError),
12}
13
14impl fmt::Display for Error {
15    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
16        use Error::*;
17        match self {
18            InvalidInput(msg) => write!(f, "invalid input: {}", msg),
19            Eval(err) => write!(f, "{}", err),
20        }
21    }
22}
23
24impl std::error::Error for Error {}
25
26#[derive(Debug)]
27pub(crate) struct InvalidOperatorError<'a> {
28    raw: Cow<'a, str>,
29}
30
31impl<'a> InvalidOperatorError<'a> {
32    pub(crate) fn new(op: impl Into<Cow<'a, str>>) -> Self {
33        InvalidOperatorError { raw: op.into() }
34    }
35}
36
37impl<'a> fmt::Display for InvalidOperatorError<'a> {
38    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
39        write!(
40            f,
41            "invalid operator '{}' currently ['+', '-', '*', '/'] supported",
42            self.raw
43        )
44    }
45}
46
47impl<'a> std::error::Error for InvalidOperatorError<'a> {}
48
49#[derive(Debug)]
50pub(crate) struct InvalidConstantError<'a> {
51    raw: Cow<'a, str>,
52}
53
54impl<'a> InvalidConstantError<'a> {
55    pub(crate) fn new(op: impl Into<Cow<'a, str>>) -> Self {
56        InvalidConstantError { raw: op.into() }
57    }
58}
59
60impl<'a> fmt::Display for InvalidConstantError<'a> {
61    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
62        write!(f, "invalid constant '{}'", self.raw)
63    }
64}
65
66impl<'a> std::error::Error for InvalidConstantError<'a> {}
67
68/// Error in eval stage.
69#[derive(Debug, PartialEq)]
70pub enum EvalError {
71    /// zero division occurred.
72    /// '100 / 0'
73    DivisionByZero,
74    /// undefined function called.
75    /// 'foo(100)'
76    UndefinedFunction {
77        /// Undefined function identifier.
78        ident: String,
79    },
80    /// Expected args not provided.
81    /// 'pow(2)'
82    ArgCountDoesNotMatch {
83        /// Evaluated function identifier.
84        ident: &'static str,
85        /// Expected arg count.
86        expected: usize,
87        /// Actual arg count.
88        actual: usize,
89    },
90    /// Given variable not found in scope.
91    VariableNotFound {
92        /// Evaluated variable identifier.
93        ident: String,
94    },
95}
96
97impl EvalError {
98    pub(crate) fn arg_count_does_not_match(
99        ident: &'static str,
100        expected: usize,
101        actual: usize,
102    ) -> Self {
103        EvalError::ArgCountDoesNotMatch {
104            ident,
105            expected,
106            actual,
107        }
108    }
109}
110
111impl fmt::Display for EvalError {
112    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
113        use EvalError::*;
114        match self {
115            DivisionByZero => write!(f, "divided by zero"),
116            UndefinedFunction { ident } => write!(f, "function '{ident}' undefined"),
117            ArgCountDoesNotMatch {
118                ident,
119                expected,
120                actual,
121            } => write!(
122                f,
123                "function '{ident}' arg count does not match. {actual} vs {expected}."
124            ),
125            VariableNotFound { ident } => write!(f, "variable '{ident}' not found"),
126        }
127    }
128}
129
130impl std::error::Error for EvalError {}