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}