在语法扩展中使用程序标识符
Use a program identifier in a syntax extension
在 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
作为参数传递?
我不这么认为。问题是,为了匹配现有的 name
标识符,您 需要 了解其语法上下文:标识符相等比较文本名称 和 完全符合语法上下文。
这是一个问题,因为您没有被告知,也无法知道周围的语法上下文 是什么。
如果你想引用它,你必须将标识符传递到宏中。
当我将其他标识符作为参数发送给宏时,我能够使用外部标识符。
我需要从呼叫站点获取 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);
}
在 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
作为参数传递?
我不这么认为。问题是,为了匹配现有的 name
标识符,您 需要 了解其语法上下文:标识符相等比较文本名称 和 完全符合语法上下文。
这是一个问题,因为您没有被告知,也无法知道周围的语法上下文 是什么。
如果你想引用它,你必须将标识符传递到宏中。
当我将其他标识符作为参数发送给宏时,我能够使用外部标识符。
我需要从呼叫站点获取 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);
}