about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJohn Clements <clements@racket-lang.org>2013-06-25 11:43:52 -0700
committerJohn Clements <clements@racket-lang.org>2013-09-06 13:35:08 -0700
commit91d3c364303c3a057feadd40adef0880531e08cc (patch)
tree75426f5dd94c6bace0bd4c7cd52168b48ef5abb7
parentb7c0512b27d287cf0657ae4b195d1ca41623c944 (diff)
downloadrust-91d3c364303c3a057feadd40adef0880531e08cc.tar.gz
rust-91d3c364303c3a057feadd40adef0880531e08cc.zip
adding test case to check marking/unmarking
-rw-r--r--src/libsyntax/ext/expand.rs26
-rw-r--r--src/libsyntax/fold.rs4
-rw-r--r--src/libsyntax/parse/token.rs7
3 files changed, 25 insertions, 12 deletions
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index fbaeab03e8a..25edcf63faa 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -23,7 +23,7 @@ use opt_vec;
 use parse;
 use parse::{parse_item_from_source_str};
 use parse::token;
-use parse::token::{fresh_name, ident_to_str, intern};
+use parse::token::{fresh_mark, fresh_name, ident_to_str, intern};
 use visit;
 use visit::Visitor;
 
@@ -67,7 +67,9 @@ pub fn expand_expr(extsbox: @mut SyntaxEnv,
                                 },
                             });
 
-                            let expanded = match expandfun(cx, mac.span, *tts) {
+                            let fm = fresh_mark();
+                            let marked_tts = mark_tts(*tts,fm);
+                            let expanded = match expandfun(cx, mac.span, marked_tts) {
                                 MRExpr(e) => e,
                                 MRAny(expr_maker,_,_) => expr_maker(),
                                 _ => {
@@ -259,6 +261,12 @@ pub fn expand_expr(extsbox: @mut SyntaxEnv,
     }
 }
 
+// apply a fresh 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))
+}
+
+
 // This is a secondary mechanism for invoking syntax extensions on items:
 // "decorator" attributes, such as #[auto_encode]. These are invoked by an
 // attribute prefixing an item, and are interpreted by feeding the item
@@ -1285,7 +1293,7 @@ pub fn new_ident_renamer(from: ast::Ident,
 
 
 // update the ctxts in a path to get a mark node
-pub fn new_ident_marker(mark: uint) ->
+pub fn new_ident_marker(mark: Mrk) ->
     @fn(ast::Ident)->ast::Ident {
     |id : ast::Ident|
     ast::Ident{
@@ -1461,18 +1469,18 @@ mod test {
 
     #[test]
     fn automatic_renaming () {
-        // "fn a() -> int { let b = 13; let c = b; b+c }"
-        //    --> b & c should get new names, in the expr too.
-        // "macro_rules! f (($x:ident) => ($x + b)) fn a() -> int { let b = 13; f!(b)}"
-        //    --> one should be renamed, one should not.
-
         let teststrs =
             ~[// b & c should get new names throughout, in the expr too:
                 @"fn a() -> int { let b = 13; let c = b; b+c }",
                 // the use of b before the + should be renamed, the other one not:
                 @"macro_rules! f (($x:ident) => ($x + b)) fn a() -> int { let b = 13; f!(b)}",
                 // the b before the plus should not be renamed (requires marks)
-                @"macro_rules! f (($x:ident) => ({let b=9; ($x + b)})) fn a() -> int { f!(b)}"];
+                @"macro_rules! f (($x:ident) => ({let b=9; ($x + b)})) fn a() -> int { f!(b)}",
+                // the z flows into and out of two macros (g & f) along one path, and one (just g) along the
+                // other, so the result of the whole thing should be "let z_123 = 3; z_123"
+                @"macro_rules! g (($x:ident) => ({macro_rules! f(($y:ident)=>({let $y=3;$x}));f!($x)}))
+                   fn a(){g!(z)}"
+            ];
         for s in teststrs.iter() {
             // we need regexps to test these!
             std::io::println(expand_and_resolve_and_pretty_print(*s));
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index 750ec0be984..52c148e7ba2 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -126,7 +126,7 @@ fn fold_mac_(m: &mac, fld: @ast_fold) -> mac {
 
 // build a new vector of tts by appling the given function 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: @fn(Ident)->Ident) -> ~[token_tree] {
     do tts.map |tt| {
         match *tt {
             tt_tok(span, ref tok) =>
@@ -145,7 +145,7 @@ pub fn fold_tts(tts : &[token_tree], f: @fn(ident)->ident) -> ~[token_tree] {
 }
 
 // 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: @fn(Ident)->Ident) -> token::Token {
     match *t {
         token::IDENT(id,followed_by_colons) =>
         token::IDENT(f(id),followed_by_colons),
diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs
index 8de597733ae..66f121727af 100644
--- a/src/libsyntax/parse/token.rs
+++ b/src/libsyntax/parse/token.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use ast;
-use ast::Name;
+use ast::{Name, Mrk};
 use ast_util;
 use parse::token;
 use util::interner::StrInterner;
@@ -557,6 +557,11 @@ pub fn fresh_name(src_name : &ast::Ident) -> Name {
     gensym(fmt!("%s_%u",ident_to_str(src_name),num))
 }
 
+// create a fresh mark.
+pub fn fresh_mark() -> Mrk {
+    gensym("mark")
+}
+
 /**
  * All the valid words that have meaning in the Rust language.
  *