use crate::token::Span; use std::fmt; /// Compile-time error with source location #[derive(Debug, Clone)] pub struct CompileError { pub message: String, pub span: Span, pub hint: Option, } impl CompileError { pub fn new(message: impl Into, span: Span) -> Self { Self { message: message.into(), span, hint: None, } } pub fn with_hint(mut self, hint: impl Into) -> Self { self.hint = Some(hint.into()); self } } impl fmt::Display for CompileError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "Error at line {}, col {}: {}", self.span.line, self.span.col, self.message)?; if let Some(hint) = &self.hint { write!(f, "\n Hint: {}", hint)?; } Ok(()) } } /// Runtime error during VM execution #[derive(Debug, Clone)] pub enum ScriptError { ExecutionLimitExceeded, StackOverflow, StackUnderflow, InvalidOpcode(u8), } impl fmt::Display for ScriptError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { ScriptError::ExecutionLimitExceeded => write!(f, "Execution limit exceeded (possible infinite loop)"), ScriptError::StackOverflow => write!(f, "Stack overflow"), ScriptError::StackUnderflow => write!(f, "Stack underflow"), ScriptError::InvalidOpcode(op) => write!(f, "Invalid opcode: {}", op), } } }