helix/dna/hel/
error.rs

1use std::path::PathBuf;
2use std::fmt;
3use thiserror::Error;
4use crate::dna::atp::lexer::SourceLocation;
5#[derive(Error, Debug, Clone)]
6pub enum HlxError {
7    #[error("Configuration conversion failed: {field} - {details}")]
8    ConfigConversion { field: String, details: String, suggestion: String },
9    #[error("Dataset processing failed: {message}")]
10    DatasetProcessing { message: String, suggestion: String },
11    #[error("Dataset quality validation failed: score {score:.2}")]
12    QualityValidation { score: f64, issues: Vec<String>, suggestions: Vec<String> },
13    #[error("Format conversion failed: {from} → {to}")]
14    FormatConversion { from: String, to: String, suggestion: String },
15    #[error("Algorithm '{algorithm}' not supported")]
16    UnsupportedAlgorithm { algorithm: String, supported: Vec<String> },
17    #[error("Dataset not found: {path}")]
18    DatasetNotFound { path: PathBuf, suggestion: String },
19    #[error("HLX processing failed: {message}")]
20    HlxProcessing { message: String, suggestion: String },
21    #[error("Forge integration failed: {message}")]
22    ForgeIntegration { message: String, suggestion: String },
23    #[error("Configuration validation failed: {field} = {value}")]
24    ConfigValidation { field: String, value: String, suggestion: String },
25    #[error("Invalid input: {message}")]
26    InvalidInput { message: String, suggestion: String },
27    #[error("Execution error: {message}")]
28    ExecutionError { message: String, suggestion: String },
29    #[error("Invalid parameters: {message}")]
30    InvalidParameters { message: String, suggestion: String },
31    #[error("Unknown operator: {message}")]
32    UnknownOperator { message: String, suggestion: String },
33    #[error("Validation error: {message}")]
34    ValidationError { message: String, suggestion: String },
35    #[error("Hash error: {message}")]
36    HashError { message: String, suggestion: String },
37    #[error("JSON error: {message}")]
38    JsonError { message: String, suggestion: String },
39    #[error("Base64 error: {message}")]
40    Base64Error { message: String, suggestion: String },
41    #[error("Unknown error: {message}")]
42    Unknown { message: String, suggestion: String },
43    #[error("Compilation error: {message}")]
44    Compilation { message: String, suggestion: String },
45    #[error("IO error: {message}")]
46    Io { message: String, suggestion: String },
47    #[error("Serialization error: {message}")]
48    SerializationError { message: String, suggestion: String },
49    #[error("Deserialization error: {message}")]
50    DeserializationError { message: String, suggestion: String },
51    #[error("Compression error: {message}")]
52    CompressionError { message: String, suggestion: String },
53    #[error("Decompression error: {message}")]
54    DecompressionError { message: String, suggestion: String },
55    #[error("Feature not available: {feature}")]
56    FeatureError { feature: String, message: String },
57}
58impl HlxError {
59    pub fn config_conversion(
60        field: impl Into<String>,
61        details: impl Into<String>,
62    ) -> Self {
63        let field = field.into();
64        let details = details.into();
65        let suggestion = format!(
66            "Check your Forge.toml configuration for the '{}' field", field
67        );
68        Self::ConfigConversion {
69            field,
70            details,
71            suggestion,
72        }
73    }
74    pub fn dataset_processing(message: impl Into<String>) -> Self {
75        let message = message.into();
76        let suggestion = "Try running 'forge hlx dataset validate' to check dataset compatibility"
77            .to_string();
78        Self::DatasetProcessing {
79            message,
80            suggestion,
81        }
82    }
83    pub fn quality_validation(score: f64, issues: Vec<String>) -> Self {
84        let suggestions = vec![
85            "Run 'forge hlx dataset analyze' for detailed quality metrics".to_string(),
86            "Consider filtering or augmenting low-quality samples".to_string(),
87            "Check dataset format and required columns".to_string(),
88        ];
89        Self::QualityValidation {
90            score,
91            issues,
92            suggestions,
93        }
94    }
95    pub fn format_conversion(from: impl Into<String>, to: impl Into<String>) -> Self {
96        let from = from.into();
97        let to = to.into();
98        let suggestion = format!(
99            "Ensure your dataset contains the required fields for {} format", to
100        );
101        Self::FormatConversion {
102            from,
103            to,
104            suggestion,
105        }
106    }
107    pub fn unsupported_algorithm(algorithm: impl Into<String>) -> Self {
108        let algorithm = algorithm.into();
109        let supported = vec!["bco", "dpo", "ppo", "sft"]
110            .into_iter()
111            .map(String::from)
112            .collect();
113        Self::UnsupportedAlgorithm {
114            algorithm,
115            supported,
116        }
117    }
118    pub fn dataset_not_found(path: PathBuf) -> Self {
119        let suggestion = format!(
120            "Ensure the dataset file exists at: {}", path.display()
121        );
122        Self::DatasetNotFound {
123            path,
124            suggestion,
125        }
126    }
127    pub fn execution_error(
128        message: impl Into<String>,
129        suggestion: impl Into<String>,
130    ) -> Self {
131        let message = message.into();
132        let suggestion = suggestion.into();
133        Self::ExecutionError {
134            message,
135            suggestion,
136        }
137    }
138    pub fn invalid_input(
139        message: impl Into<String>,
140        suggestion: impl Into<String>,
141    ) -> Self {
142        let message = message.into();
143        let suggestion = suggestion.into();
144        Self::InvalidInput {
145            message,
146            suggestion,
147        }
148    }
149    pub fn invalid_parameters(operator: &str, params: &str) -> Self {
150        let message = format!(
151            "Invalid parameters for operator '{}': {}", operator, params
152        );
153        let suggestion = format!("Check the operator '{}' parameter format", operator);
154        Self::InvalidParameters {
155            message,
156            suggestion,
157        }
158    }
159    pub fn unknown_operator(operator: impl Into<String>) -> Self {
160        let operator = operator.into();
161        let message = format!("Unknown operator: {}", operator);
162        let suggestion = "Check the operator name and ensure it is supported"
163            .to_string();
164        Self::UnknownOperator {
165            message,
166            suggestion,
167        }
168    }
169    pub fn validation_error(
170        message: impl Into<String>,
171        suggestion: impl Into<String>,
172    ) -> Self {
173        let message = message.into();
174        let suggestion = suggestion.into();
175        Self::ValidationError {
176            message,
177            suggestion,
178        }
179    }
180    pub fn hash_error(
181        message: impl Into<String>,
182        suggestion: impl Into<String>,
183    ) -> Self {
184        let message = message.into();
185        let suggestion = suggestion.into();
186        Self::HashError {
187            message,
188            suggestion,
189        }
190    }
191    pub fn json_error(
192        message: impl Into<String>,
193        suggestion: impl Into<String>,
194    ) -> Self {
195        let message = message.into();
196        let suggestion = suggestion.into();
197        Self::JsonError {
198            message,
199            suggestion,
200        }
201    }
202    pub fn base64_error(
203        message: impl Into<String>,
204        suggestion: impl Into<String>,
205    ) -> Self {
206        let message = message.into();
207        let suggestion = suggestion.into();
208        Self::Base64Error {
209            message,
210            suggestion,
211        }
212    }
213    pub fn unknown_error(
214        message: impl Into<String>,
215        suggestion: impl Into<String>,
216    ) -> Self {
217        let message = message.into();
218        let suggestion = suggestion.into();
219        Self::Unknown {
220            message,
221            suggestion,
222        }
223    }
224    pub fn compilation_error(
225        message: impl Into<String>,
226        suggestion: impl Into<String>,
227    ) -> Self {
228        let message = message.into();
229        let suggestion = suggestion.into();
230        Self::Compilation {
231            message,
232            suggestion,
233        }
234    }
235    pub fn io_error(message: impl Into<String>, suggestion: impl Into<String>) -> Self {
236        let message = message.into();
237        let suggestion = suggestion.into();
238        Self::Io { message, suggestion }
239    }
240    pub fn serialization_error(
241        message: impl Into<String>,
242        suggestion: impl Into<String>,
243    ) -> Self {
244        let message = message.into();
245        let suggestion = suggestion.into();
246        Self::SerializationError {
247            message,
248            suggestion,
249        }
250    }
251    pub fn deserialization_error(
252        message: impl Into<String>,
253        suggestion: impl Into<String>,
254    ) -> Self {
255        let message = message.into();
256        let suggestion = suggestion.into();
257        Self::DeserializationError {
258            message,
259            suggestion,
260        }
261    }
262    pub fn compression_error(
263        message: impl Into<String>,
264        suggestion: impl Into<String>,
265    ) -> Self {
266        let message = message.into();
267        let suggestion = suggestion.into();
268        Self::CompressionError {
269            message,
270            suggestion,
271        }
272    }
273    pub fn decompression_error(
274        message: impl Into<String>,
275        suggestion: impl Into<String>,
276    ) -> Self {
277        let message = message.into();
278        let suggestion = suggestion.into();
279        Self::DecompressionError {
280            message,
281            suggestion,
282        }
283    }
284    pub fn feature_error(
285        feature: impl Into<String>,
286        message: impl Into<String>,
287    ) -> Self {
288        let feature = feature.into();
289        let message = message.into();
290        Self::FeatureError {
291            feature,
292            message,
293        }
294    }
295    pub fn suggestions(&self) -> Vec<String> {
296        match self {
297            Self::ConfigConversion { suggestion, .. } => vec![suggestion.clone()],
298            Self::DatasetProcessing { suggestion, .. } => vec![suggestion.clone()],
299            Self::QualityValidation { suggestions, .. } => suggestions.clone(),
300            Self::FormatConversion { suggestion, .. } => vec![suggestion.clone()],
301            Self::UnsupportedAlgorithm { supported, .. } => {
302                vec![format!("Supported algorithms: {}", supported.join(", "))]
303            }
304            Self::DatasetNotFound { suggestion, .. } => vec![suggestion.clone()],
305            Self::HlxProcessing { suggestion, .. } => vec![suggestion.clone()],
306            Self::ForgeIntegration { suggestion, .. } => vec![suggestion.clone()],
307            Self::ConfigValidation { suggestion, .. } => vec![suggestion.clone()],
308            Self::InvalidInput { suggestion, .. } => vec![suggestion.clone()],
309            Self::ExecutionError { suggestion, .. } => vec![suggestion.clone()],
310            Self::InvalidParameters { suggestion, .. } => vec![suggestion.clone()],
311            Self::UnknownOperator { suggestion, .. } => vec![suggestion.clone()],
312            Self::ValidationError { suggestion, .. } => vec![suggestion.clone()],
313            Self::HashError { suggestion, .. } => vec![suggestion.clone()],
314            Self::JsonError { suggestion, .. } => vec![suggestion.clone()],
315            Self::Base64Error { suggestion, .. } => vec![suggestion.clone()],
316            Self::Unknown { suggestion, .. } => vec![suggestion.clone()],
317            Self::Compilation { suggestion, .. } => vec![suggestion.clone()],
318            Self::Io { suggestion, .. } => vec![suggestion.clone()],
319            Self::SerializationError { suggestion, .. } => vec![suggestion.clone()],
320            Self::DeserializationError { suggestion, .. } => vec![suggestion.clone()],
321            Self::CompressionError { suggestion, .. } => vec![suggestion.clone()],
322            Self::DecompressionError { suggestion, .. } => vec![suggestion.clone()],
323            Self::FeatureError { message, .. } => vec![message.clone()],
324        }
325    }
326    pub fn is_recoverable(&self) -> bool {
327        match self {
328            Self::ConfigConversion { .. } => true,
329            Self::DatasetProcessing { .. } => true,
330            Self::QualityValidation { score, .. } => *score > 0.3,
331            Self::FormatConversion { .. } => true,
332            Self::UnsupportedAlgorithm { .. } => false,
333            Self::DatasetNotFound { .. } => false,
334            Self::HlxProcessing { .. } => true,
335            Self::ForgeIntegration { .. } => true,
336            Self::ConfigValidation { .. } => true,
337            Self::InvalidInput { .. } => true,
338            Self::ExecutionError { .. } => true,
339            Self::InvalidParameters { .. } => true,
340            Self::UnknownOperator { .. } => true,
341            Self::ValidationError { .. } => true,
342            Self::HashError { .. } => true,
343            Self::JsonError { .. } => true,
344            Self::Base64Error { .. } => true,
345            Self::Unknown { .. } => true,
346            Self::Compilation { .. } => true,
347            Self::Io { .. } => true,
348            Self::SerializationError { .. } => true,
349            Self::DeserializationError { .. } => true,
350            Self::CompressionError { .. } => true,
351            Self::DecompressionError { .. } => true,
352            Self::FeatureError { .. } => false,
353        }
354    }
355}
356impl From<std::io::Error> for HlxError {
357    fn from(err: std::io::Error) -> Self {
358        Self::io_error(err.to_string(), "Check file permissions and paths")
359    }
360}
361impl From<serde_json::Error> for HlxError {
362    fn from(err: serde_json::Error) -> Self {
363        Self::json_error(err.to_string(), "Check JSON format and structure")
364    }
365}
366#[derive(Debug)]
367pub struct LexerError {
368    pub message: String,
369    pub location: SourceLocation,
370    pub source_line: String,
371    pub suggestion: Option<String>,
372}
373#[derive(Debug)]
374pub struct ParserError {
375    pub message: String,
376    pub location: SourceLocation,
377    pub expected: Vec<String>,
378    pub found: String,
379    pub source_line: String,
380    pub suggestion: Option<String>,
381}
382#[derive(Debug)]
383pub struct SemanticError {
384    pub kind: SemanticErrorKind,
385    pub location: SourceLocation,
386    pub entity: String,
387    pub context: Vec<String>,
388}
389#[derive(Debug)]
390pub enum SemanticErrorKind {
391    UndefinedReference,
392    DuplicateDefinition,
393    TypeMismatch { expected: String, found: String },
394    CircularDependency,
395    InvalidValue,
396    MissingRequired,
397    DeprecatedFeature,
398}
399#[derive(Debug)]
400pub struct CompilationError {
401    pub stage: CompilationStage,
402    pub message: String,
403    pub file: Option<PathBuf>,
404    pub recoverable: bool,
405}
406#[derive(Debug)]
407pub enum CompilationStage {
408    Parsing,
409    Validation,
410    Optimization,
411    CodeGeneration,
412    Serialization,
413    Bundling,
414}
415#[derive(Debug)]
416pub struct RuntimeError {
417    pub kind: RuntimeErrorKind,
418    pub message: String,
419    pub stack_trace: Vec<String>,
420}
421#[derive(Debug, PartialEq)]
422pub enum RuntimeErrorKind {
423    InvalidInstruction,
424    StackUnderflow,
425    StackOverflow,
426    MemoryAccessViolation,
427    DivisionByZero,
428    TypeConversion,
429    ResourceNotFound,
430}
431#[derive(Debug)]
432pub struct IoError {
433    pub operation: IoOperation,
434    pub path: PathBuf,
435    pub message: String,
436}
437#[derive(Debug)]
438pub enum IoOperation {
439    Read,
440    Write,
441    Create,
442    Delete,
443    Rename,
444    Metadata,
445}
446impl fmt::Display for LexerError {
447    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
448        writeln!(f, "Lexer error at {}:{}", self.location.line, self.location.column)?;
449        writeln!(f, "  {}", self.message)?;
450        writeln!(f, "  {}", self.source_line)?;
451        writeln!(f, "  {}^", " ".repeat(self.location.column))?;
452        if let Some(suggestion) = &self.suggestion {
453            writeln!(f, "  Suggestion: {}", suggestion)?;
454        }
455        Ok(())
456    }
457}
458impl fmt::Display for ParserError {
459    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
460        writeln!(f, "Parser error at {}:{}", self.location.line, self.location.column)?;
461        writeln!(f, "  {}", self.message)?;
462        writeln!(f, "  {}", self.source_line)?;
463        writeln!(f, "  {}^", " ".repeat(self.location.column))?;
464        if !self.expected.is_empty() {
465            writeln!(f, "  Expected: {}", self.expected.join(" | "))?;
466        }
467        writeln!(f, "  Found: {}", self.found)?;
468        if let Some(suggestion) = &self.suggestion {
469            writeln!(f, "  Suggestion: {}", suggestion)?;
470        }
471        Ok(())
472    }
473}
474impl fmt::Display for SemanticError {
475    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
476        write!(f, "Semantic error: ")?;
477        match &self.kind {
478            SemanticErrorKind::UndefinedReference => {
479                writeln!(f, "Undefined reference to '{}'", self.entity)?;
480            }
481            SemanticErrorKind::DuplicateDefinition => {
482                writeln!(f, "Duplicate definition of '{}'", self.entity)?;
483            }
484            SemanticErrorKind::TypeMismatch { expected, found } => {
485                writeln!(
486                    f, "Type mismatch for '{}': expected {}, found {}", self.entity,
487                    expected, found
488                )?;
489            }
490            SemanticErrorKind::CircularDependency => {
491                writeln!(f, "Circular dependency involving '{}'", self.entity)?;
492            }
493            SemanticErrorKind::InvalidValue => {
494                writeln!(f, "Invalid value for '{}'", self.entity)?;
495            }
496            SemanticErrorKind::MissingRequired => {
497                writeln!(f, "Missing required field '{}'", self.entity)?;
498            }
499            SemanticErrorKind::DeprecatedFeature => {
500                writeln!(f, "Use of deprecated feature '{}'", self.entity)?;
501            }
502        }
503        writeln!(f, "  at {}:{}", self.location.line, self.location.column)?;
504        if !self.context.is_empty() {
505            writeln!(f, "  Context:")?;
506            for ctx in &self.context {
507                writeln!(f, "    - {}", ctx)?;
508            }
509        }
510        Ok(())
511    }
512}
513impl fmt::Display for CompilationError {
514    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
515        write!(f, "Compilation error during {:?}: {}", self.stage, self.message)?;
516        if let Some(file) = &self.file {
517            write!(f, " in file {:?}", file)?;
518        }
519        if self.recoverable {
520            write!(f, " (recoverable)")?;
521        }
522        Ok(())
523    }
524}
525impl fmt::Display for RuntimeError {
526    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
527        writeln!(f, "Runtime error: {:?}", self.kind)?;
528        writeln!(f, "  {}", self.message)?;
529        if !self.stack_trace.is_empty() {
530            writeln!(f, "  Stack trace:")?;
531            for frame in &self.stack_trace {
532                writeln!(f, "    {}", frame)?;
533            }
534        }
535        Ok(())
536    }
537}
538impl fmt::Display for IoError {
539    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
540        write!(
541            f, "IO error during {:?} operation on {:?}: {}", self.operation, self.path,
542            self.message
543        )
544    }
545}
546impl std::error::Error for LexerError {}
547impl std::error::Error for ParserError {}
548impl std::error::Error for SemanticError {}
549impl std::error::Error for CompilationError {}
550impl std::error::Error for RuntimeError {}
551impl std::error::Error for IoError {}
552pub type Result<T> = std::result::Result<T, HlxError>;
553pub type HlxResult<T> = std::result::Result<T, HlxError>;
554pub struct ErrorRecovery;
555impl ErrorRecovery {
556    pub fn suggest_for_undefined_reference(name: &str) -> Option<String> {
557        if name == "agnet" {
558            return Some("Did you mean 'agent'?".to_string());
559        }
560        if name == "worfklow" || name == "workfow" {
561            return Some("Did you mean 'workflow'?".to_string());
562        }
563        None
564    }
565    pub fn suggest_for_syntax_error(found: &str, expected: &[String]) -> Option<String> {
566        if expected.contains(&"=".to_string()) && found == ":" {
567            return Some("Use '=' for assignment, not ':'".to_string());
568        }
569        if expected.contains(&"{".to_string()) && found == "(" {
570            return Some("Use '{' for block start, not '('".to_string());
571        }
572        None
573    }
574}