1use crate::builder::Builder;
87use crate::table::Table;
88use std::convert::From;
89use std::fmt;
90mod debug;
91mod from_byte_code;
92mod to_byte_code;
93
94pub struct Code<T> {
98 pub symbols: Vec<(usize, String)>,
99 pub code: Vec<usize>,
100 pub data: Vec<T>,
101 pub labels: Vec<(usize, String)>,
102}
103
104impl<T: fmt::Debug> Code<T> {
105 pub fn empty() -> Code<T> {
109 Code {
110 symbols: vec![],
111 code: vec![],
112 data: vec![],
113 labels: vec![],
114 }
115 }
116
117 pub fn symbols(&self) -> &[(usize, String)] {
121 self.symbols.as_slice()
122 }
123
124 pub fn code(&self) -> &[usize] {
134 self.code.as_slice()
135 }
136
137 pub fn data(&self) -> &[T] {
139 self.data.as_slice()
140 }
141
142 pub fn labels(&self) -> &[(usize, String)] {
147 self.labels.as_slice()
148 }
149
150 pub fn get_label_ip(&self, name: &str) -> Option<usize> {
154 for label in self.labels.as_slice() {
155 if label.1 == name {
156 return Some(label.0);
157 }
158 }
159 None
160 }
161}
162
163impl<'a, T: fmt::Debug + PartialEq> From<Builder<'a, T>> for Code<T> {
164 fn from(builder: Builder<T>) -> Code<T> {
168 let symbols = builder.instruction_table.symbols();
169 let code = builder.instructions;
170 let data = builder.data;
171 let mut labels = vec![];
172 for key in builder.labels.keys() {
173 let idx = builder.labels.get(&key).unwrap();
174 labels.push((*idx, key.clone()));
175 }
176 labels.sort_by(|lhs, rhs| lhs.0.cmp(&rhs.0));
177
178 Code {
179 symbols,
180 code,
181 data,
182 labels,
183 }
184 }
185}
186
187#[cfg(test)]
188mod test {
189 use super::*;
190 use crate::from_byte_code::FromByteCode;
191 use crate::instruction::Instruction;
192 use crate::instruction_table::InstructionTable;
193 use crate::machine::Machine;
194 use crate::to_byte_code::ToByteCode;
195 use rmp::{decode, encode};
196 use std::io::{Read, Write};
197
198 impl ToByteCode for usize {
199 fn to_byte_code(&self, mut buf: &mut Write) {
200 encode::write_uint(&mut buf, *self as u64).unwrap();
201 }
202 }
203
204 impl FromByteCode for usize {
205 fn from_byte_code(mut buf: &mut Read) -> usize {
206 decode::read_int(&mut buf).unwrap()
207 }
208 }
209
210 fn noop(_machine: &mut Machine<usize>, _args: &[usize]) {}
211
212 fn example_instruction_table() -> InstructionTable<usize> {
213 let mut it = InstructionTable::new();
214 it.insert(Instruction::new(0, "noop", 0, noop));
215 it.insert(Instruction::new(1, "push", 1, noop));
216 it.insert(Instruction::new(2, "pop", 0, noop));
217 it
218 }
219
220 #[test]
221 fn from_builder() {
222 let it = example_instruction_table();
223 let mut builder: Builder<usize> = Builder::new(&it);
224 builder.push("push", vec![13]);
225 builder.push("push", vec![14]);
226 let code: Code<usize> = Code::from(builder);
227
228 assert_eq!(code.symbols().len(), 3);
229 assert_eq!(code.symbols()[0], (0 as usize, "noop".to_string()));
230 assert_eq!(code.symbols()[1], (1 as usize, "push".to_string()));
231 assert_eq!(code.symbols()[2], (2 as usize, "pop".to_string()));
232
233 assert_eq!(code.code(), [1, 1, 0, 1, 1, 1]);
234 assert_eq!(code.data(), [13, 14]);
235 assert_eq!(code.labels().len(), 1);
236 assert_eq!(code.labels()[0], (0 as usize, "main".to_string()));
237 }
238
239 #[test]
240 fn get_label_ip() {
241 let it = example_instruction_table();
242 let builder: Builder<usize> = Builder::new(&it);
243 let code: Code<usize> = Code::from(builder);
244 assert_eq!(code.get_label_ip("main").unwrap(), 0);
245 }
246
247 #[test]
248 fn debug_formatter() {
249 let it = example_instruction_table();
250 let mut builder: Builder<usize> = Builder::new(&it);
251 builder.push("noop", vec![]);
252 builder.push("push", vec![123]);
253 builder.push("push", vec![456]);
254 builder.label("some_function");
255 builder.push("pop", vec![]);
256 let code = Code::from(builder);
257
258 let actual = format!("{:?}", code);
259 let expected = "@0 = 123
260@1 = 456
261
262.main:
263\tnoop
264\tpush @0
265\tpush @1
266
267.some_function:
268\tpop
269";
270 assert_eq!(actual, expected);
271 }
272
273 #[test]
274 fn to_byte_code() {
275 let it = example_instruction_table();
276 let mut builder: Builder<usize> = Builder::new(&it);
277 builder.push("noop", vec![]);
278 builder.push("push", vec![123]);
279 builder.push("push", vec![456]);
280 builder.label("some_function");
281 builder.push("pop", vec![]);
282 let code = Code::from(builder);
283 let mut actual: Vec<u8> = vec![];
284 code.to_byte_code(&mut actual);
285 let expected = [
286 132, 164, 99, 111, 100, 101, 154, 0, 0, 1, 1, 0, 1, 1, 1, 2, 0, 164, 100, 97, 116, 97,
287 146, 123, 205, 1, 200, 167, 115, 121, 109, 98, 111, 108, 115, 150, 0, 164, 110, 111,
288 111, 112, 1, 164, 112, 117, 115, 104, 2, 163, 112, 111, 112, 166, 108, 97, 98, 101,
289 108, 115, 148, 0, 164, 109, 97, 105, 110, 8, 173, 115, 111, 109, 101, 95, 102, 117,
290 110, 99, 116, 105, 111, 110,
291 ];
292 assert_eq!(&actual[..], &expected[..]);
293 }
294
295 #[test]
296 fn from_byte_code() {
297 let bytecode: [u8; 82] = [
298 132, 164, 99, 111, 100, 101, 154, 0, 0, 1, 1, 0, 1, 1, 1, 2, 0, 164, 100, 97, 116, 97,
299 146, 123, 205, 1, 200, 167, 115, 121, 109, 98, 111, 108, 115, 150, 0, 164, 110, 111,
300 111, 112, 1, 164, 112, 117, 115, 104, 2, 163, 112, 111, 112, 166, 108, 97, 98, 101,
301 108, 115, 148, 0, 164, 109, 97, 105, 110, 8, 173, 115, 111, 109, 101, 95, 102, 117,
302 110, 99, 116, 105, 111, 110,
303 ];
304 let code: Code<usize> = Code::from_byte_code(&mut &bytecode[..]);
305 assert_eq!(
306 code.code,
307 [0x0, 0x0, 0x1, 0x1, 0x0, 0x1, 0x1, 0x1, 0x2, 0x0]
308 );
309 assert_eq!(code.data, [123, 456]);
310 assert_eq!(
311 code.symbols,
312 [
313 (0 as usize, "noop".to_string()),
314 (1 as usize, "push".to_string()),
315 (2 as usize, "pop".to_string())
316 ]
317 );
318 assert_eq!(
319 code.labels,
320 [
321 (0 as usize, "main".to_string()),
322 (8 as usize, "some_function".to_string())
323 ]
324 )
325 }
326}