about summary refs log tree commit diff
path: root/src/libsyntax/ext
diff options
context:
space:
mode:
Diffstat (limited to 'src/libsyntax/ext')
-rw-r--r--src/libsyntax/ext/base.rs108
-rw-r--r--src/libsyntax/ext/build.rs4
-rw-r--r--src/libsyntax/ext/deriving/generic/mod.rs3
-rw-r--r--src/libsyntax/ext/expand.rs33
-rw-r--r--src/libsyntax/ext/format.rs33
-rw-r--r--src/libsyntax/ext/source_util.rs46
6 files changed, 106 insertions, 121 deletions
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index 773daa4a4c5..b35a9456757 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -11,7 +11,7 @@
 use ast;
 use ast::Name;
 use codemap;
-use codemap::{CodeMap, Span, ExpnInfo};
+use codemap::{CodeMap, Span, ExpnId, ExpnInfo, NO_EXPANSION};
 use ext;
 use ext::expand;
 use parse;
@@ -24,7 +24,6 @@ use ext::mtwt;
 use fold::Folder;
 
 use std::collections::HashMap;
-use std::gc::{Gc, GC};
 use std::rc::Rc;
 
 // new-style macro! tt code:
@@ -203,25 +202,20 @@ impl MacResult for MacPat {
         Some(self.p)
     }
 }
-/// A convenience type for macros that return a single item.
-pub struct MacItem {
-    i: P<ast::Item>
+/// A type for macros that return multiple items.
+pub struct MacItems {
+    items: SmallVector<P<ast::Item>>
 }
-impl MacItem {
-    pub fn new(i: P<ast::Item>) -> Box<MacResult+'static> {
-        box MacItem { i: i } as Box<MacResult+'static>
+
+impl MacItems {
+    pub fn new<I: Iterator<P<ast::Item>>>(mut it: I) -> Box<MacResult+'static> {
+        box MacItems { items: it.collect() } as Box<MacResult+'static>
     }
 }
-impl MacResult for MacItem {
-    fn make_items(self: Box<MacItem>) -> Option<SmallVector<P<ast::Item>>> {
-        Some(SmallVector::one(self.i))
-    }
-    fn make_stmt(self: Box<MacItem>) -> Option<P<ast::Stmt>> {
-        Some(P(codemap::respan(
-            self.i.span,
-            ast::StmtDecl(
-                P(codemap::respan(self.i.span, ast::DeclItem(self.i))),
-                ast::DUMMY_NODE_ID))))
+
+impl MacResult for MacItems {
+    fn make_items(self: Box<MacItems>) -> Option<SmallVector<P<ast::Item>>> {
+        Some(self.items)
     }
 }
 
@@ -305,11 +299,11 @@ pub enum SyntaxExtension {
     /// based upon it.
     ///
     /// `#[deriving(...)]` is an `ItemDecorator`.
-    ItemDecorator(Box<ItemDecorator + 'static>),
+    Decorator(Box<ItemDecorator + 'static>),
 
     /// A syntax extension that is attached to an item and modifies it
     /// in-place.
-    ItemModifier(Box<ItemModifier + 'static>),
+    Modifier(Box<ItemModifier + 'static>),
 
     /// A normal, function-like syntax extension.
     ///
@@ -387,7 +381,7 @@ fn initial_syntax_expander_table() -> SyntaxEnv {
                             builtin_normal_expander(
                                     ext::log_syntax::expand_syntax_ext));
     syntax_expanders.insert(intern("deriving"),
-                            ItemDecorator(box ext::deriving::expand_meta_deriving));
+                            Decorator(box ext::deriving::expand_meta_deriving));
 
     // Quasi-quoting expanders
     syntax_expanders.insert(intern("quote_tokens"),
@@ -457,7 +451,7 @@ fn initial_syntax_expander_table() -> SyntaxEnv {
 pub struct ExtCtxt<'a> {
     pub parse_sess: &'a parse::ParseSess,
     pub cfg: ast::CrateConfig,
-    pub backtrace: Option<Gc<ExpnInfo>>,
+    pub backtrace: ExpnId,
     pub ecfg: expand::ExpansionConfig,
 
     pub mod_path: Vec<ast::Ident> ,
@@ -473,7 +467,7 @@ impl<'a> ExtCtxt<'a> {
         ExtCtxt {
             parse_sess: parse_sess,
             cfg: cfg,
-            backtrace: None,
+            backtrace: NO_EXPANSION,
             mod_path: Vec::new(),
             ecfg: ecfg,
             trace_mac: false,
@@ -501,13 +495,49 @@ impl<'a> ExtCtxt<'a> {
     pub fn parse_sess(&self) -> &'a parse::ParseSess { self.parse_sess }
     pub fn cfg(&self) -> ast::CrateConfig { self.cfg.clone() }
     pub fn call_site(&self) -> Span {
-        match self.backtrace {
+        self.codemap().with_expn_info(self.backtrace, |ei| match ei {
             Some(expn_info) => expn_info.call_site,
             None => self.bug("missing top span")
-        }
+        })
     }
     pub fn print_backtrace(&self) { }
-    pub fn backtrace(&self) -> Option<Gc<ExpnInfo>> { self.backtrace }
+    pub fn backtrace(&self) -> ExpnId { self.backtrace }
+    pub fn original_span(&self) -> Span {
+        let mut expn_id = self.backtrace;
+        let mut call_site = None;
+        loop {
+            match self.codemap().with_expn_info(expn_id, |ei| ei.map(|ei| ei.call_site)) {
+                None => break,
+                Some(cs) => {
+                    call_site = Some(cs);
+                    expn_id = cs.expn_id;
+                }
+            }
+        }
+        call_site.expect("missing expansion backtrace")
+    }
+    pub fn original_span_in_file(&self) -> Span {
+        let mut expn_id = self.backtrace;
+        let mut call_site = None;
+        loop {
+            let expn_info = self.codemap().with_expn_info(expn_id, |ei| {
+                ei.map(|ei| (ei.call_site, ei.callee.name.as_slice() == "include"))
+            });
+            match expn_info {
+                None => break,
+                Some((cs, is_include)) => {
+                    if is_include {
+                        // Don't recurse into file using "include!".
+                        break;
+                    }
+                    call_site = Some(cs);
+                    expn_id = cs.expn_id;
+                }
+            }
+        }
+        call_site.expect("missing expansion backtrace")
+    }
+
     pub fn mod_push(&mut self, i: ast::Ident) { self.mod_path.push(i); }
     pub fn mod_pop(&mut self) { self.mod_path.pop().unwrap(); }
     pub fn mod_path(&self) -> Vec<ast::Ident> {
@@ -516,22 +546,22 @@ impl<'a> ExtCtxt<'a> {
         v.extend(self.mod_path.iter().map(|a| *a));
         return v;
     }
-    pub fn bt_push(&mut self, ei: codemap::ExpnInfo) {
-        match ei {
-            ExpnInfo {call_site: cs, callee: ref callee} => {
-                self.backtrace =
-                    Some(box(GC) ExpnInfo {
-                        call_site: Span {lo: cs.lo, hi: cs.hi,
-                                         expn_info: self.backtrace.clone()},
-                        callee: (*callee).clone()
-                    });
-            }
-        }
+    pub fn bt_push(&mut self, ei: ExpnInfo) {
+        let mut call_site = ei.call_site;
+        call_site.expn_id = self.backtrace;
+        self.backtrace = self.codemap().record_expansion(ExpnInfo {
+            call_site: call_site,
+            callee: ei.callee
+        });
     }
     pub fn bt_pop(&mut self) {
         match self.backtrace {
-            Some(expn_info) => self.backtrace = expn_info.call_site.expn_info,
-            _ => self.bug("tried to pop without a push")
+            NO_EXPANSION => self.bug("tried to pop without a push"),
+            expn_id => {
+                self.backtrace = self.codemap().with_expn_info(expn_id, |expn_info| {
+                    expn_info.map_or(NO_EXPANSION, |ei| ei.call_site.expn_id)
+                });
+            }
         }
     }
     /// Emit `msg` attached to `sp`, and stop compilation immediately.
diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index 7b2613d4e8b..16ecd83180e 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -573,7 +573,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
         let field_span = Span {
             lo: sp.lo - Pos::from_uint(field_name.get().len()),
             hi: sp.hi,
-            expn_info: sp.expn_info,
+            expn_id: sp.expn_id,
         };
 
         let id = Spanned { node: ident, span: field_span };
@@ -583,7 +583,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
         let field_span = Span {
             lo: sp.lo - Pos::from_uint(idx.to_string().len()),
             hi: sp.hi,
-            expn_info: sp.expn_info,
+            expn_id: sp.expn_id,
         };
 
         let id = Spanned { node: idx, span: field_span };
diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs
index ff249495bd7..142adc9b721 100644
--- a/src/libsyntax/ext/deriving/generic/mod.rs
+++ b/src/libsyntax/ext/deriving/generic/mod.rs
@@ -181,7 +181,6 @@
 //! ~~~
 
 use std::cell::RefCell;
-use std::gc::GC;
 use std::vec;
 
 use abi::Abi;
@@ -1169,7 +1168,7 @@ impl<'a> TraitDef<'a> {
             None => cx.span_bug(self.span, "trait with empty path in generic `deriving`"),
             Some(name) => *name
         };
-        to_set.expn_info = Some(box(GC) codemap::ExpnInfo {
+        to_set.expn_id = cx.codemap().record_expansion(codemap::ExpnInfo {
             call_site: to_set,
             callee: codemap::NameAndSpan {
                 name: format!("deriving({})", trait_name),
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index 4ff9912645a..e173b93e468 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -30,8 +30,6 @@ use util::small_vector::SmallVector;
 use visit;
 use visit::Visitor;
 
-use std::gc::Gc;
-
 enum Either<L,R> {
     Left(L),
     Right(R)
@@ -161,11 +159,11 @@ fn expand_mac_invoc<T>(mac: ast::Mac, span: codemap::Span,
                         // be the root of the call stack. That's the most
                         // relevant span and it's the actual invocation of
                         // the macro.
-                        let mac_span = original_span(fld.cx);
+                        let mac_span = fld.cx.original_span();
 
                         let opt_parsed = {
                             let expanded = expandfun.expand(fld.cx,
-                                                            mac_span.call_site,
+                                                            mac_span,
                                                             marked_before.as_slice());
                             parse_thunk(expanded)
                         };
@@ -254,7 +252,7 @@ pub fn expand_item(it: P<ast::Item>, fld: &mut MacroExpander)
 
         match fld.cx.syntax_env.find(&intern(mname.get())) {
             Some(rc) => match *rc {
-                ItemDecorator(ref dec) => {
+                Decorator(ref dec) => {
                     attr::mark_used(attr);
 
                     fld.cx.bt_push(ExpnInfo {
@@ -311,7 +309,7 @@ fn expand_item_modifiers(mut it: P<ast::Item>, fld: &mut MacroExpander)
     // partition the attributes into ItemModifiers and others
     let (modifiers, other_attrs) = it.attrs.partitioned(|attr| {
         match fld.cx.syntax_env.find(&intern(attr.name().get())) {
-            Some(rc) => match *rc { ItemModifier(_) => true, _ => false },
+            Some(rc) => match *rc { Modifier(_) => true, _ => false },
             _ => false
         }
     });
@@ -330,7 +328,7 @@ fn expand_item_modifiers(mut it: P<ast::Item>, fld: &mut MacroExpander)
 
         match fld.cx.syntax_env.find(&intern(mname.get())) {
             Some(rc) => match *rc {
-                ItemModifier(ref mac) => {
+                Modifier(ref mac) => {
                     attr::mark_used(attr);
                     fld.cx.bt_push(ExpnInfo {
                         call_site: attr.span,
@@ -759,9 +757,9 @@ fn expand_pat(p: P<ast::Pat>, fld: &mut MacroExpander) -> P<ast::Pat> {
 
                     let fm = fresh_mark();
                     let marked_before = mark_tts(tts.as_slice(), fm);
-                    let mac_span = original_span(fld.cx);
+                    let mac_span = fld.cx.original_span();
                     let expanded = match expander.expand(fld.cx,
-                                        mac_span.call_site,
+                                        mac_span,
                                         marked_before.as_slice()).make_pat() {
                         Some(e) => e,
                         None => {
@@ -969,7 +967,7 @@ fn new_span(cx: &ExtCtxt, sp: Span) -> Span {
     Span {
         lo: sp.lo,
         hi: sp.hi,
-        expn_info: cx.backtrace(),
+        expn_id: cx.backtrace(),
     }
 }
 
@@ -1083,21 +1081,6 @@ fn mark_method(expr: P<ast::Method>, m: Mrk) -> P<ast::Method> {
         .expect_one("marking an item didn't return exactly one method")
 }
 
-fn original_span(cx: &ExtCtxt) -> Gc<codemap::ExpnInfo> {
-    let mut relevant_info = cx.backtrace();
-    let mut einfo = relevant_info.unwrap();
-    loop {
-        match relevant_info {
-            None => { break }
-            Some(e) => {
-                einfo = e;
-                relevant_info = einfo.call_site.expn_info;
-            }
-        }
-    }
-    return einfo;
-}
-
 /// Check that there are no macro invocations left in the AST:
 pub fn check_for_macros(sess: &parse::ParseSess, krate: &ast::Crate) {
     visit::walk_crate(&mut MacroExterminator{sess:sess}, krate);
diff --git a/src/libsyntax/ext/format.rs b/src/libsyntax/ext/format.rs
index 26586684309..b760c893a10 100644
--- a/src/libsyntax/ext/format.rs
+++ b/src/libsyntax/ext/format.rs
@@ -19,17 +19,18 @@ use parse::token;
 use ptr::P;
 
 use std::collections::HashMap;
+use std::string;
 
 #[deriving(PartialEq)]
 enum ArgumentType {
-    Known(String),
+    Known(string::String),
     Unsigned,
     String,
 }
 
 enum Position {
     Exact(uint),
-    Named(String),
+    Named(string::String),
 }
 
 struct Context<'a, 'b:'a> {
@@ -44,12 +45,12 @@ struct Context<'a, 'b:'a> {
     /// Note that we keep a side-array of the ordering of the named arguments
     /// found to be sure that we can translate them in the same order that they
     /// were declared in.
-    names: HashMap<String, P<ast::Expr>>,
-    name_types: HashMap<String, ArgumentType>,
-    name_ordering: Vec<String>,
+    names: HashMap<string::String, P<ast::Expr>>,
+    name_types: HashMap<string::String, ArgumentType>,
+    name_ordering: Vec<string::String>,
 
     /// The latest consecutive literal strings, or empty if there weren't any.
-    literal: String,
+    literal: string::String,
 
     /// Collection of the compiled `rt::Argument` structures
     pieces: Vec<P<ast::Expr>>,
@@ -58,7 +59,7 @@ struct Context<'a, 'b:'a> {
     /// Stays `true` if all formatting parameters are default (as in "{}{}").
     all_pieces_simple: bool,
 
-    name_positions: HashMap<String, uint>,
+    name_positions: HashMap<string::String, uint>,
     method_statics: Vec<P<ast::Item>>,
 
     /// Updated as arguments are consumed or methods are entered
@@ -81,10 +82,10 @@ pub enum Invocation {
 ///           named arguments))
 fn parse_args(ecx: &mut ExtCtxt, sp: Span, allow_method: bool,
               tts: &[ast::TokenTree])
-    -> (Invocation, Option<(P<ast::Expr>, Vec<P<ast::Expr>>, Vec<String>,
-                            HashMap<String, P<ast::Expr>>)>) {
+    -> (Invocation, Option<(P<ast::Expr>, Vec<P<ast::Expr>>, Vec<string::String>,
+                            HashMap<string::String, P<ast::Expr>>)>) {
     let mut args = Vec::new();
-    let mut names = HashMap::<String, P<ast::Expr>>::new();
+    let mut names = HashMap::<string::String, P<ast::Expr>>::new();
     let mut order = Vec::new();
 
     let mut p = ecx.new_parser_from_tts(tts);
@@ -167,7 +168,7 @@ impl<'a, 'b> Context<'a, 'b> {
     fn verify_piece(&mut self, p: &parse::Piece) {
         match *p {
             parse::String(..) => {}
-            parse::Argument(ref arg) => {
+            parse::NextArgument(ref arg) => {
                 // width/precision first, if they have implicit positional
                 // parameters it makes more sense to consume them first.
                 self.verify_count(arg.format.width);
@@ -222,7 +223,7 @@ impl<'a, 'b> Context<'a, 'b> {
         }
     }
 
-    fn describe_num_args(&self) -> String {
+    fn describe_num_args(&self) -> string::String {
         match self.args.len() {
             0 => "no arguments given".to_string(),
             1 => "there is 1 argument".to_string(),
@@ -391,7 +392,7 @@ impl<'a, 'b> Context<'a, 'b> {
                 self.literal.push_str(s);
                 None
             }
-            parse::Argument(ref arg) => {
+            parse::NextArgument(ref arg) => {
                 // Translate the position
                 let pos = match arg.position {
                     // These two have a direct mapping
@@ -747,8 +748,8 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, sp: Span,
                                     invocation: Invocation,
                                     efmt: P<ast::Expr>,
                                     args: Vec<P<ast::Expr>>,
-                                    name_ordering: Vec<String>,
-                                    names: HashMap<String, P<ast::Expr>>)
+                                    name_ordering: Vec<string::String>,
+                                    names: HashMap<string::String, P<ast::Expr>>)
                                     -> P<ast::Expr> {
     let arg_types = Vec::from_fn(args.len(), |_| None);
     let mut cx = Context {
@@ -761,7 +762,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, sp: Span,
         name_ordering: name_ordering,
         nest_level: 0,
         next_arg: 0,
-        literal: String::new(),
+        literal: string::String::new(),
         pieces: Vec::new(),
         str_pieces: Vec::new(),
         all_pieces_simple: true,
diff --git a/src/libsyntax/ext/source_util.rs b/src/libsyntax/ext/source_util.rs
index 5cc0ec4a122..41967b0680c 100644
--- a/src/libsyntax/ext/source_util.rs
+++ b/src/libsyntax/ext/source_util.rs
@@ -11,7 +11,6 @@
 use ast;
 use codemap;
 use codemap::{Pos, Span};
-use codemap::{ExpnInfo, NameAndSpan};
 use ext::base::*;
 use ext::base;
 use ext::build::AstBuilder;
@@ -19,7 +18,6 @@ use parse;
 use parse::token;
 use print::pprust;
 
-use std::gc::Gc;
 use std::io::File;
 use std::rc::Rc;
 
@@ -32,10 +30,10 @@ pub fn expand_line(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
                    -> Box<base::MacResult+'static> {
     base::check_zero_tts(cx, sp, tts, "line!");
 
-    let topmost = topmost_expn_info(cx.backtrace().unwrap());
-    let loc = cx.codemap().lookup_char_pos(topmost.call_site.lo);
+    let topmost = cx.original_span_in_file();
+    let loc = cx.codemap().lookup_char_pos(topmost.lo);
 
-    base::MacExpr::new(cx.expr_uint(topmost.call_site, loc.line))
+    base::MacExpr::new(cx.expr_uint(topmost, loc.line))
 }
 
 /* col!(): expands to the current column number */
@@ -43,9 +41,9 @@ pub fn expand_col(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
                   -> Box<base::MacResult+'static> {
     base::check_zero_tts(cx, sp, tts, "col!");
 
-    let topmost = topmost_expn_info(cx.backtrace().unwrap());
-    let loc = cx.codemap().lookup_char_pos(topmost.call_site.lo);
-    base::MacExpr::new(cx.expr_uint(topmost.call_site, loc.col.to_uint()))
+    let topmost = cx.original_span_in_file();
+    let loc = cx.codemap().lookup_char_pos(topmost.lo);
+    base::MacExpr::new(cx.expr_uint(topmost, loc.col.to_uint()))
 }
 
 /// file!(): expands to the current filename */
@@ -55,10 +53,10 @@ pub fn expand_file(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
                    -> Box<base::MacResult+'static> {
     base::check_zero_tts(cx, sp, tts, "file!");
 
-    let topmost = topmost_expn_info(cx.backtrace().unwrap());
-    let loc = cx.codemap().lookup_char_pos(topmost.call_site.lo);
+    let topmost = cx.original_span_in_file();
+    let loc = cx.codemap().lookup_char_pos(topmost.lo);
     let filename = token::intern_and_get_ident(loc.file.name.as_slice());
-    base::MacExpr::new(cx.expr_str(topmost.call_site, filename))
+    base::MacExpr::new(cx.expr_str(topmost, filename))
 }
 
 pub fn expand_stringify(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
@@ -162,32 +160,6 @@ pub fn expand_include_bin(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
     }
 }
 
-// recur along an ExpnInfo chain to find the original expression
-fn topmost_expn_info(expn_info: Gc<codemap::ExpnInfo>) -> Gc<codemap::ExpnInfo> {
-    match *expn_info {
-        ExpnInfo { call_site: ref call_site, .. } => {
-            match call_site.expn_info {
-                Some(next_expn_info) => {
-                    match *next_expn_info {
-                        ExpnInfo {
-                            callee: NameAndSpan { name: ref name, .. },
-                            ..
-                        } => {
-                            // Don't recurse into file using "include!"
-                            if "include" == name.as_slice() {
-                                expn_info
-                            } else {
-                                topmost_expn_info(next_expn_info)
-                            }
-                        }
-                    }
-                },
-                None => expn_info
-            }
-        }
-    }
-}
-
 // resolve a file-system path to an absolute file-system path (if it
 // isn't already)
 fn res_rel_file(cx: &mut ExtCtxt, sp: codemap::Span, arg: &Path) -> Path {