lust/
error.rs

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