export fold; export fold_crate, fold_mod, fold_fn; export default_seq_fold; 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_res; export default_seq_fold_iface; export default_seq_fold_impl; export default_seq_fold_type; export default_par_fold; export default_par_fold_mod; export default_any_fold; export default_any_fold_mod; enum fold = t; type fold_crate = fn~(fold: fold, doc: doc::cratedoc) -> doc::cratedoc; type fold_item = fn~(fold: fold, doc: doc::itemdoc) -> doc::itemdoc; type fold_mod = fn~(fold: fold, doc: doc::moddoc) -> doc::moddoc; type fold_nmod = fn~(fold: fold, doc: doc::nmoddoc) -> doc::nmoddoc; type fold_fn = fn~(fold: fold, doc: doc::fndoc) -> doc::fndoc; type fold_const = fn~(fold: fold, doc: doc::constdoc) -> doc::constdoc; type fold_enum = fn~(fold: fold, doc: doc::enumdoc) -> doc::enumdoc; type fold_res = fn~(fold: fold, doc: doc::resdoc) -> doc::resdoc; type fold_iface = fn~(fold: fold, doc: doc::ifacedoc) -> doc::ifacedoc; type fold_impl = fn~(fold: fold, doc: doc::impldoc) -> doc::impldoc; type fold_type = fn~(fold: fold, doc: doc::tydoc) -> doc::tydoc; type t = { ctxt: T, 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_res: fold_res, fold_iface: fold_iface, fold_impl: fold_impl, fold_type: fold_type }; // This exists because fn types don't infer correctly as record // initializers, but they do as function arguments fn mk_fold( ctxt: T, 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_res: fold_res, fold_iface: fold_iface, fold_impl: fold_impl, fold_type: fold_type ) -> fold { fold({ ctxt: ctxt, 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_res: fold_res, fold_iface: fold_iface, fold_impl: fold_impl, fold_type: fold_type }) } fn default_seq_fold(ctxt: T) -> fold { mk_fold( ctxt, {|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_res(f, d)}, {|f, d| default_seq_fold_iface(f, d)}, {|f, d| default_seq_fold_impl(f, d)}, {|f, d| default_seq_fold_type(f, d)} ) } fn default_par_fold(ctxt: T) -> fold { mk_fold( ctxt, {|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_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_res(f, d)}, {|f, d| default_seq_fold_iface(f, d)}, {|f, d| default_seq_fold_impl(f, d)}, {|f, d| default_seq_fold_type(f, d)} ) } // Just a convenient wrapper to convert back and forth between // parallel and sequential folds for perf testing fn default_any_fold(ctxt: T) -> fold { default_seq_fold(ctxt) } 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_seq_fold_mod( fold: fold, doc: doc::moddoc ) -> doc::moddoc { { item: fold.fold_item(fold, doc.item), items: vec::map(doc.items) {|itemtag| fold_itemtag(fold, itemtag) } with 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) } with doc } } fn default_par_fold_mod( fold: fold, doc: doc::moddoc ) -> doc::moddoc { { item: fold.fold_item(fold, doc.item), items: util::parmap(doc.items) {|itemtag| fold_itemtag(fold, itemtag) } with doc } } fn default_any_fold_mod( fold: fold, doc: doc::moddoc ) -> doc::moddoc { default_seq_fold_mod(fold, doc) } fn fold_itemtag(fold: fold, doc: doc::itemtag) -> doc::itemtag { alt 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::restag(resdoc) { doc::restag(fold.fold_res(fold, resdoc)) } doc::ifacetag(ifacedoc) { doc::ifacetag(fold.fold_iface(fold, ifacedoc)) } doc::impltag(impldoc) { doc::impltag(fold.fold_impl(fold, impldoc)) } doc::tytag(tydoc) { doc::tytag(fold.fold_type(fold, tydoc)) } } } fn default_seq_fold_fn( fold: fold, doc: doc::fndoc ) -> doc::fndoc { { item: fold.fold_item(fold, doc.item) with doc } } fn default_seq_fold_const( fold: fold, doc: doc::constdoc ) -> doc::constdoc { { item: fold.fold_item(fold, doc.item) with doc } } fn default_seq_fold_enum( fold: fold, doc: doc::enumdoc ) -> doc::enumdoc { { item: fold.fold_item(fold, doc.item) with doc } } fn default_seq_fold_res( fold: fold, doc: doc::resdoc ) -> doc::resdoc { { item: fold.fold_item(fold, doc.item) with doc } } fn default_seq_fold_iface( fold: fold, doc: doc::ifacedoc ) -> doc::ifacedoc { { item: fold.fold_item(fold, doc.item) with doc } } fn default_seq_fold_impl( fold: fold, doc: doc::impldoc ) -> doc::impldoc { { item: fold.fold_item(fold, doc.item) with doc } } fn default_seq_fold_type( fold: fold, doc: doc::tydoc ) -> doc::tydoc { { item: fold.fold_item(fold, doc.item) with 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_crate(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_crate(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_crate(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_crate(fld, doc); assert doc == folded; }