1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
use super::Variable; use crate::trivial::structure::Instruction; use std::fmt::{self, Debug, Formatter}; use std::ops::{Index, IndexMut}; #[derive(Clone, Copy, Eq, Hash, PartialEq)] pub struct VariableId(usize); impl Debug for VariableId { fn fmt(&self, formatter: &mut Formatter) -> fmt::Result { write!(formatter, "tv{}", self.0) } } #[derive(Clone, Copy, Eq, Hash, PartialEq)] struct Label { occurs_in_static_body: bool, } #[derive(Clone, Copy, Eq, Hash, PartialEq)] pub struct LabelId(usize); impl LabelId { pub fn raw(&self) -> usize { self.0 } } impl Debug for LabelId { fn fmt(&self, formatter: &mut Formatter) -> fmt::Result { write!(formatter, "l{}", self.0) } } pub struct Program { static_init: Vec<Instruction>, instructions: Vec<Instruction>, variables: Vec<Variable>, static_vars: Vec<VariableId>, inputs: Vec<VariableId>, outputs: Vec<VariableId>, errors: Vec<String>, labels: Vec<Label>, } impl Debug for Program { fn fmt(&self, formatter: &mut Formatter) -> fmt::Result { writeln!(formatter, "variables:")?; for (index, variable) in self.variables.iter().enumerate() { writeln!(formatter, " tv{}: {:?}", index, variable)?; } write!(formatter, "static vars:")?; for variable in self.static_vars.iter() { write!(formatter, " {:?}", variable)?; } writeln!(formatter)?; write!(formatter, "inputs:")?; for variable in self.inputs.iter() { write!(formatter, " {:?}", variable)?; } writeln!(formatter)?; write!(formatter, "outputs:")?; for variable in self.outputs.iter() { write!(formatter, " {:?}", variable)?; } writeln!(formatter)?; writeln!(formatter, "{} labels", self.labels.len())?; writeln!(formatter, "error codes:")?; for (code, description) in self.errors.iter().enumerate() { writeln!(formatter, " {}: {}", code, description)?; } writeln!(formatter, "static init:")?; for instruction in self.static_init.iter() { writeln!(formatter, " {:?}", instruction)?; } writeln!(formatter, "instructions:")?; for instruction in self.instructions.iter() { writeln!(formatter, " {:?}", instruction)?; } write!(formatter, "") } } impl Index<VariableId> for Program { type Output = Variable; fn index(&self, variable: VariableId) -> &Self::Output { &self.variables[variable.0] } } impl IndexMut<VariableId> for Program { fn index_mut(&mut self, variable: VariableId) -> &mut Self::Output { &mut self.variables[variable.0] } } impl Program { pub fn new() -> Program { Program { instructions: Vec::new(), static_init: Vec::new(), variables: Vec::new(), static_vars: Vec::new(), inputs: Vec::new(), outputs: Vec::new(), errors: vec!["Success".to_owned()], labels: Vec::new(), } } pub fn add_instruction(&mut self, instruction: Instruction) { self.instructions.push(instruction); } pub fn add_static_init_instruction(&mut self, instruction: Instruction) { self.static_init.push(instruction); } pub fn borrow_instructions(&self) -> &Vec<Instruction> { &self.instructions } pub fn borrow_static_init_instructions(&self) -> &Vec<Instruction> { &self.static_init } pub fn adopt_variable(&mut self, variable: Variable) -> VariableId { let id = VariableId(self.variables.len()); self.variables.push(variable); id } pub fn borrow_variable(&self, id: VariableId) -> &Variable { &self.variables[id.0] } pub fn borrow_variable_mut(&mut self, id: VariableId) -> &mut Variable { &mut self.variables[id.0] } pub fn iterate_all_variables(&self) -> impl Iterator<Item = VariableId> { (0..self.variables.len()).map(|i| VariableId(i)) } pub fn create_label(&mut self, occurs_in_static_body: bool) -> LabelId { let id = LabelId(self.labels.len()); self.labels.push(Label { occurs_in_static_body, }); id } pub fn is_label_in_static_body(&self, label: LabelId) -> bool { assert!(label.0 < self.labels.len()); self.labels[label.0].occurs_in_static_body } pub fn iterate_all_labels(&self) -> impl Iterator<Item = LabelId> { (0..self.labels.len()).map(|i| LabelId(i)) } pub fn add_error(&mut self, description: String) -> u32 { let code = self.errors.len() as u32; self.errors.push(description); code } pub fn borrow_error_descriptions(&self) -> &Vec<String> { &self.errors } }