adding test case to check marking/unmarking

This commit is contained in:
John Clements 2013-06-25 11:43:52 -07:00
parent b7c0512b27
commit 91d3c36430
3 changed files with 25 additions and 12 deletions

View File

@ -23,7 +23,7 @@
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 @@ fn mk_simple_path(ident: ast::Ident, span: Span) -> ast::Path {
}
}
// 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 @@ fn expand_and_resolve_and_pretty_print (crate_str : @str) -> ~str {
#[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));

View File

@ -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),

View File

@ -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.
*