use std::borrow::Cow; use std::error::Error; use thiserror::Error; use sexp::SourcePosition; use crate::asm::data::{Register}; use crate::asm::data::literal::Label; use crate::asm::instr::Cond; use std::io; /// csn_asm unified error type #[derive(Error, Debug)] pub enum CrsnError { #[error("S-expression parsing error: {0}")] Sexp(#[from] Box), #[error("Parse error: {0} at {1}")] Parse(Cow<'static, str>, SourcePosition), #[error("Parse error: {0} at {1}")] ParseOther(Box, SourcePosition), #[error("Assembler error: {0} at {1}")] Asm(AsmError, SourcePosition), #[error("IO error: {0}")] IOError(#[from] io::Error), } impl CrsnError { /// Get error pos pub fn pos(&self) -> Option<&SourcePosition> { match self { CrsnError::Parse(_, p) => Some(p), CrsnError::ParseOther(_, p) => Some(p), CrsnError::Asm(_, p) => Some(p), CrsnError::Sexp(se) => Some(&se.pos), CrsnError::IOError(_) =>None, } } } /// Error from the assembler stage (after parsing S-expressions and basic validation) #[derive(Error, Debug)] pub enum AsmError { #[error("Unknown instruction")] UnknownInstruction, #[error("Value provided as output argument")] ValueAsOutput, #[error("Discard (_) provided as input argument")] DiscardAsValue, #[error("Conditional branch already defined for \"{0}\"")] ConditionalAlreadyUsed(Cond), #[error("Label \"{0}\" not defined")] LabelNotDefined(Label), #[error("Label \"{0}\" already defined in this scope")] LabelDuplicate(Label), #[error("Bad register type: {0}")] BadRegisterType(Register), }