summaryrefslogtreecommitdiff
path: root/src/stages/bytecode.rs
diff options
context:
space:
mode:
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),
+ }
+}