use crate::Word; use super::{ Program, Address }; impl Program { /* Intermediate code generation */ pub(crate) fn collapse_instructions(&mut self) { // Fix instruction addresses let mut offsets = Vec::new(); for instr in &self.instructions { offsets.push(instr.collapse_len() + offsets.last().unwrap_or(&0)); } offsets.insert(0, 0); for instr in &mut self.instructions { for arg in &mut instr.args { if let Address::Instruction(num) = arg { *arg = Address::Instruction(offsets[*num]); } } } // Collapse all instructions let mut collapsed = Vec::new(); for instr in &mut self.instructions { collapsed.extend(instr.collapse(collapsed.len())); } self.instructions = collapsed; } /* Machine code generation */ pub(crate) fn instructions_to_constants(&mut self, mut absolute_start: usize) { absolute_start += 1; let constlen = self.constants.len(); self.constants.insert(0, (absolute_start + constlen) as Word); for instr in &mut self.instructions { for arg in &mut instr.args { self.constants.push(match arg { Address::Memory(num) => *num, Address::Constants(num) => absolute_start + *num, Address::Instruction(num) => constlen + absolute_start + *num * 3, _ => unreachable!("Definition addresses should've already been removed!"), } as Word); } } self.instructions.clear(); } pub(crate) fn to_bytes(self, absolute_start: usize, pc: usize) -> Vec { let mut res = Vec::new(); res.resize(absolute_start, Default::default()); res[pc] = self.constants[0]; res.extend(self.constants); res .into_iter() .map(|x| x.to_be_bytes()) .flatten() .collect() } }