summaryrefslogtreecommitdiff
path: root/src/stages/bytecode.rs
diff options
context:
space:
mode:
authorBen Bridle <ben@derelict.engineering>2025-10-14 21:33:30 +1300
committerBen Bridle <ben@derelict.engineering>2025-10-14 21:33:42 +1300
commitd9e0c4895608cdcb04b868222b49b3f117766ed0 (patch)
tree57d240b331ced3f4704799a6337c1e90c5c17b42 /src/stages/bytecode.rs
parent981bb70e5077bd30ef85a0092117a875dcc614fc (diff)
downloadtorque-asm-d9e0c4895608cdcb04b868222b49b3f117766ed0.zip
Implement new bytecode stage
This completes the Torque version 3 rewrite, other than some extensive testing that is yet to be done.
Diffstat (limited to 'src/stages/bytecode.rs')
-rw-r--r--src/stages/bytecode.rs47
1 files changed, 47 insertions, 0 deletions
diff --git a/src/stages/bytecode.rs b/src/stages/bytecode.rs
new file mode 100644
index 0000000..2d73767
--- /dev/null
+++ b/src/stages/bytecode.rs
@@ -0,0 +1,47 @@
+use crate::*;
+
+
+pub fn parse_bytecode(intermediate: Vec<Tracked<IntermediateToken>>, width: Option<u32>) -> Result<Vec<Segment>, Vec<Tracked<BytecodeError>>> {
+ let mut segments = Vec::new();
+ let mut errors = Vec::new();
+ let mut current_segment = Vec::new();
+ let mut segment_source = None;
+ let mut segment_address = 0;
+
+
+ for token in intermediate {
+ match token.value {
+ IntermediateToken::Word(word) => {
+ if let Some(width) = width {
+ if word.width != width {
+ let error = BytecodeError::IncorrectWidth(width, word.width);
+ errors.push(Tracked::from(error, token.source.clone()));
+ }
+ }
+ let source = token.source.clone();
+ current_segment.push(Tracked::from(word, source));
+ }
+ IntermediateToken::PinnedAddress(pinned_address) => {
+ if !current_segment.is_empty() {
+ let address = segment_address;
+ let words = std::mem::take(&mut current_segment);
+ let source = std::mem::take(&mut segment_source);
+ segments.push(Segment { address, source, words });
+ segment_address = pinned_address;
+ }
+ }
+ }
+ }
+ // Finish final segment.
+ if !current_segment.is_empty() {
+ let address = segment_address;
+ let words = std::mem::take(&mut current_segment);
+ let source = std::mem::take(&mut segment_source);
+ segments.push(Segment { address, source, words });
+ }
+
+ match errors.is_empty() {
+ true => Ok(segments),
+ false => Err(errors),
+ }
+}