macros - 如何在 Rust 程序宏中创建多个项目?

标签 macros rust

我正在尝试创建一个宏,当这样使用时:

foo!()

扩展为两个项目,一个静态项目和一个函数。像这样:

static x: uint = 5;

fn bar() -> uint { x + 1 }

有人向我指出 MacResultmake_items 方法支持这一点,所以我只需要创建一个正确实现它的类型。我这样做了:

struct MacItems {
    items: Vec<::std::gc::Gc<Item>>,
}

impl MacResult for MacItems {
    fn make_def(&self) -> Option<::syntax::ext::base::MacroDef> { None }
    fn make_expr(&self) -> Option<::std::gc::Gc<ast::Expr>> { None }
    fn make_pat(&self) -> Option<::std::gc::Gc<ast::Pat>> { None }
    fn make_stmt(&self) -> Option<::std::gc::Gc<ast::Stmt>> { None }

    fn make_items(&self) -> Option<::syntax::util::small_vector::SmallVector<::std::gc::Gc<Item>>> {
        Some(::syntax::util::small_vector::SmallVector::many(self.items.clone()))
    }
}

我曾尝试使用 quote_item! 宏,但这个宏显然移动了 ExtCtxt,因此无法连续使用它两次。这是我的代码:

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_macro("foo", expand);
}

fn expand(cx: &mut ExtCtxt, sp: codemap::Span, _: &[ast::TokenTree]) -> Box<MacResult> {
    let mut v = vec!();

    v.push( quote_item!(cx, static x: uint = 5;).unwrap() );
    v.push( quote_item!(cx, fn bar() -> uint { x + 1 }).unwrap() );

    box MacItems { items: v } as Box<MacResult>
}

这里是错误:

test.rs:37:13: 37:57 error: use of moved value: `cx`
test.rs:37     v.push( quote_item!(cx, fn bar() -> uint { x + 1 }).unwrap() );
                                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
note: in expansion of quote_item!
test.rs:37:13: 37:57 note: expansion site
test.rs:36:13: 36:50 note: `cx` moved here because it has type `&mut syntax::ext::base::ExtCtxt<'_>`, which is moved by default (use `ref` to override)
test.rs:36     v.push( quote_item!(cx, static x: uint = 5;).unwrap() );
                                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
note: in expansion of quote_item!
test.rs:36:13: 36:50 note: expansion site
error: aborting due to previous error

我怎样才能做到这一点?我试图使用 AstBuilder::item_static 来创建静态项,但我无法确定 Ty_ 的哪个变体对应于此处的 uint。 (此外,这只是一个玩具示例,我真正的静态声明是 &'static str,因此我需要构建该项目)。

我这样做完全错了吗?如何实现?

最佳答案

您需要手动将 cx 重新借用到临时的 &mut ExtCtxt。编译器通常可以自动插入重新借用,但 quote_* 宏不会扩展到适合于此的内容。

也就是说,

quote_item!(&mut *cx, ...)

关于macros - 如何在 Rust 程序宏中创建多个项目?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25111712/

相关文章:

我可以附加到预处理器宏吗?

c - 卡在 do{} while(false) 循环中

rust - 使用 hyper 将 block 流异步写入文件

html - 如何创建 <tr><td> 宏?

macros - DrRacket 中的 While 循环宏

rust - 如何处理特征对象中的 Sized 要求?

string - 如何复制向量的第一个和最后一个元素?

compiler-errors - 为什么借用检查器会拒绝内联表达式但接受其分解形式?

rust - 如何阻塞直到两个接收器之一有可用数据?

c++ - 抑制代码内部的 "unused parameter"警告