summaryrefslogtreecommitdiff
path: root/src/translators/bytecode_generator.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/translators/bytecode_generator.rs')
-rw-r--r--src/translators/bytecode_generator.rs131
1 files changed, 0 insertions, 131 deletions
diff --git a/src/translators/bytecode_generator.rs b/src/translators/bytecode_generator.rs
deleted file mode 100644
index 956aca5..0000000
--- a/src/translators/bytecode_generator.rs
+++ /dev/null
@@ -1,131 +0,0 @@
-use crate::*;
-
-use SemanticTokenVariant as SemVar;
-
-
-pub fn generate_bytecode(semantic_tokens: &mut [SemanticToken]) -> Vec<u8> {
- let generator = BytecodeGenerator::from_semantic_tokens(semantic_tokens);
- generator.generate()
-}
-
-
-/// Translate semantic tokens into bytecode.
-struct BytecodeGenerator<'a> {
- semantic_tokens: &'a mut [SemanticToken],
- block_stack: Vec<usize>,
- bytecode: Vec<u8>,
- /// (address in bytecode, label definition token index)
- label_references: Vec<(usize, usize)>,
-}
-
-impl<'a> BytecodeGenerator<'a> {
- pub fn from_semantic_tokens(semantic_tokens: &'a mut [SemanticToken]) -> Self {
- Self {
- semantic_tokens,
- block_stack: Vec::new(),
- bytecode: Vec::new(),
- label_references: Vec::new(),
- }
- }
-
- pub fn generate(mut self) -> Vec<u8> {
- for i in 0..self.semantic_tokens.len() {
- let address = self.bytecode.len();
- self.generate_bytecode_for_token(i, None);
- self.semantic_tokens[i].bytecode = BytecodeSpan {
- bytes: self.bytecode[address..].to_vec(),
- location: BytecodeLocation {
- address,
- length: self.bytecode.len().saturating_sub(address),
- }
- };
- }
-
- // Replace blank label references in bytecode with real label addresses.
- // The layer of indirection is necessary because the iteration borrows
- // self immutably.
- let mut insertions: Vec<(usize, u16)> = Vec::new();
- for (bytecode_address, token_pointer) in &self.label_references {
- let label_token = &self.semantic_tokens[*token_pointer];
- // TODO: If greater than u16, print a warning.
- let address_value = label_token.bytecode.location.address as u16;
- insertions.push((*bytecode_address, address_value));
- }
- for (bytecode_address, address_value) in insertions {
- self.replace_address_in_bytecode(bytecode_address, address_value);
- }
-
- // Strip trailing null bytes from the bytecode.
- let mut length = self.bytecode.len();
- for (i, byte) in self.bytecode.iter().enumerate().rev() {
- match *byte == 0 {
- true => length = i,
- false => break,
- };
- }
- self.bytecode.truncate(length);
-
- return self.bytecode;
- }
-
- fn generate_bytecode_for_token(&mut self, pointer: usize, macro_pointer: Option<usize>) {
- macro_rules! push_byte {
- ($byte:expr) => { self.bytecode.push($byte) }; }
- macro_rules! push_double {
- ($double:expr) => { self.bytecode.extend_from_slice(&$double.to_be_bytes()) }; }
- macro_rules! pad {
- ($len:expr) => { for _ in 0..$len { push_byte!(0); } } }
-
- let semantic_token = if let Some(macro_pointer) = macro_pointer {
- let macro_definition = &self.semantic_tokens[macro_pointer];
- if let SemVar::MacroDefinition(def) = &macro_definition.variant {
- &def.body_tokens[pointer]
- } else { unreachable!() }
- } else {
- &self.semantic_tokens[pointer]
- };
- match &semantic_token.variant {
- SemVar::MacroInvocation(pointer) => {
- let macro_definition = &self.semantic_tokens[*pointer];
- if let SemVar::MacroDefinition(def) = &macro_definition.variant {
- let length = def.body_tokens.len();
- let macro_pointer = Some(*pointer);
- for body_pointer in 0..length {
- // Recurse, generate bytecode for each macro body token.
- self.generate_bytecode_for_token(body_pointer, macro_pointer);
- }
- } else { unreachable!() }
- }
- SemVar::Literal(value) => match value {
- Value::Byte(value) => push_byte!(*value),
- Value::Double(value) => push_double!(value),
- }
- SemVar::Padding(value) => match value {
- Value::Byte(value) => pad!(*value),
- Value::Double(value) => pad!(*value),
- }
- SemVar::Instruction(instr) => push_byte!(instr.value),
- SemVar::String(bytes) => self.bytecode.extend_from_slice(&bytes),
- SemVar::LabelReference(pointer) => {
- self.label_references.push((self.bytecode.len(), *pointer));
- push_double!(0u16);
- }
- SemVar::BlockOpen(_) => {
- self.block_stack.push(self.bytecode.len());
- push_double!(0u16);
- }
- SemVar::BlockClose(_) => {
- let bytecode_address = self.block_stack.pop().unwrap();
- // TODO: If greater than u16, print a warning.
- let address_value = self.bytecode.len() as u16;
- self.replace_address_in_bytecode(bytecode_address, address_value);
- }
- _ => (),
- };
- }
-
- fn replace_address_in_bytecode(&mut self, bytecode_address: usize, address_value: u16) {
- let range = bytecode_address..bytecode_address+2;
- self.bytecode[range].clone_from_slice(&address_value.to_be_bytes());
- }
-}