brain/
compiler.rs

1use instruction::{Instruction, InstructionType};
2
3#[derive(Debug)]
4pub struct Compiler {
5    code: String,
6    code_length: usize,
7    position: usize,
8    instructions: Vec<Instruction>
9}
10
11impl Compiler {
12    pub fn new(code: &str) -> Self {
13        Compiler {
14            code: code.to_owned(),
15            code_length: code.len(),
16            position: 0,
17            instructions: Vec::new(),
18        }
19    }
20
21    pub fn compile(&mut self) -> &[Instruction] {
22        let mut loop_stack: Vec<usize> = Vec::new();
23
24        while self.position < self.code_length {
25            let current = self.code.chars().nth(self.position).unwrap();
26            match current {
27                '[' => loop_stack.push(self.emit_with_arg(InstructionType::JMP_IF_ZERO, 0)),
28                ']' => {
29                    let op_ins = loop_stack[loop_stack.len() - 1];
30                    loop_stack = loop_stack[..loop_stack.len() - 1].to_vec();
31                    let close_ins_pos = self.emit_with_arg(InstructionType::JMP_IF_NOT_ZERO, op_ins);
32                    self.instructions[op_ins].argument = close_ins_pos;
33                },
34                _ => self.compile_foldable_instruction(current, InstructionType::from(current)),
35            }
36            self.position += 1;
37        }
38        &self.instructions
39    }
40
41    fn compile_foldable_instruction(&mut self, c: char, ins_type: InstructionType) {
42        let mut count = 1;
43        while self.position < self.code_length - 1 && self.code.chars().nth(self.position + 1).unwrap() == c {
44            count += 1;
45            self.position += 1;
46        }
47        self.emit_with_arg(ins_type, count);
48    }
49
50    fn emit_with_arg(&mut self, ins_type: InstructionType, arg: usize) -> usize {
51        self.instructions.push(Instruction::new(ins_type, self.position, arg));
52        self.instructions.len() - 1
53    }
54}