about summary refs log tree commit diff
path: root/src/libsyntax/ext/expand.rs
diff options
context:
space:
mode:
authorJohn Clements <clements@racket-lang.org>2014-07-04 12:18:37 -0700
committerJohn Clements <clements@racket-lang.org>2014-07-04 13:20:14 -0700
commit92708322fd19747100ff5eda2e4584bc9d1f2b38 (patch)
treea2b1e3aee4833e793c25a7bfc0ff6a6a6166b22e /src/libsyntax/ext/expand.rs
parent6bee3c87c94a39fb7d48a119bbc105149c345bfc (diff)
downloadrust-92708322fd19747100ff5eda2e4584bc9d1f2b38.tar.gz
rust-92708322fd19747100ff5eda2e4584bc9d1f2b38.zip
comments & test cases for IdentRenamers
Diffstat (limited to 'src/libsyntax/ext/expand.rs')
-rw-r--r--src/libsyntax/ext/expand.rs74
1 files changed, 63 insertions, 11 deletions
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index 694e69c7a2c..e2c8782e13c 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -344,15 +344,16 @@ fn expand_item(it: Gc<ast::Item>, fld: &mut MacroExpander)
 
 fn expand_item_modifiers(mut it: Gc<ast::Item>, fld: &mut MacroExpander)
                          -> Gc<ast::Item> {
-    let (modifiers, attrs) = it.attrs.partitioned(|attr| {
+    // partition the attributes into ItemModifiers and others
+    let (modifiers, other_attrs) = it.attrs.partitioned(|attr| {
         match fld.extsbox.find(&intern(attr.name().get())) {
             Some(&ItemModifier(_)) => true,
             _ => false
         }
     });
-
+    // update the attrs, leave everything else alone. Is this mutation really a good idea?
     it = box(GC) ast::Item {
-        attrs: attrs,
+        attrs: other_attrs,
         ..(*it).clone()
     };
 
@@ -1047,13 +1048,14 @@ fn original_span(cx: &ExtCtxt) -> Gc<codemap::ExpnInfo> {
 #[cfg(test)]
 mod test {
     use super::{pattern_bindings, expand_crate, contains_macro_escape};
-    use super::{PatIdentFinder};
+    use super::{PatIdentFinder, IdentRenamer, PatIdentRenamer};
     use ast;
     use ast::{Attribute_, AttrOuter, MetaWord};
     use attr;
     use codemap;
     use codemap::Spanned;
     use ext::mtwt;
+    use fold::Folder;
     use parse;
     use parse::token;
     use util::parser_testing::{string_to_parser};
@@ -1091,7 +1093,24 @@ mod test {
         path_finder.path_accumulator
     }
 
+    /// A Visitor that extracts the identifiers from a thingy.
+    // as a side note, I'm starting to want to abstract over these....
+    struct IdentFinder{
+        ident_accumulator: Vec<ast::Ident>
+    }
 
+    impl Visitor<()> for IdentFinder {
+        fn visit_ident(&mut self, _: codemap::Span, id: ast::Ident, _: ()){
+            self.ident_accumulator.push(id);
+        }
+    }
+
+    /// Find the idents in a crate
+    fn crate_idents(the_crate: &ast::Crate) -> Vec<ast::Ident> {
+        let mut ident_finder = IdentFinder{ident_accumulator: Vec::new()};
+        visit::walk_crate(&mut ident_finder, the_crate, ());
+        ident_finder.ident_accumulator
+    }
 
     // these following tests are quite fragile, in that they don't test what
     // *kind* of failure occurs.
@@ -1316,7 +1335,7 @@ mod test {
     // but *shouldn't* bind because it was inserted by a different macro....
     // can't write this test case until we have macro-generating macros.
 
-    // FIXME #9383 : lambda var hygiene
+    // lambda var hygiene
     // expands to fn q(x_1:int){fn g(x_2:int){x_2 + x_1};}
     #[test]
     fn issue_9383(){
@@ -1375,9 +1394,9 @@ mod test {
                         assert_eq!(varref_marks,binding_marks.clone());
                     }
                 } else {
+                    let varref_name = mtwt::resolve(varref.segments.get(0).identifier);
                     let fail = (varref.segments.len() == 1)
-                        && (mtwt::resolve(varref.segments.get(0).identifier)
-                            == binding_name);
+                        && (varref_name == binding_name);
                     // temp debugging:
                     if fail {
                         let varref_idents : Vec<ast::Ident>
@@ -1388,7 +1407,8 @@ mod test {
                         println!("text of test case: \"{}\"", teststr);
                         println!("");
                         println!("uh oh, matches but shouldn't:");
-                        println!("varref: {}",varref_idents);
+                        println!("varref #{}: {}, resolves to {}",idx, varref_idents,
+                                 varref_name);
                         // good lord, you can't make a path with 0 segments, can you?
                         let string = token::get_ident(varref.segments
                                                             .get(0)
@@ -1396,7 +1416,9 @@ mod test {
                         println!("varref's first segment's uint: {}, and string: \"{}\"",
                                  varref.segments.get(0).identifier.name,
                                  string.get());
-                        println!("binding: {}", *bindings.get(binding_idx));
+                        println!("binding #{}: {}, resolves to {}",
+                                 binding_idx, *bindings.get(binding_idx),
+                                 binding_name);
                         mtwt::with_sctable(|x| mtwt::display_sctable(x));
                     }
                     assert!(!fail);
@@ -1459,13 +1481,43 @@ foo_module!()
     // 'None' is listed as an identifier pattern because we don't yet know that
     // it's the name of a 0-ary variant, and that 'i' appears twice in succession.
     #[test]
-    fn crate_idents(){
+    fn crate_bindings_test(){
         let the_crate = string_to_crate("fn main (a : int) -> int {|b| {
         match 34 {None => 3, Some(i) | i => j, Foo{k:z,l:y} => \"banana\"}} }".to_string());
         let idents = crate_bindings(&the_crate);
         assert_eq!(idents, strs_to_idents(vec!("a","b","None","i","i","z","y")));
     }
 
-    //
+    // test the IdentRenamer directly
+    #[test]
+    fn ident_renamer_test () {
+        let the_crate = string_to_crate("fn f(x : int){let x = x; x}".to_string());
+        let f_ident = token::str_to_ident("f");
+        let x_ident = token::str_to_ident("x");
+        let int_ident = token::str_to_ident("int");
+        let renames = vec!((x_ident,16));
+        let mut renamer = IdentRenamer{renames: &renames};
+        let renamed_crate = renamer.fold_crate(the_crate);
+        let idents = crate_idents(&renamed_crate);
+        let resolved : Vec<ast::Name> = idents.iter().map(|id| mtwt::resolve(*id)).collect();
+        assert_eq!(resolved,vec!(f_ident.name,16,int_ident.name,16,16,16));
+    }
+
+    // test the PatIdentRenamer; only PatIdents get renamed
+    #[test]
+    fn pat_ident_renamer_test () {
+        let the_crate = string_to_crate("fn f(x : int){let x = x; x}".to_string());
+        let f_ident = token::str_to_ident("f");
+        let x_ident = token::str_to_ident("x");
+        let int_ident = token::str_to_ident("int");
+        let renames = vec!((x_ident,16));
+        let mut renamer = PatIdentRenamer{renames: &renames};
+        let renamed_crate = renamer.fold_crate(the_crate);
+        let idents = crate_idents(&renamed_crate);
+        let resolved : Vec<ast::Name> = idents.iter().map(|id| mtwt::resolve(*id)).collect();
+        let x_name = x_ident.name;
+        assert_eq!(resolved,vec!(f_ident.name,16,int_ident.name,16,x_name,x_name));
+    }
+
 
 }