cas_compiler/
error.rs

1use ariadne::Fmt;
2use cas_attrs::ErrorKind;
3use cas_error::EXPR;
4
5/// Tried to override a builtin constant.
6#[derive(Debug, Clone, ErrorKind, PartialEq)]
7#[error(
8    message = format!("cannot override builtin constant: `{}`", self.name),
9    labels = ["this variable"],
10    help = "choose a different name for this variable",
11    note = "builtin constants include: `i`, `e`, `phi`, `pi`, or `tau`",
12    // TODO: ariadne does not allow multiple notes
13    // note = "consider using `let` to shadow the constant",
14)]
15pub struct OverrideBuiltinConstant {
16    /// The name of the variable that was attempted to be overridden.
17    pub name: String,
18}
19
20/// Tried to override a builtin function.
21#[derive(Debug, Clone, ErrorKind, PartialEq)]
22#[error(
23    message = format!("cannot override builtin function: `{}`", self.name),
24    labels = ["this function"],
25    help = "choose a different name for this function",
26)]
27pub struct OverrideBuiltinFunction {
28    /// The name of the function that was attempted to be overridden.
29    pub name: String,
30}
31
32/// The variable is undefined.
33#[derive(Debug, Clone, ErrorKind, PartialEq)]
34#[error(
35    message = format!("unknown variable: `{}`", self.name),
36    labels = ["this variable"],
37    help = format!("to define it, type: {} = {}", (&self.name).fg(EXPR), "<expression>".fg(EXPR)),
38)]
39pub struct UnknownVariable {
40    /// The name of the variable that was undefined.
41    pub name: String,
42}
43
44/// The function is undefined.
45#[derive(Debug, Clone, ErrorKind, PartialEq)]
46#[error(
47    message = format!("unknown function: `{}`", self.name),
48    labels = ["this function"],
49    help = if self.suggestions.is_empty() {
50        "see the documentation for a list of available functions".to_string()
51    } else if self.suggestions.len() == 1 {
52        format!("did you mean the `{}` function?", (&*self.suggestions[0]).fg(EXPR))
53    } else {
54        format!(
55            "did you mean one of these functions? {}",
56            self.suggestions
57                .iter()
58                .map(|s| format!("`{}`", s.fg(EXPR)))
59                .collect::<Vec<_>>()
60                .join(", ")
61        )
62    }
63)]
64pub struct UnknownFunction {
65    /// The name of the function that was undefined.
66    pub name: String,
67
68    /// A list of similarly named functions, if any.
69    pub suggestions: Vec<String>,
70}
71
72/// Too many arguments were given to a function call.
73#[derive(Debug, Clone, ErrorKind, PartialEq)]
74#[error(
75    message = format!("too many arguments given to the `{}` function", self.name),
76    labels = ["this function call", "", "these argument(s) are extraneous"],
77    help = format!(
78        "the `{}` function takes {} argument(s); there are {} argument(s) provided here",
79        (&self.name).fg(EXPR),
80        self.expected,
81        self.given
82    ),
83    note = format!("function signature: `{}({})`", self.name, self.signature),
84)]
85pub struct TooManyArguments {
86    /// The name of the function that was called.
87    pub name: String,
88
89    /// The number of arguments that were expected.
90    pub expected: usize,
91
92    /// The number of arguments that were given.
93    pub given: usize,
94
95    /// The signature of the function, not including the function name.
96    pub signature: String,
97}
98
99/// An argument to a function call is missing.
100#[derive(Debug, Clone, ErrorKind, PartialEq)]
101#[error(
102    message = match &*self.indices {
103        &[index] => format!("missing required argument #{} for the `{}` function", index + 1, self.name),
104        _ => format!(
105            "missing required arguments {} for the `{}` function",
106            self.indices
107                .iter()
108                .map(|i| format!("#{}", i + 1))
109                .collect::<Vec<_>>()
110                .join(", "),
111            self.name
112        ),
113    },
114    labels = ["this function call", ""],
115    help = format!(
116        "the `{}` function takes {} argument(s); there are {} argument(s) provided here",
117        (&self.name).fg(EXPR),
118        self.expected,
119        self.given
120    ),
121    note = format!("function signature: `{}({})`", self.name, self.signature),
122)]
123pub struct MissingArgument {
124    /// The name of the function that was called.
125    pub name: String,
126
127    /// The indices of the missing arguments.
128    pub indices: Vec<usize>,
129
130    /// The number of arguments that were expected.
131    pub expected: usize,
132
133    /// The number of arguments that were given.
134    pub given: usize,
135
136    /// The signature of the function, not including the function name.
137    pub signature: String,
138}