Skip to main content

wave_compiler/diagnostics/
error.rs

1// Copyright 2026 Ojima Abraham
2// SPDX-License-Identifier: Apache-2.0
3
4//! Compiler error types covering all stages of compilation.
5//!
6//! Errors carry enough context for rich error reporting including
7//! source locations, expected vs found types, and suggestions.
8
9use thiserror::Error;
10
11/// Source location in the input file.
12#[derive(Debug, Clone, Copy, PartialEq, Eq)]
13pub struct SourceLoc {
14    /// Line number (1-based).
15    pub line: u32,
16    /// Column number (1-based).
17    pub col: u32,
18}
19
20/// Compiler error covering all compilation stages.
21#[derive(Debug, Error)]
22pub enum CompileError {
23    /// Type mismatch in expression.
24    #[error("type mismatch: expected {expected}, found {found}")]
25    TypeMismatch {
26        /// Expected type.
27        expected: String,
28        /// Found type.
29        found: String,
30    },
31
32    /// Reference to undefined variable.
33    #[error("undefined variable: {name}")]
34    UndefinedVariable {
35        /// Variable name.
36        name: String,
37    },
38
39    /// Parse error in frontend.
40    #[error("parse error: {message}")]
41    ParseError {
42        /// Error message.
43        message: String,
44    },
45
46    /// Unsupported language construct.
47    #[error("unsupported: {message}")]
48    Unsupported {
49        /// Description of unsupported construct.
50        message: String,
51    },
52
53    /// Internal compiler error (bug).
54    #[error("internal error: {message}")]
55    InternalError {
56        /// Error message.
57        message: String,
58    },
59
60    /// I/O error.
61    #[error("I/O error: {message}")]
62    IoError {
63        /// Error message.
64        message: String,
65    },
66
67    /// Code generation error.
68    #[error("codegen error: {message}")]
69    CodegenError {
70        /// Error message.
71        message: String,
72    },
73
74    /// Register allocation failure.
75    #[error("register allocation failed: {message}")]
76    RegAllocError {
77        /// Error message.
78        message: String,
79    },
80}
81
82impl From<std::io::Error> for CompileError {
83    fn from(err: std::io::Error) -> Self {
84        Self::IoError {
85            message: err.to_string(),
86        }
87    }
88}
89
90#[cfg(test)]
91mod tests {
92    use super::*;
93
94    #[test]
95    fn test_error_display() {
96        let err = CompileError::TypeMismatch {
97            expected: "i32".into(),
98            found: "f32".into(),
99        };
100        assert_eq!(err.to_string(), "type mismatch: expected i32, found f32");
101    }
102
103    #[test]
104    fn test_undefined_variable_error() {
105        let err = CompileError::UndefinedVariable { name: "foo".into() };
106        assert_eq!(err.to_string(), "undefined variable: foo");
107    }
108
109    #[test]
110    fn test_io_error_conversion() {
111        let io_err = std::io::Error::new(std::io::ErrorKind::NotFound, "file not found");
112        let compile_err: CompileError = io_err.into();
113        assert!(compile_err.to_string().contains("file not found"));
114    }
115}