helix_core/
error.rs

1use std::fmt;
2use std::path::PathBuf;
3use crate::lexer::SourceLocation;
4#[derive(Debug)]
5pub enum HelixError {
6    Lexer(LexerError),
7    Parser(ParserError),
8    Semantic(SemanticError),
9    Compilation(CompilationError),
10    Runtime(RuntimeError),
11    Io(IoError),
12}
13#[derive(Debug)]
14pub struct LexerError {
15    pub message: String,
16    pub location: SourceLocation,
17    pub source_line: String,
18    pub suggestion: Option<String>,
19}
20#[derive(Debug)]
21pub struct ParserError {
22    pub message: String,
23    pub location: SourceLocation,
24    pub expected: Vec<String>,
25    pub found: String,
26    pub source_line: String,
27    pub suggestion: Option<String>,
28}
29#[derive(Debug)]
30pub struct SemanticError {
31    pub kind: SemanticErrorKind,
32    pub location: SourceLocation,
33    pub entity: String,
34    pub context: Vec<String>,
35}
36#[derive(Debug)]
37pub enum SemanticErrorKind {
38    UndefinedReference,
39    DuplicateDefinition,
40    TypeMismatch { expected: String, found: String },
41    CircularDependency,
42    InvalidValue,
43    MissingRequired,
44    DeprecatedFeature,
45}
46#[derive(Debug)]
47pub struct CompilationError {
48    pub stage: CompilationStage,
49    pub message: String,
50    pub file: Option<PathBuf>,
51    pub recoverable: bool,
52}
53#[derive(Debug)]
54pub enum CompilationStage {
55    Parsing,
56    Validation,
57    Optimization,
58    CodeGeneration,
59    Serialization,
60    Bundling,
61}
62#[derive(Debug)]
63pub struct RuntimeError {
64    pub kind: RuntimeErrorKind,
65    pub message: String,
66    pub stack_trace: Vec<String>,
67}
68#[derive(Debug, PartialEq)]
69pub enum RuntimeErrorKind {
70    InvalidInstruction,
71    StackUnderflow,
72    StackOverflow,
73    MemoryAccessViolation,
74    DivisionByZero,
75    TypeConversion,
76    ResourceNotFound,
77}
78#[derive(Debug)]
79pub struct IoError {
80    pub operation: IoOperation,
81    pub path: PathBuf,
82    pub message: String,
83}
84#[derive(Debug)]
85pub enum IoOperation {
86    Read,
87    Write,
88    Create,
89    Delete,
90    Rename,
91    Metadata,
92}
93impl fmt::Display for HelixError {
94    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
95        match self {
96            HelixError::Lexer(e) => write!(f, "{}", e),
97            HelixError::Parser(e) => write!(f, "{}", e),
98            HelixError::Semantic(e) => write!(f, "{}", e),
99            HelixError::Compilation(e) => write!(f, "{}", e),
100            HelixError::Runtime(e) => write!(f, "{}", e),
101            HelixError::Io(e) => write!(f, "{}", e),
102        }
103    }
104}
105impl fmt::Display for LexerError {
106    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
107        writeln!(f, "Lexer error at {}:{}", self.location.line, self.location.column)?;
108        writeln!(f, "  {}", self.message)?;
109        writeln!(f, "  {}", self.source_line)?;
110        writeln!(f, "  {}^", " ".repeat(self.location.column))?;
111        if let Some(suggestion) = &self.suggestion {
112            writeln!(f, "  Suggestion: {}", suggestion)?;
113        }
114        Ok(())
115    }
116}
117impl fmt::Display for ParserError {
118    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
119        writeln!(f, "Parser error at {}:{}", self.location.line, self.location.column)?;
120        writeln!(f, "  {}", self.message)?;
121        writeln!(f, "  {}", self.source_line)?;
122        writeln!(f, "  {}^", " ".repeat(self.location.column))?;
123        if !self.expected.is_empty() {
124            writeln!(f, "  Expected: {}", self.expected.join(" | "))?;
125        }
126        writeln!(f, "  Found: {}", self.found)?;
127        if let Some(suggestion) = &self.suggestion {
128            writeln!(f, "  Suggestion: {}", suggestion)?;
129        }
130        Ok(())
131    }
132}
133impl fmt::Display for SemanticError {
134    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
135        write!(f, "Semantic error: ")?;
136        match &self.kind {
137            SemanticErrorKind::UndefinedReference => {
138                writeln!(f, "Undefined reference to '{}'", self.entity)?;
139            }
140            SemanticErrorKind::DuplicateDefinition => {
141                writeln!(f, "Duplicate definition of '{}'", self.entity)?;
142            }
143            SemanticErrorKind::TypeMismatch { expected, found } => {
144                writeln!(
145                    f, "Type mismatch for '{}': expected {}, found {}", self.entity,
146                    expected, found
147                )?;
148            }
149            SemanticErrorKind::CircularDependency => {
150                writeln!(f, "Circular dependency involving '{}'", self.entity)?;
151            }
152            SemanticErrorKind::InvalidValue => {
153                writeln!(f, "Invalid value for '{}'", self.entity)?;
154            }
155            SemanticErrorKind::MissingRequired => {
156                writeln!(f, "Missing required field '{}'", self.entity)?;
157            }
158            SemanticErrorKind::DeprecatedFeature => {
159                writeln!(f, "Use of deprecated feature '{}'", self.entity)?;
160            }
161        }
162        writeln!(f, "  at {}:{}", self.location.line, self.location.column)?;
163        if !self.context.is_empty() {
164            writeln!(f, "  Context:")?;
165            for ctx in &self.context {
166                writeln!(f, "    - {}", ctx)?;
167            }
168        }
169        Ok(())
170    }
171}
172impl fmt::Display for CompilationError {
173    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
174        write!(f, "Compilation error during {:?}: {}", self.stage, self.message)?;
175        if let Some(file) = &self.file {
176            write!(f, " in file {:?}", file)?;
177        }
178        if self.recoverable {
179            write!(f, " (recoverable)")?;
180        }
181        Ok(())
182    }
183}
184impl fmt::Display for RuntimeError {
185    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
186        writeln!(f, "Runtime error: {:?}", self.kind)?;
187        writeln!(f, "  {}", self.message)?;
188        if !self.stack_trace.is_empty() {
189            writeln!(f, "  Stack trace:")?;
190            for frame in &self.stack_trace {
191                writeln!(f, "    {}", frame)?;
192            }
193        }
194        Ok(())
195    }
196}
197impl fmt::Display for IoError {
198    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
199        write!(
200            f, "IO error during {:?} operation on {:?}: {}", self.operation, self.path,
201            self.message
202        )
203    }
204}
205impl std::error::Error for HelixError {}
206impl std::error::Error for LexerError {}
207impl std::error::Error for ParserError {}
208impl std::error::Error for SemanticError {}
209impl std::error::Error for CompilationError {}
210impl std::error::Error for RuntimeError {}
211impl std::error::Error for IoError {}
212impl From<std::io::Error> for HelixError {
213    fn from(err: std::io::Error) -> Self {
214        HelixError::Io(IoError {
215            operation: IoOperation::Read,
216            path: PathBuf::new(),
217            message: err.to_string(),
218        })
219    }
220}
221pub type Result<T> = std::result::Result<T, HelixError>;
222pub struct ErrorRecovery;
223impl ErrorRecovery {
224    pub fn suggest_for_undefined_reference(name: &str) -> Option<String> {
225        if name == "agnet" {
226            return Some("Did you mean 'agent'?".to_string());
227        }
228        if name == "worfklow" || name == "workfow" {
229            return Some("Did you mean 'workflow'?".to_string());
230        }
231        None
232    }
233    pub fn suggest_for_syntax_error(found: &str, expected: &[String]) -> Option<String> {
234        if expected.contains(&"=".to_string()) && found == ":" {
235            return Some("Use '=' for assignment, not ':'".to_string());
236        }
237        if expected.contains(&"{".to_string()) && found == "(" {
238            return Some("Use '{' for block start, not '('".to_string());
239        }
240        None
241    }
242}