Skip to main content

runmat_vm/compiler/
error.rs

1use miette::{SourceOffset, SourceSpan};
2use runmat_hir::{SemanticError, Span};
3use runmat_runtime::{build_runtime_error, RuntimeError};
4
5#[derive(Debug, Clone)]
6pub struct CompileError {
7    pub message: String,
8    pub span: Option<Span>,
9    pub identifier: Option<String>,
10}
11
12impl CompileError {
13    pub fn new(message: impl Into<String>) -> Self {
14        Self {
15            message: message.into(),
16            span: None,
17            identifier: None,
18        }
19    }
20
21    pub fn with_span(mut self, span: Span) -> Self {
22        self.span = Some(span);
23        self
24    }
25
26    pub fn with_identifier(mut self, identifier: impl Into<String>) -> Self {
27        self.identifier = Some(identifier.into());
28        self
29    }
30}
31
32impl std::fmt::Display for CompileError {
33    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
34        write!(f, "{}", self.message)
35    }
36}
37
38impl std::error::Error for CompileError {}
39
40impl From<String> for CompileError {
41    fn from(value: String) -> Self {
42        CompileError::new(value)
43    }
44}
45
46impl From<&str> for CompileError {
47    fn from(value: &str) -> Self {
48        CompileError::new(value)
49    }
50}
51
52impl From<SemanticError> for CompileError {
53    fn from(value: SemanticError) -> Self {
54        let mut err = CompileError::new(value.message);
55        if let Some(span) = value.span {
56            err = err.with_span(span);
57        }
58        if let Some(identifier) = value.identifier {
59            err = err.with_identifier(identifier);
60        }
61        err
62    }
63}
64
65impl From<CompileError> for RuntimeError {
66    fn from(value: CompileError) -> Self {
67        let mut builder = build_runtime_error(value.message);
68        if let Some(identifier) = value.identifier {
69            builder = builder.with_identifier(identifier);
70        }
71        if let Some(span) = value.span {
72            let len = span.end.saturating_sub(span.start).max(1);
73            builder = builder.with_span(SourceSpan::new(SourceOffset::from(span.start), len));
74        }
75        builder.build()
76    }
77}