🦀

Rustで作るBEAMライクなLanguage VM - 3

2022/02/06に公開

引き続き、BEAM-like VM in Rustをしていく。

前回の記事

今日は Part 03

オペコードを追加していって簡単な算数ができるようになった。
こんな感じ。(エッセンスだけ抜粋)

// instruction.rs
#[derive(Debug, PartialEq)]
pub enum Opcode {
    LOAD,
    ADD,
    SUB,
    MUL,
    DIV,
    HLT,
    IGL,
}
// vm.rs
fn execute_instruction(&mut self) -> bool {
    if self.pc >= self.program.len() {
        return false;
    }
    match self.decode_opcode() {
        Opcode::LOAD => {
            let target_register = self.next_8_bits() as usize;
            let number = self.next_16_bits() as u16;
            self.registers[target_register] = number as i32;
        }
        Opcode::ADD => {
            let register1 = self.registers[self.next_8_bits() as usize];
            let register2 = self.registers[self.next_8_bits() as usize];
            self.registers[self.next_8_bits() as usize] = register1 + register2;
        }
        Opcode::SUB => {
            let register1 = self.registers[self.next_8_bits() as usize];
            let register2 = self.registers[self.next_8_bits() as usize];
	    self.registers[self.next_8_bits() as usize] = register1 - register2;
        }
        Opcode::MUL => {
            let register1 = self.registers[self.next_8_bits() as usize];
            let register2 = self.registers[self.next_8_bits() as usize];
            self.registers[self.next_8_bits() as usize] = register1 * register2;
        }
        Opcode::DIV => {
            let register1 = self.registers[self.next_8_bits() as usize];
            let register2 = self.registers[self.next_8_bits() as usize];
            self.registers[self.next_8_bits() as usize] = register1 / register2;
            self.remainder = (register1 % register2) as u32;
        }
        Opcode::HLT => {
           println!("HLT encoutered");
           return false;
        }
        Opcode::IGL => {
            println!("Illegal instruction encountered");
            return false;
        }
    }
    true
}

見た目は言語処理系あるあるな感じがありつつ、レジスターベースで書くのは初めてなので新鮮な気持ち。

パターンマッチがかける言語って気持ちいいですよね。
Rust本格的にやるしかない。

おまけ

ブログの筆者がテストを逐一書いていくスタイルなので、
と前回書いたものの、どうやら今回からはコードの本体もテストもハショられていく模様。

記事を写経してもコンパイルすらしない。
そういうことってあるよね。どんまいどんまい。

公開されている完成品のリポジトリを参考にしつつ、自分なりにテストコード+コメントを書きながら記事分の内容を完了させた。

Rustの変遷もよくわかっていないのだけど、ブログの執筆当初のバージョンだとコンパイルできた、とかあるのかな。
ただ単に、教科書を読むときのように、行間を補ってくれということか。
(おそらく後者)

今回のコードはこちら。
https://github.com/ymdarake/iridium/pull/3

次回に続く

Discussion