🦀
Rustで作るBEAMライクなLanguage VM - 3
引き続き、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