}
impl<'a, 'b> Folder for MacroExpander<'a, 'b> {
+ fn fold_crate(&mut self, c: Crate) -> Crate {
+ self.cx.filename = Some(self.cx.parse_sess.codemap().span_to_filename(c.span));
+ noop_fold_crate(c, self)
+ }
+
fn fold_expr(&mut self, expr: P<ast::Expr>) -> P<ast::Expr> {
expand_expr(expr, self)
}
}
fn fold_item(&mut self, item: P<ast::Item>) -> SmallVector<P<ast::Item>> {
- expand_item(item, self)
+ use std::mem::replace;
+ let result;
+ if let ast::ItemKind::Mod(ast::Mod { inner, .. }) = item.node {
+ if item.span.contains(inner) {
+ self.push_mod_path(item.ident, &item.attrs);
+ result = expand_item(item, self);
+ self.pop_mod_path();
+ } else {
+ let filename = if inner != codemap::DUMMY_SP {
+ Some(self.cx.parse_sess.codemap().span_to_filename(inner))
+ } else { None };
+ let orig_filename = replace(&mut self.cx.filename, filename);
+ let orig_mod_path_stack = replace(&mut self.cx.mod_path_stack, Vec::new());
+ result = expand_item(item, self);
+ self.cx.filename = orig_filename;
+ self.cx.mod_path_stack = orig_mod_path_stack;
+ }
+ } else {
+ result = expand_item(item, self);
+ }
+ result
}
fn fold_item_kind(&mut self, item: ast::ItemKind) -> ast::ItemKind {
}
fn fold_block(&mut self, block: P<Block>) -> P<Block> {
- expand_block(block, self)
+ let was_in_block = ::std::mem::replace(&mut self.cx.in_block, true);
+ let result = expand_block(block, self);
+ self.cx.in_block = was_in_block;
+ result
}
fn fold_arm(&mut self, arm: ast::Arm) -> ast::Arm {
}
}
+impl<'a, 'b> MacroExpander<'a, 'b> {
+ fn push_mod_path(&mut self, id: Ident, attrs: &[ast::Attribute]) {
+ let default_path = id.name.as_str();
+ let file_path = match ::attr::first_attr_value_str_by_name(attrs, "path") {
+ Some(d) => d,
+ None => default_path,
+ };
+ self.cx.mod_path_stack.push(file_path)
+ }
+
+ fn pop_mod_path(&mut self) {
+ self.cx.mod_path_stack.pop().unwrap();
+ }
+}
+
fn new_span(cx: &ExtCtxt, sp: Span) -> Span {
/* this discards information in the case of macro-defining macros */
Span {
use ext::tt::macro_parser::{MatchedSeq, MatchedNonterminal};
use ext::tt::macro_parser::parse;
use parse::lexer::new_tt_reader;
-use parse::parser::Parser;
+use parse::parser::{Parser, Restrictions};
use parse::token::{self, special_idents, gensym_ident, NtTT, Token};
use parse::token::Token::*;
use print;
imported_from,
rhs);
let mut p = Parser::new(cx.parse_sess(), cx.cfg(), Box::new(trncbr));
+ p.filename = cx.filename.clone();
+ p.mod_path_stack = cx.mod_path_stack.clone();
+ p.restrictions = match cx.in_block {
+ true => Restrictions::NO_NONINLINE_MOD,
+ false => Restrictions::empty(),
+ };
p.check_unknown_macro_variable();
// Let the context choose how to interpret the result.
// Weird, but useful for X-macros.