1use cl_ast::{Pat, types::Symbol};
4use cl_structures::span::Span;
5
6use crate::typeinfo::Type;
7
8use super::convalue::ConValue;
9
10pub type IResult<T> = Result<T, Error>;
11
12#[derive(Clone, Debug)]
13pub struct Error {
14 pub kind: ErrorKind,
15 pub(super) span: Option<Span>,
16}
17
18impl Error {
19 #![allow(non_snake_case)]
20
21 pub fn with_span(self, span: Span) -> Self {
23 Self { span: self.span.or(Some(span)), ..self }
24 }
25
26 pub fn kind(&self) -> &ErrorKind {
27 &self.kind
28 }
29
30 pub fn Return(value: ConValue) -> Self {
32 Self { kind: ErrorKind::Return(value), span: None }
33 }
34 pub fn Break(value: ConValue) -> Self {
36 Self { kind: ErrorKind::Break(value), span: None }
37 }
38 pub fn BadBreak(value: ConValue) -> Self {
40 Self { kind: ErrorKind::BadBreak(value), span: None }
41 }
42 pub fn Continue() -> Self {
44 Self { kind: ErrorKind::Continue, span: None }
45 }
46 pub fn StackOob(place: usize) -> Self {
48 Self { kind: ErrorKind::StackOob(place), span: None }
49 }
50 pub fn ScopeExit() -> Self {
52 Self { kind: ErrorKind::ScopeExit, span: None }
53 }
54 pub fn TypeError(want: impl ToString, got: Type) -> Self {
57 Self { kind: ErrorKind::TypeError(want.to_string(), got), span: None }
58 }
59 pub fn NotIterable() -> Self {
61 Self { kind: ErrorKind::NotIterable, span: None }
62 }
63 pub fn NotIndexable() -> Self {
65 Self { kind: ErrorKind::NotIndexable, span: None }
66 }
67 pub fn OobIndex(index: usize, length: usize) -> Self {
69 Self { kind: ErrorKind::OobIndex(index, length), span: None }
70 }
71 pub fn NotPlace() -> Self {
73 Self { kind: ErrorKind::NotPlace, span: None }
74 }
75 pub fn NotDefined(name: Symbol) -> Self {
77 Self { kind: ErrorKind::NotDefined(name), span: None }
78 }
79 pub fn NotInitialized(name: Symbol) -> Self {
81 Self { kind: ErrorKind::NotInitialized(name), span: None }
82 }
83 pub fn NotCallable(value: ConValue) -> Self {
85 Self { kind: ErrorKind::NotCallable(value), span: None }
86 }
87 pub fn ArgNumber(want: usize, got: usize) -> Self {
89 Self { kind: ErrorKind::ArgNumber { want, got }, span: None }
90 }
91 pub fn PatFailed(pat: Box<Pat>) -> Self {
93 Self { kind: ErrorKind::PatFailed(pat), span: None }
94 }
95 pub fn MatchNonexhaustive(value: ConValue) -> Self {
97 Self { kind: ErrorKind::MatchNonexhaustive(value), span: None }
98 }
99 pub fn Panic(msg: String) -> Self {
101 Self { kind: ErrorKind::Panic(msg, 0), span: None }
102 }
103 pub fn BuiltinError(msg: impl ToString) -> Self {
105 Self { kind: ErrorKind::BuiltinError(msg.to_string()), span: None }
106 }
107}
108
109impl std::error::Error for Error {}
110impl std::fmt::Display for Error {
111 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
112 let Self { kind, span } = self;
113 if let Some(Span { path, head, tail }) = span {
114 write!(f, "{path}:{head}..{tail}: ")?;
115 }
116 write!(f, "{kind}")
117 }
118}
119
120#[derive(Clone, Debug)]
122pub enum ErrorKind {
123 Return(ConValue),
125 Break(ConValue),
127 BadBreak(ConValue),
129 Continue,
131 StackOob(usize),
133 ScopeExit,
135 TypeError(String, Type),
138 NotIterable,
140 NotIndexable,
142 OobIndex(usize, usize),
144 NotPlace,
146 NotDefined(Symbol),
148 NotInitialized(Symbol),
150 NotCallable(ConValue),
152 ArgNumber { want: usize, got: usize },
154 PatFailed(Box<Pat>),
156 MatchNonexhaustive(ConValue),
158 Panic(String, usize),
160 BuiltinError(String),
162}
163
164impl std::error::Error for ErrorKind {}
165impl std::fmt::Display for ErrorKind {
166 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
167 match self {
168 ErrorKind::Return(value) => write!(f, "return {value}"),
169 ErrorKind::Break(value) => write!(f, "break {value}"),
170 ErrorKind::BadBreak(value) => write!(f, "rogue break: {value}"),
171 ErrorKind::Continue => "continue".fmt(f),
172 ErrorKind::StackOob(id) => {
173 write!(f, "Out of bounds access of stack entry <{id}>.")
174 }
175 ErrorKind::ScopeExit => "Exited the last scope. This is a logic bug.".fmt(f),
176 ErrorKind::TypeError(want, got) => {
177 write!(f, "Incompatible types: wanted {want}, got {got}")
178 }
179 ErrorKind::NotIterable => "`in` clause of `for` loop did not yield an iterable".fmt(f),
180 ErrorKind::NotIndexable => {
181 write!(f, "expression cannot be indexed")
182 }
183 ErrorKind::OobIndex(idx, len) => {
184 write!(f, "Index out of bounds: index was {idx}. but len is {len}")
185 }
186 ErrorKind::NotPlace => {
187 write!(f, "expression does not refer to a place")
188 }
189 ErrorKind::NotDefined(value) => {
190 write!(f, "{value} not bound.")
191 }
192 ErrorKind::NotInitialized(value) => {
193 write!(f, "{value} bound, but not initialized")
194 }
195 ErrorKind::NotCallable(value) => {
196 write!(f, "{value} is not callable.")
197 }
198 ErrorKind::ArgNumber { want, got } => {
199 write!(
200 f,
201 "Expected {want} argument{}, got {got}",
202 if *want == 1 { "" } else { "s" }
203 )
204 }
205 ErrorKind::PatFailed(pattern) => {
206 write!(f, "Failed to match pattern {pattern}")
207 }
208 ErrorKind::MatchNonexhaustive(value) => {
209 write!(f, "Failed to match {value}!")
210 }
211 ErrorKind::Panic(s, _depth) => write!(f, "{s}"),
212 ErrorKind::BuiltinError(s) => write!(f, "{s}"),
213 }
214 }
215}