diff options
Diffstat (limited to 'src/stages/bytecode_tokens.rs')
-rw-r--r-- | src/stages/bytecode_tokens.rs | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/src/stages/bytecode_tokens.rs b/src/stages/bytecode_tokens.rs new file mode 100644 index 0000000..b54cb0e --- /dev/null +++ b/src/stages/bytecode_tokens.rs @@ -0,0 +1,78 @@ +use crate::*; + + +pub struct Segment { + pub address: usize, + /// Source of the address value. + pub source: Option<SourceSpan>, + pub words: Vec<Tracked<Word>>, +} + +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<StackError>), +} + + +pub fn report_bytecode_errors(errors: &[Tracked<BytecodeError>], source_code: &str) { + for error in errors { + report_bytecode_error(error, source_code); + } +} + +fn report_bytecode_error(error: &Tracked<BytecodeError>, 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); + } +} |