1use cl_ast::{Pattern, Sym};
4use cl_structures::span::Span;
5
6use super::{convalue::ConValue, env::Place};
7
8pub type IResult<T> = Result<T, Error>;
9
10#[derive(Clone, Debug)]
11pub struct Error {
12 pub kind: ErrorKind,
13 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: Place) -> 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 BuiltinError(msg: String) -> Self {
103 Self { kind: ErrorKind::BuiltinError(msg), span: None }
104 }
105}
106
107impl std::error::Error for Error {}
108impl std::fmt::Display for Error {
109 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
110 let Self { kind, span } = self;
111 if let Some(Span { head, tail }) = span {
112 write!(f, "{head}..{tail}: ")?;
113 }
114 write!(f, "{kind}")
115 }
116}
117
118#[derive(Clone, Debug)]
120pub enum ErrorKind {
121 Return(ConValue),
123 Break(ConValue),
125 BadBreak(ConValue),
127 Continue,
129 StackUnderflow,
131 StackOverflow(Place),
133 ScopeExit,
135 TypeError,
138 NotIterable,
140 NotIndexable,
142 OobIndex(usize, usize),
144 NotAssignable,
146 NotDefined(Sym),
148 NotInitialized(Sym),
150 NotCallable(ConValue),
152 ArgNumber { want: usize, got: usize },
154 PatFailed(Box<Pattern>),
156 MatchNonexhaustive,
158 BuiltinError(String),
160}
161
162impl std::error::Error for ErrorKind {}
163impl std::fmt::Display for ErrorKind {
164 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
165 match self {
166 ErrorKind::Return(value) => write!(f, "return {value}"),
167 ErrorKind::Break(value) => write!(f, "break {value}"),
168 ErrorKind::BadBreak(value) => write!(f, "rogue break: {value}"),
169 ErrorKind::Continue => "continue".fmt(f),
170 ErrorKind::StackUnderflow => "Stack underflow".fmt(f),
171 ErrorKind::StackOverflow(id) => {
172 write!(f, "Attempt to access <{id}> resulted in stack overflow.")
173 }
174 ErrorKind::ScopeExit => "Exited the last scope. This is a logic bug.".fmt(f),
175 ErrorKind::TypeError => "Incompatible types".fmt(f),
176 ErrorKind::NotIterable => "`in` clause of `for` loop did not yield an iterable".fmt(f),
177 ErrorKind::NotIndexable => {
178 write!(f, "expression cannot be indexed")
179 }
180 ErrorKind::OobIndex(idx, len) => {
181 write!(f, "Index out of bounds: index was {idx}. but len is {len}")
182 }
183 ErrorKind::NotAssignable => {
184 write!(f, "expression is not assignable")
185 }
186 ErrorKind::NotDefined(value) => {
187 write!(f, "{value} not bound. Did you mean `let {value};`?")
188 }
189 ErrorKind::NotInitialized(value) => {
190 write!(f, "{value} bound, but not initialized")
191 }
192 ErrorKind::NotCallable(value) => {
193 write!(f, "{value} is not callable.")
194 }
195 ErrorKind::ArgNumber { want, got } => {
196 write!(
197 f,
198 "Expected {want} argument{}, got {got}",
199 if *want == 1 { "" } else { "s" }
200 )
201 }
202 ErrorKind::PatFailed(pattern) => {
203 write!(f, "Failed to match pattern {pattern}")
204 }
205 ErrorKind::MatchNonexhaustive => {
206 write!(f, "Fell through a non-exhaustive match expression!")
207 }
208 ErrorKind::BuiltinError(s) => write!(f, "{s}"),
209 }
210 }
211}