@@ -23,7 +23,7 @@ use opt_vec;
23
23
use parse;
24
24
use parse:: { parse_item_from_source_str} ;
25
25
use parse:: token;
26
- use parse:: token:: { fresh_name, ident_to_str, intern} ;
26
+ use parse:: token:: { fresh_mark , fresh_name, ident_to_str, intern} ;
27
27
use visit;
28
28
use visit:: Visitor ;
29
29
@@ -67,7 +67,9 @@ pub fn expand_expr(extsbox: @mut SyntaxEnv,
67
67
} ,
68
68
} ) ;
69
69
70
- let expanded = match expandfun ( cx, mac. span , * tts) {
70
+ let fm = fresh_mark ( ) ;
71
+ let marked_tts = mark_tts ( * tts, fm) ;
72
+ let expanded = match expandfun ( cx, mac. span , marked_tts) {
71
73
MRExpr ( e) => e,
72
74
MRAny ( expr_maker, _, _) => expr_maker ( ) ,
73
75
_ => {
@@ -259,6 +261,12 @@ pub fn expand_expr(extsbox: @mut SyntaxEnv,
259
261
}
260
262
}
261
263
264
+ // apply a fresh mark to the given token trees. Used prior to expansion of a macro.
265
+ fn mark_tts ( tts : & [ token_tree ] , m : Mrk ) -> ~[ token_tree ] {
266
+ fold_tts ( tts, new_ident_marker ( m) )
267
+ }
268
+
269
+
262
270
// This is a secondary mechanism for invoking syntax extensions on items:
263
271
// "decorator" attributes, such as #[auto_encode]. These are invoked by an
264
272
// attribute prefixing an item, and are interpreted by feeding the item
@@ -1285,7 +1293,7 @@ pub fn new_ident_renamer(from: ast::Ident,
1285
1293
1286
1294
1287
1295
// update the ctxts in a path to get a mark node
1288
- pub fn new_ident_marker ( mark : uint ) ->
1296
+ pub fn new_ident_marker ( mark : Mrk ) ->
1289
1297
@fn ( ast:: Ident ) ->ast:: Ident {
1290
1298
|id : ast:: Ident |
1291
1299
ast:: Ident {
@@ -1461,18 +1469,18 @@ mod test {
1461
1469
1462
1470
#[ test]
1463
1471
fn automatic_renaming ( ) {
1464
- // "fn a() -> int { let b = 13; let c = b; b+c }"
1465
- // --> b & c should get new names, in the expr too.
1466
- // "macro_rules! f (($x:ident) => ($x + b)) fn a() -> int { let b = 13; f!(b)}"
1467
- // --> one should be renamed, one should not.
1468
-
1469
1472
let teststrs =
1470
1473
~[ // b & c should get new names throughout, in the expr too:
1471
1474
@"fn a ( ) -> int { let b = 13 ; let c = b; b+c } ",
1472
1475
// the use of b before the + should be renamed, the other one not:
1473
1476
@" macro_rules! f ( ( $x: ident) => ( $x + b) ) fn a ( ) -> int { let b = 13 ; f ! ( b) } ",
1474
1477
// the b before the plus should not be renamed (requires marks)
1475
- @" macro_rules! f ( ( $x: ident) => ( { let b=9 ; ( $x + b) } ) ) fn a ( ) -> int { f ! ( b) } "];
1478
+ @" macro_rules! f ( ( $x: ident) => ( { let b=9 ; ( $x + b) } ) ) fn a ( ) -> int { f ! ( b) } ",
1479
+ // the z flows into and out of two macros (g & f) along one path, and one (just g) along the
1480
+ // other, so the result of the whole thing should be " let z_123 = 3 ; z_123"
1481
+ @"macro_rules! g ( ( $x: ident) => ( { macro_rules! f( ( $y: ident) =>( { let $y=3 ; $x} ) ) ; f!( $x) } ) )
1482
+ fn a ( ) { g ! ( z) } "
1483
+ ];
1476
1484
for s in teststrs.iter() {
1477
1485
// we need regexps to test these!
1478
1486
std::io::println(expand_and_resolve_and_pretty_print(*s));
0 commit comments