- Context: we are writing a forth interpreter. We have something like:
#[repr(u8)]
pub enum OpCode {
}
#[derive(Debug)]
pub enum Data {
I32(i32),
F32(f32),
Str(String),
}
pub fn exec(code_stack: &mut Vec<u8>, data_stack: &mut Vec<Data>) {
code_stack.reverse();
while let Some(op_code) = code_stack.pop() {
println!("data_stack: {:?}", data_stack);
match op_code {
1u8 => { // print
let x = data_stack.pop().unwrap();
println!("{:?}", x); },
2u8 => { // +
let rhs = data_stack.pop().unwrap();
let lhs = data_stack.pop().unwrap();
match (lhs, rhs) {
(Data::I32(lhs), Data::I32(rhs)) => data_stack.push(Data::I32(lhs + rhs)),
(Data::F32(lhs), Data::F32(rhs)) => data_stack.push(Data::F32(lhs + rhs)),
_ => panic!("+ fail"),
} },
3u8 => { // -
let rhs = data_stack.pop().unwrap();
let lhs = data_stack.pop().unwrap();
match (lhs, rhs) {
(Data::I32(lhs), Data::I32(rhs)) => data_stack.push(Data::I32(lhs - rhs)),
(Data::F32(lhs), Data::F32(rhs)) => data_stack.push(Data::F32(lhs - rhs)),
_ => panic!("- fail"),
} },
4u8 => { // *
let rhs = data_stack.pop().unwrap();
let lhs = data_stack.pop().unwrap();
match (lhs, rhs) {
(Data::I32(lhs), Data::I32(rhs)) => data_stack.push(Data::I32(lhs * rhs)),
(Data::F32(lhs), Data::F32(rhs)) => data_stack.push(Data::F32(lhs * rhs)),
_ => panic!("* fail"),
} },
5u8 => { // /
let rhs = data_stack.pop().unwrap();
let lhs = data_stack.pop().unwrap();
match (lhs, rhs) {
(Data::I32(lhs), Data::I32(rhs)) => data_stack.push(Data::I32(lhs / rhs)),
(Data::F32(lhs), Data::F32(rhs)) => data_stack.push(Data::F32(lhs / rhs)),
_ => panic!("/ fail"),
} },
_ => panic!(format!("unrecognized instr: {:?}", op_code))
}
}
}
#[test]
fn test_00() {
let mut code_stack = Vec::<u8>::new();
let mut data_stack = Vec::<Data>::new();
data_stack.push(Data::I32(1));
data_stack.push(Data::I32(2));
data_stack.push(Data::I32(3));
code_stack.push(2);
code_stack.push(3);
code_stack.push(1);
exec(&mut code_stack, &mut data_stack);
}
- Question: How do we create Print, Plus, Minus, Mul, Div in
enum OpCode
so that:
Print == 1
Plus == 2
Minus == 3
...
It's not enough to just have the enum, I want the actual u8 mapping (so storing Forth bitcode in file is "stable")