} else {
encode_symbol(ecx, ebml_w, m.def_id.node);
}
- encode_method_argument_names(ebml_w, &*ast_method.decl);
+ encode_method_argument_names(ebml_w, method_fn_decl(&*ast_method));
}
ebml_w.end_tag();
encode_method_sort(ebml_w, 'p');
encode_inlined_item(ecx, ebml_w,
IIMethodRef(def_id, true, &*m));
- encode_method_argument_names(ebml_w, &*m.decl);
+ encode_method_argument_names(ebml_w, method_fn_decl(m));
}
}
let ident = match ii {
ast::IIItem(i) => i.ident,
ast::IIForeign(i) => i.ident,
- ast::IIMethod(_, _, m) => m.ident,
+ ast::IIMethod(_, _, m) => ast_util::method_ident(&*m),
};
debug!("Fn named: {}", token::get_ident(ident));
debug!("< Decoded inlined fn: {}::{}",
use std::collections::HashSet;
use syntax::ast;
use syntax::ast_map;
+use syntax::ast_util;
use syntax::ast_util::{local_def, is_local};
use syntax::attr::AttrMetaMethods;
use syntax::attr;
visit::walk_trait_method(self, &*trait_method, ctxt);
}
ast_map::NodeMethod(method) => {
- visit::walk_block(self, &*method.body, ctxt);
+ visit::walk_block(self, ast_util::method_body(&*method), ctxt);
}
ast_map::NodeForeignItem(foreign_item) => {
visit::walk_foreign_item(self, &*foreign_item, ctxt);
// Overwrite so that we don't warn the trait method itself.
fn visit_trait_method(&mut self, trait_method: &ast::TraitMethod, _: ()) {
match *trait_method {
- ast::Provided(ref method) => visit::walk_block(self, &*method.body, ()),
+ ast::Provided(ref method) => visit::walk_block(self,
+ ast_util::method_body(&**method), ()),
ast::Required(_) => ()
}
}
use util::ppaux;
use syntax::ast;
+use syntax::ast_util;
use syntax::codemap::Span;
use syntax::visit;
use syntax::visit::Visitor;
visit::FkItemFn(_, _, fn_style, _) =>
(true, fn_style == ast::UnsafeFn),
visit::FkMethod(_, _, method) =>
- (true, method.fn_style == ast::UnsafeFn),
+ (true, ast_util::method_fn_style(method) == ast::UnsafeFn),
_ => (false, false),
};
use syntax::ast;
use syntax::ast_map;
+use syntax::ast_util;
use syntax::ast_util::{is_local, local_def};
use syntax::attr;
use syntax::codemap::Span;
if public_ty || public_trait {
for method in methods.iter() {
- let meth_public = match method.explicit_self.node {
+ let meth_public = match ast_util::method_explicit_self(&**method).node {
ast::SelfStatic => public_ty,
_ => true,
- } && method.vis == ast::Public;
+ } && ast_util::method_vis(&**method) == ast::Public;
if meth_public || tr.is_some() {
self.exported_items.insert(method.id);
}
let imp = self.tcx.map.get_parent_did(closest_private_id);
match ty::impl_trait_ref(self.tcx, imp) {
Some(..) => return Allowable,
- _ if m.vis == ast::Public => return Allowable,
- _ => m.vis
+ _ if ast_util::method_vis(&**m) == ast::Public => return Allowable,
+ _ => ast_util::method_vis(&**m)
}
}
Some(ast_map::NodeTraitMethod(_)) => {
"visibility qualifiers have no effect on trait \
impls");
for m in methods.iter() {
- check_inherited(m.span, m.vis, "");
+ check_inherited(m.span, ast_util::method_vis(&**m), "");
}
}
for m in methods.iter() {
match *m {
ast::Provided(ref m) => {
- check_inherited(m.span, m.vis,
+ check_inherited(m.span, ast_util::method_vis(&**m),
"unnecessary visibility");
}
ast::Required(ref m) => {
match item.node {
ast::ItemImpl(_, _, _, ref methods) => {
for m in methods.iter() {
- check_inherited(tcx, m.span, m.vis);
+ check_inherited(tcx, m.span, ast_util::method_vis(&**m));
}
}
ast::ItemForeignMod(ref fm) => {
match *m {
ast::Required(..) => {}
ast::Provided(ref m) => check_inherited(tcx, m.span,
- m.vis),
+ ast_util::method_vis(&**m)),
}
}
}
// methods will be visible as `Public::foo`.
let mut found_pub_static = false;
for method in methods.iter() {
- if method.explicit_self.node == ast::SelfStatic &&
+ if ast_util::method_explicit_self(&**method).node == ast::SelfStatic &&
self.exported_items.contains(&method.id) {
found_pub_static = true;
visit::walk_method_helper(self, &**method, ());
fn method_might_be_inlined(tcx: &ty::ctxt, method: &ast::Method,
impl_src: ast::DefId) -> bool {
if attributes_specify_inlining(method.attrs.as_slice()) ||
- generics_require_inlining(&method.generics) {
+ generics_require_inlining(ast_util::method_generics(&*method)) {
return true
}
if is_local(impl_src) {
}
}
Some(ast_map::NodeMethod(method)) => {
- if generics_require_inlining(&method.generics) ||
+ if generics_require_inlining(ast_util::method_generics(&*method)) ||
attributes_specify_inlining(method.attrs.as_slice()) {
true
} else {
// Keep going, nothing to get exported
}
ast::Provided(ref method) => {
- visit::walk_block(self, &*method.body, ())
+ visit::walk_block(self, ast_util::method_body(&**method), ())
}
}
}
ast_map::NodeMethod(method) => {
let did = self.tcx.map.get_parent_did(search_item);
if method_might_be_inlined(self.tcx, &*method, did) {
- visit::walk_block(self, &*method.body, ())
+ visit::walk_block(self, ast_util::method_body(&*method), ())
}
}
// Nothing to recurse on for these
use syntax::ast::*;
use syntax::ast;
+use syntax::ast_util;
use syntax::ast_util::{local_def};
use syntax::ast_util::{walk_pat, trait_method_to_ty_method};
use syntax::ext::mtwt;
// For each method...
for method in methods.iter() {
// Add the method to the module.
- let ident = method.ident;
+ let ident = ast_util::method_ident(&**method);
let method_name_bindings =
self.add_child(ident,
new_parent.clone(),
ForbidDuplicateValues,
method.span);
- let def = match method.explicit_self.node {
+ let def = match ast_util::method_explicit_self(&**method).node {
SelfStatic => {
// Static methods become
// `def_static_method`s.
DefStaticMethod(local_def(method.id),
FromImpl(local_def(
item.id)),
- method.fn_style)
+ ast_util::method_fn_style(&**method))
}
_ => {
// Non-static methods become
}
};
- let is_public = method.vis == ast::Public;
+ let is_public = ast_util::method_vis(&**method) == ast::Public;
method_name_bindings.define_value(def,
method.span,
is_public);
fn resolve_method(&mut self,
rib_kind: RibKind,
method: &Method) {
- let method_generics = &method.generics;
+ let method_generics = ast_util::method_generics(method);
let type_parameters = HasTypeParameters(method_generics,
FnSpace,
method.id,
rib_kind);
- self.resolve_function(rib_kind, Some(method.decl), type_parameters, method.body);
+ self.resolve_function(rib_kind, Some(ast_util::method_fn_decl(method)),
+ type_parameters,
+ ast_util::method_body(method));
}
fn with_current_self_type<T>(&mut self, self_type: &Ty, f: |&mut Resolver| -> T) -> T {
fn check_trait_method(&self, method: &Method) {
// If there is a TraitRef in scope for an impl, then the method must be in the trait.
for &(did, ref trait_ref) in self.current_trait_ref.iter() {
- let method_name = method.ident.name;
+ let method_name = ast_util::method_ident(method).name;
if self.method_map.borrow().find(&(method_name, did)).is_none() {
let path_str = self.path_idents_to_string(&trait_ref.path);
},
};
- qualname.push_str(get_ident(method.ident).get());
+ qualname.push_str(get_ident(ast_util::method_ident(&*method)).get());
let qualname = qualname.as_slice();
// record the decl for this def (if it has one)
decl_id,
scope_id);
- self.process_formals(&method.decl.inputs, qualname, e);
+ let m_decl = ast_util::method_fn_decl(&*method);
+ self.process_formals(&m_decl.inputs, qualname, e);
// walk arg and return types
- for arg in method.decl.inputs.iter() {
+ for arg in m_decl.inputs.iter() {
self.visit_ty(&*arg.ty, e);
}
- self.visit_ty(&*method.decl.output, e);
+ self.visit_ty(m_decl.output, e);
// walk the fn body
- self.visit_block(&*method.body, DxrVisitorEnv::new_nested(method.id));
+ self.visit_block(ast_util::method_body(&*method), DxrVisitorEnv::new_nested(method.id));
- self.process_generic_params(&method.generics,
+ self.process_generic_params(ast_util::method_generics(&*method),
method.span,
qualname,
method.id,
}
}
ast_map::NodeMethod(ref method) => {
- (method.ident,
- method.decl,
- &method.generics,
- method.body,
+ (ast_util::method_ident(&**method),
+ ast_util::method_fn_decl(&**method),
+ ast_util::method_generics(&**method),
+ ast_util::method_body(&**method),
method.span,
true)
}
ast_map::NodeTraitMethod(ref trait_method) => {
match **trait_method {
ast::Provided(ref method) => {
- (method.ident,
- method.decl,
- &method.generics,
- method.body,
+ (ast_util::method_ident(&**method),
+ ast_util::method_fn_decl(&**method),
+ ast_util::method_generics(&**method),
+ ast_util::method_body(&**method),
method.span,
true)
}
let impl_tpt = ty::lookup_item_type(ccx.tcx(), impl_did);
let unparameterized =
impl_tpt.generics.types.is_empty() &&
- mth.generics.ty_params.is_empty();
+ ast_util::method_generics(&*mth).ty_params.is_empty();
if unparameterized {
let llfn = get_item_val(ccx, mth.id);
- trans_fn(ccx, &*mth.decl, &*mth.body, llfn,
+ trans_fn(ccx, ast_util::method_fn_decl(&*mth),
+ ast_util::method_body(&*mth), llfn,
¶m_substs::empty(), mth.id, []);
}
local_def(mth.id)
use std::gc::Gc;
use syntax::abi::Rust;
use syntax::parse::token;
-use syntax::{ast, ast_map, visit};
+use syntax::{ast, ast_map, visit, ast_util};
/**
The main "translation" pass for methods. Generates code
return;
}
for method in methods.iter() {
- if method.generics.ty_params.len() == 0u {
+ if ast_util::method_generics(&**method).ty_params.len() == 0u {
let llfn = get_item_val(ccx, method.id);
- trans_fn(ccx, &*method.decl, &*method.body,
+ trans_fn(ccx, ast_util::method_fn_decl(&**method),
+ ast_util::method_body(&**method),
llfn, ¶m_substs::empty(), method.id, []);
} else {
let mut v = TransItemVisitor{ ccx: ccx };
ast_map::NodeTraitMethod(method) => {
let ident = match *method {
ast::Required(ref m) => m.ident,
- ast::Provided(ref m) => m.ident
+ ast::Provided(ref m) => ast_util::method_ident(&**m)
};
ident.name
}
use syntax::abi;
use syntax::ast;
use syntax::ast_map;
+use syntax::ast_util;
use syntax::ast_util::local_def;
use std::hash::{sip, Hash};
ast_map::NodeMethod(mth) => {
let d = mk_lldecl();
set_llvm_fn_attrs(mth.attrs.as_slice(), d);
- trans_fn(ccx, &*mth.decl, &*mth.body, d, &psubsts, mth.id, []);
+ trans_fn(ccx, ast_util::method_fn_decl(&*mth),
+ ast_util::method_body(&*mth), d, &psubsts, mth.id, []);
d
}
ast_map::NodeTraitMethod(method) => {
ast::Provided(mth) => {
let d = mk_lldecl();
set_llvm_fn_attrs(mth.attrs.as_slice(), d);
- trans_fn(ccx, &*mth.decl, &*mth.body, d, &psubsts, mth.id, []);
+ trans_fn(ccx, ast_util::method_fn_decl(&*mth),
+ ast_util::method_body(&*mth), d, &psubsts, mth.id, []);
d
}
_ => {
let method_def_id = local_def(method.id);
let method_ty = ty::method(ccx.tcx, method_def_id);
let method_generics = &method_ty.generics;
+ let m_body = ast_util::method_body(&*method);
let param_env = ty::construct_parameter_environment(ccx.tcx,
method_generics,
- method.body.id);
+ m_body.id);
let fty = ty::node_id_to_type(ccx.tcx, method.id);
- check_bare_fn(ccx, &*method.decl, &*method.body, method.id, fty, param_env);
+ check_bare_fn(ccx, ast_util::method_fn_decl(&*method),
+ m_body, method.id, fty, param_env);
}
fn check_impl_methods_against_trait(ccx: &CrateCtxt,
compare_impl_method(ccx.tcx,
&*impl_method_ty,
impl_method.span,
- impl_method.body.id,
+ ast_util::method_body(&**impl_method).id,
&**trait_method_ty,
&impl_trait_ref.substs);
}
for trait_method in trait_methods.iter() {
let is_implemented =
impl_methods.iter().any(
- |m| m.ident.name == trait_method.ident.name);
+ |m| ast_util::method_ident(&**m).name == trait_method.ident.name);
let is_provided =
provided_methods.iter().any(
|m| m.ident.name == trait_method.ident.name);
use syntax::ast::{TraitTyParamBound, UnboxedFnTyParamBound};
use syntax::ast;
use syntax::ast_map;
-use syntax::ast_util::{local_def, split_trait_methods};
+use syntax::ast_util;
+use syntax::ast_util::{local_def, method_ident, split_trait_methods};
use syntax::codemap::Span;
use syntax::codemap;
use syntax::owned_slice::OwnedSlice;
&ast::Provided(ref m) => {
ty_method_of_trait_method(
ccx, trait_id, &trait_def.generics,
- &m.id, &m.ident, &m.explicit_self,
- &m.generics, &m.fn_style, &*m.decl)
+ &m.id, &ast_util::method_ident(&**m),
+ ast_util::method_explicit_self(&**m),
+ ast_util::method_generics(&**m),
+ &ast_util::method_fn_style(&**m),
+ ast_util::method_fn_decl(&**m))
}
});
let tcx = ccx.tcx;
let mut seen_methods = HashSet::new();
for m in ms.iter() {
- if !seen_methods.insert(m.ident.repr(ccx.tcx)) {
+ if !seen_methods.insert(ast_util::method_ident(&**m).repr(tcx)) {
tcx.sess.span_err(m.span, "duplicate method in trait impl");
}
rcvr_visibility));
let fty = ty::mk_bare_fn(tcx, mty.fty.clone());
debug!("method {} (id {}) has type {}",
- m.ident.repr(ccx.tcx),
+ method_ident(&**m).repr(tcx),
m.id,
- fty.repr(ccx.tcx));
+ fty.repr(tcx));
tcx.tcache.borrow_mut().insert(
local_def(m.id),
Polytype {
rcvr_visibility: ast::Visibility)
-> ty::Method
{
- let fty = astconv::ty_of_method(ccx, m.id, m.fn_style,
+ let fty = astconv::ty_of_method(ccx, m.id, ast_util::method_fn_style(&*m),
untransformed_rcvr_ty,
- m.explicit_self, &*m.decl);
+ *ast_util::method_explicit_self(&*m),
+ ast_util::method_fn_decl(&*m));
// if the method specifies a visibility, use that, otherwise
// inherit the visibility from the impl (so `foo` in `pub impl
// { fn foo(); }` is public, but private in `priv impl { fn
// foo(); }`).
- let method_vis = m.vis.inherit_from(rcvr_visibility);
+ let method_vis = ast_util::method_vis(&*m).inherit_from(rcvr_visibility);
let m_ty_generics =
- ty_generics_for_fn_or_method(ccx, &m.generics,
+ ty_generics_for_fn_or_method(ccx, ast_util::method_generics(&*m),
(*rcvr_ty_generics).clone());
- ty::Method::new(m.ident,
+ ty::Method::new(ast_util::method_ident(&*m),
m_ty_generics,
fty,
- m.explicit_self.node,
+ ast_util::method_explicit_self(&*m).node,
method_vis,
local_def(m.id),
container,
Some(ref node) => match *node {
ast_map::NodeItem(ref item) => {
match item.node {
- ast::ItemFn(ref fn_decl, ref pur, _, ref gen, _) => {
+ ast::ItemFn(fn_decl, ref pur, _, ref gen, _) => {
Some((fn_decl, gen, *pur, item.ident, None, item.span))
},
_ => None
}
}
ast_map::NodeMethod(ref m) => {
- Some((&m.decl, &m.generics, m.fn_style,
- m.ident, Some(m.explicit_self.node), m.span))
+ Some((ast_util::method_fn_decl(&**m),
+ ast_util::method_generics(&**m),
+ ast_util::method_fn_style(&**m),
+ ast_util::method_ident(&**m),
+ Some(ast_util::method_explicit_self(&**m).node), m.span))
},
_ => None
},
= node_inner.expect("expect item fn");
let taken = lifetimes_in_scope(self.tcx, scope_id);
let life_giver = LifeGiver::with_taken(taken.as_slice());
- let rebuilder = Rebuilder::new(self.tcx, *fn_decl, expl_self,
+ let rebuilder = Rebuilder::new(self.tcx, fn_decl, expl_self,
generics, same_regions, &life_giver);
let (fn_decl, expl_self, generics) = rebuilder.rebuild();
self.give_expl_lifetime_param(&fn_decl, fn_style, ident,
_ => None
},
ast_map::NodeMethod(m) => {
- taken.push_all(m.generics.lifetimes.as_slice());
+ taken.push_all(ast_util::method_generics(&*m).lifetimes.as_slice());
Some(m.id)
},
_ => None
impl Clean<Item> for ast::Method {
fn clean(&self) -> Item {
- let inputs = match self.explicit_self.node {
- ast::SelfStatic => self.decl.inputs.as_slice(),
- _ => self.decl.inputs.slice_from(1)
+ let fn_decl = ast_util::method_fn_decl(self);
+ let inputs = match ast_util::method_explicit_self(self).node {
+ ast::SelfStatic => fn_decl.inputs.as_slice(),
+ _ => fn_decl.inputs.slice_from(1)
};
let decl = FnDecl {
inputs: Arguments {
values: inputs.iter().map(|x| x.clean()).collect(),
},
- output: (self.decl.output.clean()),
- cf: self.decl.cf.clean(),
+ output: (fn_decl.output.clean()),
+ cf: fn_decl.cf.clean(),
attrs: Vec::new()
};
Item {
- name: Some(self.ident.clean()),
+ name: Some(ast_util::method_ident(self).clean()),
attrs: self.attrs.clean().move_iter().collect(),
source: self.span.clean(),
def_id: ast_util::local_def(self.id),
- visibility: self.vis.clean(),
+ visibility: ast_util::method_vis(self).clean(),
stability: get_stability(ast_util::local_def(self.id)),
inner: MethodItem(Method {
- generics: self.generics.clean(),
- self_: self.explicit_self.node.clean(),
- fn_style: self.fn_style.clone(),
+ generics: ast_util::method_generics(self).clean(),
+ self_: ast_util::method_explicit_self(self).node.clean(),
+ fn_style: ast_util::method_fn_style(self).clone(),
decl: decl,
}),
}
/// 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
}
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)]
}
}
+ /// 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(_) => {
}
}
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)
}
}
}
}
+ /// 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 {
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={})",
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")
}
+
}
}
}
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,
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::*;
.iter().map(ident_to_segment).collect::<Vec<PathSegment>>().as_slice()));
}
}
+
// 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)
}
}
// 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!")
+ }
}
}
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)),
+ }
}
}
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)
})
}
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),
}
}
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),
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()
}
}
}
+ /// 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));
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,
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())
}
}
}
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(..) => {}
}