Came across this while trying to follow the excellent Crafting Interpreters book but using Rust instead of C.
The book builds a stack based virtual machine, of which I have a simple Rust version that looks something like:
struct VM {
stack: Vec<Value>
}
impl VM {
//...
pub fn interpret(op: OpCode) {
match op {
Op::Add => {
let r = self.stack.pop();
let l = self.stack.pop();
self.stack.push(l + r);
}
// Repeated for -, *, and /
}
}
}
The book uses a C style macro to prevent copy/pasting the same code for all binops.
#define BINOP(op) \
do { \
double r = pop(); \
double l = pop(); \
push(l op r); \
} while (false)
void interpret(VM *vm, OpCode op) {
switch op {
case OP_ADD: BINOP(+); break;
case OP_SUB: BINOP(-); break;
case OP_MUL: BINOP(*); break;
case OP_DIV: BINOP(/); break;
}
I tried to do something similar using a Rust macro
macro_rules! binop {
($op:tt) => {
{
let l = self.stack.pop();
let r = self.stack.pop();
self.stack.push(l $op r) };
}
}
// ... inside VM impl ...
pub fn interpret(&mut self, op: OpCode) {
match op {
Op::Add => binop!(+)
// Repeated for -, *, and /
}
}
but the macro does know what self
is and I am not sure what the best way to make the macro aware of self
.
Is there a way to achieve something similar to the C macro in Rust?