在语法扩展

时间:2015-10-05 23:53:54

标签: macros rust

在Rust语法扩展中,我如何使用程序范围内的标识符?

例如,我们说我有以下代码:

fn test() {
    let name = "test";
    let result = my_macro!();
}

我尝试将过程宏定义如下:

fn expand_my_macro(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree]) -> Box<MacResult + 'static> {
    MacEager::expr(cx.expr_ident(sp, Ident::with_empty_ctxt(intern("name"))))
}

但是,我收到以下错误:

error: unresolved name `name` [E0425]

在用户代码中。

我知道正常的Rust宏是卫生的,但程序宏呢?

有没有办法在不必将变量name作为参数传递的情况下执行此操作?

2 个答案:

答案 0 :(得分:4)

我不相信。问题是,为了使您能够匹配现有的name标识符,需要才能知道其语法上下文:标识符相等性比较文本名称​​和完全是语法上下文。

这是一个问题,因为您没有被告知,并且无法知道周围的语法上下文

如果你想引用它,你将标识符传递给宏。

答案 1 :(得分:0)

当我将其他标识符作为参数发送到宏时,我能够使用外部标识符。

我需要从呼叫网站获取SyntaxContext

fn expand_my_macro(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree]) -> Box<MacResult + 'static> {
    if let TokenTree::TtToken(_, Token::Ident(ident, _)) = args[0] {
        let name_ident = Ident::new(intern("name"), ident.ctxt);
        MacEager::expr(cx.expr_ident(sp, name_ident)))
    }
    DummyResult::any(sp)
}

可以这样使用:

fn test() {
    let name = "test";
    let result = my_macro!(foo);
}