1use 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 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 pub fn Return(value: ConValue) -> Self {
30 Self { kind: ErrorKind::Return(value), span: None }
31 }
32 pub fn Break(value: ConValue) -> Self {
34 Self { kind: ErrorKind::Break(value), span: None }
35 }
36 pub fn BadBreak(value: ConValue) -> Self {
38 Self { kind: ErrorKind::BadBreak(value), span: None }
39 }
40 pub fn Continue() -> Self {
42 Self { kind: ErrorKind::Continue, span: None }
43 }
44 pub fn StackUnderflow() -> Self {
46 Self { kind: ErrorKind::StackUnderflow, span: None }
47 }
48 pub fn StackOverflow(place: usize) -> Self {
50 Self { kind: ErrorKind::StackOverflow(place), span: None }
51 }
52 pub fn ScopeExit() -> Self {
54 Self { kind: ErrorKind::ScopeExit, span: None }
55 }
56 pub fn TypeError() -> Self {
59 Self { kind: ErrorKind::TypeError, span: None }
60 }
61 pub fn NotIterable() -> Self {
63 Self { kind: ErrorKind::NotIterable, span: None }
64 }
65 pub fn NotIndexable() -> Self {
67 Self { kind: ErrorKind::NotIndexable, span: None }
68 }
69 pub fn OobIndex(index: usize, length: usize) -> Self {
71 Self { kind: ErrorKind::OobIndex(index, length), span: None }
72 }
73 pub fn NotAssignable() -> Self {
75 Self { kind: ErrorKind::NotAssignable, span: None }
76 }
77 pub fn NotDefined(name: Sym) -> Self {
79 Self { kind: ErrorKind::NotDefined(name), span: None }
80 }
81 pub fn NotInitialized(name: Sym) -> Self {
83 Self { kind: ErrorKind::NotInitialized(name), span: None }
84 }
85 pub fn NotCallable(value: ConValue) -> Self {
87 Self { kind: ErrorKind::NotCallable(value), span: None }
88 }
89 pub fn ArgNumber(want: usize, got: usize) -> Self {
91 Self { kind: ErrorKind::ArgNumber { want, got }, span: None }
92 }
93 pub fn PatFailed(pat: Box<Pattern>) -> Self {
95 Self { kind: ErrorKind::PatFailed(pat), span: None }
96 }
97 pub fn MatchNonexhaustive() -> Self {
99 Self { kind: ErrorKind::MatchNonexhaustive, span: None }
100 }
101 pub fn Panic(msg: String) -> Self {
103 Self { kind: ErrorKind::Panic(msg, 0), span: None }
104 }
105 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#[derive(Clone, Debug)]
124pub enum ErrorKind {
125 Return(ConValue),
127 Break(ConValue),
129 BadBreak(ConValue),
131 Continue,
133 StackUnderflow,
135 StackOverflow(usize),
137 ScopeExit,
139 TypeError,
142 NotIterable,
144 NotIndexable,
146 OobIndex(usize, usize),
148 NotAssignable,
150 NotDefined(Sym),
152 NotInitialized(Sym),
154 NotCallable(ConValue),
156 ArgNumber { want: usize, got: usize },
158 PatFailed(Box<Pattern>),
160 MatchNonexhaustive,
162 Panic(String, usize),
164 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}