Skip to main content

lust/
error.rs

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>;