export Fold; export default_seq_fold; export default_seq_fold_doc; export default_seq_fold_crate; export default_seq_fold_item; export default_seq_fold_mod; export default_seq_fold_nmod; export default_seq_fold_fn; export default_seq_fold_const; export default_seq_fold_enum; export default_seq_fold_trait; export default_seq_fold_impl; export default_seq_fold_type; export default_seq_fold_struct; export default_par_fold; export default_par_fold_mod; export default_par_fold_nmod; export default_any_fold; export default_any_fold_mod; export default_any_fold_nmod; enum Fold = Fold_; type FoldDoc = fn~(fold: Fold, doc: doc::Doc) -> doc::Doc; type FoldCrate = fn~(fold: Fold, doc: doc::CrateDoc) -> doc::CrateDoc; type FoldItem = fn~(fold: Fold, doc: doc::ItemDoc) -> doc::ItemDoc; type FoldMod = fn~(fold: Fold, doc: doc::ModDoc) -> doc::ModDoc; type FoldNmod = fn~(fold: Fold, doc: doc::NmodDoc) -> doc::NmodDoc; type FoldFn = fn~(fold: Fold, doc: doc::FnDoc) -> doc::FnDoc; type FoldConst = fn~(fold: Fold, doc: doc::ConstDoc) -> doc::ConstDoc; type FoldEnum = fn~(fold: Fold, doc: doc::EnumDoc) -> doc::EnumDoc; type FoldTrait = fn~(fold: Fold, doc: doc::TraitDoc) -> doc::TraitDoc; type FoldImpl = fn~(fold: Fold, doc: doc::ImplDoc) -> doc::ImplDoc; type FoldType = fn~(fold: Fold, doc: doc::TyDoc) -> doc::TyDoc; type FoldStruct = fn~(fold: Fold, doc: doc::StructDoc) -> doc::StructDoc; type Fold_ = { ctxt: T, fold_doc: FoldDoc, fold_crate: FoldCrate, fold_item: FoldItem, fold_mod: FoldMod, fold_nmod: FoldNmod, fold_fn: FoldFn, fold_const: FoldConst, fold_enum: FoldEnum, fold_trait: FoldTrait, fold_impl: FoldImpl, fold_type: FoldType, fold_struct: FoldStruct }; // This exists because fn types don't infer correctly as record // initializers, but they do as function arguments fn mk_fold( ctxt: T, +fold_doc: FoldDoc, +fold_crate: FoldCrate, +fold_item: FoldItem, +fold_mod: FoldMod, +fold_nmod: FoldNmod, +fold_fn: FoldFn, +fold_const: FoldConst, +fold_enum: FoldEnum, +fold_trait: FoldTrait, +fold_impl: FoldImpl, +fold_type: FoldType, +fold_struct: FoldStruct ) -> Fold { Fold({ ctxt: ctxt, fold_doc: fold_doc, fold_crate: fold_crate, fold_item: fold_item, fold_mod: fold_mod, fold_nmod: fold_nmod, fold_fn: fold_fn, fold_const: fold_const, fold_enum: fold_enum, fold_trait: fold_trait, fold_impl: fold_impl, fold_type: fold_type, fold_struct: fold_struct, }) } fn default_any_fold(ctxt: T) -> Fold { mk_fold( ctxt, |f, d| default_seq_fold_doc(f, d), |f, d| default_seq_fold_crate(f, d), |f, d| default_seq_fold_item(f, d), |f, d| default_any_fold_mod(f, d), |f, d| default_any_fold_nmod(f, d), |f, d| default_seq_fold_fn(f, d), |f, d| default_seq_fold_const(f, d), |f, d| default_seq_fold_enum(f, d), |f, d| default_seq_fold_trait(f, d), |f, d| default_seq_fold_impl(f, d), |f, d| default_seq_fold_type(f, d), |f, d| default_seq_fold_struct(f, d) ) } fn default_seq_fold(ctxt: T) -> Fold { mk_fold( ctxt, |f, d| default_seq_fold_doc(f, d), |f, d| default_seq_fold_crate(f, d), |f, d| default_seq_fold_item(f, d), |f, d| default_seq_fold_mod(f, d), |f, d| default_seq_fold_nmod(f, d), |f, d| default_seq_fold_fn(f, d), |f, d| default_seq_fold_const(f, d), |f, d| default_seq_fold_enum(f, d), |f, d| default_seq_fold_trait(f, d), |f, d| default_seq_fold_impl(f, d), |f, d| default_seq_fold_type(f, d), |f, d| default_seq_fold_struct(f, d) ) } fn default_par_fold(ctxt: T) -> Fold { mk_fold( ctxt, |f, d| default_seq_fold_doc(f, d), |f, d| default_seq_fold_crate(f, d), |f, d| default_seq_fold_item(f, d), |f, d| default_par_fold_mod(f, d), |f, d| default_par_fold_nmod(f, d), |f, d| default_seq_fold_fn(f, d), |f, d| default_seq_fold_const(f, d), |f, d| default_seq_fold_enum(f, d), |f, d| default_seq_fold_trait(f, d), |f, d| default_seq_fold_impl(f, d), |f, d| default_seq_fold_type(f, d), |f, d| default_seq_fold_struct(f, d) ) } fn default_seq_fold_doc(fold: Fold, doc: doc::Doc) -> doc::Doc { doc::Doc_({ pages: do vec::map(doc.pages) |page| { match page { doc::CratePage(doc) => { doc::CratePage(fold.fold_crate(fold, doc)) } doc::ItemPage(doc) => { doc::ItemPage(fold_ItemTag(fold, doc)) } } }, .. *doc }) } fn default_seq_fold_crate( fold: Fold, doc: doc::CrateDoc ) -> doc::CrateDoc { { topmod: fold.fold_mod(fold, doc.topmod) } } fn default_seq_fold_item( _fold: Fold, doc: doc::ItemDoc ) -> doc::ItemDoc { doc } fn default_any_fold_mod( fold: Fold, doc: doc::ModDoc ) -> doc::ModDoc { doc::ModDoc_({ item: fold.fold_item(fold, doc.item), items: par::map(doc.items, |ItemTag, copy fold| { fold_ItemTag(fold, ItemTag) }), .. *doc }) } fn default_seq_fold_mod( fold: Fold, doc: doc::ModDoc ) -> doc::ModDoc { doc::ModDoc_({ item: fold.fold_item(fold, doc.item), items: vec::map(doc.items, |ItemTag| { fold_ItemTag(fold, ItemTag) }), .. *doc }) } fn default_par_fold_mod( fold: Fold, doc: doc::ModDoc ) -> doc::ModDoc { doc::ModDoc_({ item: fold.fold_item(fold, doc.item), items: par::map(doc.items, |ItemTag, copy fold| { fold_ItemTag(fold, ItemTag) }), .. *doc }) } fn default_any_fold_nmod( fold: Fold, doc: doc::NmodDoc ) -> doc::NmodDoc { { item: fold.fold_item(fold, doc.item), fns: par::map(doc.fns, |FnDoc, copy fold| { fold.fold_fn(fold, FnDoc) }), .. doc } } fn default_seq_fold_nmod( fold: Fold, doc: doc::NmodDoc ) -> doc::NmodDoc { { item: fold.fold_item(fold, doc.item), fns: vec::map(doc.fns, |FnDoc| { fold.fold_fn(fold, FnDoc) }), .. doc } } fn default_par_fold_nmod( fold: Fold, doc: doc::NmodDoc ) -> doc::NmodDoc { { item: fold.fold_item(fold, doc.item), fns: par::map(doc.fns, |FnDoc, copy fold| { fold.fold_fn(fold, FnDoc) }), .. doc } } fn fold_ItemTag(fold: Fold, doc: doc::ItemTag) -> doc::ItemTag { match doc { doc::ModTag(ModDoc) => { doc::ModTag(fold.fold_mod(fold, ModDoc)) } doc::NmodTag(nModDoc) => { doc::NmodTag(fold.fold_nmod(fold, nModDoc)) } doc::FnTag(FnDoc) => { doc::FnTag(fold.fold_fn(fold, FnDoc)) } doc::ConstTag(ConstDoc) => { doc::ConstTag(fold.fold_const(fold, ConstDoc)) } doc::EnumTag(EnumDoc) => { doc::EnumTag(fold.fold_enum(fold, EnumDoc)) } doc::TraitTag(TraitDoc) => { doc::TraitTag(fold.fold_trait(fold, TraitDoc)) } doc::ImplTag(ImplDoc) => { doc::ImplTag(fold.fold_impl(fold, ImplDoc)) } doc::TyTag(TyDoc) => { doc::TyTag(fold.fold_type(fold, TyDoc)) } doc::StructTag(StructDoc) => { doc::StructTag(fold.fold_struct(fold, StructDoc)) } } } fn default_seq_fold_fn( fold: Fold, doc: doc::FnDoc ) -> doc::FnDoc { { item: fold.fold_item(fold, doc.item), .. doc } } fn default_seq_fold_const( fold: Fold, doc: doc::ConstDoc ) -> doc::ConstDoc { { item: fold.fold_item(fold, doc.item), .. doc } } fn default_seq_fold_enum( fold: Fold, doc: doc::EnumDoc ) -> doc::EnumDoc { { item: fold.fold_item(fold, doc.item), .. doc } } fn default_seq_fold_trait( fold: Fold, doc: doc::TraitDoc ) -> doc::TraitDoc { { item: fold.fold_item(fold, doc.item), .. doc } } fn default_seq_fold_impl( fold: Fold, doc: doc::ImplDoc ) -> doc::ImplDoc { { item: fold.fold_item(fold, doc.item), .. doc } } fn default_seq_fold_type( fold: Fold, doc: doc::TyDoc ) -> doc::TyDoc { { item: fold.fold_item(fold, doc.item), .. doc } } fn default_seq_fold_struct( fold: Fold, doc: doc::StructDoc ) -> doc::StructDoc { { item: fold.fold_item(fold, doc.item), .. doc } } #[test] fn default_fold_should_produce_same_doc() { let source = ~"mod a { fn b() { } mod c { fn d() { } } }"; let ast = parse::from_str(source); let doc = extract::extract(ast, ~""); let fld = default_seq_fold(()); let folded = fld.fold_doc(fld, doc); assert doc == folded; } #[test] fn default_fold_should_produce_same_consts() { let source = ~"const a: int = 0;"; let ast = parse::from_str(source); let doc = extract::extract(ast, ~""); let fld = default_seq_fold(()); let folded = fld.fold_doc(fld, doc); assert doc == folded; } #[test] fn default_fold_should_produce_same_enums() { let source = ~"enum a { b }"; let ast = parse::from_str(source); let doc = extract::extract(ast, ~""); let fld = default_seq_fold(()); let folded = fld.fold_doc(fld, doc); assert doc == folded; } #[test] fn default_parallel_fold_should_produce_same_doc() { let source = ~"mod a { fn b() { } mod c { fn d() { } } }"; let ast = parse::from_str(source); let doc = extract::extract(ast, ~""); let fld = default_par_fold(()); let folded = fld.fold_doc(fld, doc); assert doc == folded; }