diff options
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/ast.rs | 19 | ||||
| -rw-r--r-- | src/libsyntax/ast_map.rs | 32 | ||||
| -rw-r--r-- | src/libsyntax/ast_util.rs | 75 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/generic/mod.rs | 14 | ||||
| -rw-r--r-- | src/libsyntax/ext/expand.rs | 28 | ||||
| -rw-r--r-- | src/libsyntax/fold.rs | 21 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 16 | ||||
| -rw-r--r-- | src/libsyntax/print/pprust.rs | 31 | ||||
| -rw-r--r-- | src/libsyntax/visit.rs | 32 |
9 files changed, 174 insertions, 94 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index dd830401443..98318312d58 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -633,6 +633,8 @@ pub type Mac = Spanned<Mac_>; /// There's only one flavor, now, so this could presumably be simplified. #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] pub enum Mac_ { + // NB: the additional ident for a macro_rules-style macro is actually + // stored in the enclosing item. Oog. MacInvocTT(Path, Vec<TokenTree> , SyntaxContext), // new macro-invocation } @@ -950,19 +952,20 @@ pub enum ExplicitSelf_ { pub type ExplicitSelf = Spanned<ExplicitSelf_>; -// Represents a method declaration #[deriving(PartialEq, Eq, Encodable, Decodable, Hash)] pub struct Method { - pub ident: Ident, pub attrs: Vec<Attribute>, - pub generics: Generics, - pub explicit_self: ExplicitSelf, - pub fn_style: FnStyle, - pub decl: P<FnDecl>, - pub body: P<Block>, pub id: NodeId, pub span: Span, - pub vis: Visibility, + pub node: Method_ +} + +#[deriving(PartialEq, Eq, Encodable, Decodable, Hash)] +pub enum Method_ { + /// Represents a method declaration + MethDecl(Ident, Generics, ExplicitSelf, FnStyle, P<FnDecl>, P<Block>, Visibility), + /// Represents a macro in method position + MethMac(Mac), } #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] diff --git a/src/libsyntax/ast_map.rs b/src/libsyntax/ast_map.rs index de2ecd9a264..d0a0c4fe380 100644 --- a/src/libsyntax/ast_map.rs +++ b/src/libsyntax/ast_map.rs @@ -304,8 +304,10 @@ impl Map { } } + /// returns the name associated with the given NodeId's AST pub fn get_path_elem(&self, id: NodeId) -> PathElem { - match self.get(id) { + let node = self.get(id); + match node { NodeItem(item) => { match item.node { ItemMod(_) | ItemForeignMod(_) => { @@ -315,13 +317,19 @@ impl Map { } } NodeForeignItem(i) => PathName(i.ident.name), - NodeMethod(m) => PathName(m.ident.name), + NodeMethod(m) => match m.node { + MethDecl(ident, _, _, _, _, _, _) => PathName(ident.name), + MethMac(_) => fail!("no path elem for {:?}", node) + }, NodeTraitMethod(tm) => match *tm { Required(ref m) => PathName(m.ident.name), - Provided(ref m) => PathName(m.ident.name) + Provided(m) => match m.node { + MethDecl(ident, _, _, _, _, _, _) => PathName(ident.name), + MethMac(_) => fail!("no path elem for {:?}", node), + } }, NodeVariant(v) => PathName(v.node.name.name), - node => fail!("no path elem for {:?}", node) + _ => fail!("no path elem for {:?}", node) } } @@ -369,6 +377,8 @@ impl Map { } } + /// Given a node ID and a closure, apply the closure to the array + /// of attributes associated with the AST corresponding to the Node ID pub fn with_attrs<T>(&self, id: NodeId, f: |Option<&[Attribute]>| -> T) -> T { let node = self.get(id); let attrs = match node { @@ -695,11 +705,15 @@ fn node_id_to_string(map: &Map, id: NodeId) -> String { let path_str = map.path_to_str_with_ident(id, item.ident); format!("foreign item {} (id={})", path_str, id) } - Some(NodeMethod(m)) => { - format!("method {} in {} (id={})", - token::get_ident(m.ident), - map.path_to_string(id), id) - } + Some(NodeMethod(m)) => match m.node { + MethDecl(ident, _, _, _, _, _, _) => + format!("method {} in {} (id={})", + token::get_ident(ident), + map.path_to_string(id), id), + MethMac(ref mac) => + format!("method macro {} (id={})", + pprust::mac_to_string(mac), id) + }, Some(NodeTraitMethod(ref tm)) => { let m = ast_util::trait_method_to_ty_method(&**tm); format!("method {} in {} (id={})", diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index cd38c9b3e98..a18d8a81ef4 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -240,32 +240,31 @@ pub fn impl_pretty_name(trait_ref: &Option<TraitRef>, ty: &Ty) -> Ident { token::gensym_ident(pretty.as_slice()) } -pub fn public_methods(ms: Vec<Gc<Method>> ) -> Vec<Gc<Method>> { - ms.move_iter().filter(|m| { - match m.vis { - Public => true, - _ => false - } - }).collect() -} - /// extract a TypeMethod from a TraitMethod. if the TraitMethod is /// a default, pull out the useful fields to make a TypeMethod +// +// NB: to be used only after expansion is complete, and macros are gone. pub fn trait_method_to_ty_method(method: &TraitMethod) -> TypeMethod { match *method { Required(ref m) => (*m).clone(), - Provided(ref m) => { - TypeMethod { - ident: m.ident, - attrs: m.attrs.clone(), - fn_style: m.fn_style, - decl: m.decl, - generics: m.generics.clone(), - explicit_self: m.explicit_self, - id: m.id, - span: m.span, - vis: m.vis, + Provided(m) => { + match m.node { + MethDecl(ident, ref generics, explicit_self, fn_style, decl, _, vis) => { + TypeMethod { + ident: ident, + attrs: m.attrs.clone(), + fn_style: fn_style, + decl: decl, + generics: generics.clone(), + explicit_self: explicit_self, + id: m.id, + span: m.span, + vis: vis, + } + }, + MethMac(_) => fail!("expected non-macro method declaration") } + } } } @@ -346,6 +345,9 @@ pub trait IdVisitingOperation { fn visit_id(&self, node_id: NodeId); } +/// A visitor that applies its operation to all of the node IDs +/// in a visitable thing. + pub struct IdVisitor<'a, O> { pub operation: &'a O, pub pass_through_items: bool, @@ -740,6 +742,38 @@ pub fn static_has_significant_address(mutbl: ast::Mutability, inline == InlineNever || inline == InlineNone } + +/// Macro invocations are guaranteed not to occur after expansion is complete. +/// extracting fields of a method requires a dynamic check to make sure that it's +/// not a macro invocation, though this check is guaranteed to succeed, assuming +/// that the invocations are indeed gone. +macro_rules! method_field_extractor { + ($fn_name:ident, $field_ty:ty, $field_pat:pat, $result:ident) => { + /// Returns the ident of a Method. To be used after expansion is complete + pub fn $fn_name<'a>(method: &'a ast::Method) -> $field_ty { + match method.node { + $field_pat => $result, + MethMac(_) => { + fail!("expected an AST without macro invocations"); + } + } + } + } +} + +// Note: this is unhygienic in the lifetime 'a. In order to fix this, we'd have to +// add :lifetime as a macro argument type, so that the 'a could be supplied by the macro +// invocation. +pub method_field_extractor!(method_ident,ast::Ident,MethDecl(ident,_,_,_,_,_,_),ident) +pub method_field_extractor!(method_generics,&'a ast::Generics, + MethDecl(_,ref generics,_,_,_,_,_),generics) +pub method_field_extractor!(method_explicit_self,&'a ast::ExplicitSelf, + MethDecl(_,_,ref explicit_self,_,_,_,_),explicit_self) +pub method_field_extractor!(method_fn_style,ast::FnStyle,MethDecl(_,_,_,fn_style,_,_,_),fn_style) +pub method_field_extractor!(method_fn_decl,P<ast::FnDecl>,MethDecl(_,_,_,_,decl,_,_),decl) +pub method_field_extractor!(method_body,P<ast::Block>,MethDecl(_,_,_,_,_,body,_),body) +pub method_field_extractor!(method_vis,ast::Visibility,MethDecl(_,_,_,_,_,_,vis),vis) + #[cfg(test)] mod test { use ast::*; @@ -765,3 +799,4 @@ mod test { .iter().map(ident_to_segment).collect::<Vec<PathSegment>>().as_slice())); } } + diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs index 7d454016d60..46efdccadec 100644 --- a/src/libsyntax/ext/deriving/generic/mod.rs +++ b/src/libsyntax/ext/deriving/generic/mod.rs @@ -648,16 +648,16 @@ impl<'a> MethodDef<'a> { // Create the method. box(GC) ast::Method { - ident: method_ident, attrs: self.attributes.clone(), - generics: fn_generics, - explicit_self: explicit_self, - fn_style: ast::NormalFn, - decl: fn_decl, - body: body_block, id: ast::DUMMY_NODE_ID, span: trait_.span, - vis: ast::Inherited, + node: ast::MethDecl(method_ident, + fn_generics, + explicit_self, + ast::NormalFn, + fn_decl, + body_block, + ast::Inherited) } } diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 6e44bfa6747..81309181bc0 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -941,21 +941,25 @@ impl<'a> Folder for PatIdentRenamer<'a> { // expand a method fn expand_method(m: &ast::Method, fld: &mut MacroExpander) -> Gc<ast::Method> { let id = fld.new_id(m.id); - let (rewritten_fn_decl, rewritten_body) - = expand_and_rename_fn_decl_and_block(m.decl,m.body,fld); - - // all of the other standard stuff: box(GC) ast::Method { - id: id, - ident: fld.fold_ident(m.ident), attrs: m.attrs.iter().map(|a| fld.fold_attribute(*a)).collect(), - generics: fold_generics(&m.generics, fld), - explicit_self: fld.fold_explicit_self(&m.explicit_self), - fn_style: m.fn_style, - decl: rewritten_fn_decl, - body: rewritten_body, + id: id, span: fld.new_span(m.span), - vis: m.vis + node: match m.node { + ast::MethDecl(ident, ref generics, ref explicit_self, fn_style, decl, body, vis) => { + let (rewritten_fn_decl, rewritten_body) + = expand_and_rename_fn_decl_and_block(decl,body,fld); + + ast::MethDecl(fld.fold_ident(ident), + fold_generics(generics, fld), + fld.fold_explicit_self(explicit_self), + fn_style, + rewritten_fn_decl, + rewritten_body, + vis) + }, + ast::MethMac(ref _mac) => fail!("expansion in method position not implemented yet!") + } } } diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 3e3b57be6e4..88c8318e1b7 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -794,16 +794,21 @@ pub fn noop_fold_foreign_item<T: Folder>(ni: &ForeignItem, pub fn noop_fold_method<T: Folder>(m: &Method, folder: &mut T) -> Gc<Method> { let id = folder.new_id(m.id); // Needs to be first, for ast_map. box(GC) Method { - id: id, - ident: folder.fold_ident(m.ident), attrs: m.attrs.iter().map(|a| folder.fold_attribute(*a)).collect(), - generics: fold_generics(&m.generics, folder), - explicit_self: folder.fold_explicit_self(&m.explicit_self), - fn_style: m.fn_style, - decl: folder.fold_fn_decl(&*m.decl), - body: folder.fold_block(m.body), + id: id, span: folder.new_span(m.span), - vis: m.vis + node: match m.node { + MethDecl(ident, ref generics, ref explicit_self, fn_style, decl, body, vis) => { + MethDecl(folder.fold_ident(ident), + fold_generics(generics, folder), + folder.fold_explicit_self(explicit_self), + fn_style, + folder.fold_fn_decl(&*decl), + folder.fold_block(body), + vis) + }, + MethMac(ref mac) => MethMac(folder.fold_mac(mac)), + } } } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 84db2bc5a22..cc3a7dc095b 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1249,16 +1249,10 @@ impl<'a> Parser<'a> { p.parse_inner_attrs_and_block(); let attrs = attrs.append(inner_attrs.as_slice()); Provided(box(GC) ast::Method { - ident: ident, attrs: attrs, - generics: generics, - explicit_self: explicit_self, - fn_style: style, - decl: d, - body: body, id: ast::DUMMY_NODE_ID, span: mk_sp(lo, hi), - vis: vis, + node: ast::MethDecl(ident, generics, explicit_self, style, d, body, vis) }) } @@ -4049,16 +4043,10 @@ impl<'a> Parser<'a> { let hi = body.span.hi; let attrs = attrs.append(inner_attrs.as_slice()); box(GC) ast::Method { - ident: ident, attrs: attrs, - generics: generics, - explicit_self: explicit_self, - fn_style: fn_style, - decl: decl, - body: body, id: ast::DUMMY_NODE_ID, span: mk_sp(lo, hi), - vis: visa, + node: ast::MethDecl(ident, generics, explicit_self, fn_style, decl, body, visa), } } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 9589a923485..615a4489a73 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -245,6 +245,10 @@ pub fn arg_to_string(arg: &ast::Arg) -> String { to_string(|s| s.print_arg(arg)) } +pub fn mac_to_string(arg: &ast::Mac) -> String { + to_string(|s| s.print_mac(arg)) +} + pub fn visibility_qualified(vis: ast::Visibility, s: &str) -> String { match vis { ast::Public => format!("pub {}", s), @@ -342,6 +346,7 @@ impl<'a> State<'a> { match self.s.last_token() { pp::End => true, _ => false } } + // is this the beginning of a line? pub fn is_bol(&mut self) -> bool { self.s.last_token().is_eof() || self.s.last_token().is_hardbreak_tok() } @@ -627,6 +632,7 @@ impl<'a> State<'a> { } } + /// Pretty-print an item pub fn print_item(&mut self, item: &ast::Item) -> IoResult<()> { try!(self.hardbreak_if_not_bol()); try!(self.maybe_print_comment(item.span.lo)); @@ -998,11 +1004,26 @@ impl<'a> State<'a> { try!(self.hardbreak_if_not_bol()); try!(self.maybe_print_comment(meth.span.lo)); try!(self.print_outer_attributes(meth.attrs.as_slice())); - try!(self.print_fn(&*meth.decl, Some(meth.fn_style), abi::Rust, - meth.ident, &meth.generics, Some(meth.explicit_self.node), - meth.vis)); - try!(word(&mut self.s, " ")); - self.print_block_with_attrs(&*meth.body, meth.attrs.as_slice()) + match meth.node { + ast::MethDecl(ident, ref generics, ref explicit_self, fn_style, decl, body, vis) => { + try!(self.print_fn(&*decl, Some(fn_style), abi::Rust, + ident, generics, Some(explicit_self.node), + vis)); + try!(word(&mut self.s, " ")); + self.print_block_with_attrs(&*body, meth.attrs.as_slice()) + }, + ast::MethMac(codemap::Spanned { node: ast::MacInvocTT(ref pth, ref tts, _), + ..}) => { + // code copied from ItemMac: + try!(self.print_path(pth, false)); + try!(word(&mut self.s, "! ")); + try!(self.cbox(indent_unit)); + try!(self.popen()); + try!(self.print_tts(tts.as_slice())); + try!(self.pclose()); + self.end() + } + } } pub fn print_outer_attributes(&mut self, diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 7caaf2f6cc1..795f19d0cfb 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -560,15 +560,21 @@ pub fn walk_fn_decl<E: Clone, V: Visitor<E>>(visitor: &mut V, pub fn walk_method_helper<E: Clone, V: Visitor<E>>(visitor: &mut V, method: &Method, env: E) { - visitor.visit_ident(method.span, method.ident, env.clone()); - visitor.visit_fn(&FkMethod(method.ident, &method.generics, method), - &*method.decl, - &*method.body, - method.span, - method.id, - env.clone()); - for attr in method.attrs.iter() { - visitor.visit_attribute(attr, env.clone()); + match method.node { + MethDecl(ident, ref generics, _, _, decl, body, _) => { + visitor.visit_ident(method.span, ident, env.clone()); + visitor.visit_fn(&FkMethod(ident, generics, method), + decl, + body, + method.span, + method.id, + env.clone()); + for attr in method.attrs.iter() { + visitor.visit_attribute(attr, env.clone()); + } + + }, + MethMac(ref mac) => visitor.visit_mac(mac, env.clone()) } } @@ -586,8 +592,12 @@ pub fn walk_fn<E: Clone, V: Visitor<E>>(visitor: &mut V, } FkMethod(_, generics, method) => { visitor.visit_generics(generics, env.clone()); - - visitor.visit_explicit_self(&method.explicit_self, env.clone()); + match method.node { + MethDecl(_, _, ref explicit_self, _, _, _, _) => + visitor.visit_explicit_self(explicit_self, env.clone()), + MethMac(ref mac) => + visitor.visit_mac(mac, env.clone()) + } } FkFnBlock(..) => {} } |
