diff options
author | Ben Bridle <ben@derelict.engineering> | 2025-02-28 13:23:20 +1300 |
---|---|---|
committer | Ben Bridle <ben@derelict.engineering> | 2025-02-28 13:34:23 +1300 |
commit | dba769e13ca5029643c6068e53fa34ae0fea8421 (patch) | |
tree | 47b45ecddaf08bcef19de29ad65206c34af85f53 /src/parsers/bytecode.rs | |
parent | 1a810d036195395c182f6cd6e011b8fb868d9872 (diff) | |
download | torque-asm-dba769e13ca5029643c6068e53fa34ae0fea8421.zip |
Implement string literals
String literals are treated as integers. If a string is passed as an
integer argument to a packed binary literal, a new instance of the
packed binary literal is invoked for every character in the string,
with each character being passed to the packed binary literal as a
Unicode character value.
Diffstat (limited to 'src/parsers/bytecode.rs')
-rw-r--r-- | src/parsers/bytecode.rs | 78 |
1 files changed, 53 insertions, 25 deletions
diff --git a/src/parsers/bytecode.rs b/src/parsers/bytecode.rs index ec19d9f..6cdfd3a 100644 --- a/src/parsers/bytecode.rs +++ b/src/parsers/bytecode.rs @@ -25,28 +25,7 @@ impl<'a> BytecodeGenerator<'a> { for token in self.tokens { match token { AssembledToken::Word(assembled_word) => { - let mut value = assembled_word.value; - for field in &assembled_word.fields { - let (field_value, source) = match &field.value { - IntegerArgument::Expression(expr) => - (self.resolve_expression(expr), expr.source.clone()), - IntegerArgument::LabelReference(name) => - (self.resolve_label_reference(name), name.source.clone()), - IntegerArgument::Integer(integer) => - (integer.value, integer.source.clone()), - }; - let bitcount = match field_value { - 0 => 0, - _ => (field_value.ilog2() + 1) as usize, - }; - if field.bits < bitcount { - let variant = BytecodeErrorVariant::ValueTooLarge(field.bits, bitcount); - self.errors.push(BytecodeError { source, variant }); - } else { - value |= (field_value << field.shift) as usize; - } - } - self.words.push(Word { bits: assembled_word.bits, value }); + self.assemble_word(assembled_word); } AssembledToken::PinnedAddress(pinned) => { if self.words.len() > pinned.address { @@ -74,7 +53,7 @@ impl<'a> BytecodeGenerator<'a> { for token in self.tokens { match token { AssembledToken::LabelDefinition(definition) => { - let address = Tracked::from(i, &definition.source); + let address = Tracked::from(i, definition.source.clone()); if let Some(_) = self.addresses.insert(definition.name.clone(), address) { let name = definition.name.clone(); let variant = BytecodeErrorVariant::DuplicateLabelDefinition(name); @@ -82,8 +61,8 @@ impl<'a> BytecodeGenerator<'a> { self.errors.push(BytecodeError { source, variant }); } } - AssembledToken::Word(_) => { - i += 1; + AssembledToken::Word(word) => { + i += word.count(); } AssembledToken::PinnedAddress(pinned) => { i = pinned.address; @@ -158,4 +137,53 @@ impl<'a> BytecodeGenerator<'a> { 0 } } + + fn assemble_word(&mut self, assembled_word: &AssembledWord) { + let mut field_values = Vec::new(); + for field in &assembled_word.fields { + match &field.value { + IntegerArgument::Expression(expr) => { + let source = expr.source.clone(); + let value = self.resolve_expression(expr); + field_values.push(vec![Tracked::from(value, source)]) + } + IntegerArgument::LabelReference(name) => { + let source = name.source.clone(); + let value = self.resolve_label_reference(name); + field_values.push(vec![Tracked::from(value, source)]) + } + IntegerArgument::Integer(integer) => { + let source = integer.source.clone(); + let value = integer.value; + field_values.push(vec![Tracked::from(value, source)]) + } + IntegerArgument::String(string) => { + let values = string.chars.iter() + .map(|c| Tracked::from(c.value as isize, c.source.clone())) + .collect(); + field_values.push(values); + } + }; + } + for i in 0..assembled_word.count() { + let mut value = assembled_word.value; + for (f, field) in assembled_word.fields.iter().enumerate() { + let (field_value, source) = match field_values[f].get(i) { + Some(tracked) => (tracked.value, Some(tracked.source.clone())), + None => (0, None), + }; + let bitcount = match field_value { + 0 => 0, + _ => (field_value.ilog2() + 1) as usize, + }; + if field.bits < bitcount { + let variant = BytecodeErrorVariant::ValueTooLarge(field.bits, bitcount); + self.errors.push(BytecodeError { source: source.unwrap(), variant }); + } else { + value |= (field_value << field.shift) as usize; + } + } + self.words.push(Word { bits: assembled_word.bits, value }); + } + } } |