about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/ext/expand.rs106
-rw-r--r--src/libsyntax/fold.rs14
2 files changed, 69 insertions, 51 deletions
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index 5e68a75bffa..c73f8b01b9c 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -1421,38 +1421,52 @@ pub fn expand_crate(parse_sess: @mut parse::ParseSess,
     return ret;
 }
 
-// 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)
+// a function in SyntaxContext -> SyntaxContext
+pub trait CtxtFn{
+    fn f(&self, ast::SyntaxContext) -> ast::SyntaxContext;
 }
 
-// update the ctxts in a path to get a rename node
-pub fn new_ident_renamer(from: ast::Ident,
-                      to: ast::Name) ->
-    @fn(ast::Ident)->ast::Ident {
-    |id : ast::Ident|
-    ast::Ident{
-        name: id.name,
-        ctxt: new_rename(from,to,id.ctxt)
+pub struct Renamer {
+    from : ast::Ident,
+    to : ast::Name
+}
+
+impl CtxtFn for Renamer {
+    fn f(&self, ctxt : ast::SyntaxContext) -> ast::SyntaxContext {
+        new_rename(self.from,self.to,ctxt)
     }
 }
 
-// update the ctxts in a path to get a mark node
-pub fn new_ident_marker(mark: Mrk) ->
-    @fn(ast::Ident)->ast::Ident {
-    |id : ast::Ident|
-    ast::Ident{
-        name: id.name,
-        ctxt: new_mark(mark,id.ctxt)
+pub struct Marker { mark : Mrk }
+
+impl CtxtFn for Marker {
+    fn f(&self, ctxt : ast::SyntaxContext) -> ast::SyntaxContext {
+        new_mark(self.mark,ctxt)
+    }
+}
+
+// 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)}
+    };
+    @AstFoldFns{
+        fold_ident : fi,
+        // check that it works, then add the fold_expr clause....
+        .. *afp
     }
 }
 
+// just a convenience:
+pub fn new_mark_folder(m : Mrk) -> @AstFoldFns { fun_to_ctxt_folder(@Marker{mark:m}) }
+pub fn new_rename_folder(from : ast::Ident, to : ast::Name) -> @AstFoldFns {
+    fun_to_ctxt_folder(@Renamer{from:from,to:to})
+}
+
+/*
 // perform resolution (in the MTWT sense) on all of the
 // idents in the tree. This is the final step in expansion.
 // FIXME #6993: this function could go away, along with
@@ -1465,25 +1479,26 @@ pub fn new_ident_resolver() ->
         ctxt : EMPTY_CTXT
     }
 }
+*/
 
 // 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_ident_marker(m))
+    fold_tts(tts,new_mark_folder(m) as @ast_fold)
 }
 
 // apply a given mark to the given expr. Used following the expansion of a macro.
 fn mark_expr(expr : @ast::Expr, m : Mrk) -> @ast::Expr {
-    fun_to_ident_folder(new_ident_marker(m)).fold_expr(expr)
+    new_mark_folder(m).fold_expr(expr)
 }
 
 // apply a given mark to the given stmt. Used following the expansion of a macro.
 fn mark_stmt(expr : &ast::Stmt, m : Mrk) -> @ast::Stmt {
-    fun_to_ident_folder(new_ident_marker(m)).fold_stmt(expr).unwrap()
+    new_mark_folder(m).fold_stmt(expr).unwrap()
 }
 
 // apply a given mark to the given item. Used following the expansion of a macro.
 fn mark_item(expr : @ast::item, m : Mrk) -> Option<@ast::item> {
-    fun_to_ident_folder(new_ident_marker(m)).fold_item(expr)
+    new_mark_folder(m).fold_item(expr)
 }
 
 #[cfg(test)]
@@ -1499,8 +1514,8 @@ mod test {
     use print::pprust;
     use std;
     use std::vec;
-    use util::parser_testing::{string_to_crate_and_sess, string_to_item, string_to_pat};
-    use util::parser_testing::{strs_to_idents};
+    use util::parser_testing::{string_to_crate, string_to_crate_and_sess, string_to_item};
+    use util::parser_testing::{string_to_pat, strs_to_idents};
     use visit;
 
     // make sure that fail! is present
@@ -1601,30 +1616,31 @@ mod test {
 
     #[test]
     fn renaming () {
-        let item_ast = string_to_item(@"fn a() -> int { let b = 13; b }").unwrap();
+        let item_ast = string_to_crate(@"fn f() -> int { a }");
         let a_name = intern("a");
         let a2_name = gensym("a2");
-        let renamer = new_ident_renamer(ast::Ident{name:a_name,ctxt:EMPTY_CTXT},
+        let renamer = new_rename_folder(ast::Ident{name:a_name,ctxt:EMPTY_CTXT},
                                         a2_name);
-        let renamed_ast = fun_to_ident_folder(renamer).fold_item(item_ast).unwrap();
-        let resolver = new_ident_resolver();
-        let resolver_fold = fun_to_ident_folder(resolver);
-        let resolved_ast = resolver_fold.fold_item(renamed_ast).unwrap();
-        let resolved_as_str = pprust::item_to_str(resolved_ast,
-                                                  get_ident_interner());
-        assert_eq!(resolved_as_str,~"fn a2() -> int { let b = 13; b }");
+        let renamed_ast = renamer.fold_crate(item_ast);
+        let varrefs = @mut ~[];
+        visit::walk_crate(&mut new_path_finder(varrefs), &renamed_ast, ());
+        match varrefs {
+            @[Path{segments:[ref seg],_}] => assert_eq!(mtwt_resolve(seg.identifier),a2_name),
+            _ => assert_eq!(0,1)
+        }
 
         // try a double-rename, with pending_renames.
         let a3_name = gensym("a3");
         let ctxt2 = new_rename(ast::Ident::new(a_name),a2_name,EMPTY_CTXT);
         let pending_renames = @mut ~[(ast::Ident::new(a_name),a2_name),
                                      (ast::Ident{name:a_name,ctxt:ctxt2},a3_name)];
-        let double_renamed = renames_to_fold(pending_renames).fold_item(item_ast).unwrap();
-        let resolved_again = resolver_fold.fold_item(double_renamed).unwrap();
-        let double_renamed_as_str = pprust::item_to_str(resolved_again,
-                                                        get_ident_interner());
-        assert_eq!(double_renamed_as_str,~"fn a3() -> int { let b = 13; b }");
-
+        let double_renamed = renames_to_fold(pending_renames).fold_crate(item_ast);
+        let varrefs = @mut ~[];
+        visit::walk_crate(&mut new_path_finder(varrefs), &double_renamed, ());
+        match varrefs {
+            @[Path{segments:[ref seg],_}] => assert_eq!(mtwt_resolve(seg.identifier),a2_name),
+            _ => assert_eq!(0,1)
+        }
     }
 
     fn fake_print_crate(s: @pprust::ps, crate: &ast::Crate) {
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index 799ff855cbe..9aacc18eabf 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -118,16 +118,16 @@ fn fold_mac_(m: &mac, fld: @ast_fold) -> mac {
         node: match m.node {
             mac_invoc_tt(ref p,ref tts,ctxt) =>
             mac_invoc_tt(fld.fold_path(p),
-                         fold_tts(*tts,|id|{fld.fold_ident(id)}),
+                         fold_tts(*tts,fld),
                          ctxt)
         },
         span: fld.new_span(m.span)
     }
 }
 
-// build a new vector of tts by appling the given function to
+// 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(tts : &[token_tree], f: @fn(Ident)->Ident) -> ~[token_tree] {
+pub fn fold_tts(tts : &[token_tree], f : @ast_fold) -> ~[token_tree] {
     do tts.map |tt| {
         match *tt {
             tt_tok(span, ref tok) =>
@@ -140,16 +140,16 @@ pub fn fold_tts(tts : &[token_tree], f: @fn(Ident)->Ident) -> ~[token_tree] {
                    sep.map(|tok|maybe_fold_ident(tok,f)),
                    is_optional),
             tt_nonterminal(sp,ref ident) =>
-            tt_nonterminal(sp,f(*ident))
+            tt_nonterminal(sp,f.fold_ident(*ident))
         }
     }
 }
 
 // apply ident folder if it's an ident, otherwise leave it alone
-fn maybe_fold_ident(t : &token::Token, f: @fn(Ident)->Ident) -> token::Token {
+fn maybe_fold_ident(t : &token::Token, f: @ast_fold) -> token::Token {
     match *t {
         token::IDENT(id,followed_by_colons) =>
-        token::IDENT(f(id),followed_by_colons),
+        token::IDENT(f.fold_ident(id),followed_by_colons),
         _ => (*t).clone()
     }
 }
@@ -948,6 +948,8 @@ impl AstFoldExtensions for @ast_fold {
     }
 }
 
+// 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
 }