brain/
bytecode.rs

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}