首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >仿刻的BINARY_OP宏

仿刻的BINARY_OP宏
EN

Stack Overflow用户
提问于 2021-10-18 03:13:51
回答 1查看 114关注 0票数 0

在尝试遵循优秀的手工艺翻译书但使用锈蚀代替C的时候遇到了这种情况。

这本书构建了一个基于堆栈的虚拟机,其中我有一个简单的Rust版本,类似于:

代码语言:javascript
运行
复制
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 /
  }
}
}

本书使用C样式宏来防止复制/粘贴所有二进制文件的相同代码。

代码语言:javascript
运行
复制
#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;
  }

我试着用Rust宏做类似的事情

代码语言:javascript
运行
复制
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 /
  }
}

但是宏知道self是什么,我也不知道什么是使宏了解self的最佳方法。

是否有一种方法可以实现类似于Rust中的C宏?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-10-18 04:41:36

您可以将self作为宏的参数传递:

代码语言:javascript
运行
复制
macro_rules! binop {
    ($self:expr, $op:tt) => {{
        let l = $self.stack.pop(); 
        let r = $self.stack.pop(); 
        $self.stack.push(l $op r);
    }};
}

如果在其他地方不需要宏,也可以在函数中定义宏:

代码语言:javascript
运行
复制
pub fn interpret(&mut self, op: OpCode) {
    macro_rules! binop {
        ($op:tt) => {{
            let l = self.stack.pop(); 
            let r = self.stack.pop(); 
            self.stack.push(l $op r);
        }};
    }

    match op {
        Op::Add => binop!(+)
        // Repeated for -, *, and /
    }
}

另一种选择可以是使用闭包而不是宏:

代码语言:javascript
运行
复制
impl VM {
    pub fn interpret(&mut self, op: OpCode) {
        match op {
            OpCode::Add => self.binop(|l, r| l + r),
            OpCode::Sub => self.binop(|l, r| l - r),
            OpCode::Mul => self.binop(|l, r| l * r),
            OpCode::Div => self.binop(|l, r| l / r),
        }
    }

    pub fn binop(&mut self, f: impl Fn(Value, Value) -> Value) {
        // Of course, in a real case you should handle unwrap:
        let l = self.stack.pop().unwrap();
        let r = self.stack.pop().unwrap();
        self.stack.push(f(l, r));
    }
}
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69610395

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档