@@ -13,6 +13,7 @@ use core::prelude::*;
13
13
use ast:: * ;
14
14
use ast;
15
15
use codemap:: { span, spanned} ;
16
+ use parse:: token;
16
17
use opt_vec:: OptVec ;
17
18
18
19
use core:: vec;
@@ -115,11 +116,43 @@ fn fold_arg_(a: arg, fld: @ast_fold) -> arg {
115
116
id : fld. new_id( a. id) ,
116
117
}
117
118
}
119
+
118
120
//used in noop_fold_expr, and possibly elsewhere in the future
119
121
fn fold_mac_ ( m : & mac , fld : @ast_fold ) -> mac {
120
122
spanned {
121
- node : match m. node { mac_invoc_tt( * ) => copy m. node } ,
122
- span : fld. new_span( m. span) ,
123
+ node : match m. node {
124
+ mac_invoc_tt( p, ref tts) =>
125
+ mac_invoc_tt( fld. fold_path( p) ,
126
+ fold_tts( * tts, fld) )
127
+ } ,
128
+ span : fld. new_span ( m. span )
129
+ }
130
+ }
131
+
132
+ fn fold_tts ( tts : & [ token_tree ] , fld : @ast_fold ) -> ~[ token_tree ] {
133
+ do tts. map |tt| {
134
+ match * tt {
135
+ tt_tok( span, ref tok) =>
136
+ tt_tok ( span , maybe_fold_ident ( tok , fld ) ) ,
137
+ tt_delim( ref tts) =>
138
+ tt_delim ( fold_tts ( * tts , fld ) ) ,
139
+ tt_seq( span, ref pattern, ref sep, is_optional) =>
140
+ tt_seq ( span ,
141
+ fold_tts ( * pattern , fld ) ,
142
+ sep. map( |tok|maybe_fold_ident( tok, fld) ) ,
143
+ is_optional ) ,
144
+ tt_nonterminal( sp, ref ident) =>
145
+ tt_nonterminal( sp, fld. fold_ident( * ident) )
146
+ }
147
+ }
148
+ }
149
+
150
+ // apply ident folder if it's an ident, otherwise leave it alone
151
+ fn maybe_fold_ident ( t : & token:: Token , fld : @ast_fold ) -> token:: Token {
152
+ match * t {
153
+ token:: IDENT ( id, followed_by_colons) =>
154
+ token:: IDENT ( fld. fold_ident ( id) , followed_by_colons) ,
155
+ _ => copy * t
123
156
}
124
157
}
125
158
@@ -290,7 +323,10 @@ pub fn noop_fold_item_underscore(i: &item_, fld: @ast_fold) -> item_ {
290
323
}
291
324
item_mac( ref m) => {
292
325
// FIXME #2888: we might actually want to do something here.
293
- item_mac ( copy * m)
326
+ // ... okay, we're doing something. It would probably be nicer
327
+ // to add something to the ast_fold trait, but I'll defer
328
+ // that work.
329
+ item_mac ( fold_mac_ ( m, fld) )
294
330
}
295
331
}
296
332
}
@@ -904,3 +940,74 @@ impl AstFoldExtensions for @ast_fold {
904
940
pub fn make_fold( afp : ast_fold_fns ) -> @ast_fold {
905
941
afp as @ast_fold
906
942
}
943
+
944
+ #[ cfg( test) ]
945
+ mod test {
946
+ use ast;
947
+ use util : : parser_testing:: { string_to_crate, matches_codepattern} ;
948
+ use parse:: token ;
949
+ use print:: pprust;
950
+ use super :: * ;
951
+
952
+ // taken from expand
953
+ // given a function from idents to idents, produce
954
+ // an ast_fold that applies that function:
955
+ pub fn fun_to_ident_folder ( f : @fn ( ast:: ident) ->ast:: ident) -> @ast_fold{
956
+ let afp = default_ast_fold ( ) ;
957
+ let f_pre = @AstFoldFns {
958
+ fold_ident : |id, _| f ( id) ,
959
+ .. * afp
960
+ } ;
961
+ make_fold ( f_pre)
962
+ }
963
+
964
+ // this version doesn't care about getting comments or docstrings in.
965
+ fn fake_print_crate ( s: @pprust:: ps, crate : ast:: crate) {
966
+ pprust:: print_mod ( s, & crate . node. module , crate . node. attrs ) ;
967
+ }
968
+
969
+ // change every identifier to "zz"
970
+ pub fn to_zz ( ) -> @fn ( ast:: ident ) ->ast:: ident {
971
+ let zz_id = token:: str_to_ident ( "zz" ) ;
972
+ |id| { zz_id}
973
+ }
974
+
975
+ // maybe add to expand.rs...
976
+ macro_rules! assert_pred (
977
+ ( $pred: expr, $predname: expr, $a: expr , $b: expr) => (
978
+ {
979
+ let pred_val = $pred;
980
+ let a_val = $a;
981
+ let b_val = $b;
982
+ if !( pred_val( a_val, b_val) ) {
983
+ fail!( "expected args satisfying %s, got %? and %?" ,
984
+ $predname, a_val, b_val) ;
985
+ }
986
+ }
987
+ )
988
+ )
989
+
990
+ // make sure idents get transformed everywhere
991
+ #[ test] fn ident_transformation ( ) {
992
+ let zz_fold = fun_to_ident_folder ( to_zz ( ) ) ;
993
+ let ast = string_to_crate ( @~"#[ a] mod b { fn c ( d : e, f : g) { h ! ( i, j, k) ; l; m} } ") ;
994
+ assert_pred ! ( matches_codepattern,
995
+ "matches_codepattern" ,
996
+ pprust:: to_str( zz_fold. fold_crate( ast) , fake_print_crate,
997
+ token:: get_ident_interner( ) ) ,
998
+ ~"#[ a] mod zz{ fn zz( zz: zz, zz: zz) { zz!( zz, zz, zz) ; zz; zz} } ");
999
+ }
1000
+
1001
+ // even inside macro defs....
1002
+ #[test] fn ident_transformation_in_defs () {
1003
+ let zz_fold = fun_to_ident_folder(to_zz());
1004
+ let ast = string_to_crate(@~" macro_rules! a { ( b $c: expr $( d $e: token) f+
1005
+ => ( g $( d $d $e) +) ) } ");
1006
+ assert_pred!(matches_codepattern,
1007
+ " matches_codepattern",
1008
+ pprust::to_str(zz_fold.fold_crate(ast),fake_print_crate,
1009
+ token::get_ident_interner()),
1010
+ ~" zz!zz( ( zz$zz: zz$( zz $zz: zz) zz+=>( zz$( zz$zz$zz) +) ) ) " ) ;
1011
+ }
1012
+
1013
+ }
0 commit comments