1 // Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
14 use codemap::{respan, Span, Spanned};
16 use owned_slice::OwnedSlice;
17 use util::small_vector::SmallVector;
20 use std::gc::{Gc, GC};
22 // We may eventually want to be able to fold over type parameters, too.
24 fn fold_crate(&mut self, c: Crate) -> Crate {
25 noop_fold_crate(c, self)
28 fn fold_meta_items(&mut self, meta_items: &[Gc<MetaItem>]) -> Vec<Gc<MetaItem>> {
29 meta_items.iter().map(|x| fold_meta_item_(*x, self)).collect()
32 fn fold_view_path(&mut self, view_path: Gc<ViewPath>) -> Gc<ViewPath> {
33 let inner_view_path = match view_path.node {
34 ViewPathSimple(ref ident, ref path, node_id) => {
35 let id = self.new_id(node_id);
36 ViewPathSimple(ident.clone(),
40 ViewPathGlob(ref path, node_id) => {
41 let id = self.new_id(node_id);
42 ViewPathGlob(self.fold_path(path), id)
44 ViewPathList(ref path, ref path_list_idents, node_id) => {
45 let id = self.new_id(node_id);
46 ViewPathList(self.fold_path(path),
47 path_list_idents.iter().map(|path_list_ident| {
48 let id = self.new_id(path_list_ident.node
51 node: PathListIdent_ {
52 name: path_list_ident.node
65 node: inner_view_path,
66 span: self.new_span(view_path.span),
70 fn fold_view_item(&mut self, vi: &ViewItem) -> ViewItem {
71 noop_fold_view_item(vi, self)
74 fn fold_foreign_item(&mut self, ni: Gc<ForeignItem>) -> Gc<ForeignItem> {
75 noop_fold_foreign_item(&*ni, self)
78 fn fold_item(&mut self, i: Gc<Item>) -> SmallVector<Gc<Item>> {
79 noop_fold_item(&*i, self)
82 fn fold_struct_field(&mut self, sf: &StructField) -> StructField {
83 let id = self.new_id(sf.node.id);
85 node: ast::StructField_ {
88 ty: self.fold_ty(sf.node.ty),
89 attrs: sf.node.attrs.iter().map(|e| self.fold_attribute(*e)).collect()
91 span: self.new_span(sf.span)
95 fn fold_item_underscore(&mut self, i: &Item_) -> Item_ {
96 noop_fold_item_underscore(i, self)
99 fn fold_fn_decl(&mut self, d: &FnDecl) -> P<FnDecl> {
100 noop_fold_fn_decl(d, self)
103 fn fold_type_method(&mut self, m: &TypeMethod) -> TypeMethod {
104 noop_fold_type_method(m, self)
107 fn fold_method(&mut self, m: Gc<Method>) -> Gc<Method> {
108 noop_fold_method(&*m, self)
111 fn fold_block(&mut self, b: P<Block>) -> P<Block> {
112 noop_fold_block(b, self)
115 fn fold_stmt(&mut self, s: &Stmt) -> SmallVector<Gc<Stmt>> {
116 noop_fold_stmt(s, self)
119 fn fold_arm(&mut self, a: &Arm) -> Arm {
121 attrs: a.attrs.iter().map(|x| self.fold_attribute(*x)).collect(),
122 pats: a.pats.iter().map(|x| self.fold_pat(*x)).collect(),
123 guard: a.guard.map(|x| self.fold_expr(x)),
124 body: self.fold_expr(a.body),
128 fn fold_pat(&mut self, p: Gc<Pat>) -> Gc<Pat> {
129 noop_fold_pat(p, self)
132 fn fold_decl(&mut self, d: Gc<Decl>) -> SmallVector<Gc<Decl>> {
133 let node = match d.node {
134 DeclLocal(ref l) => SmallVector::one(DeclLocal(self.fold_local(*l))),
136 self.fold_item(it).move_iter().map(|i| DeclItem(i)).collect()
140 node.move_iter().map(|node| {
143 span: self.new_span(d.span),
148 fn fold_expr(&mut self, e: Gc<Expr>) -> Gc<Expr> {
149 noop_fold_expr(e, self)
152 fn fold_ty(&mut self, t: P<Ty>) -> P<Ty> {
153 let id = self.new_id(t.id);
154 let node = match t.node {
155 TyNil | TyBot | TyInfer => t.node.clone(),
156 TyBox(ty) => TyBox(self.fold_ty(ty)),
157 TyUniq(ty) => TyUniq(self.fold_ty(ty)),
158 TyVec(ty) => TyVec(self.fold_ty(ty)),
159 TyPtr(ref mt) => TyPtr(fold_mt(mt, self)),
160 TyRptr(ref region, ref mt) => {
161 TyRptr(fold_opt_lifetime(region, self), fold_mt(mt, self))
163 TyClosure(ref f, ref region) => {
164 TyClosure(box(GC) ClosureTy {
165 fn_style: f.fn_style,
166 onceness: f.onceness,
167 bounds: fold_opt_bounds(&f.bounds, self),
168 decl: self.fold_fn_decl(&*f.decl),
169 lifetimes: f.lifetimes.iter().map(|l| self.fold_lifetime(l)).collect(),
170 }, fold_opt_lifetime(region, self))
173 TyProc(box(GC) ClosureTy {
174 fn_style: f.fn_style,
175 onceness: f.onceness,
176 bounds: fold_opt_bounds(&f.bounds, self),
177 decl: self.fold_fn_decl(&*f.decl),
178 lifetimes: f.lifetimes.iter().map(|l| self.fold_lifetime(l)).collect(),
182 TyBareFn(box(GC) BareFnTy {
183 lifetimes: f.lifetimes.iter().map(|l| self.fold_lifetime(l)).collect(),
184 fn_style: f.fn_style,
186 decl: self.fold_fn_decl(&*f.decl)
189 TyUnboxedFn(ref f) => {
190 TyUnboxedFn(box(GC) UnboxedFnTy {
191 decl: self.fold_fn_decl(&*f.decl),
194 TyTup(ref tys) => TyTup(tys.iter().map(|&ty| self.fold_ty(ty)).collect()),
195 TyParen(ref ty) => TyParen(self.fold_ty(*ty)),
196 TyPath(ref path, ref bounds, id) => {
197 let id = self.new_id(id);
198 TyPath(self.fold_path(path),
199 fold_opt_bounds(bounds, self),
202 TyFixedLengthVec(ty, e) => {
203 TyFixedLengthVec(self.fold_ty(ty), self.fold_expr(e))
205 TyTypeof(expr) => TyTypeof(self.fold_expr(expr)),
209 span: self.new_span(t.span),
214 fn fold_mod(&mut self, m: &Mod) -> Mod {
215 noop_fold_mod(m, self)
218 fn fold_foreign_mod(&mut self, nm: &ForeignMod) -> ForeignMod {
221 view_items: nm.view_items
223 .map(|x| self.fold_view_item(x))
227 .map(|x| self.fold_foreign_item(*x))
232 fn fold_variant(&mut self, v: &Variant) -> P<Variant> {
233 let id = self.new_id(v.node.id);
236 TupleVariantKind(ref variant_args) => {
237 kind = TupleVariantKind(variant_args.iter().map(|x|
238 fold_variant_arg_(x, self)).collect())
240 StructVariantKind(ref struct_def) => {
241 kind = StructVariantKind(box(GC) ast::StructDef {
242 fields: struct_def.fields.iter()
243 .map(|f| self.fold_struct_field(f)).collect(),
244 ctor_id: struct_def.ctor_id.map(|c| self.new_id(c)),
245 super_struct: match struct_def.super_struct {
246 Some(t) => Some(self.fold_ty(t)),
249 is_virtual: struct_def.is_virtual,
254 let attrs = v.node.attrs.iter().map(|x| self.fold_attribute(*x)).collect();
256 let de = match v.node.disr_expr {
257 Some(e) => Some(self.fold_expr(e)),
260 let node = ast::Variant_ {
270 span: self.new_span(v.span),
274 fn fold_ident(&mut self, i: Ident) -> Ident {
278 fn fold_path(&mut self, p: &Path) -> Path {
280 span: self.new_span(p.span),
282 segments: p.segments.iter().map(|segment| ast::PathSegment {
283 identifier: self.fold_ident(segment.identifier),
284 lifetimes: segment.lifetimes.iter().map(|l| self.fold_lifetime(l)).collect(),
285 types: segment.types.iter().map(|&typ| self.fold_ty(typ)).collect(),
290 fn fold_local(&mut self, l: Gc<Local>) -> Gc<Local> {
291 let id = self.new_id(l.id); // Needs to be first, for ast_map.
294 ty: self.fold_ty(l.ty),
295 pat: self.fold_pat(l.pat),
296 init: l.init.map(|e| self.fold_expr(e)),
297 span: self.new_span(l.span),
302 fn fold_mac(&mut self, macro: &Mac) -> Mac {
304 node: match macro.node {
305 MacInvocTT(ref p, ref tts, ctxt) => {
306 MacInvocTT(self.fold_path(p),
307 fold_tts(tts.as_slice(), self),
311 span: self.new_span(macro.span)
315 fn map_exprs(&self, f: |Gc<Expr>| -> Gc<Expr>,
316 es: &[Gc<Expr>]) -> Vec<Gc<Expr>> {
317 es.iter().map(|x| f(*x)).collect()
320 fn new_id(&mut self, i: NodeId) -> NodeId {
324 fn new_span(&mut self, sp: Span) -> Span {
328 fn fold_explicit_self(&mut self, es: &ExplicitSelf) -> ExplicitSelf {
330 span: self.new_span(es.span),
331 node: self.fold_explicit_self_(&es.node)
335 fn fold_explicit_self_(&mut self, es: &ExplicitSelf_) -> ExplicitSelf_ {
337 SelfStatic | SelfValue | SelfUniq => *es,
338 SelfRegion(ref lifetime, m) => {
339 SelfRegion(fold_opt_lifetime(lifetime, self), m)
344 fn fold_lifetime(&mut self, l: &Lifetime) -> Lifetime {
345 noop_fold_lifetime(l, self)
348 //used in noop_fold_item and noop_fold_crate
349 fn fold_attribute(&mut self, at: Attribute) -> Attribute {
351 span: self.new_span(at.span),
352 node: ast::Attribute_ {
354 style: at.node.style,
355 value: fold_meta_item_(at.node.value, self),
356 is_sugared_doc: at.node.is_sugared_doc
364 /* some little folds that probably aren't useful to have in Folder itself*/
366 //used in noop_fold_item and noop_fold_crate and noop_fold_crate_directive
367 fn fold_meta_item_<T: Folder>(mi: Gc<MetaItem>, fld: &mut T) -> Gc<MetaItem> {
371 MetaWord(ref id) => MetaWord((*id).clone()),
372 MetaList(ref id, ref mis) => {
373 MetaList((*id).clone(), mis.iter().map(|e| fold_meta_item_(*e, fld)).collect())
375 MetaNameValue(ref id, ref s) => {
376 MetaNameValue((*id).clone(), (*s).clone())
379 span: fld.new_span(mi.span) }
382 //used in noop_fold_foreign_item and noop_fold_fn_decl
383 fn fold_arg_<T: Folder>(a: &Arg, fld: &mut T) -> Arg {
384 let id = fld.new_id(a.id); // Needs to be first, for ast_map.
387 ty: fld.fold_ty(a.ty),
388 pat: fld.fold_pat(a.pat),
392 pub fn fold_tt<T: Folder>(tt: &TokenTree, fld: &mut T) -> TokenTree {
394 TTTok(span, ref tok) =>
395 TTTok(span, fold_token(tok,fld)),
396 TTDelim(ref tts) => TTDelim(Rc::new(fold_tts(tts.as_slice(), fld))),
397 TTSeq(span, ref pattern, ref sep, is_optional) =>
399 Rc::new(fold_tts(pattern.as_slice(), fld)),
400 sep.as_ref().map(|tok| fold_token(tok,fld)),
402 TTNonterminal(sp,ref ident) =>
403 TTNonterminal(sp,fld.fold_ident(*ident))
407 pub fn fold_tts<T: Folder>(tts: &[TokenTree], fld: &mut T) -> Vec<TokenTree> {
408 tts.iter().map(|tt| fold_tt(tt,fld)).collect()
412 // apply ident folder if it's an ident, apply other folds to interpolated nodes
413 fn fold_token<T: Folder>(t: &token::Token, fld: &mut T) -> token::Token {
415 token::IDENT(id, followed_by_colons) => {
416 token::IDENT(fld.fold_ident(id), followed_by_colons)
418 token::LIFETIME(id) => token::LIFETIME(fld.fold_ident(id)),
419 token::INTERPOLATED(ref nt) => token::INTERPOLATED(fold_interpolated(nt,fld)),
424 // apply folder to elements of interpolated nodes
426 // NB: this can occur only when applying a fold to partially expanded code, where
427 // parsed pieces have gotten implanted ito *other* macro invocations. This is relevant
428 // for macro hygiene, but possibly not elsewhere.
430 // One problem here occurs because the types for fold_item, fold_stmt, etc. allow the
431 // folder to return *multiple* items; this is a problem for the nodes here, because
432 // they insist on having exactly one piece. One solution would be to mangle the fold
433 // trait to include one-to-many and one-to-one versions of these entry points, but that
434 // would probably confuse a lot of people and help very few. Instead, I'm just going
435 // to put in dynamic checks. I think the performance impact of this will be pretty much
436 // nonexistent. The danger is that someone will apply a fold to a partially expanded
437 // node, and will be confused by the fact that their "fold_item" or "fold_stmt" isn't
438 // getting called on NtItem or NtStmt nodes. Hopefully they'll wind up reading this
439 // comment, and doing something appropriate.
441 // BTW, design choice: I considered just changing the type of, e.g., NtItem to contain
442 // multiple items, but decided against it when I looked at parse_item_or_view_item and
443 // tried to figure out what I would do with multiple items there....
444 fn fold_interpolated<T: Folder>(nt : &token::Nonterminal, fld: &mut T) -> token::Nonterminal {
446 token::NtItem(item) =>
447 token::NtItem(fld.fold_item(item)
448 .expect_one("expected fold to produce exactly one item")),
449 token::NtBlock(block) => token::NtBlock(fld.fold_block(block)),
450 token::NtStmt(stmt) =>
451 token::NtStmt(fld.fold_stmt(stmt)
452 .expect_one("expected fold to produce exactly one statement")),
453 token::NtPat(pat) => token::NtPat(fld.fold_pat(pat)),
454 token::NtExpr(expr) => token::NtExpr(fld.fold_expr(expr)),
455 token::NtTy(ty) => token::NtTy(fld.fold_ty(ty)),
456 token::NtIdent(ref id, is_mod_name) =>
457 token::NtIdent(box fld.fold_ident(**id),is_mod_name),
458 token::NtMeta(meta_item) => token::NtMeta(fold_meta_item_(meta_item,fld)),
459 token::NtPath(ref path) => token::NtPath(box fld.fold_path(*path)),
460 token::NtTT(tt) => token::NtTT(box (GC) fold_tt(tt,fld)),
461 // it looks to me like we can leave out the matchers: token::NtMatchers(matchers)
466 pub fn noop_fold_fn_decl<T: Folder>(decl: &FnDecl, fld: &mut T) -> P<FnDecl> {
468 inputs: decl.inputs.iter().map(|x| fold_arg_(x, fld)).collect(), // bad copy
469 output: fld.fold_ty(decl.output),
471 variadic: decl.variadic
475 fn fold_ty_param_bound<T: Folder>(tpb: &TyParamBound, fld: &mut T)
478 TraitTyParamBound(ref ty) => TraitTyParamBound(fold_trait_ref(ty, fld)),
479 StaticRegionTyParamBound => StaticRegionTyParamBound,
480 UnboxedFnTyParamBound(ref unboxed_function_type) => {
481 UnboxedFnTyParamBound(UnboxedFnTy {
482 decl: fld.fold_fn_decl(&*unboxed_function_type.decl),
485 OtherRegionTyParamBound(s) => OtherRegionTyParamBound(s)
489 pub fn fold_ty_param<T: Folder>(tp: &TyParam, fld: &mut T) -> TyParam {
490 let id = fld.new_id(tp.id);
494 bounds: tp.bounds.map(|x| fold_ty_param_bound(x, fld)),
495 unbound: tp.unbound.as_ref().map(|x| fold_ty_param_bound(x, fld)),
496 default: tp.default.map(|x| fld.fold_ty(x)),
501 pub fn fold_ty_params<T: Folder>(tps: &OwnedSlice<TyParam>, fld: &mut T)
502 -> OwnedSlice<TyParam> {
503 tps.map(|tp| fold_ty_param(tp, fld))
506 pub fn noop_fold_lifetime<T: Folder>(l: &Lifetime, fld: &mut T) -> Lifetime {
507 let id = fld.new_id(l.id);
510 span: fld.new_span(l.span),
515 pub fn fold_lifetimes<T: Folder>(lts: &Vec<Lifetime>, fld: &mut T)
517 lts.iter().map(|l| fld.fold_lifetime(l)).collect()
520 pub fn fold_opt_lifetime<T: Folder>(o_lt: &Option<Lifetime>, fld: &mut T)
521 -> Option<Lifetime> {
522 o_lt.as_ref().map(|lt| fld.fold_lifetime(lt))
525 pub fn fold_generics<T: Folder>(generics: &Generics, fld: &mut T) -> Generics {
526 Generics {ty_params: fold_ty_params(&generics.ty_params, fld),
527 lifetimes: fold_lifetimes(&generics.lifetimes, fld)}
530 fn fold_struct_def<T: Folder>(struct_def: Gc<StructDef>,
531 fld: &mut T) -> Gc<StructDef> {
532 box(GC) ast::StructDef {
533 fields: struct_def.fields.iter().map(|f| fold_struct_field(f, fld)).collect(),
534 ctor_id: struct_def.ctor_id.map(|cid| fld.new_id(cid)),
535 super_struct: match struct_def.super_struct {
536 Some(t) => Some(fld.fold_ty(t)),
539 is_virtual: struct_def.is_virtual,
543 fn fold_trait_ref<T: Folder>(p: &TraitRef, fld: &mut T) -> TraitRef {
544 let id = fld.new_id(p.ref_id);
546 path: fld.fold_path(&p.path),
551 fn fold_struct_field<T: Folder>(f: &StructField, fld: &mut T) -> StructField {
552 let id = fld.new_id(f.node.id);
554 node: ast::StructField_ {
557 ty: fld.fold_ty(f.node.ty),
558 attrs: f.node.attrs.iter().map(|a| fld.fold_attribute(*a)).collect(),
560 span: fld.new_span(f.span),
564 fn fold_field_<T: Folder>(field: Field, folder: &mut T) -> Field {
566 ident: respan(field.ident.span, folder.fold_ident(field.ident.node)),
567 expr: folder.fold_expr(field.expr),
568 span: folder.new_span(field.span),
572 fn fold_mt<T: Folder>(mt: &MutTy, folder: &mut T) -> MutTy {
574 ty: folder.fold_ty(mt.ty),
579 fn fold_opt_bounds<T: Folder>(b: &Option<OwnedSlice<TyParamBound>>, folder: &mut T)
580 -> Option<OwnedSlice<TyParamBound>> {
581 b.as_ref().map(|bounds| {
583 fold_ty_param_bound(bound, folder)
588 fn fold_variant_arg_<T: Folder>(va: &VariantArg, folder: &mut T) -> VariantArg {
589 let id = folder.new_id(va.id);
591 ty: folder.fold_ty(va.ty),
596 pub fn noop_fold_view_item<T: Folder>(vi: &ViewItem, folder: &mut T)
598 let inner_view_item = match vi.node {
599 ViewItemExternCrate(ref ident, ref string, node_id) => {
600 ViewItemExternCrate(ident.clone(),
602 folder.new_id(node_id))
604 ViewItemUse(ref view_path) => {
605 ViewItemUse(folder.fold_view_path(*view_path))
609 node: inner_view_item,
610 attrs: vi.attrs.iter().map(|a| folder.fold_attribute(*a)).collect(),
612 span: folder.new_span(vi.span),
616 pub fn noop_fold_block<T: Folder>(b: P<Block>, folder: &mut T) -> P<Block> {
617 let id = folder.new_id(b.id); // Needs to be first, for ast_map.
618 let view_items = b.view_items.iter().map(|x| folder.fold_view_item(x)).collect();
619 let stmts = b.stmts.iter().flat_map(|s| folder.fold_stmt(&**s).move_iter()).collect();
622 view_items: view_items,
624 expr: b.expr.map(|x| folder.fold_expr(x)),
626 span: folder.new_span(b.span),
630 pub fn noop_fold_item_underscore<T: Folder>(i: &Item_, folder: &mut T) -> Item_ {
632 ItemStatic(t, m, e) => {
633 ItemStatic(folder.fold_ty(t), m, folder.fold_expr(e))
635 ItemFn(decl, fn_style, abi, ref generics, body) => {
637 folder.fold_fn_decl(&*decl),
640 fold_generics(generics, folder),
641 folder.fold_block(body)
644 ItemMod(ref m) => ItemMod(folder.fold_mod(m)),
645 ItemForeignMod(ref nm) => ItemForeignMod(folder.fold_foreign_mod(nm)),
646 ItemTy(t, ref generics) => {
647 ItemTy(folder.fold_ty(t), fold_generics(generics, folder))
649 ItemEnum(ref enum_definition, ref generics) => {
652 variants: enum_definition.variants.iter().map(|&x| {
653 folder.fold_variant(&*x)
656 fold_generics(generics, folder))
658 ItemStruct(ref struct_def, ref generics) => {
659 let struct_def = fold_struct_def(*struct_def, folder);
660 ItemStruct(struct_def, fold_generics(generics, folder))
662 ItemImpl(ref generics, ref ifce, ty, ref methods) => {
663 ItemImpl(fold_generics(generics, folder),
664 ifce.as_ref().map(|p| fold_trait_ref(p, folder)),
666 methods.iter().map(|x| folder.fold_method(*x)).collect()
669 ItemTrait(ref generics, ref unbound, ref traits, ref methods) => {
670 let methods = methods.iter().map(|method| {
672 Required(ref m) => Required(folder.fold_type_method(m)),
673 Provided(method) => Provided(folder.fold_method(method))
676 ItemTrait(fold_generics(generics, folder),
678 traits.iter().map(|p| fold_trait_ref(p, folder)).collect(),
681 ItemMac(ref m) => ItemMac(folder.fold_mac(m)),
685 pub fn noop_fold_type_method<T: Folder>(m: &TypeMethod, fld: &mut T) -> TypeMethod {
686 let id = fld.new_id(m.id); // Needs to be first, for ast_map.
689 ident: fld.fold_ident(m.ident),
690 attrs: m.attrs.iter().map(|a| fld.fold_attribute(*a)).collect(),
691 fn_style: m.fn_style,
692 decl: fld.fold_fn_decl(&*m.decl),
693 generics: fold_generics(&m.generics, fld),
694 explicit_self: fld.fold_explicit_self(&m.explicit_self),
695 span: fld.new_span(m.span),
700 pub fn noop_fold_mod<T: Folder>(m: &Mod, folder: &mut T) -> Mod {
702 inner: folder.new_span(m.inner),
703 view_items: m.view_items
705 .map(|x| folder.fold_view_item(x)).collect(),
706 items: m.items.iter().flat_map(|x| folder.fold_item(*x).move_iter()).collect(),
710 pub fn noop_fold_crate<T: Folder>(c: Crate, folder: &mut T) -> Crate {
712 module: folder.fold_mod(&c.module),
713 attrs: c.attrs.iter().map(|x| folder.fold_attribute(*x)).collect(),
714 config: c.config.iter().map(|x| fold_meta_item_(*x, folder)).collect(),
715 span: folder.new_span(c.span),
719 // fold one item into possibly many items
720 pub fn noop_fold_item<T: Folder>(i: &Item,
721 folder: &mut T) -> SmallVector<Gc<Item>> {
722 SmallVector::one(box(GC) noop_fold_item_(i,folder))
726 // fold one item into exactly one item
727 pub fn noop_fold_item_<T: Folder>(i: &Item, folder: &mut T) -> Item {
728 let id = folder.new_id(i.id); // Needs to be first, for ast_map.
729 let node = folder.fold_item_underscore(&i.node);
730 let ident = match node {
731 // The node may have changed, recompute the "pretty" impl name.
732 ItemImpl(_, ref maybe_trait, ty, _) => {
733 ast_util::impl_pretty_name(maybe_trait, &*ty)
740 ident: folder.fold_ident(ident),
741 attrs: i.attrs.iter().map(|e| folder.fold_attribute(*e)).collect(),
744 span: folder.new_span(i.span)
748 pub fn noop_fold_foreign_item<T: Folder>(ni: &ForeignItem,
749 folder: &mut T) -> Gc<ForeignItem> {
750 let id = folder.new_id(ni.id); // Needs to be first, for ast_map.
751 box(GC) ForeignItem {
753 ident: folder.fold_ident(ni.ident),
754 attrs: ni.attrs.iter().map(|x| folder.fold_attribute(*x)).collect(),
755 node: match ni.node {
756 ForeignItemFn(ref fdec, ref generics) => {
757 ForeignItemFn(P(FnDecl {
758 inputs: fdec.inputs.iter().map(|a| fold_arg_(a, folder)).collect(),
759 output: folder.fold_ty(fdec.output),
761 variadic: fdec.variadic
762 }), fold_generics(generics, folder))
764 ForeignItemStatic(t, m) => {
765 ForeignItemStatic(folder.fold_ty(t), m)
768 span: folder.new_span(ni.span),
773 pub fn noop_fold_method<T: Folder>(m: &Method, folder: &mut T) -> Gc<Method> {
774 let id = folder.new_id(m.id); // Needs to be first, for ast_map.
777 ident: folder.fold_ident(m.ident),
778 attrs: m.attrs.iter().map(|a| folder.fold_attribute(*a)).collect(),
779 generics: fold_generics(&m.generics, folder),
780 explicit_self: folder.fold_explicit_self(&m.explicit_self),
781 fn_style: m.fn_style,
782 decl: folder.fold_fn_decl(&*m.decl),
783 body: folder.fold_block(m.body),
784 span: folder.new_span(m.span),
789 pub fn noop_fold_pat<T: Folder>(p: Gc<Pat>, folder: &mut T) -> Gc<Pat> {
790 let id = folder.new_id(p.id);
791 let node = match p.node {
793 PatWildMulti => PatWildMulti,
794 PatIdent(binding_mode, ref pth1, ref sub) => {
795 PatIdent(binding_mode,
796 Spanned{span: folder.new_span(pth1.span),
797 node: folder.fold_ident(pth1.node)},
798 sub.map(|x| folder.fold_pat(x)))
800 PatLit(e) => PatLit(folder.fold_expr(e)),
801 PatEnum(ref pth, ref pats) => {
802 PatEnum(folder.fold_path(pth),
803 pats.as_ref().map(|pats| pats.iter().map(|x| folder.fold_pat(*x)).collect()))
805 PatStruct(ref pth, ref fields, etc) => {
806 let pth_ = folder.fold_path(pth);
807 let fs = fields.iter().map(|f| {
810 pat: folder.fold_pat(f.pat)
813 PatStruct(pth_, fs, etc)
815 PatTup(ref elts) => PatTup(elts.iter().map(|x| folder.fold_pat(*x)).collect()),
816 PatBox(inner) => PatBox(folder.fold_pat(inner)),
817 PatRegion(inner) => PatRegion(folder.fold_pat(inner)),
818 PatRange(e1, e2) => {
819 PatRange(folder.fold_expr(e1), folder.fold_expr(e2))
821 PatVec(ref before, ref slice, ref after) => {
822 PatVec(before.iter().map(|x| folder.fold_pat(*x)).collect(),
823 slice.map(|x| folder.fold_pat(x)),
824 after.iter().map(|x| folder.fold_pat(*x)).collect())
826 PatMac(ref mac) => PatMac(folder.fold_mac(mac)),
831 span: folder.new_span(p.span),
836 pub fn noop_fold_expr<T: Folder>(e: Gc<Expr>, folder: &mut T) -> Gc<Expr> {
837 let id = folder.new_id(e.id);
838 let node = match e.node {
839 ExprVstore(e, v) => {
840 ExprVstore(folder.fold_expr(e), v)
843 ExprBox(folder.fold_expr(p), folder.fold_expr(e))
845 ExprVec(ref exprs) => {
846 ExprVec(exprs.iter().map(|&x| folder.fold_expr(x)).collect())
848 ExprRepeat(expr, count) => {
849 ExprRepeat(folder.fold_expr(expr), folder.fold_expr(count))
851 ExprTup(ref elts) => ExprTup(elts.iter().map(|x| folder.fold_expr(*x)).collect()),
852 ExprCall(f, ref args) => {
853 ExprCall(folder.fold_expr(f),
854 args.iter().map(|&x| folder.fold_expr(x)).collect())
856 ExprMethodCall(i, ref tps, ref args) => {
858 respan(i.span, folder.fold_ident(i.node)),
859 tps.iter().map(|&x| folder.fold_ty(x)).collect(),
860 args.iter().map(|&x| folder.fold_expr(x)).collect())
862 ExprBinary(binop, lhs, rhs) => {
864 folder.fold_expr(lhs),
865 folder.fold_expr(rhs))
867 ExprUnary(binop, ohs) => {
868 ExprUnary(binop, folder.fold_expr(ohs))
870 ExprLit(_) => e.node.clone(),
871 ExprCast(expr, ty) => {
872 ExprCast(folder.fold_expr(expr), folder.fold_ty(ty))
874 ExprAddrOf(m, ohs) => ExprAddrOf(m, folder.fold_expr(ohs)),
875 ExprIf(cond, tr, fl) => {
876 ExprIf(folder.fold_expr(cond),
877 folder.fold_block(tr),
878 fl.map(|x| folder.fold_expr(x)))
880 ExprWhile(cond, body) => {
881 ExprWhile(folder.fold_expr(cond), folder.fold_block(body))
883 ExprForLoop(pat, iter, body, ref maybe_ident) => {
884 ExprForLoop(folder.fold_pat(pat),
885 folder.fold_expr(iter),
886 folder.fold_block(body),
887 maybe_ident.map(|i| folder.fold_ident(i)))
889 ExprLoop(body, opt_ident) => {
890 ExprLoop(folder.fold_block(body),
891 opt_ident.map(|x| folder.fold_ident(x)))
893 ExprMatch(expr, ref arms) => {
894 ExprMatch(folder.fold_expr(expr),
895 arms.iter().map(|x| folder.fold_arm(x)).collect())
897 ExprFnBlock(ref decl, ref body) => {
898 ExprFnBlock(folder.fold_fn_decl(&**decl),
899 folder.fold_block(body.clone()))
901 ExprProc(ref decl, ref body) => {
902 ExprProc(folder.fold_fn_decl(&**decl),
903 folder.fold_block(body.clone()))
905 ExprBlock(ref blk) => ExprBlock(folder.fold_block(blk.clone())),
906 ExprAssign(el, er) => {
907 ExprAssign(folder.fold_expr(el), folder.fold_expr(er))
909 ExprAssignOp(op, el, er) => {
911 folder.fold_expr(el),
912 folder.fold_expr(er))
914 ExprField(el, id, ref tys) => {
915 ExprField(folder.fold_expr(el),
916 respan(id.span, folder.fold_ident(id.node)),
917 tys.iter().map(|&x| folder.fold_ty(x)).collect())
919 ExprIndex(el, er) => {
920 ExprIndex(folder.fold_expr(el), folder.fold_expr(er))
922 ExprPath(ref pth) => ExprPath(folder.fold_path(pth)),
923 ExprBreak(opt_ident) => ExprBreak(opt_ident.map(|x| folder.fold_ident(x))),
924 ExprAgain(opt_ident) => ExprAgain(opt_ident.map(|x| folder.fold_ident(x))),
926 ExprRet(e.map(|x| folder.fold_expr(x)))
928 ExprInlineAsm(ref a) => {
929 ExprInlineAsm(InlineAsm {
930 inputs: a.inputs.iter().map(|&(ref c, input)| {
931 ((*c).clone(), folder.fold_expr(input))
933 outputs: a.outputs.iter().map(|&(ref c, out)| {
934 ((*c).clone(), folder.fold_expr(out))
939 ExprMac(ref mac) => ExprMac(folder.fold_mac(mac)),
940 ExprStruct(ref path, ref fields, maybe_expr) => {
941 ExprStruct(folder.fold_path(path),
942 fields.iter().map(|x| fold_field_(*x, folder)).collect(),
943 maybe_expr.map(|x| folder.fold_expr(x)))
945 ExprParen(ex) => ExprParen(folder.fold_expr(ex))
951 span: folder.new_span(e.span),
955 pub fn noop_fold_stmt<T: Folder>(s: &Stmt,
956 folder: &mut T) -> SmallVector<Gc<Stmt>> {
957 let nodes = match s.node {
959 let id = folder.new_id(id);
960 folder.fold_decl(d).move_iter()
961 .map(|d| StmtDecl(d, id))
965 let id = folder.new_id(id);
966 SmallVector::one(StmtExpr(folder.fold_expr(e), id))
969 let id = folder.new_id(id);
970 SmallVector::one(StmtSemi(folder.fold_expr(e), id))
972 StmtMac(ref mac, semi) => SmallVector::one(StmtMac(folder.fold_mac(mac), semi))
975 nodes.move_iter().map(|node| box(GC) Spanned {
977 span: folder.new_span(s.span),
985 use util::parser_testing::{string_to_crate, matches_codepattern};
990 // this version doesn't care about getting comments or docstrings in.
991 fn fake_print_crate(s: &mut pprust::State,
992 krate: &ast::Crate) -> io::IoResult<()> {
993 s.print_mod(&krate.module, krate.attrs.as_slice())
996 // change every identifier to "zz"
997 struct ToZzIdentFolder;
999 impl Folder for ToZzIdentFolder {
1000 fn fold_ident(&mut self, _: ast::Ident) -> ast::Ident {
1001 token::str_to_ident("zz")
1005 // maybe add to expand.rs...
1006 macro_rules! assert_pred (
1007 ($pred:expr, $predname:expr, $a:expr , $b:expr) => (
1009 let pred_val = $pred;
1012 if !(pred_val(a_val.as_slice(),b_val.as_slice())) {
1013 fail!("expected args satisfying {}, got {:?} and {:?}",
1014 $predname, a_val, b_val);
1020 // make sure idents get transformed everywhere
1021 #[test] fn ident_transformation () {
1022 let mut zz_fold = ToZzIdentFolder;
1023 let ast = string_to_crate(
1024 "#[a] mod b {fn c (d : e, f : g) {h!(i,j,k);l;m}}".to_string());
1025 let folded_crate = zz_fold.fold_crate(ast);
1027 matches_codepattern,
1028 "matches_codepattern",
1029 pprust::to_string(|s| fake_print_crate(s, &folded_crate)),
1030 "#[a]mod zz{fn zz(zz:zz,zz:zz){zz!(zz,zz,zz);zz;zz}}".to_string());
1033 // even inside macro defs....
1034 #[test] fn ident_transformation_in_defs () {
1035 let mut zz_fold = ToZzIdentFolder;
1036 let ast = string_to_crate(
1037 "macro_rules! a {(b $c:expr $(d $e:token)f+ => \
1038 (g $(d $d $e)+))} ".to_string());
1039 let folded_crate = zz_fold.fold_crate(ast);
1041 matches_codepattern,
1042 "matches_codepattern",
1043 pprust::to_string(|s| fake_print_crate(s, &folded_crate)),
1044 "zz!zz((zz$zz:zz$(zz $zz:zz)zz+=>(zz$(zz$zz$zz)+)))".to_string());