use crate::*; #[derive(Clone)] pub enum AssembledToken { Word(AssembledWord), LabelDefinition(LabelDefinition), PinnedAddress(PinnedAddress), Error(AssemblerError), } #[derive(Clone)] pub struct AssembledWord { pub source: SourceSpan, pub value: usize, pub bits: usize, pub fields: Vec, pub errors: Vec, } #[derive(Clone)] pub struct AssembledField { pub source: SourceSpan, pub value: IntegerArgument, /// Length of field in bits pub bits: usize, /// Distance to left-shift field in value pub shift: usize, } #[derive(Clone)] pub struct AssembledExpression { pub source: SourceSpan, pub tokens: Vec, } #[derive(Clone)] pub enum AssembledExpressionToken { Integer(TrackedInteger), LabelReference(Tracked), Operator(Operator), Expression(Box), } #[derive(Clone)] pub enum Argument { Integer(IntegerArgument), Block(Vec), } #[derive(Clone)] pub enum IntegerArgument { LabelReference(Tracked), Integer(TrackedInteger), Expression(AssembledExpression), } #[derive(Clone)] pub struct AssemblerError { pub source: SourceSpan, pub variant: AssemblerErrorVariant, } #[derive(Clone, Debug)] pub enum AssemblerErrorVariant { DefinitionNotFound(String), NotAnInteger, NotABlock, IntegerInBlock, /// expected, received IncorrectArgumentCount(usize, usize), /// expected, received, index IncorrectArgumentType(ArgumentVariant, ArgumentVariant), } // ------------------------------------------------------------------------ // macro_rules! indent { ($indent:expr => $($tokens:tt)*) => {{ for _ in 0..$indent { print!(" "); } println!($($tokens)*); }}; } pub fn print_assembled_tokens(tokens: &[AssembledToken]) { println!(); println!("--------------------------------------------------------------"); println!(); for token in tokens { match token { AssembledToken::LabelDefinition(definition) => { println!("LABEL {}", definition.name) } AssembledToken::PinnedAddress(address) => { println!("PINNED {}", address.address) } AssembledToken::Word(word) => { println!("WORD {:b}", word.value); for field in &word.fields { print!(" FIELD ({} << {}) ", field.bits, field.shift); match &field.value { IntegerArgument::LabelReference(name) => { println!("LABEL '{name}'"); } IntegerArgument::Integer(integer) => { println!("INTEGER '{}'", integer.value); } IntegerArgument::Expression(expr) => { println!("EXPRESSION"); print_assembled_expression(2, expr); } } } } AssembledToken::Error(error) => { println!("ERROR {:?}", error.variant) } } } } fn print_assembled_expression(indent: usize, expr: &AssembledExpression) { for token in &expr.tokens { match token { AssembledExpressionToken::Integer(integer) => { indent!(indent => "INTEGER {}", integer.value) } AssembledExpressionToken::LabelReference(name) => { indent!(indent => "LABEL '{name}'") } AssembledExpressionToken::Operator(operator) => { indent!(indent => "OPERATOR {operator:?}") } AssembledExpressionToken::Expression(expr) => { indent!(indent => "EXPRESSION"); print_assembled_expression(indent+1, expr); } } } }