1use std::fmt::{self, Display};
2use instruction::{Instruction, InstructionType};
3
4#[allow(dead_code)]
5#[derive(Debug)]
6pub enum ByteCodeType {
7 ICONST(i32),
8 IADD(usize),
9 ISUB(usize),
10 FOWARD(usize),
11 BACKWARD(usize),
12 LOOP(usize),
13 END(usize),
14 WRITE(usize),
15 READ(usize),
16 INVALID,
17}
18
19impl<'a> From<&'a Instruction> for ByteCodeType {
20 fn from(ins: &Instruction) -> Self {
21 match ins.ins_type {
22 InstructionType::PLUS => ByteCodeType::IADD(ins.argument),
23 InstructionType::MINUS => ByteCodeType::ISUB(ins.argument),
24 InstructionType::RIGHT => ByteCodeType::FOWARD(ins.argument),
25 InstructionType::LEFT => ByteCodeType::BACKWARD(ins.argument),
26 InstructionType::JMP_IF_ZERO => ByteCodeType::LOOP(ins.argument),
27 InstructionType::JMP_IF_NOT_ZERO => ByteCodeType::END(ins.argument),
28 InstructionType::PUT_CHAR => ByteCodeType::WRITE(ins.argument),
29 InstructionType::READ_CHAR => ByteCodeType::READ(ins.argument),
30 _ => { ByteCodeType::INVALID },
31 }
32 }
33}
34
35impl<'a> From<&'a str> for ByteCodeType {
36 fn from(line: &str) -> ByteCodeType {
37 let code_arr = line.split_whitespace().collect::<Vec<&str>>();
38 match code_arr[0] {
39 "IADD" => ByteCodeType::IADD(code_arr[1].parse().unwrap()),
40 "ISUB" => ByteCodeType::ISUB(code_arr[1].parse().unwrap()),
41 "FOWARD" => ByteCodeType::FOWARD(code_arr[1].parse().unwrap()),
42 "BACKWARD" => ByteCodeType::BACKWARD(code_arr[1].parse().unwrap()),
43 "LOOP" => ByteCodeType::LOOP(code_arr[1].parse().unwrap()),
44 "END" => ByteCodeType::END(code_arr[1].parse().unwrap()),
45 "WRITE" => ByteCodeType::WRITE(code_arr[1].parse().unwrap()),
46 "READ" => ByteCodeType::READ(code_arr[1].parse().unwrap()),
47 _ => ByteCodeType::INVALID,
48 }
49 }
50}
51
52impl Display for ByteCodeType {
53 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
54 match *self {
55 ByteCodeType::IADD(i) => write!(f, "IADD {}", i),
56 ByteCodeType::ISUB(i) => write!(f, "ISUB {}", i),
57 ByteCodeType::FOWARD(i) => write!(f, "FOWARD {}", i),
58 ByteCodeType::BACKWARD(i) => write!(f, "BACKWARD {}", i),
59 ByteCodeType::LOOP(i) => write!(f, "LOOP {}", i),
60 ByteCodeType::END(i) => write!(f, "END {}", i),
61 ByteCodeType::WRITE(i) => write!(f, "WRITE {}", i),
62 ByteCodeType::READ(i) => write!(f, "READ {}", i),
63 _ => write!(f, "{:?}", self),
64 }
65 }
66}
67
68#[derive(Debug)]
69pub struct ByteCode {
70 byte_code: Vec<ByteCodeType>,
71 memory: Vec<usize>,
72 index: usize,
73 length: usize,
74}
75
76impl ByteCode {
77 pub fn new(code: &str) -> ByteCode {
78 let bcs = code.lines().map(|bc| ByteCodeType::from(bc) ).collect::<Vec<ByteCodeType>>();
79 let length = bcs.len();
80 ByteCode {
81 byte_code: bcs,
82 memory: Vec::new(),
83 index: 0,
84 length: length,
85 }
86 }
87
88 pub fn generate_bytecode(insts: &[Instruction]) -> String {
89 insts.iter()
90 .filter(|inst| inst.ins_type != InstructionType::NEW_LINE)
91 .map(|inst| format!("{}\n", ByteCodeType::from(inst).to_string()))
92 .collect::<String>()
93 }
94
95 pub fn execute(&mut self) {
96 for (_, bc) in self.byte_code.iter().enumerate() {
97 match *bc {
98 ByteCodeType::IADD(v) => {
99 if self.memory.len() <= self.index {
100 self.memory.push(v);
101 continue
102 }
103 self.memory[self.index] += v;
104 },
105 _ => return,
106 }
107 }
108 }
109}