1use alloc::{format, string::String, vec::Vec};
2use thiserror::Error;
3#[derive(Debug, Clone, PartialEq, Eq)]
4pub struct StackFrame {
5 pub function: String,
6 pub line: usize,
7 pub ip: usize,
8}
9
10impl StackFrame {
11 pub fn new(function: impl Into<String>, line: usize, ip: usize) -> Self {
12 Self {
13 function: function.into(),
14 line,
15 ip,
16 }
17 }
18}
19
20#[derive(Error, Debug, Clone, PartialEq)]
21pub enum LustError {
22 #[error("Lexer error at line {line}, column {column}: {message}")]
23 LexerError {
24 line: usize,
25 column: usize,
26 message: String,
27 module: Option<String>,
28 },
29 #[error("Parser error at line {line}, column {column}: {message}")]
30 ParserError {
31 line: usize,
32 column: usize,
33 message: String,
34 module: Option<String>,
35 },
36 #[error("Type error: {message}")]
37 TypeError { message: String },
38 #[error("Type error at line {line}, column {column}: {message}")]
39 TypeErrorWithSpan {
40 message: String,
41 line: usize,
42 column: usize,
43 module: Option<String>,
44 },
45 #[error("Compile error: {0}")]
46 CompileError(String),
47 #[error("Compile error at line {line}, column {column}: {message}")]
48 CompileErrorWithSpan {
49 message: String,
50 line: usize,
51 column: usize,
52 module: Option<String>,
53 },
54 #[error("Runtime error: {message}")]
55 RuntimeError { message: String },
56 #[error(
57 "Runtime error at line {line} in {function}: {message}\n{}",
58 format_stack_trace(stack_trace)
59 )]
60 RuntimeErrorWithTrace {
61 message: String,
62 function: String,
63 line: usize,
64 stack_trace: Vec<StackFrame>,
65 },
66 #[error("Unknown error: {0}")]
67 Unknown(String),
68}
69
70fn format_stack_trace(frames: &[StackFrame]) -> String {
71 if frames.is_empty() {
72 return String::new();
73 }
74
75 let mut output = String::from("Stack trace:\n");
76 for (i, frame) in frames.iter().enumerate() {
77 output.push_str(&format!(
78 " [{}] {} (line {})\n",
79 i, frame.function, frame.line
80 ));
81 }
82
83 output
84}
85
86pub type Result<T> = core::result::Result<T, LustError>;