use crate::*; pub struct Segment { pub address: usize, /// Source of the address value. pub source: Option, pub words: Vec>, } pub struct Word { pub value: usize, pub width: u32, } impl std::fmt::Display for Word { fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { if self.width == 0 { write!(f, "0") } else { for i in (0..self.width).rev() { let is_first_bit = i+1 == self.width; if !is_first_bit && (i+1) % 4 == 0 { write!(f, "_")?; } match (self.value >> i) & 1 { 0 => write!(f, "0")?, _ => write!(f, "1")?, } } Ok(()) } } } pub enum BytecodeError { /// expected, received IncorrectWidth(u32, u32), /// pinned, real PinnedAddressBacktrack(usize, usize), /// expected, received ValueTooWide(u32, u32), StackError(Tracked), } pub fn report_bytecode_errors(errors: &[Tracked], source_code: &str) { for error in errors { report_bytecode_error(error, source_code); } } fn report_bytecode_error(error: &Tracked, source_code: &str) { let context = Context { source_code: &source_code, source: &error.source }; let message = match &error.value { BytecodeError::IncorrectWidth(expected, received) => &format!("Word is {received} bits wide, but was expected to have a fixed width of {expected} bits"), BytecodeError::PinnedAddressBacktrack(pinned, real) => &format!("Cannot pin to address {pinned} when address is already {real}"), BytecodeError::StackError(stack_error) => { report_stack_error(stack_error, source_code); return; }, BytecodeError::ValueTooWide(expected, received) => &format!("Field is {expected} bits wide, but received a value that is {received} bits wide"), }; report_source_issue(LogLevel::Error, &context, message); } pub fn print_segment(segment: &Segment) { println!("SEGMENT: 0x{:>04x}", segment.address); // Find maximum width of all words in the segment. let width = segment.words.iter().map(|w| w.to_string().chars().count()).max().unwrap_or(0); for word in &segment.words { let string = word.to_string(); println!(" {string:>w$}", w=width as usize); } }