cl_interpret/
error.rs

1//! The [Error] type represents any error thrown by the [Environment](super::Environment)
2
3use cl_ast::{Pattern, Sym};
4use cl_structures::span::Span;
5
6use super::convalue::ConValue;
7
8pub type IResult<T> = Result<T, Error>;
9
10#[derive(Clone, Debug)]
11pub struct Error {
12    pub kind: ErrorKind,
13    pub(super) span: Option<Span>,
14}
15
16impl Error {
17    #![allow(non_snake_case)]
18
19    /// Adds a [struct Span] to this [Error], if there isn't already a more specific one.
20    pub fn with_span(self, span: Span) -> Self {
21        Self { span: self.span.or(Some(span)), ..self }
22    }
23
24    pub fn kind(&self) -> &ErrorKind {
25        &self.kind
26    }
27
28    /// Propagate a Return value
29    pub fn Return(value: ConValue) -> Self {
30        Self { kind: ErrorKind::Return(value), span: None }
31    }
32    /// Propagate a Break value
33    pub fn Break(value: ConValue) -> Self {
34        Self { kind: ErrorKind::Break(value), span: None }
35    }
36    /// Break propagated across function bounds
37    pub fn BadBreak(value: ConValue) -> Self {
38        Self { kind: ErrorKind::BadBreak(value), span: None }
39    }
40    /// Continue to the next iteration of a loop
41    pub fn Continue() -> Self {
42        Self { kind: ErrorKind::Continue, span: None }
43    }
44    /// Underflowed the stack
45    pub fn StackUnderflow() -> Self {
46        Self { kind: ErrorKind::StackUnderflow, span: None }
47    }
48    /// Overflowed the stack
49    pub fn StackOverflow(place: usize) -> Self {
50        Self { kind: ErrorKind::StackOverflow(place), span: None }
51    }
52    /// Exited the last scope
53    pub fn ScopeExit() -> Self {
54        Self { kind: ErrorKind::ScopeExit, span: None }
55    }
56    /// Type incompatibility
57    // TODO: store the type information in this error
58    pub fn TypeError() -> Self {
59        Self { kind: ErrorKind::TypeError, span: None }
60    }
61    /// In clause of For loop didn't yield a Range
62    pub fn NotIterable() -> Self {
63        Self { kind: ErrorKind::NotIterable, span: None }
64    }
65    /// A value could not be indexed
66    pub fn NotIndexable() -> Self {
67        Self { kind: ErrorKind::NotIndexable, span: None }
68    }
69    /// An array index went out of bounds
70    pub fn OobIndex(index: usize, length: usize) -> Self {
71        Self { kind: ErrorKind::OobIndex(index, length), span: None }
72    }
73    /// An expression is not assignable
74    pub fn NotAssignable() -> Self {
75        Self { kind: ErrorKind::NotAssignable, span: None }
76    }
77    /// A name was not defined in scope before being used
78    pub fn NotDefined(name: Sym) -> Self {
79        Self { kind: ErrorKind::NotDefined(name), span: None }
80    }
81    /// A name was defined but not initialized
82    pub fn NotInitialized(name: Sym) -> Self {
83        Self { kind: ErrorKind::NotInitialized(name), span: None }
84    }
85    /// A value was called, but is not callable
86    pub fn NotCallable(value: ConValue) -> Self {
87        Self { kind: ErrorKind::NotCallable(value), span: None }
88    }
89    /// A function was called with the wrong number of arguments
90    pub fn ArgNumber(want: usize, got: usize) -> Self {
91        Self { kind: ErrorKind::ArgNumber { want, got }, span: None }
92    }
93    /// A pattern failed to match
94    pub fn PatFailed(pat: Box<Pattern>) -> Self {
95        Self { kind: ErrorKind::PatFailed(pat), span: None }
96    }
97    /// Fell through a non-exhaustive match
98    pub fn MatchNonexhaustive() -> Self {
99        Self { kind: ErrorKind::MatchNonexhaustive, span: None }
100    }
101    /// Explicit panic
102    pub fn Panic(msg: String) -> Self {
103        Self { kind: ErrorKind::Panic(msg, 0), span: None }
104    }
105    /// Error produced by a Builtin
106    pub fn BuiltinError(msg: String) -> Self {
107        Self { kind: ErrorKind::BuiltinError(msg), span: None }
108    }
109}
110
111impl std::error::Error for Error {}
112impl std::fmt::Display for Error {
113    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
114        let Self { kind, span } = self;
115        if let Some(Span { head, tail }) = span {
116            write!(f, "{head}..{tail}: ")?;
117        }
118        write!(f, "{kind}")
119    }
120}
121
122/// Represents any error thrown by the [Environment](super::Environment)
123#[derive(Clone, Debug)]
124pub enum ErrorKind {
125    /// Propagate a Return value
126    Return(ConValue),
127    /// Propagate a Break value
128    Break(ConValue),
129    /// Break propagated across function bounds
130    BadBreak(ConValue),
131    /// Continue to the next iteration of a loop
132    Continue,
133    /// Underflowed the stack
134    StackUnderflow,
135    /// Overflowed the stack
136    StackOverflow(usize),
137    /// Exited the last scope
138    ScopeExit,
139    /// Type incompatibility
140    // TODO: store the type information in this error
141    TypeError,
142    /// In clause of For loop didn't yield a Range
143    NotIterable,
144    /// A value could not be indexed
145    NotIndexable,
146    /// An array index went out of bounds
147    OobIndex(usize, usize),
148    /// An expression is not assignable
149    NotAssignable,
150    /// A name was not defined in scope before being used
151    NotDefined(Sym),
152    /// A name was defined but not initialized
153    NotInitialized(Sym),
154    /// A value was called, but is not callable
155    NotCallable(ConValue),
156    /// A function was called with the wrong number of arguments
157    ArgNumber { want: usize, got: usize },
158    /// A pattern failed to match
159    PatFailed(Box<Pattern>),
160    /// Fell through a non-exhaustive match
161    MatchNonexhaustive,
162    /// Explicit panic
163    Panic(String, usize),
164    /// Error produced by a Builtin
165    BuiltinError(String),
166}
167
168impl std::error::Error for ErrorKind {}
169impl std::fmt::Display for ErrorKind {
170    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
171        match self {
172            ErrorKind::Return(value) => write!(f, "return {value}"),
173            ErrorKind::Break(value) => write!(f, "break {value}"),
174            ErrorKind::BadBreak(value) => write!(f, "rogue break: {value}"),
175            ErrorKind::Continue => "continue".fmt(f),
176            ErrorKind::StackUnderflow => "Stack underflow".fmt(f),
177            ErrorKind::StackOverflow(id) => {
178                write!(f, "Attempt to access <{id}> resulted in stack overflow.")
179            }
180            ErrorKind::ScopeExit => "Exited the last scope. This is a logic bug.".fmt(f),
181            ErrorKind::TypeError => "Incompatible types".fmt(f),
182            ErrorKind::NotIterable => "`in` clause of `for` loop did not yield an iterable".fmt(f),
183            ErrorKind::NotIndexable => {
184                write!(f, "expression cannot be indexed")
185            }
186            ErrorKind::OobIndex(idx, len) => {
187                write!(f, "Index out of bounds: index was {idx}. but len is {len}")
188            }
189            ErrorKind::NotAssignable => {
190                write!(f, "expression is not assignable")
191            }
192            ErrorKind::NotDefined(value) => {
193                write!(f, "{value} not bound. Did you mean `let {value};`?")
194            }
195            ErrorKind::NotInitialized(value) => {
196                write!(f, "{value} bound, but not initialized")
197            }
198            ErrorKind::NotCallable(value) => {
199                write!(f, "{value} is not callable.")
200            }
201            ErrorKind::ArgNumber { want, got } => {
202                write!(
203                    f,
204                    "Expected {want} argument{}, got {got}",
205                    if *want == 1 { "" } else { "s" }
206                )
207            }
208            ErrorKind::PatFailed(pattern) => {
209                write!(f, "Failed to match pattern {pattern}")
210            }
211            ErrorKind::MatchNonexhaustive => {
212                write!(f, "Fell through a non-exhaustive match expression!")
213            }
214            ErrorKind::Panic(s, _depth) => write!(f, "Explicit panic: {s}"),
215            ErrorKind::BuiltinError(s) => write!(f, "{s}"),
216        }
217    }
218}