2016-06-02 3 views
5

Я хочу, чтобы мой процедурный макрос заменил некоторые методы BinaryOps. Как установить интервалы, чтобы при возникновении ошибок мои пользователи не были полностью смущены?Как правильно обрабатывать промежутки в процедурных макросах?

+0

Можете привести пример? Вы хотите, чтобы span выделял только BinaryOp или целое двоичное выражение? – kennytm

+0

Каждому Expr требуется пролет. У нас есть оригинальный 'BinaryOp'' Expr', оператор 'Expr' (который не изменяется, поэтому они сохраняют '' Span ''), вновь созданный 'MethodCall'' Expr' с 'Span' для обоих 'Expr' и' Ident' метода. Это те последние два «Спана», которые меня интересуют. – llogiq

ответ

1

После того, как я посмотрел на источник rustc, я пришел к выводу, что, следуя модели «расширения», вы получите наилучшие результаты. Поэтому мы сохраняем оригинал Span, но для expn_id, который мы можем получить, позвонив по телефону ExtCtxt::backtrace().

Представляется целесообразным установить это в обоих случаях, указанных в вопросе. Оператор можно рассматривать как расширенный в путь (вызов функции) и исходное двоичное выражение выражение, расширенное в вызове функции. Код:

match expr.unwrap() { 
    .. 
    Expr { node: ExprKind::Binary(Spanned { node: Add, span: op }, l, r), span, .. } => { 
     let bt = self.cx.backtrace(); // get the expansion ID 
     let path = self.cx.path(Span { expn_id: bt, ..op }, vec![crate_name, trait_name, fn_name]); 
     let epath = self.cx.expr_path(path); // path expression 
     let args_expanded = self.fold_exprs(args); 
     self.cx.expr_call(Span { expn_id: bt, ..span }, epath, args_expanded) 
     //^outer expression 
    } 
    .. 
} 
Смежные вопросы