diff options
author | Ben Bridle <ben@derelict.engineering> | 2025-03-06 20:33:27 +1300 |
---|---|---|
committer | Ben Bridle <ben@derelict.engineering> | 2025-03-11 16:59:26 +1300 |
commit | 1ecee352f5844b0809d7ae66df52e34f42b44c8e (patch) | |
tree | 472b6fd57ff7f64ac3f8cd676cbe7a113ba01f05 /src/tokens/assembler.rs | |
parent | f2ed89083f5326a7a6f0a1720033d3388aa431fb (diff) | |
download | torque-asm-1ecee352f5844b0809d7ae66df52e34f42b44c8e.zip |
Rewrite entire assembler
The language is now more general, the code is better structured, error
reporting is more detailed, and many new language features have
been implemented:
- conditional blocks
- first-class strings
- more expression operators
- binary literals
- negative values
- invocations in constant expressions
Diffstat (limited to 'src/tokens/assembler.rs')
-rw-r--r-- | src/tokens/assembler.rs | 162 |
1 files changed, 0 insertions, 162 deletions
diff --git a/src/tokens/assembler.rs b/src/tokens/assembler.rs deleted file mode 100644 index 048062b..0000000 --- a/src/tokens/assembler.rs +++ /dev/null @@ -1,162 +0,0 @@ -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<AssembledField>, - pub errors: Vec<AssemblerError>, -} - -impl AssembledWord { - pub fn count(&self) -> usize { - // If there is at least one field, and all fields have empty string - // values, then count will be zero. Else count will be at least one. - let mut count = 0; - let mut all_strings = !self.fields.is_empty(); - for field in &self.fields { - if let IntegerArgument::String(string) = &field.value { - count = std::cmp::max(count, string.chars.len()); - } else { - all_strings = false; - } - } - if !all_strings { - count = std::cmp::max(count, 1); - } - return count; - } -} - -#[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<AssembledExpressionToken>, -} - -#[derive(Clone)] -pub enum AssembledExpressionToken { - Integer(TrackedInteger), - LabelReference(Tracked<String>), - Operator(Operator), - Expression(Box<AssembledExpression>), -} - -#[derive(Clone)] -pub enum Argument { - Integer(IntegerArgument), - Block(Vec<AssembledToken>), -} - -#[derive(Clone)] -pub enum IntegerArgument { - LabelReference(Tracked<String>), - Integer(TrackedInteger), - Expression(AssembledExpression), - String(TrackedString), -} - -#[derive(Clone)] -pub struct AssemblerError { - pub source: SourceSpan, - pub variant: AssemblerErrorVariant, -} - -#[derive(Clone, Debug)] -pub enum AssemblerErrorVariant { - DefinitionNotFound(String), - NotAnInteger, - NotABlock, - IntegerInBlock, - StringInExpression, - /// 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]) { - 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::String(string) => { - println!("STRING {string}"); - } - 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); - } - } - } -} |