diff options
| author | Patrick Walton <pcwalton@mimiga.net> | 2013-08-29 12:10:02 -0700 |
|---|---|---|
| committer | Patrick Walton <pcwalton@mimiga.net> | 2013-09-23 18:23:17 -0700 |
| commit | 3e5de06135fa9a857931191101d61a4abe149c96 (patch) | |
| tree | 761478a49c1f1c2796e7f367c96688bc9794471f /src/libsyntax | |
| parent | 97053995046636c0e11d23c4f0523d278a4210c9 (diff) | |
| download | rust-3e5de06135fa9a857931191101d61a4abe149c96.tar.gz rust-3e5de06135fa9a857931191101d61a4abe149c96.zip | |
librustc: Change fold to use traits instead of `@fn`.
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/ast_util.rs | 16 | ||||
| -rw-r--r-- | src/libsyntax/ext/build.rs | 30 | ||||
| -rw-r--r-- | src/libsyntax/ext/expand.rs | 465 | ||||
| -rw-r--r-- | src/libsyntax/fold.rs | 1440 |
4 files changed, 979 insertions, 972 deletions
diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index f0f86911f50..2e47050ad6a 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -12,7 +12,6 @@ use ast::*; use ast; use ast_util; use codemap::{Span, dummy_sp}; -use fold; use opt_vec; use parse::token; use visit::Visitor; @@ -371,21 +370,6 @@ pub fn empty_generics() -> Generics { ty_params: opt_vec::Empty} } -/////////////////////////////////////////////////////////////////////////// -// Assigning node ids - -fn node_id_assigner(next_id: @fn() -> ast::NodeId) -> @fold::ast_fold { - let precursor = @fold::AstFoldFns { - new_id: |old_id| { - assert_eq!(old_id, ast::DUMMY_NODE_ID); - next_id() - }, - ..*fold::default_ast_fold() - }; - - fold::make_fold(precursor) -} - // ______________________________________________________________________ // Enumerating the IDs which appear in an AST diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 889c2a5976e..aa4238ae908 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -15,6 +15,7 @@ use ast_util; use codemap::{Span, respan, dummy_sp}; use ext::base::ExtCtxt; use ext::quote::rt::*; +use fold; use opt_vec; use opt_vec::OptVec; @@ -862,3 +863,32 @@ impl AstBuilder for @ExtCtxt { ast::view_path_glob(self.path(sp, path), ast::DUMMY_NODE_ID))]) } } + +struct Duplicator { + cx: @ExtCtxt, +} + +impl fold::ast_fold for Duplicator { + fn new_id(&self, _: NodeId) -> NodeId { + ast::DUMMY_NODE_ID + } +} + +pub trait Duplicate { + // + // Duplication functions + // + // These functions just duplicate AST nodes. + // + + fn duplicate(&self, cx: @ExtCtxt) -> Self; +} + +impl Duplicate for @ast::Expr { + fn duplicate(&self, cx: @ExtCtxt) -> @ast::Expr { + let folder = @Duplicator { + cx: cx, + } as @fold::ast_fold; + folder.fold_expr(*self) + } +} diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 82d452bc734..0aefbe31338 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -10,7 +10,7 @@ use ast::{Block, Crate, DeclLocal, Expr_, ExprMac, SyntaxContext}; use ast::{Local, Ident, mac_invoc_tt}; -use ast::{item_mac, Mrk, Stmt_, StmtDecl, StmtMac, StmtExpr, StmtSemi}; +use ast::{item_mac, Mrk, Stmt, StmtDecl, StmtMac, StmtExpr, StmtSemi}; use ast::{token_tree}; use ast; use ast_util::{mtwt_outer_mark, new_rename, new_mark}; @@ -21,6 +21,7 @@ use codemap; use codemap::{Span, Spanned, ExpnInfo, NameAndSpan}; use ext::base::*; use fold::*; +use opt_vec; use parse; use parse::{parse_item_from_source_str}; use parse::token; @@ -32,12 +33,10 @@ use std::vec; pub fn expand_expr(extsbox: @mut SyntaxEnv, cx: @ExtCtxt, - e: &Expr_, - span: Span, - fld: @ast_fold, - orig: @fn(&Expr_, Span, @ast_fold) -> (Expr_, Span)) - -> (Expr_, Span) { - match *e { + e: @ast::Expr, + fld: &MacroExpander) + -> @ast::Expr { + match e.node { // expr_mac should really be expr_ext or something; it's the // entry-point for all syntax extensions. ExprMac(ref mac) => { @@ -66,7 +65,7 @@ pub fn expand_expr(extsbox: @mut SyntaxEnv, } Some(@SE(NormalTT(expandfun, exp_span))) => { cx.bt_push(ExpnInfo { - call_site: span, + call_site: e.span, callee: NameAndSpan { name: extnamestr, span: exp_span, @@ -101,12 +100,19 @@ pub fn expand_expr(extsbox: @mut SyntaxEnv, // mark after: let marked_after = mark_expr(expanded,fm); - //keep going, outside-in + // Keep going, outside-in. + // + // XXX(pcwalton): Is it necessary to clone the + // node here? let fully_expanded = fld.fold_expr(marked_after).node.clone(); cx.bt_pop(); - (fully_expanded, span) + @ast::Expr { + id: ast::DUMMY_NODE_ID, + node: fully_expanded, + span: e.span, + } } _ => { cx.span_fatal( @@ -125,8 +131,48 @@ pub fn expand_expr(extsbox: @mut SyntaxEnv, ast::ExprForLoop(src_pat, src_expr, ref src_loop_block, opt_ident) => { // Expand any interior macros etc. // NB: we don't fold pats yet. Curious. - let src_expr = fld.fold_expr(src_expr); - let src_loop_block = fld.fold_block(src_loop_block); + let src_expr = fld.fold_expr(src_expr).clone(); + let src_loop_block = fld.fold_block(src_loop_block).clone(); + + let span = e.span; + + pub fn mk_expr(_: @ExtCtxt, span: Span, node: Expr_) + -> @ast::Expr { + @ast::Expr { + id: ast::DUMMY_NODE_ID, + node: node, + span: span, + } + } + + fn mk_block(_: @ExtCtxt, + stmts: &[@ast::Stmt], + expr: Option<@ast::Expr>, + span: Span) + -> ast::Block { + ast::Block { + view_items: ~[], + stmts: stmts.to_owned(), + expr: expr, + id: ast::DUMMY_NODE_ID, + rules: ast::DefaultBlock, + span: span, + } + } + + fn mk_simple_path(ident: ast::Ident, span: Span) -> ast::Path { + ast::Path { + span: span, + global: false, + segments: ~[ + ast::PathSegment { + identifier: ident, + lifetime: None, + types: opt_vec::Empty, + } + ], + } + } // to: // @@ -182,10 +228,14 @@ pub fn expand_expr(extsbox: @mut SyntaxEnv, ~[iter_decl_stmt], Some(loop_expr)); - (ast::ExprBlock(block), span) + @ast::Expr { + id: ast::DUMMY_NODE_ID, + node: ast::ExprBlock(block), + span: span, + } } - _ => orig(e, span, fld) + _ => noop_fold_expr(e, fld) } } @@ -201,12 +251,10 @@ pub fn expand_expr(extsbox: @mut SyntaxEnv, pub fn expand_mod_items(extsbox: @mut SyntaxEnv, cx: @ExtCtxt, module_: &ast::_mod, - fld: @ast_fold, - orig: @fn(&ast::_mod, @ast_fold) -> ast::_mod) - -> ast::_mod { - + fld: &MacroExpander) + -> ast::_mod { // Fold the contents first: - let module_ = orig(module_, fld); + let module_ = noop_fold_mod(module_, fld); // For each item, look through the attributes. If any of them are // decorated with "item decorators", then use that function to transform @@ -233,7 +281,10 @@ pub fn expand_mod_items(extsbox: @mut SyntaxEnv, } }; - ast::_mod { items: new_items, ..module_ } + ast::_mod { + items: new_items, + ..module_ + } } // eval $e with a new exts frame: @@ -256,19 +307,20 @@ static special_block_name : &'static str = " block"; pub fn expand_item(extsbox: @mut SyntaxEnv, cx: @ExtCtxt, it: @ast::item, - fld: @ast_fold, - orig: @fn(@ast::item, @ast_fold) -> Option<@ast::item>) - -> Option<@ast::item> { + fld: &MacroExpander) + -> Option<@ast::item> { match it.node { ast::item_mac(*) => expand_item_mac(extsbox, cx, it, fld), ast::item_mod(_) | ast::item_foreign_mod(_) => { cx.mod_push(it.ident); let macro_escape = contains_macro_escape(it.attrs); - let result = with_exts_frame!(extsbox,macro_escape,orig(it,fld)); + let result = with_exts_frame!(extsbox, + macro_escape, + noop_fold_item(it, fld)); cx.mod_pop(); result }, - _ => orig(it,fld) + _ => noop_fold_item(it, fld) } } @@ -280,11 +332,15 @@ pub fn contains_macro_escape(attrs: &[ast::Attribute]) -> bool { // Support for item-position macro invocations, exactly the same // logic as for expression-position macro invocations. pub fn expand_item_mac(extsbox: @mut SyntaxEnv, - cx: @ExtCtxt, it: @ast::item, - fld: @ast_fold) - -> Option<@ast::item> { + cx: @ExtCtxt, + it: @ast::item, + fld: &MacroExpander) + -> Option<@ast::item> { let (pth, tts, ctxt) = match it.node { - item_mac(codemap::Spanned { node: mac_invoc_tt(ref pth, ref tts, ctxt), _}) => { + item_mac(codemap::Spanned { + node: mac_invoc_tt(ref pth, ref tts, ctxt), + _ + }) => { (pth, (*tts).clone(), ctxt) } _ => cx.span_bug(it.span, "invalid item macro invocation") @@ -382,15 +438,12 @@ fn insert_macro(exts: SyntaxEnv, name: ast::Name, transformer: @Transformer) { // expand a stmt pub fn expand_stmt(extsbox: @mut SyntaxEnv, cx: @ExtCtxt, - s: &Stmt_, - sp: Span, - fld: @ast_fold, - orig: @fn(&Stmt_, Span, @ast_fold) - -> (Option<Stmt_>, Span)) - -> (Option<Stmt_>, Span) { + s: &Stmt, + fld: &MacroExpander) + -> Option<@Stmt> { // why the copying here and not in expand_expr? // looks like classic changed-in-only-one-place - let (pth, tts, semi, ctxt) = match *s { + let (pth, tts, semi, ctxt) = match s.node { StmtMac(ref mac, semi) => { match mac.node { mac_invoc_tt(ref pth, ref tts, ctxt) => { @@ -398,24 +451,26 @@ pub fn expand_stmt(extsbox: @mut SyntaxEnv, } } } - _ => return expand_non_macro_stmt(*extsbox,s,sp,fld,orig) + _ => return expand_non_macro_stmt(*extsbox, s, fld) }; if (pth.segments.len() > 1u) { - cx.span_fatal( - pth.span, - fmt!("expected macro name without module \ - separators")); + cx.span_fatal(pth.span, + "expected macro name without module separators"); } let extname = &pth.segments[0].identifier; let extnamestr = ident_to_str(extname); - let (fully_expanded, sp) = match (*extsbox).find(&extname.name) { - None => - cx.span_fatal(pth.span, fmt!("macro undefined: '%s'", extnamestr)), + let fully_expanded: @ast::Stmt = match (*extsbox).find(&extname.name) { + None => { + cx.span_fatal(pth.span, fmt!("macro undefined: '%s'", extnamestr)) + } Some(@SE(NormalTT(expandfun, exp_span))) => { cx.bt_push(ExpnInfo { - call_site: sp, - callee: NameAndSpan { name: extnamestr, span: exp_span } + call_site: s.span, + callee: NameAndSpan { + name: extnamestr, + span: exp_span, + } }); let fm = fresh_mark(); // mark before expansion: @@ -426,11 +481,16 @@ pub fn expand_stmt(extsbox: @mut SyntaxEnv, // not the current mac.span. let mac_span = original_span(cx); - let expanded = match expandfun(cx, mac_span.call_site, - marked_tts, marked_ctxt) { - MRExpr(e) => - @codemap::Spanned { node: StmtExpr(e, ast::DUMMY_NODE_ID), - span: e.span}, + let expanded = match expandfun(cx, + mac_span.call_site, + marked_tts, + marked_ctxt) { + MRExpr(e) => { + @codemap::Spanned { + node: StmtExpr(e, ast::DUMMY_NODE_ID), + span: e.span, + } + } MRAny(_,_,stmt_mkr) => stmt_mkr(), _ => cx.span_fatal( pth.span, @@ -438,12 +498,15 @@ pub fn expand_stmt(extsbox: @mut SyntaxEnv, }; let marked_after = mark_stmt(expanded,fm); - //keep going, outside-in + // Keep going, outside-in. let fully_expanded = match fld.fold_stmt(marked_after) { Some(stmt) => { let fully_expanded = &stmt.node; cx.bt_pop(); - (*fully_expanded).clone() + @Spanned { + span: stmt.span, + node: (*fully_expanded).clone(), + } } None => { cx.span_fatal(pth.span, @@ -451,7 +514,7 @@ pub fn expand_stmt(extsbox: @mut SyntaxEnv, } }; - (fully_expanded, sp) + fully_expanded } _ => { @@ -460,24 +523,28 @@ pub fn expand_stmt(extsbox: @mut SyntaxEnv, } }; - (match fully_expanded { - StmtExpr(e, stmt_id) if semi => Some(StmtSemi(e, stmt_id)), - _ => { Some(fully_expanded) } /* might already have a semi */ - }, sp) - + match fully_expanded.node { + StmtExpr(e, stmt_id) if semi => { + Some(@Spanned { + span: fully_expanded.span, + node: StmtSemi(e, stmt_id), + }) + } + _ => Some(fully_expanded), /* might already have a semi */ + } } // expand a non-macro stmt. this is essentially the fallthrough for // expand_stmt, above. -fn expand_non_macro_stmt (exts: SyntaxEnv, - s: &Stmt_, - sp: Span, - fld: @ast_fold, - orig: @fn(&Stmt_, Span, @ast_fold) -> (Option<Stmt_>, Span)) - -> (Option<Stmt_>,Span) { +fn expand_non_macro_stmt(exts: SyntaxEnv, s: &Stmt, fld: &MacroExpander) + -> Option<@Stmt> { // is it a let? - match *s { - StmtDecl(@Spanned{node: DeclLocal(ref local), span: stmt_span}, node_id) => { + match s.node { + StmtDecl(@Spanned { + node: DeclLocal(ref local), + span: stmt_span + }, + node_id) => { let block_info = get_block_info(exts); let pending_renames = block_info.pending_renames; @@ -515,19 +582,24 @@ fn expand_non_macro_stmt (exts: SyntaxEnv, // also, don't forget to expand the init: let new_init_opt = init.map(|e| fld.fold_expr(*e)); let rewritten_local = - @Local{is_mutbl:is_mutbl, - ty:ty, - pat:rewritten_pat, - init:new_init_opt, - id:id, - span:span}; - (Some(StmtDecl(@Spanned{node:DeclLocal(rewritten_local), - span: stmt_span},node_id)), - sp) + @Local { + is_mutbl: is_mutbl, + ty: ty, + pat: rewritten_pat, + init: new_init_opt, + id: id, + span: span, + }; + Some(@Spanned { + node: StmtDecl(@Spanned { + node: DeclLocal(rewritten_local), + span: stmt_span + }, + node_id), + span: span + }) }, - _ => { - orig(s, sp, fld) - } + _ => noop_fold_stmt(s, fld), } } @@ -628,18 +700,18 @@ pub fn new_path_finder(paths: @mut ~[ast::Path]) -> @mut Visitor<()> { // expand a block. pushes a new exts_frame, then calls expand_block_elts pub fn expand_block(extsbox: @mut SyntaxEnv, - _cx: @ExtCtxt, + _: @ExtCtxt, blk: &Block, - fld: @ast_fold, - _orig: @fn(&Block, @ast_fold) -> Block) - -> Block { + fld: &MacroExpander) + -> Block { // see note below about treatment of exts table with_exts_frame!(extsbox,false, expand_block_elts(*extsbox, blk, fld)) } // expand the elements of a block. -pub fn expand_block_elts(exts: SyntaxEnv, b: &Block, fld: @ast_fold) -> Block { +pub fn expand_block_elts(exts: SyntaxEnv, b: &Block, fld: &MacroExpander) + -> Block { let block_info = get_block_info(exts); let pending_renames = block_info.pending_renames; let rename_fld = renames_to_fold(pending_renames); @@ -680,9 +752,47 @@ fn get_block_info(exts : SyntaxEnv) -> BlockInfo { } } +struct IdentRenamer { + renames: @mut ~[(ast::Ident,ast::Name)], +} + +impl ast_fold for IdentRenamer { + fn fold_ident(&self, id: ast::Ident) -> ast::Ident { + let new_ctxt = self.renames.iter().fold(id.ctxt, |ctxt, &(from, to)| { + new_rename(from, to, ctxt) + }); + ast::Ident { + name: id.name, + ctxt: new_ctxt, + } + } +} + +// given a mutable list of renames, return a tree-folder that applies those +// renames. +fn renames_to_fold(renames: @mut ~[(ast::Ident,ast::Name)]) -> @ast_fold { + @IdentRenamer { + renames: renames, + } as @ast_fold +} + +// perform a bunch of renames +fn apply_pending_renames(folder : @ast_fold, stmt : ast::Stmt) -> @ast::Stmt { + match folder.fold_stmt(&stmt) { + Some(s) => s, + None => fail!(fmt!("renaming of stmt produced None")) + } +} + + + pub fn new_span(cx: @ExtCtxt, sp: Span) -> Span { /* this discards information in the case of macro-defining macros */ - return Span {lo: sp.lo, hi: sp.hi, expn_info: cx.backtrace()}; + Span { + lo: sp.lo, + hi: sp.hi, + expn_info: cx.backtrace(), + } } // FIXME (#2247): this is a moderately bad kludge to inject some macros into @@ -1025,10 +1135,28 @@ pub fn std_macros() -> @str { }"; } +struct Injector { + sm: @ast::item, +} + +impl ast_fold for Injector { + fn fold_mod(&self, module: &ast::_mod) -> ast::_mod { + // Just inject the standard macros at the start of the first module + // in the crate: that is, at the start of the crate file itself. + let items = vec::append(~[ self.sm ], module.items); + ast::_mod { + items: items, + ..(*module).clone() // FIXME #2543: Bad copy. + } + } +} + // add a bunch of macros as though they were placed at the head of the // program (ick). This should run before cfg stripping. pub fn inject_std_macros(parse_sess: @mut parse::ParseSess, - cfg: ast::CrateConfig, c: &Crate) -> @Crate { + cfg: ast::CrateConfig, + c: @Crate) + -> @Crate { let sm = match parse_item_from_source_str(@"<std-macros>", std_macros(), cfg.clone(), @@ -1038,48 +1166,80 @@ pub fn inject_std_macros(parse_sess: @mut parse::ParseSess, None => fail!("expected core macros to parse correctly") }; - let injecter = @AstFoldFns { - fold_mod: |modd, _| { - // just inject the std macros at the start of the first - // module in the crate (i.e the crate file itself.) - let items = vec::append(~[sm], modd.items); - ast::_mod { - items: items, - // FIXME #2543: Bad copy. - .. (*modd).clone() - } - }, - .. *default_ast_fold() - }; - @make_fold(injecter).fold_crate(c) + let injector = @Injector { + sm: sm, + } as @ast_fold; + @injector.fold_crate(c) +} + +struct NoOpFolder { + contents: (), +} + +impl ast_fold for NoOpFolder {} + +struct MacroExpander { + extsbox: @mut SyntaxEnv, + cx: @ExtCtxt, +} + +impl ast_fold for MacroExpander { + fn fold_expr(&self, expr: @ast::Expr) -> @ast::Expr { + expand_expr(self.extsbox, + self.cx, + expr, + self) + } + + fn fold_mod(&self, module: &ast::_mod) -> ast::_mod { + expand_mod_items(self.extsbox, + self.cx, + module, + self) + } + + fn fold_item(&self, item: @ast::item) -> Option<@ast::item> { + expand_item(self.extsbox, + self.cx, + item, + self) + } + + fn fold_stmt(&self, stmt: &ast::Stmt) -> Option<@ast::Stmt> { + expand_stmt(self.extsbox, + self.cx, + stmt, + self) + } + + fn fold_block(&self, block: &ast::Block) -> ast::Block { + expand_block(self.extsbox, + self.cx, + block, + self) + } + + fn new_span(&self, span: Span) -> Span { + new_span(self.cx, span) + } } pub fn expand_crate(parse_sess: @mut parse::ParseSess, - cfg: ast::CrateConfig, c: &Crate) -> @Crate { + cfg: ast::CrateConfig, + c: &Crate) -> @Crate { // adding *another* layer of indirection here so that the block // visitor can swap out one exts table for another for the duration // of the block. The cleaner alternative would be to thread the // exts table through the fold, but that would require updating // every method/element of AstFoldFns in fold.rs. - let extsbox = @mut syntax_expander_table(); - let afp = default_ast_fold(); + let extsbox = syntax_expander_table(); let cx = ExtCtxt::new(parse_sess, cfg.clone()); - let f_pre = @AstFoldFns { - fold_expr: |expr,span,recur| - expand_expr(extsbox, cx, expr, span, recur, afp.fold_expr), - fold_mod: |modd,recur| - expand_mod_items(extsbox, cx, modd, recur, afp.fold_mod), - fold_item: |item,recur| - expand_item(extsbox, cx, item, recur, afp.fold_item), - fold_stmt: |stmt,span,recur| - expand_stmt(extsbox, cx, stmt, span, recur, afp.fold_stmt), - fold_block: |blk,recur| - expand_block(extsbox, cx, blk, recur, afp.fold_block), - new_span: |a| new_span(cx, a), - .. *afp}; - let f = make_fold(f_pre); - - let ret = @f.fold_crate(c); + let expander = @MacroExpander { + extsbox: @mut extsbox, + cx: cx, + } as @ast_fold; + + let ret = @expander.fold_crate(c); parse_sess.span_diagnostic.handler().abort_if_errors(); return ret; } @@ -1145,53 +1305,56 @@ impl CtxtFn for Repainter { } } -// given a function from ctxts to ctxts, produce -// an ast_fold that applies that function to all ctxts: -pub fn fun_to_ctxt_folder<T : 'static + CtxtFn>(cf: @T) -> @AstFoldFns { - let afp = default_ast_fold(); - let fi : @fn(ast::Ident, @ast_fold) -> ast::Ident = - |ast::Ident{name, ctxt}, _| { - ast::Ident{name:name,ctxt:cf.f(ctxt)} - }; - let fm : @fn(&ast::mac_, Span, @ast_fold) -> (ast::mac_,Span) = - |m, sp, fld| { - match *m { - mac_invoc_tt(ref path, ref tts, ctxt) => - (mac_invoc_tt(fld.fold_path(path), - fold_tts(*tts,fld), - cf.f(ctxt)), - sp) - } +pub struct ContextWrapper { + context_function: @CtxtFn, +} - }; - @AstFoldFns{ - fold_ident : fi, - fold_mac : fm, - .. *afp +impl ast_fold for ContextWrapper { + fn fold_ident(&self, id: ast::Ident) -> ast::Ident { + let ast::Ident { + name, + ctxt + } = id; + ast::Ident { + name: name, + ctxt: self.context_function.f(ctxt), + } + } + fn fold_mac(&self, m: &ast::mac) -> ast::mac { + let macro = match m.node { + mac_invoc_tt(ref path, ref tts, ctxt) => { + mac_invoc_tt(self.fold_path(path), + fold_tts(*tts, self), + self.context_function.f(ctxt)) + } + }; + Spanned { + node: macro, + span: m.span, + } } } - - -// given a mutable list of renames, return a tree-folder that applies those -// renames. -// FIXME #4536: currently pub to allow testing -pub fn renames_to_fold(renames : @mut ~[(ast::Ident,ast::Name)]) -> @AstFoldFns { - fun_to_ctxt_folder(@MultiRenamer{renames : renames}) +// given a function from ctxts to ctxts, produce +// an ast_fold that applies that function to all ctxts: +pub fn fun_to_ctxt_folder<T : 'static + CtxtFn>(cf: @T) -> @ContextWrapper { + @ContextWrapper { + context_function: cf as @CtxtFn, + } } // just a convenience: -pub fn new_mark_folder(m : Mrk) -> @AstFoldFns { +pub fn new_mark_folder(m: Mrk) -> @ContextWrapper { fun_to_ctxt_folder(@Marker{mark:m}) } -pub fn new_rename_folder(from : ast::Ident, to : ast::Name) -> @AstFoldFns { +pub fn new_rename_folder(from: ast::Ident, to: ast::Name) -> @ContextWrapper { fun_to_ctxt_folder(@Renamer{from:from,to:to}) } // apply a given mark to the given token trees. Used prior to expansion of a macro. fn mark_tts(tts : &[token_tree], m : Mrk) -> ~[token_tree] { - fold_tts(tts,new_mark_folder(m) as @ast_fold) + fold_tts(tts,new_mark_folder(m)) } // apply a given mark to the given expr. Used following the expansion of a macro. diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 5472c61a155..18ddee34171 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -14,227 +14,434 @@ use codemap::{Span, Spanned}; use parse::token; use opt_vec::OptVec; -// this file defines an ast_fold trait for objects that can perform -// a "fold" on Rust ASTs. It also contains a structure that implements -// that trait, and a "default_fold" whose fields contain closures -// that perform "default traversals", visiting all of the sub-elements -// and re-assembling the result. The "fun_to_ident_folder" in the -// test module provides a simple example of creating a very simple -// fold that only looks at identifiers. - +// We may eventually want to be able to fold over type parameters, too. pub trait ast_fold { - fn fold_crate(@self, &Crate) -> Crate; - fn fold_view_item(@self, &view_item) -> view_item; - fn fold_foreign_item(@self, @foreign_item) -> @foreign_item; - fn fold_item(@self, @item) -> Option<@item>; - fn fold_struct_field(@self, @struct_field) -> @struct_field; - fn fold_item_underscore(@self, &item_) -> item_; - fn fold_type_method(@self, m: &TypeMethod) -> TypeMethod; - fn fold_method(@self, @method) -> @method; - fn fold_block(@self, &Block) -> Block; - fn fold_stmt(@self, &Stmt) -> Option<@Stmt>; - fn fold_arm(@self, &Arm) -> Arm; - fn fold_pat(@self, @Pat) -> @Pat; - fn fold_decl(@self, @Decl) -> Option<@Decl>; - fn fold_expr(@self, @Expr) -> @Expr; - fn fold_ty(@self, &Ty) -> Ty; - fn fold_mod(@self, &_mod) -> _mod; - fn fold_foreign_mod(@self, &foreign_mod) -> foreign_mod; - fn fold_variant(@self, &variant) -> variant; - fn fold_ident(@self, Ident) -> Ident; - fn fold_path(@self, &Path) -> Path; - fn fold_local(@self, @Local) -> @Local; - fn fold_mac(@self, &mac) -> mac; - fn map_exprs(@self, @fn(@Expr) -> @Expr, &[@Expr]) -> ~[@Expr]; - fn new_id(@self, NodeId) -> NodeId; - fn new_span(@self, Span) -> Span; - - // New style, using default methods: - - fn fold_variant_arg(@self, va: &variant_arg) -> variant_arg { - variant_arg { - ty: self.fold_ty(&va.ty), - id: self.new_id(va.id) - } - } - - fn fold_spanned<T>(@self, s: &Spanned<T>, f: &fn(&T) -> T) -> Spanned<T> { - Spanned { - node: f(&s.node), - span: self.new_span(s.span) - } + fn fold_crate(&self, c: &Crate) -> Crate { + noop_fold_crate(c, self) } - fn fold_view_path(@self, vp: &view_path) -> view_path { - self.fold_spanned(vp, |v| self.fold_view_path_(v)) + fn fold_meta_items(&self, meta_items: &[@MetaItem]) -> ~[@MetaItem] { + meta_items.map(|x| fold_meta_item_(*x, self)) } - fn fold_view_paths(@self, vps: &[@view_path]) -> ~[@view_path] { - vps.map(|vp| @self.fold_view_path(*vp)) + fn fold_view_paths(&self, view_paths: &[@view_path]) -> ~[@view_path] { + view_paths.map(|view_path| { + let inner_view_path = match view_path.node { + view_path_simple(ref ident, ref path, node_id) => { + view_path_simple(ident.clone(), + self.fold_path(path), + self.new_id(node_id)) + } + view_path_glob(ref path, node_id) => { + view_path_glob(self.fold_path(path), self.new_id(node_id)) + } + view_path_list(ref path, ref path_list_idents, node_id) => { + view_path_list(self.fold_path(path), + path_list_idents.map(|path_list_ident| { + let id = self.new_id(path_list_ident.node + .id); + Spanned { + node: path_list_ident_ { + name: path_list_ident.node + .name + .clone(), + id: id, + }, + span: self.new_span( + path_list_ident.span) + } + }), + self.new_id(node_id)) + } + }; + @Spanned { + node: inner_view_path, + span: self.new_span(view_path.span), + } + }) } - fn fold_view_path_(@self, vp: &view_path_) -> view_path_ { - match *vp { - view_path_simple(ident, ref path, node_id) => { - view_path_simple(self.fold_ident(ident), - self.fold_path(path), - self.new_id(node_id)) - } - view_path_glob(ref path, node_id) => { - view_path_glob(self.fold_path(path), - self.new_id(node_id)) + fn fold_view_item(&self, vi: &view_item) -> view_item { + let inner_view_item = match vi.node { + view_item_extern_mod(ref ident, + string, + ref meta_items, + node_id) => { + view_item_extern_mod(ident.clone(), + string, + self.fold_meta_items(*meta_items), + self.new_id(node_id)) } - view_path_list(ref path, ref idents, node_id) => { - view_path_list(self.fold_path(path), - self.fold_path_list_idents(*idents), - self.new_id(node_id)) + view_item_use(ref view_paths) => { + view_item_use(self.fold_view_paths(*view_paths)) } + }; + view_item { + node: inner_view_item, + attrs: vi.attrs.map(|a| fold_attribute_(*a, self)), + vis: vi.vis, + span: self.new_span(vi.span), + } + } + + fn fold_foreign_item(&self, ni: @foreign_item) -> @foreign_item { + let fold_attribute = |x| fold_attribute_(x, self); + + @ast::foreign_item { + ident: self.fold_ident(ni.ident), + attrs: ni.attrs.map(|x| fold_attribute(*x)), + node: + match ni.node { + foreign_item_fn(ref fdec, ref generics) => { + foreign_item_fn( + ast::fn_decl { + inputs: fdec.inputs.map(|a| fold_arg_(a, + self)), + output: self.fold_ty(&fdec.output), + cf: fdec.cf, + }, + fold_generics(generics, self)) + } + foreign_item_static(ref t, m) => { + foreign_item_static(self.fold_ty(t), m) + } + }, + id: self.new_id(ni.id), + span: self.new_span(ni.span), + vis: ni.vis, } } - fn fold_path_list_idents(@self, idents: &[path_list_ident]) -> ~[path_list_ident] { - idents.map(|i| self.fold_path_list_ident(i)) + fn fold_item(&self, i: @item) -> Option<@item> { + noop_fold_item(i, self) } - fn fold_path_list_ident(@self, ident: &path_list_ident) -> path_list_ident { - self.fold_spanned(ident, |i| self.fold_path_list_ident_(i)) - } + fn fold_struct_field(&self, sf: @struct_field) -> @struct_field { + let fold_attribute = |x| fold_attribute_(x, self); - fn fold_path_list_ident_(@self, ident: &path_list_ident_) -> path_list_ident_ { - path_list_ident_ { - name: self.fold_ident(ident.name), - id: self.new_id(ident.id) + @Spanned { + node: ast::struct_field_ { + kind: sf.node.kind, + id: self.new_id(sf.node.id), + ty: self.fold_ty(&sf.node.ty), + attrs: sf.node.attrs.map(|e| fold_attribute(*e)) + }, + span: self.new_span(sf.span) } } - fn fold_arg(@self, a: &arg) -> arg { - arg { - is_mutbl: a.is_mutbl, - ty: self.fold_ty(&a.ty), - pat: self.fold_pat(a.pat), - id: self.new_id(a.id), + fn fold_item_underscore(&self, i: &item_) -> item_ { + noop_fold_item_underscore(i, self) + } + + fn fold_type_method(&self, m: &TypeMethod) -> TypeMethod { + noop_fold_type_method(m, self) + } + + fn fold_method(&self, m: @method) -> @method { + @ast::method { + ident: self.fold_ident(m.ident), + attrs: m.attrs.map(|a| fold_attribute_(*a, self)), + generics: fold_generics(&m.generics, self), + explicit_self: m.explicit_self, + purity: m.purity, + decl: fold_fn_decl(&m.decl, self), + body: self.fold_block(&m.body), + id: self.new_id(m.id), + span: self.new_span(m.span), + self_id: self.new_id(m.self_id), + vis: m.vis, } } - fn fold_trait_ref(@self, p: &trait_ref) -> trait_ref { - trait_ref { - path: self.fold_path(&p.path), - ref_id: self.new_id(p.ref_id), + fn fold_block(&self, b: &Block) -> Block { + noop_fold_block(b, self) + } + + fn fold_stmt(&self, s: &Stmt) -> Option<@Stmt> { + noop_fold_stmt(s, self) + } + + fn fold_arm(&self, a: &Arm) -> Arm { + Arm { + pats: a.pats.map(|x| self.fold_pat(*x)), + guard: a.guard.map_move(|x| self.fold_expr(x)), + body: self.fold_block(&a.body), } } - fn fold_ty_param_bound(@self, tpb: &TyParamBound) -> TyParamBound { - match *tpb { - TraitTyParamBound(ref ty) => { - TraitTyParamBound(self.fold_trait_ref(ty)) + fn fold_pat(&self, p: @Pat) -> @Pat { + let node = match p.node { + PatWild => PatWild, + PatIdent(binding_mode, ref pth, ref sub) => { + PatIdent(binding_mode, + self.fold_path(pth), + sub.map_move(|x| self.fold_pat(x))) + } + PatLit(e) => PatLit(self.fold_expr(e)), + PatEnum(ref pth, ref pats) => { + PatEnum(self.fold_path(pth), + pats.map(|pats| pats.map(|x| self.fold_pat(*x)))) } - RegionTyParamBound => { - RegionTyParamBound + PatStruct(ref pth, ref fields, etc) => { + let pth_ = self.fold_path(pth); + let fs = do fields.map |f| { + ast::FieldPat { + ident: f.ident, + pat: self.fold_pat(f.pat) + } + }; + PatStruct(pth_, fs, etc) } + PatTup(ref elts) => PatTup(elts.map(|x| self.fold_pat(*x))), + PatBox(inner) => PatBox(self.fold_pat(inner)), + PatUniq(inner) => PatUniq(self.fold_pat(inner)), + PatRegion(inner) => PatRegion(self.fold_pat(inner)), + PatRange(e1, e2) => { + PatRange(self.fold_expr(e1), self.fold_expr(e2)) + }, + PatVec(ref before, ref slice, ref after) => { + PatVec(before.map(|x| self.fold_pat(*x)), + slice.map_move(|x| self.fold_pat(x)), + after.map(|x| self.fold_pat(*x))) + } + }; + + @Pat { + id: self.new_id(p.id), + span: self.new_span(p.span), + node: node, } } - fn fold_ty_param(@self, tp: &TyParam) -> TyParam { - TyParam { - ident: self.fold_ident(tp.ident), - id: self.new_id(tp.id), - bounds: tp.bounds.map(|x| self.fold_ty_param_bound(x)) + fn fold_decl(&self, d: @Decl) -> Option<@Decl> { + let node = match d.node { + DeclLocal(ref l) => Some(DeclLocal(self.fold_local(*l))), + DeclItem(it) => { + match self.fold_item(it) { + Some(it_folded) => Some(DeclItem(it_folded)), + None => None, + } + } + }; + + node.map_move(|node| { + @Spanned { + node: node, + span: d.span, + } + }) + } + + fn fold_expr(&self, e: @Expr) -> @Expr { + noop_fold_expr(e, self) + } + + fn fold_ty(&self, t: &Ty) -> Ty { + let node = match t.node { + ty_nil | ty_bot | ty_infer => t.node.clone(), + ty_box(ref mt) => ty_box(fold_mt(mt, self)), + ty_uniq(ref mt) => ty_uniq(fold_mt(mt, self)), + ty_vec(ref mt) => ty_vec(fold_mt(mt, self)), + ty_ptr(ref mt) => ty_ptr(fold_mt(mt, self)), + ty_rptr(region, ref mt) => ty_rptr(region, fold_mt(mt, self)), + ty_closure(ref f) => { + ty_closure(@TyClosure { + sigil: f.sigil, + purity: f.purity, + region: f.region, + onceness: f.onceness, + bounds: fold_opt_bounds(&f.bounds, self), + decl: fold_fn_decl(&f.decl, self), + lifetimes: f.lifetimes.map(|l| fold_lifetime(l, self)), + }) + } + ty_bare_fn(ref f) => { + ty_bare_fn(@TyBareFn { + lifetimes: f.lifetimes.map(|l| fold_lifetime(l, self)), + purity: f.purity, + abis: f.abis, + decl: fold_fn_decl(&f.decl, self) + }) + } + ty_tup(ref tys) => ty_tup(tys.map(|ty| self.fold_ty(ty))), + ty_path(ref path, ref bounds, id) => { + ty_path(self.fold_path(path), + fold_opt_bounds(bounds, self), + self.new_id(id)) + } + ty_fixed_length_vec(ref mt, e) => { + ty_fixed_length_vec(fold_mt(mt, self), self.fold_expr(e)) + } + ty_mac(ref mac) => ty_mac(self.fold_mac(mac)), + ty_typeof(expr) => ty_typeof(self.fold_expr(expr)), + }; + Ty { + id: self.new_id(t.id), + span: self.new_span(t.span), + node: node, } } - fn fold_ty_params(@self, tps: &OptVec<TyParam>) -> OptVec<TyParam> { - tps.map(|tp| self.fold_ty_param(tp)) + fn fold_mod(&self, m: &_mod) -> _mod { + noop_fold_mod(m, self) } - fn fold_lifetime(@self, l: &Lifetime) -> Lifetime { - Lifetime { - id: self.new_id(l.id), - span: self.new_span(l.span), - ident: l.ident, // Folding this ident causes hygiene errors - ndm + fn fold_foreign_mod(&self, nm: &foreign_mod) -> foreign_mod { + ast::foreign_mod { + sort: nm.sort, + abis: nm.abis, + view_items: nm.view_items + .iter() + .map(|x| self.fold_view_item(x)) + .collect(), + items: nm.items + .iter() + .map(|x| self.fold_foreign_item(*x)) + .collect(), } } - fn fold_lifetimes(@self, lts: &OptVec<Lifetime>) -> OptVec<Lifetime> { - lts.map(|l| self.fold_lifetime(l)) + fn fold_variant(&self, v: &variant) -> variant { + let kind; + match v.node.kind { + tuple_variant_kind(ref variant_args) => { + kind = tuple_variant_kind(variant_args.map(|x| + fold_variant_arg_(x, self))) + } + struct_variant_kind(ref struct_def) => { + kind = struct_variant_kind(@ast::struct_def { + fields: struct_def.fields.iter() + .map(|f| self.fold_struct_field(*f)).collect(), + ctor_id: struct_def.ctor_id.map(|c| self.new_id(*c)) + }) + } + } + + let fold_attribute = |x| fold_attribute_(x, self); + let attrs = v.node.attrs.map(|x| fold_attribute(*x)); + + let de = match v.node.disr_expr { + Some(e) => Some(self.fold_expr(e)), + None => None + }; + let node = ast::variant_ { + name: v.node.name, + attrs: attrs, + kind: kind, + id: self.new_id(v.node.id), + disr_expr: de, + vis: v.node.vis, + }; + Spanned { + node: node, + span: self.new_span(v.span), + } } + fn fold_ident(&self, i: Ident) -> Ident { + i + } - fn fold_meta_item(@self, mi: &MetaItem) -> @MetaItem { - @self.fold_spanned(mi, |n| match *n { - MetaWord(id) => { - MetaWord(id) - } - MetaList(id, ref mis) => { - MetaList(id, self.fold_meta_items(*mis)) - } - MetaNameValue(id, s) => { - MetaNameValue(id, s) - } + fn fold_path(&self, p: &Path) -> Path { + ast::Path { + span: self.new_span(p.span), + global: p.global, + segments: p.segments.map(|segment| ast::PathSegment { + identifier: self.fold_ident(segment.identifier), + lifetime: segment.lifetime, + types: segment.types.map(|typ| self.fold_ty(typ)), }) + } } - fn fold_meta_items(@self, mis: &[@MetaItem]) -> ~[@MetaItem] { - mis.map(|&mi| self.fold_meta_item(mi)) + fn fold_local(&self, l: @Local) -> @Local { + @Local { + is_mutbl: l.is_mutbl, + ty: self.fold_ty(&l.ty), + pat: self.fold_pat(l.pat), + init: l.init.map_move(|e| self.fold_expr(e)), + id: self.new_id(l.id), + span: self.new_span(l.span), + } } - fn fold_attribute(@self, at: &Attribute) -> Attribute { + fn fold_mac(&self, macro: &mac) -> mac { Spanned { - span: self.new_span(at.span), - node: Attribute_ { - style: at.node.style, - value: self.fold_meta_item(at.node.value), - is_sugared_doc: at.node.is_sugared_doc - } + node: match macro.node { + mac_invoc_tt(ref p, ref tts, ctxt) => { + mac_invoc_tt(self.fold_path(p), + fold_tts(*tts, self), + ctxt) + } + }, + span: self.new_span(macro.span) } } - fn fold_attributes(@self, attrs: &[Attribute]) -> ~[Attribute] { - attrs.map(|x| self.fold_attribute(x)) + fn map_exprs(&self, f: &fn(@Expr) -> @Expr, es: &[@Expr]) -> ~[@Expr] { + es.map(|x| f(*x)) + } + + fn new_id(&self, i: NodeId) -> NodeId { + i + } + + fn new_span(&self, sp: Span) -> Span { + sp } } -// We may eventually want to be able to fold over type parameters, too - -pub struct AstFoldFns { - //unlike the others, item_ is non-trivial - fold_crate: @fn(&Crate, @ast_fold) -> Crate, - fold_view_item: @fn(&view_item_, @ast_fold) -> view_item_, - fold_foreign_item: @fn(@foreign_item, @ast_fold) -> @foreign_item, - fold_item: @fn(@item, @ast_fold) -> Option<@item>, - fold_struct_field: @fn(@struct_field, @ast_fold) -> @struct_field, - fold_item_underscore: @fn(&item_, @ast_fold) -> item_, - fold_type_method: @fn(&TypeMethod, @ast_fold) -> TypeMethod, - fold_method: @fn(@method, @ast_fold) -> @method, - fold_block: @fn(&Block, @ast_fold) -> Block, - fold_stmt: @fn(&Stmt_, Span, @ast_fold) -> (Option<Stmt_>, Span), - fold_arm: @fn(&Arm, @ast_fold) -> Arm, - fold_pat: @fn(&Pat_, Span, @ast_fold) -> (Pat_, Span), - fold_decl: @fn(&Decl_, Span, @ast_fold) -> (Option<Decl_>, Span), - fold_expr: @fn(&Expr_, Span, @ast_fold) -> (Expr_, Span), - fold_ty: @fn(&ty_, Span, @ast_fold) -> (ty_, Span), - fold_mod: @fn(&_mod, @ast_fold) -> _mod, - fold_foreign_mod: @fn(&foreign_mod, @ast_fold) -> foreign_mod, - fold_variant: @fn(&variant_, Span, @ast_fold) -> (variant_, Span), - fold_ident: @fn(Ident, @ast_fold) -> Ident, - fold_path: @fn(&Path, @ast_fold) -> Path, - fold_local: @fn(@Local, @ast_fold) -> @Local, - fold_mac: @fn(&mac_, Span, @ast_fold) -> (mac_, Span), - map_exprs: @fn(@fn(@Expr) -> @Expr, &[@Expr]) -> ~[@Expr], - new_id: @fn(NodeId) -> NodeId, - new_span: @fn(Span) -> Span +/* some little folds that probably aren't useful to have in ast_fold itself*/ + +//used in noop_fold_item and noop_fold_crate and noop_fold_crate_directive +fn fold_meta_item_<T:ast_fold>(mi: @MetaItem, fld: &T) -> @MetaItem { + @Spanned { + node: + match mi.node { + MetaWord(id) => MetaWord(id), + MetaList(id, ref mis) => { + let fold_meta_item = |x| fold_meta_item_(x, fld); + MetaList( + id, + mis.map(|e| fold_meta_item(*e)) + ) + } + MetaNameValue(id, s) => MetaNameValue(id, s) + }, + span: fld.new_span(mi.span) } } -pub type ast_fold_fns = @AstFoldFns; +//used in noop_fold_item and noop_fold_crate +fn fold_attribute_<T:ast_fold>(at: Attribute, fld: &T) -> Attribute { + Spanned { + span: fld.new_span(at.span), + node: ast::Attribute_ { + style: at.node.style, + value: fold_meta_item_(at.node.value, fld), + is_sugared_doc: at.node.is_sugared_doc + } + } +} -/* some little folds that probably aren't useful to have in ast_fold itself*/ +//used in noop_fold_foreign_item and noop_fold_fn_decl +fn fold_arg_<T:ast_fold>(a: &arg, fld: &T) -> arg { + ast::arg { + is_mutbl: a.is_mutbl, + ty: fld.fold_ty(&a.ty), + pat: fld.fold_pat(a.pat), + id: fld.new_id(a.id), + } +} -pub fn fold_tts(tts : &[token_tree], fld: @ast_fold) -> ~[token_tree] { +// build a new vector of tts by appling the ast_fold's fold_ident to +// all of the identifiers in the token trees. +pub fn fold_tts<T:ast_fold>(tts: &[token_tree], fld: &T) -> ~[token_tree] { do tts.map |tt| { match *tt { tt_tok(span, ref tok) => tt_tok(span,maybe_fold_ident(tok,fld)), - tt_delim(ref tts) => - tt_delim(@mut fold_tts(**tts, fld)), + tt_delim(ref tts) => tt_delim(@mut fold_tts(**tts, fld)), tt_seq(span, ref pattern, ref sep, is_optional) => tt_seq(span, @mut fold_tts(**pattern, fld), @@ -247,33 +454,68 @@ pub fn fold_tts(tts : &[token_tree], fld: @ast_fold) -> ~[token_tree] { } // apply ident folder if it's an ident, otherwise leave it alone -fn maybe_fold_ident(t : &token::Token, f: @ast_fold) -> token::Token { +fn maybe_fold_ident<T:ast_fold>(t: &token::Token, fld: &T) -> token::Token { match *t { - token::IDENT(id,followed_by_colons) => - token::IDENT(f.fold_ident(id),followed_by_colons), + token::IDENT(id, followed_by_colons) => { + token::IDENT(fld.fold_ident(id), followed_by_colons) + } _ => (*t).clone() } } -pub fn fold_fn_decl(decl: &ast::fn_decl, fld: @ast_fold) -> ast::fn_decl { +pub fn fold_fn_decl<T:ast_fold>(decl: &ast::fn_decl, fld: &T) + -> ast::fn_decl { ast::fn_decl { - inputs: decl.inputs.map(|x| fld.fold_arg(x)), + inputs: decl.inputs.map(|x| fold_arg_(x, fld)), // bad copy output: fld.fold_ty(&decl.output), cf: decl.cf, } } -pub fn fold_generics(generics: &Generics, fld: @ast_fold) -> Generics { - Generics {ty_params: fld.fold_ty_params(&generics.ty_params), - lifetimes: fld.fold_lifetimes(&generics.lifetimes)} +fn fold_ty_param_bound<T:ast_fold>(tpb: &TyParamBound, fld: &T) + -> TyParamBound { + match *tpb { + TraitTyParamBound(ref ty) => TraitTyParamBound(fold_trait_ref(ty, fld)), + RegionTyParamBound => RegionTyParamBound + } } -pub fn noop_fold_crate(c: &Crate, fld: @ast_fold) -> Crate { - Crate { - module: fld.fold_mod(&c.module), - attrs: fld.fold_attributes(c.attrs), - config: fld.fold_meta_items(c.config), - span: fld.new_span(c.span), +pub fn fold_ty_param<T:ast_fold>(tp: &TyParam, fld: &T) -> TyParam { + TyParam { + ident: tp.ident, + id: fld.new_id(tp.id), + bounds: tp.bounds.map(|x| fold_ty_param_bound(x, fld)), + } +} + +pub fn fold_ty_params<T:ast_fold>(tps: &OptVec<TyParam>, fld: &T) + -> OptVec<TyParam> { + tps.map(|tp| fold_ty_param(tp, fld)) +} + +pub fn fold_lifetime<T:ast_fold>(l: &Lifetime, fld: &T) -> Lifetime { + Lifetime { + id: fld.new_id(l.id), + span: fld.new_span(l.span), + ident: l.ident + } +} + +pub fn fold_lifetimes<T:ast_fold>(lts: &OptVec<Lifetime>, fld: &T) + -> OptVec<Lifetime> { + lts.map(|l| fold_lifetime(l, fld)) +} + +pub fn fold_generics<T:ast_fold>(generics: &Generics, fld: &T) -> Generics { + Generics {ty_params: fold_ty_params(&generics.ty_params, fld), + lifetimes: fold_lifetimes(&generics.lifetimes, fld)} +} + +fn fold_struct_def<T:ast_fold>(struct_def: @ast::struct_def, fld: &T) + -> @ast::struct_def { + @ast::struct_def { + fields: struct_def.fields.map(|f| fold_struct_field(*f, fld)), + ctor_id: struct_def.ctor_id.map(|cid| fld.new_id(*cid)), } } @@ -291,753 +533,333 @@ fn noop_fold_view_item(vi: &view_item_, fld: @ast_fold) -> view_item_ { } } -fn noop_fold_foreign_item(ni: @foreign_item, fld: @ast_fold) - -> @foreign_item { - @ast::foreign_item { - ident: fld.fold_ident(ni.ident), - attrs: fld.fold_attributes(ni.attrs), - node: - match ni.node { - foreign_item_fn(ref fdec, ref generics) => { - foreign_item_fn( - ast::fn_decl { - inputs: fdec.inputs.map(|a| fld.fold_arg(a)), - output: fld.fold_ty(&fdec.output), - cf: fdec.cf, - }, - fold_generics(generics, fld)) - } - foreign_item_static(ref t, m) => { - foreign_item_static(fld.fold_ty(t), m) - } - }, - id: fld.new_id(ni.id), - span: fld.new_span(ni.span), - vis: ni.vis, +fn fold_trait_ref<T:ast_fold>(p: &trait_ref, fld: &T) -> trait_ref { + ast::trait_ref { + path: fld.fold_path(&p.path), + ref_id: fld.new_id(p.ref_id), } } -pub fn noop_fold_item(i: @item, fld: @ast_fold) -> Option<@item> { - Some(@ast::item { ident: fld.fold_ident(i.ident), - attrs: fld.fold_attributes(i.attrs), - id: fld.new_id(i.id), - node: fld.fold_item_underscore(&i.node), - vis: i.vis, - span: fld.new_span(i.span) }) -} - -fn noop_fold_struct_field(sf: @struct_field, fld: @ast_fold) - -> @struct_field { +fn fold_struct_field<T:ast_fold>(f: @struct_field, fld: &T) -> @struct_field { @Spanned { node: ast::struct_field_ { - kind: sf.node.kind, - id: fld.new_id(sf.node.id), - ty: fld.fold_ty(&sf.node.ty), - attrs: fld.fold_attributes(sf.node.attrs), + kind: f.node.kind, + id: fld.new_id(f.node.id), + ty: fld.fold_ty(&f.node.ty), + attrs: f.node.attrs.map(|a| fold_attribute_(*a, fld)), }, - span: sf.span + span: fld.new_span(f.span), } } -pub fn noop_fold_type_method(m: &TypeMethod, fld: @ast_fold) -> TypeMethod { - TypeMethod { - ident: fld.fold_ident(m.ident), - attrs: fld.fold_attributes(m.attrs), - purity: m.purity, - decl: fold_fn_decl(&m.decl, fld), - generics: fold_generics(&m.generics, fld), - explicit_self: m.explicit_self, - id: fld.new_id(m.id), - span: fld.new_span(m.span), +fn fold_field_<T:ast_fold>(field: Field, folder: &T) -> Field { + ast::Field { + ident: folder.fold_ident(field.ident), + expr: folder.fold_expr(field.expr), + span: folder.new_span(field.span), } } -pub fn noop_fold_item_underscore(i: &item_, fld: @ast_fold) -> item_ { +fn fold_mt<T:ast_fold>(mt: &mt, folder: &T) -> mt { + mt { + ty: ~folder.fold_ty(mt.ty), + mutbl: mt.mutbl, + } +} + +fn fold_field<T:ast_fold>(f: TypeField, folder: &T) -> TypeField { + ast::TypeField { + ident: folder.fold_ident(f.ident), + mt: fold_mt(&f.mt, folder), + span: folder.new_span(f.span), + } +} + +fn fold_opt_bounds<T:ast_fold>(b: &Option<OptVec<TyParamBound>>, folder: &T) + -> Option<OptVec<TyParamBound>> { + do b.map |bounds| { + do bounds.map |bound| { + fold_ty_param_bound(bound, folder) + } + } +} + +fn fold_variant_arg_<T:ast_fold>(va: &variant_arg, folder: &T) + -> variant_arg { + ast::variant_arg { + ty: folder.fold_ty(&va.ty), + id: folder.new_id(va.id) + } +} + +pub fn noop_fold_block<T:ast_fold>(b: &Block, folder: &T) -> Block { + let view_items = b.view_items.map(|x| folder.fold_view_item(x)); + let mut stmts = ~[]; + for stmt in b.stmts.iter() { + match folder.fold_stmt(*stmt) { + None => {} + Some(stmt) => stmts.push(stmt) + } + } + ast::Block { + view_items: view_items, + stmts: stmts, + expr: b.expr.map(|x| folder.fold_expr(*x)), + id: folder.new_id(b.id), + rules: b.rules, + span: folder.new_span(b.span), + } +} + +pub fn noop_fold_item_underscore<T:ast_fold>(i: &item_, folder: &T) -> item_ { match *i { item_static(ref t, m, e) => { - item_static(fld.fold_ty(t), m, fld.fold_expr(e)) + item_static(folder.fold_ty(t), m, folder.fold_expr(e)) } item_fn(ref decl, purity, abi, ref generics, ref body) => { item_fn( - fold_fn_decl(decl, fld), + fold_fn_decl(decl, folder), purity, abi, - fold_generics(generics, fld), - fld.fold_block(body) + fold_generics(generics, folder), + folder.fold_block(body) ) } - item_mod(ref m) => { - item_mod(fld.fold_mod(m)) - } + item_mod(ref m) => item_mod(folder.fold_mod(m)), item_foreign_mod(ref nm) => { - item_foreign_mod(fld.fold_foreign_mod(nm)) + item_foreign_mod(folder.fold_foreign_mod(nm)) } item_ty(ref t, ref generics) => { - item_ty(fld.fold_ty(t), fold_generics(generics, fld)) + item_ty(folder.fold_ty(t), + fold_generics(generics, folder)) } item_enum(ref enum_definition, ref generics) => { item_enum( ast::enum_def { variants: do enum_definition.variants.map |x| { - fld.fold_variant(x) + folder.fold_variant(x) }, }, - fold_generics(generics, fld)) + fold_generics(generics, folder)) } item_struct(ref struct_def, ref generics) => { - let struct_def = fold_struct_def(*struct_def, fld); - item_struct(struct_def, fold_generics(generics, fld)) + let struct_def = fold_struct_def(*struct_def, folder); + item_struct(struct_def, fold_generics(generics, folder)) } item_impl(ref generics, ref ifce, ref ty, ref methods) => { - item_impl( - fold_generics(generics, fld), - ifce.map(|p| fld.fold_trait_ref(p)), - fld.fold_ty(ty), - methods.map(|x| fld.fold_method(*x)) + item_impl(fold_generics(generics, folder), + ifce.map(|p| fold_trait_ref(p, folder)), + folder.fold_ty(ty), + methods.map(|x| folder.fold_method(*x)) ) } item_trait(ref generics, ref traits, ref methods) => { let methods = do methods.map |method| { match *method { - required(ref m) => required(fld.fold_type_method(m)), - provided(method) => provided(fld.fold_method(method)) + required(ref m) => required(folder.fold_type_method(m)), + provided(method) => provided(folder.fold_method(method)) } }; - item_trait( - fold_generics(generics, fld), - traits.map(|p| fld.fold_trait_ref(p)), - methods - ) - } - item_mac(ref m) => { - item_mac(fld.fold_mac(m)) + item_trait(fold_generics(generics, folder), + traits.map(|p| fold_trait_ref(p, folder)), + methods) } + item_mac(ref m) => item_mac(folder.fold_mac(m)), } } -fn fold_struct_def(struct_def: @ast::struct_def, fld: @ast_fold) - -> @ast::struct_def { - @ast::struct_def { - fields: struct_def.fields.map(|f| fold_struct_field(*f, fld)), - ctor_id: struct_def.ctor_id.map(|cid| fld.new_id(*cid)), - } -} - -fn fold_struct_field(f: @struct_field, fld: @ast_fold) -> @struct_field { - @Spanned { - node: ast::struct_field_ { - kind: f.node.kind, - id: fld.new_id(f.node.id), - ty: fld.fold_ty(&f.node.ty), - attrs: fld.fold_attributes(f.node.attrs), - }, - span: fld.new_span(f.span), - } -} - -fn noop_fold_method(m: @method, fld: @ast_fold) -> @method { - @ast::method { +pub fn noop_fold_type_method<T:ast_fold>(m: &TypeMethod, fld: &T) + -> TypeMethod { + TypeMethod { ident: fld.fold_ident(m.ident), - attrs: fld.fold_attributes(m.attrs), - generics: fold_generics(&m.generics, fld), - explicit_self: m.explicit_self, + attrs: m.attrs.map(|a| fold_attribute_(*a, fld)), purity: m.purity, decl: fold_fn_decl(&m.decl, fld), - body: fld.fold_block(&m.body), + generics: fold_generics(&m.generics, fld), + explicit_self: m.explicit_self, id: fld.new_id(m.id), span: fld.new_span(m.span), - self_id: fld.new_id(m.self_id), - vis: m.vis, - } -} - - -pub fn noop_fold_block(b: &Block, fld: @ast_fold) -> Block { - let view_items = b.view_items.map(|x| fld.fold_view_item(x)); - let mut stmts = ~[]; - for stmt in b.stmts.iter() { - match fld.fold_stmt(*stmt) { - None => {} - Some(stmt) => stmts.push(stmt) - } - } - ast::Block { - view_items: view_items, - stmts: stmts, - expr: b.expr.map(|x| fld.fold_expr(*x)), - id: fld.new_id(b.id), - rules: b.rules, - span: b.span, } } -fn noop_fold_stmt(s: &Stmt_, fld: @ast_fold) -> Option<Stmt_> { - match *s { - StmtDecl(d, nid) => { - match fld.fold_decl(d) { - Some(d) => Some(StmtDecl(d, fld.new_id(nid))), - None => None, - } - } - StmtExpr(e, nid) => { - Some(StmtExpr(fld.fold_expr(e), fld.new_id(nid))) - } - StmtSemi(e, nid) => { - Some(StmtSemi(fld.fold_expr(e), fld.new_id(nid))) - } - StmtMac(ref mac, semi) => Some(StmtMac(fld.fold_mac(mac), semi)) +pub fn noop_fold_mod<T:ast_fold>(m: &_mod, folder: &T) -> _mod { + ast::_mod { + view_items: m.view_items + .iter() + .map(|x| folder.fold_view_item(x)).collect(), + items: m.items.iter().filter_map(|x| folder.fold_item(*x)).collect(), } } -fn noop_fold_arm(a: &Arm, fld: @ast_fold) -> Arm { - Arm { - pats: a.pats.map(|x| fld.fold_pat(*x)), - guard: a.guard.map_move(|x| fld.fold_expr(x)), - body: fld.fold_block(&a.body), - } -} +pub fn noop_fold_crate<T:ast_fold>(c: &Crate, folder: &T) -> Crate { + let fold_meta_item = |x| fold_meta_item_(x, folder); + let fold_attribute = |x| fold_attribute_(x, folder); -pub fn noop_fold_pat(p: &Pat_, fld: @ast_fold) -> Pat_ { - match *p { - PatWild => PatWild, - PatIdent(binding_mode, ref pth, ref sub) => { - PatIdent( - binding_mode, - fld.fold_path(pth), - sub.map_move(|x| fld.fold_pat(x)) - ) - } - PatLit(e) => PatLit(fld.fold_expr(e)), - PatEnum(ref pth, ref pats) => { - PatEnum( - fld.fold_path(pth), - pats.map(|pats| pats.map(|x| fld.fold_pat(*x))) - ) - } - PatStruct(ref pth, ref fields, etc) => { - let pth_ = fld.fold_path(pth); - let fs = do fields.map |f| { - ast::FieldPat { - ident: f.ident, - pat: fld.fold_pat(f.pat) - } - }; - PatStruct(pth_, fs, etc) - } - PatTup(ref elts) => PatTup(elts.map(|x| fld.fold_pat(*x))), - PatBox(inner) => PatBox(fld.fold_pat(inner)), - PatUniq(inner) => PatUniq(fld.fold_pat(inner)), - PatRegion(inner) => PatRegion(fld.fold_pat(inner)), - PatRange(e1, e2) => { - PatRange(fld.fold_expr(e1), fld.fold_expr(e2)) - }, - PatVec(ref before, ref slice, ref after) => { - PatVec( - before.map(|x| fld.fold_pat(*x)), - slice.map_move(|x| fld.fold_pat(x)), - after.map(|x| fld.fold_pat(*x)) - ) - } + Crate { + module: folder.fold_mod(&c.module), + attrs: c.attrs.map(|x| fold_attribute(*x)), + config: c.config.map(|x| fold_meta_item(*x)), + span: folder.new_span(c.span), } } -fn noop_fold_decl(d: &Decl_, fld: @ast_fold) -> Option<Decl_> { - match *d { - DeclLocal(ref l) => Some(DeclLocal(fld.fold_local(*l))), - DeclItem(it) => { - match fld.fold_item(it) { - Some(it_folded) => Some(DeclItem(it_folded)), - None => None, - } - } - } -} +pub fn noop_fold_item<T:ast_fold>(i: @ast::item, folder: &T) + -> Option<@ast::item> { + let fold_attribute = |x| fold_attribute_(x, folder); -// lift a function in ast-thingy X fold -> ast-thingy to a function -// in (ast-thingy X span X fold) -> (ast-thingy X span). Basically, -// carries the span around. -// It seems strange to me that the call to new_fold doesn't happen -// here but instead in the impl down below.... probably just an -// accident? -pub fn wrap<T>(f: @fn(&T, @ast_fold) -> T) - -> @fn(&T, Span, @ast_fold) -> (T, Span) { - let result: @fn(&T, Span, @ast_fold) -> (T, Span) = |x, s, fld| { - (f(x, fld), s) - }; - result + Some(@ast::item { + ident: folder.fold_ident(i.ident), + attrs: i.attrs.map(|e| fold_attribute(*e)), + id: folder.new_id(i.id), + node: folder.fold_item_underscore(&i.node), + vis: i.vis, + span: folder.new_span(i.span) + }) } -pub fn noop_fold_expr(e: &Expr_, fld: @ast_fold) -> Expr_ { - fn fold_field_(field: Field, fld: @ast_fold) -> Field { - ast::Field { - ident: fld.fold_ident(field.ident), - expr: fld.fold_expr(field.expr), - span: fld.new_span(field.span), - } - } - let fold_field = |x| fold_field_(x, fld); +pub fn noop_fold_expr<T:ast_fold>(e: @ast::Expr, folder: &T) -> @ast::Expr { + let fold_field = |x| fold_field_(x, folder); - match *e { + let node = match e.node { ExprVstore(e, v) => { - ExprVstore(fld.fold_expr(e), v) + ExprVstore(folder.fold_expr(e), v) } ExprVec(ref exprs, mutt) => { - ExprVec(fld.map_exprs(|x| fld.fold_expr(x), *exprs), mutt) + ExprVec(folder.map_exprs(|x| folder.fold_expr(x), *exprs), mutt) } ExprRepeat(expr, count, mutt) => { - ExprRepeat(fld.fold_expr(expr), fld.fold_expr(count), mutt) + ExprRepeat(folder.fold_expr(expr), folder.fold_expr(count), mutt) } - ExprTup(ref elts) => ExprTup(elts.map(|x| fld.fold_expr(*x))), + ExprTup(ref elts) => ExprTup(elts.map(|x| folder.fold_expr(*x))), ExprCall(f, ref args, blk) => { - ExprCall( - fld.fold_expr(f), - fld.map_exprs(|x| fld.fold_expr(x), *args), - blk - ) + ExprCall(folder.fold_expr(f), + folder.map_exprs(|x| folder.fold_expr(x), *args), + blk) } ExprMethodCall(callee_id, f, i, ref tps, ref args, blk) => { ExprMethodCall( - fld.new_id(callee_id), - fld.fold_expr(f), - fld.fold_ident(i), - tps.map(|x| fld.fold_ty(x)), - fld.map_exprs(|x| fld.fold_expr(x), *args), + folder.new_id(callee_id), + folder.fold_expr(f), + folder.fold_ident(i), + tps.map(|x| folder.fold_ty(x)), + folder.map_exprs(|x| folder.fold_expr(x), *args), blk ) } ExprBinary(callee_id, binop, lhs, rhs) => { - ExprBinary( - fld.new_id(callee_id), - binop, - fld.fold_expr(lhs), - fld.fold_expr(rhs) - ) + ExprBinary(folder.new_id(callee_id), + binop, + folder.fold_expr(lhs), + folder.fold_expr(rhs)) } ExprUnary(callee_id, binop, ohs) => { - ExprUnary( - fld.new_id(callee_id), - binop, - fld.fold_expr(ohs) - ) + ExprUnary(folder.new_id(callee_id), binop, folder.fold_expr(ohs)) } - ExprDoBody(f) => ExprDoBody(fld.fold_expr(f)), - ExprLit(_) => (*e).clone(), + ExprDoBody(f) => ExprDoBody(folder.fold_expr(f)), + ExprLit(_) => e.node.clone(), ExprCast(expr, ref ty) => { - ExprCast(fld.fold_expr(expr), fld.fold_ty(ty)) + ExprCast(folder.fold_expr(expr), folder.fold_ty(ty)) } - ExprAddrOf(m, ohs) => ExprAddrOf(m, fld.fold_expr(ohs)), + ExprAddrOf(m, ohs) => ExprAddrOf(m, folder.fold_expr(ohs)), ExprIf(cond, ref tr, fl) => { - ExprIf( - fld.fold_expr(cond), - fld.fold_block(tr), - fl.map_move(|x| fld.fold_expr(x)) - ) + ExprIf(folder.fold_expr(cond), + folder.fold_block(tr), + fl.map_move(|x| folder.fold_expr(x))) } ExprWhile(cond, ref body) => { - ExprWhile(fld.fold_expr(cond), fld.fold_block(body)) + ExprWhile(folder.fold_expr(cond), folder.fold_block(body)) } - ExprForLoop(pat, iter, ref body, opt_ident) => { - ExprForLoop(fld.fold_pat(pat), - fld.fold_expr(iter), - fld.fold_block(body), - opt_ident.map_move(|x| fld.fold_ident(x))) + ExprForLoop(pat, iter, ref body, ref maybe_ident) => { + ExprForLoop(folder.fold_pat(pat), + folder.fold_expr(iter), + folder.fold_block(body), + maybe_ident.map_move(|i| folder.fold_ident(i))) } ExprLoop(ref body, opt_ident) => { - ExprLoop( - fld.fold_block(body), - opt_ident.map_move(|x| fld.fold_ident(x)) - ) + ExprLoop(folder.fold_block(body), + opt_ident.map_move(|x| folder.fold_ident(x))) } ExprMatch(expr, ref arms) => { - ExprMatch( - fld.fold_expr(expr), - arms.map(|x| fld.fold_arm(x)) - ) + ExprMatch(folder.fold_expr(expr), + arms.map(|x| folder.fold_arm(x))) } ExprFnBlock(ref decl, ref body) => { ExprFnBlock( - fold_fn_decl(decl, fld), - fld.fold_block(body) + fold_fn_decl(decl, folder), + folder.fold_block(body) ) } - ExprBlock(ref blk) => ExprBlock(fld.fold_block(blk)), + ExprBlock(ref blk) => ExprBlock(folder.fold_block(blk)), ExprAssign(el, er) => { - ExprAssign(fld.fold_expr(el), fld.fold_expr(er)) + ExprAssign(folder.fold_expr(el), folder.fold_expr(er)) } ExprAssignOp(callee_id, op, el, er) => { - ExprAssignOp( - fld.new_id(callee_id), - op, - fld.fold_expr(el), - fld.fold_expr(er) - ) + ExprAssignOp(folder.new_id(callee_id), + op, + folder.fold_expr(el), + folder.fold_expr(er)) } ExprField(el, id, ref tys) => { - ExprField( - fld.fold_expr(el), fld.fold_ident(id), - tys.map(|x| fld.fold_ty(x)) - ) + ExprField(folder.fold_expr(el), folder.fold_ident(id), + tys.map(|x| folder.fold_ty(x))) } ExprIndex(callee_id, el, er) => { - ExprIndex( - fld.new_id(callee_id), - fld.fold_expr(el), - fld.fold_expr(er) - ) + ExprIndex(folder.new_id(callee_id), + folder.fold_expr(el), + folder.fold_expr(er)) } - ExprPath(ref pth) => ExprPath(fld.fold_path(pth)), + ExprPath(ref pth) => ExprPath(folder.fold_path(pth)), ExprSelf => ExprSelf, - ExprBreak(ref opt_ident) => { - // FIXME #6993: add fold_name to fold.... then cut out the - // bogus Name->Ident->Name conversion. - ExprBreak(opt_ident.map_move(|x| { - // FIXME #9129: Assigning the new ident to a temporary to work around codegen bug - let newx = Ident::new(x); - fld.fold_ident(newx).name - })) - } - ExprAgain(ref opt_ident) => { - // FIXME #6993: add fold_name to fold.... - ExprAgain(opt_ident.map_move(|x| { - // FIXME #9129: Assigning the new ident to a temporary to work around codegen bug - let newx = Ident::new(x); - fld.fold_ident(newx).name - })) - } + ExprLogLevel => ExprLogLevel, + ExprBreak(opt_ident) => ExprBreak(opt_ident), + ExprAgain(opt_ident) => ExprAgain(opt_ident), ExprRet(ref e) => { - ExprRet(e.map_move(|x| fld.fold_expr(x))) + ExprRet(e.map_move(|x| folder.fold_expr(x))) } - ExprLogLevel => ExprLogLevel, ExprInlineAsm(ref a) => { ExprInlineAsm(inline_asm { - inputs: a.inputs.map(|&(c, input)| (c, fld.fold_expr(input))), - outputs: a.outputs.map(|&(c, out)| (c, fld.fold_expr(out))), + inputs: a.inputs.map(|&(c, input)| (c, folder.fold_expr(input))), + outputs: a.outputs.map(|&(c, out)| (c, folder.fold_expr(out))), .. (*a).clone() }) } - ExprMac(ref mac) => ExprMac(fld.fold_mac(mac)), + ExprMac(ref mac) => ExprMac(folder.fold_mac(mac)), ExprStruct(ref path, ref fields, maybe_expr) => { - ExprStruct( - fld.fold_path(path), - fields.map(|x| fold_field(*x)), - maybe_expr.map_move(|x| fld.fold_expr(x)) - ) + ExprStruct(folder.fold_path(path), + fields.map(|x| fold_field(*x)), + maybe_expr.map_move(|x| folder.fold_expr(x))) }, - ExprParen(ex) => ExprParen(fld.fold_expr(ex)) - } -} - -pub fn noop_fold_ty(t: &ty_, fld: @ast_fold) -> ty_ { - fn fold_mt(mt: &mt, fld: @ast_fold) -> mt { - mt { - ty: ~fld.fold_ty(mt.ty), - mutbl: mt.mutbl, - } - } - fn fold_field(f: TypeField, fld: @ast_fold) -> TypeField { - ast::TypeField { - ident: fld.fold_ident(f.ident), - mt: fold_mt(&f.mt, fld), - span: fld.new_span(f.span), - } - } - fn fold_opt_bounds(b: &Option<OptVec<TyParamBound>>, fld: @ast_fold) - -> Option<OptVec<TyParamBound>> { - do b.map |bounds| { - do bounds.map |bound| { fld.fold_ty_param_bound(bound) } - } - } - match *t { - ty_nil | ty_bot | ty_infer => (*t).clone(), - ty_box(ref mt) => ty_box(fold_mt(mt, fld)), - ty_uniq(ref mt) => ty_uniq(fold_mt(mt, fld)), - ty_vec(ref mt) => ty_vec(fold_mt(mt, fld)), - ty_ptr(ref mt) => ty_ptr(fold_mt(mt, fld)), - ty_rptr(region, ref mt) => ty_rptr(region, fold_mt(mt, fld)), - ty_closure(ref f) => { - ty_closure(@TyClosure { - sigil: f.sigil, - purity: f.purity, - region: f.region, - onceness: f.onceness, - bounds: fold_opt_bounds(&f.bounds, fld), - decl: fold_fn_decl(&f.decl, fld), - lifetimes: fld.fold_lifetimes(&f.lifetimes) - }) - } - ty_bare_fn(ref f) => { - ty_bare_fn(@TyBareFn { - lifetimes: fld.fold_lifetimes(&f.lifetimes), - purity: f.purity, - abis: f.abis, - decl: fold_fn_decl(&f.decl, fld) - }) - } - ty_tup(ref tys) => ty_tup(tys.map(|ty| fld.fold_ty(ty))), - ty_path(ref path, ref bounds, id) => - ty_path(fld.fold_path(path), fold_opt_bounds(bounds, fld), fld.new_id(id)), - ty_fixed_length_vec(ref mt, e) => { - ty_fixed_length_vec( - fold_mt(mt, fld), - fld.fold_expr(e) - ) - } - ty_typeof(e) => ty_typeof(fld.fold_expr(e)), - ty_mac(ref mac) => ty_mac(fld.fold_mac(mac)) - } -} - -// ...nor do modules -pub fn noop_fold_mod(m: &_mod, fld: @ast_fold) -> _mod { - ast::_mod { - view_items: m.view_items.iter().map(|x| fld.fold_view_item(x)).collect(), - items: m.items.iter().filter_map(|x| fld.fold_item(*x)).collect(), - } -} - -fn noop_fold_foreign_mod(nm: &foreign_mod, fld: @ast_fold) -> foreign_mod { - ast::foreign_mod { - sort: nm.sort, - abis: nm.abis, - view_items: nm.view_items.iter().map(|x| fld.fold_view_item(x)).collect(), - items: nm.items.iter().map(|x| fld.fold_foreign_item(*x)).collect(), - } -} - -fn noop_fold_variant(v: &variant_, fld: @ast_fold) -> variant_ { - let kind = match v.kind { - tuple_variant_kind(ref variant_args) => { - tuple_variant_kind(variant_args.map(|x| fld.fold_variant_arg(x))) - } - struct_variant_kind(ref struct_def) => { - struct_variant_kind(@ast::struct_def { - fields: struct_def.fields.iter() - .map(|f| fld.fold_struct_field(*f)).collect(), - ctor_id: struct_def.ctor_id.map(|c| fld.new_id(*c)) - }) - } + ExprParen(ex) => ExprParen(folder.fold_expr(ex)) }; - let attrs = fld.fold_attributes(v.attrs); - - let de = match v.disr_expr { - Some(e) => Some(fld.fold_expr(e)), - None => None - }; - ast::variant_ { - name: v.name, - attrs: attrs, - kind: kind, - id: fld.new_id(v.id), - disr_expr: de, - vis: v.vis, - } -} - -fn noop_fold_ident(i: Ident, _fld: @ast_fold) -> Ident { - i -} - -fn noop_fold_path(p: &Path, fld: @ast_fold) -> Path { - ast::Path { - span: fld.new_span(p.span), - global: p.global, - segments: p.segments.map(|segment| ast::PathSegment { - identifier: fld.fold_ident(segment.identifier), - lifetime: segment.lifetime, - types: segment.types.map(|typ| fld.fold_ty(typ)), - }) - } -} - -fn noop_fold_local(l: @Local, fld: @ast_fold) -> @Local { - @Local { - is_mutbl: l.is_mutbl, - ty: fld.fold_ty(&l.ty), - pat: fld.fold_pat(l.pat), - init: l.init.map_move(|e| fld.fold_expr(e)), - id: fld.new_id(l.id), - span: fld.new_span(l.span), + @Expr { + id: folder.new_id(e.id), + node: node, + span: folder.new_span(e.span), } } -// the default macro traversal. visit the path -// using fold_path, and the tts using fold_tts, -// and the span using new_span -fn noop_fold_mac(m: &mac_, fld: @ast_fold) -> mac_ { - match *m { - mac_invoc_tt(ref p,ref tts,ctxt) => - mac_invoc_tt(fld.fold_path(p), - fold_tts(*tts,fld), - ctxt) - } -} - - -/* temporarily eta-expand because of a compiler bug with using `fn<T>` as a - value */ -fn noop_map_exprs(f: @fn(@Expr) -> @Expr, es: &[@Expr]) -> ~[@Expr] { - es.map(|x| f(*x)) -} - -fn noop_id(i: NodeId) -> NodeId { return i; } - -fn noop_span(sp: Span) -> Span { return sp; } - -pub fn default_ast_fold() -> ast_fold_fns { - @AstFoldFns { - fold_crate: noop_fold_crate, - fold_view_item: noop_fold_view_item, - fold_foreign_item: noop_fold_foreign_item, - fold_item: noop_fold_item, - fold_struct_field: noop_fold_struct_field, - fold_item_underscore: noop_fold_item_underscore, - fold_type_method: noop_fold_type_method, - fold_method: noop_fold_method, - fold_block: noop_fold_block, - fold_stmt: |x, s, fld| (noop_fold_stmt(x, fld), s), - fold_arm: noop_fold_arm, - fold_pat: wrap(noop_fold_pat), - fold_decl: |x, s, fld| (noop_fold_decl(x, fld), s), - fold_expr: wrap(noop_fold_expr), - fold_ty: wrap(noop_fold_ty), - fold_mod: noop_fold_mod, - fold_foreign_mod: noop_fold_foreign_mod, - fold_variant: wrap(noop_fold_variant), - fold_ident: noop_fold_ident, - fold_path: noop_fold_path, - fold_local: noop_fold_local, - fold_mac: wrap(noop_fold_mac), - map_exprs: noop_map_exprs, - new_id: noop_id, - new_span: noop_span, - } -} - -impl ast_fold for AstFoldFns { - /* naturally, a macro to write these would be nice */ - fn fold_crate(@self, c: &Crate) -> Crate { - (self.fold_crate)(c, self as @ast_fold) - } - fn fold_view_item(@self, x: &view_item) -> view_item { - ast::view_item { - node: (self.fold_view_item)(&x.node, self as @ast_fold), - attrs: self.fold_attributes(x.attrs), - vis: x.vis, - span: (self.new_span)(x.span), - } - } - fn fold_foreign_item(@self, x: @foreign_item) -> @foreign_item { - (self.fold_foreign_item)(x, self as @ast_fold) - } - fn fold_item(@self, i: @item) -> Option<@item> { - (self.fold_item)(i, self as @ast_fold) - } - fn fold_struct_field(@self, sf: @struct_field) -> @struct_field { - @Spanned { - node: ast::struct_field_ { - kind: sf.node.kind, - id: (self.new_id)(sf.node.id), - ty: self.fold_ty(&sf.node.ty), - attrs: self.fold_attributes(sf.node.attrs), - }, - span: (self.new_span)(sf.span), - } - } - fn fold_item_underscore(@self, i: &item_) -> item_ { - (self.fold_item_underscore)(i, self as @ast_fold) - } - fn fold_type_method(@self, m: &TypeMethod) -> TypeMethod { - (self.fold_type_method)(m, self as @ast_fold) - } - fn fold_method(@self, x: @method) -> @method { - (self.fold_method)(x, self as @ast_fold) - } - fn fold_block(@self, x: &Block) -> Block { - (self.fold_block)(x, self as @ast_fold) - } - fn fold_stmt(@self, x: &Stmt) -> Option<@Stmt> { - let (n_opt, s) = (self.fold_stmt)(&x.node, x.span, self as @ast_fold); - match n_opt { - Some(n) => Some(@Spanned { node: n, span: (self.new_span)(s) }), - None => None, - } - } - fn fold_arm(@self, x: &Arm) -> Arm { - (self.fold_arm)(x, self as @ast_fold) - } - fn fold_pat(@self, x: @Pat) -> @Pat { - let (n, s) = (self.fold_pat)(&x.node, x.span, self as @ast_fold); - @Pat { - id: (self.new_id)(x.id), - node: n, - span: (self.new_span)(s), - } - } - fn fold_decl(@self, x: @Decl) -> Option<@Decl> { - let (n_opt, s) = (self.fold_decl)(&x.node, x.span, self as @ast_fold); - match n_opt { - Some(n) => Some(@Spanned { node: n, span: (self.new_span)(s) }), - None => None, +pub fn noop_fold_stmt<T:ast_fold>(s: &Stmt, folder: &T) -> Option<@Stmt> { + let node = match s.node { + StmtDecl(d, nid) => { + match folder.fold_decl(d) { + Some(d) => Some(StmtDecl(d, folder.new_id(nid))), + None => None, + } } - } - fn fold_expr(@self, x: @Expr) -> @Expr { - let (n, s) = (self.fold_expr)(&x.node, x.span, self as @ast_fold); - @Expr { - id: (self.new_id)(x.id), - node: n, - span: (self.new_span)(s), + StmtExpr(e, nid) => { + Some(StmtExpr(folder.fold_expr(e), folder.new_id(nid))) } - } - fn fold_ty(@self, x: &Ty) -> Ty { - let (n, s) = (self.fold_ty)(&x.node, x.span, self as @ast_fold); - Ty { - id: (self.new_id)(x.id), - node: n, - span: (self.new_span)(s), + StmtSemi(e, nid) => { + Some(StmtSemi(folder.fold_expr(e), folder.new_id(nid))) } - } - fn fold_mod(@self, x: &_mod) -> _mod { - (self.fold_mod)(x, self as @ast_fold) - } - fn fold_foreign_mod(@self, x: &foreign_mod) -> foreign_mod { - (self.fold_foreign_mod)(x, self as @ast_fold) - } - fn fold_variant(@self, x: &variant) -> variant { - let (n, s) = (self.fold_variant)(&x.node, x.span, self as @ast_fold); - Spanned { node: n, span: (self.new_span)(s) } - } - fn fold_ident(@self, x: Ident) -> Ident { - (self.fold_ident)(x, self as @ast_fold) - } - fn fold_path(@self, x: &Path) -> Path { - (self.fold_path)(x, self as @ast_fold) - } - fn fold_local(@self, x: @Local) -> @Local { - (self.fold_local)(x, self as @ast_fold) - } - fn fold_mac(@self, x: &mac) -> mac { - let (n, s) = (self.fold_mac)(&x.node, x.span, self as @ast_fold); - Spanned { node: n, span: (self.new_span)(s) } - } - fn map_exprs(@self, - f: @fn(@Expr) -> @Expr, - e: &[@Expr]) - -> ~[@Expr] { - (self.map_exprs)(f, e) - } - fn new_id(@self, node_id: ast::NodeId) -> NodeId { - (self.new_id)(node_id) - } - fn new_span(@self, span: Span) -> Span { - (self.new_span)(span) - } -} + StmtMac(ref mac, semi) => Some(StmtMac(folder.fold_mac(mac), semi)) + }; -// brson agrees with me that this function's existence is probably -// not a good or useful thing. -pub fn make_fold(afp: ast_fold_fns) -> @ast_fold { - afp as @ast_fold + node.map_move(|node| @Spanned { + node: node, + span: folder.new_span(s.span), + }) } #[cfg(test)] @@ -1048,16 +870,23 @@ mod test { use print::pprust; use super::*; + struct IdentFolder { + f: @fn(ast::ident)->ast::ident, + } + + impl ast_fold for IdentFolder { + fn fold_ident(@self, i: ident) -> ident { + (self.f)(i) + } + } + // taken from expand // given a function from idents to idents, produce // an ast_fold that applies that function: - pub fn fun_to_ident_folder(f: @fn(ast::Ident)->ast::Ident) -> @ast_fold{ - let afp = default_ast_fold(); - let f_pre = @AstFoldFns{ - fold_ident : |id, _| f(id), - .. *afp - }; - make_fold(f_pre) + pub fn fun_to_ident_folder(f: @fn(ast::ident)->ast::ident) -> @ast_fold { + @IdentFolder { + f: f, + } as @ast_fold } // this version doesn't care about getting comments or docstrings in. @@ -1120,3 +949,4 @@ mod test { ~"fn zz(){let zz=13 as zz;}"); } } + |
