Skip to content

Commit 3b88946

Browse files
committed
rework fold so that fold_tts takes an ast_fold rather than a thunk, stop using closures in ident traversal
1 parent 73830e4 commit 3b88946

File tree

2 files changed

+69
-51
lines changed

2 files changed

+69
-51
lines changed

src/libsyntax/ext/expand.rs

Lines changed: 61 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1421,38 +1421,52 @@ pub fn expand_crate(parse_sess: @mut parse::ParseSess,
14211421
return ret;
14221422
}
14231423

1424-
// given a function from idents to idents, produce
1425-
// an ast_fold that applies that function:
1426-
pub fn fun_to_ident_folder(f: @fn(ast::Ident)->ast::Ident) -> @ast_fold{
1427-
let afp = default_ast_fold();
1428-
let f_pre = @AstFoldFns{
1429-
fold_ident : |id, _| f(id),
1430-
.. *afp
1431-
};
1432-
make_fold(f_pre)
1424+
// a function in SyntaxContext -> SyntaxContext
1425+
pub trait CtxtFn{
1426+
fn f(&self, ast::SyntaxContext) -> ast::SyntaxContext;
14331427
}
14341428

1435-
// update the ctxts in a path to get a rename node
1436-
pub fn new_ident_renamer(from: ast::Ident,
1437-
to: ast::Name) ->
1438-
@fn(ast::Ident)->ast::Ident {
1439-
|id : ast::Ident|
1440-
ast::Ident{
1441-
name: id.name,
1442-
ctxt: new_rename(from,to,id.ctxt)
1429+
pub struct Renamer {
1430+
from : ast::Ident,
1431+
to : ast::Name
1432+
}
1433+
1434+
impl CtxtFn for Renamer {
1435+
fn f(&self, ctxt : ast::SyntaxContext) -> ast::SyntaxContext {
1436+
new_rename(self.from,self.to,ctxt)
14431437
}
14441438
}
14451439

1446-
// update the ctxts in a path to get a mark node
1447-
pub fn new_ident_marker(mark: Mrk) ->
1448-
@fn(ast::Ident)->ast::Ident {
1449-
|id : ast::Ident|
1450-
ast::Ident{
1451-
name: id.name,
1452-
ctxt: new_mark(mark,id.ctxt)
1440+
pub struct Marker { mark : Mrk }
1441+
1442+
impl CtxtFn for Marker {
1443+
fn f(&self, ctxt : ast::SyntaxContext) -> ast::SyntaxContext {
1444+
new_mark(self.mark,ctxt)
1445+
}
1446+
}
1447+
1448+
// given a function from ctxts to ctxts, produce
1449+
// an ast_fold that applies that function to all ctxts:
1450+
pub fn fun_to_ctxt_folder<T : 'static + CtxtFn>(cf: @T) -> @AstFoldFns {
1451+
let afp = default_ast_fold();
1452+
let fi : @fn(ast::Ident, @ast_fold) -> ast::Ident =
1453+
|ast::Ident{name, ctxt}, _| {
1454+
ast::Ident{name:name,ctxt:cf.f(ctxt)}
1455+
};
1456+
@AstFoldFns{
1457+
fold_ident : fi,
1458+
// check that it works, then add the fold_expr clause....
1459+
.. *afp
14531460
}
14541461
}
14551462

1463+
// just a convenience:
1464+
pub fn new_mark_folder(m : Mrk) -> @AstFoldFns { fun_to_ctxt_folder(@Marker{mark:m}) }
1465+
pub fn new_rename_folder(from : ast::Ident, to : ast::Name) -> @AstFoldFns {
1466+
fun_to_ctxt_folder(@Renamer{from:from,to:to})
1467+
}
1468+
1469+
/*
14561470
// perform resolution (in the MTWT sense) on all of the
14571471
// idents in the tree. This is the final step in expansion.
14581472
// FIXME #6993: this function could go away, along with
@@ -1465,25 +1479,26 @@ pub fn new_ident_resolver() ->
14651479
ctxt : EMPTY_CTXT
14661480
}
14671481
}
1482+
*/
14681483

14691484
// apply a given mark to the given token trees. Used prior to expansion of a macro.
14701485
fn mark_tts(tts : &[token_tree], m : Mrk) -> ~[token_tree] {
1471-
fold_tts(tts,new_ident_marker(m))
1486+
fold_tts(tts,new_mark_folder(m) as @ast_fold)
14721487
}
14731488

14741489
// apply a given mark to the given expr. Used following the expansion of a macro.
14751490
fn mark_expr(expr : @ast::Expr, m : Mrk) -> @ast::Expr {
1476-
fun_to_ident_folder(new_ident_marker(m)).fold_expr(expr)
1491+
new_mark_folder(m).fold_expr(expr)
14771492
}
14781493

14791494
// apply a given mark to the given stmt. Used following the expansion of a macro.
14801495
fn mark_stmt(expr : &ast::Stmt, m : Mrk) -> @ast::Stmt {
1481-
fun_to_ident_folder(new_ident_marker(m)).fold_stmt(expr).unwrap()
1496+
new_mark_folder(m).fold_stmt(expr).unwrap()
14821497
}
14831498

14841499
// apply a given mark to the given item. Used following the expansion of a macro.
14851500
fn mark_item(expr : @ast::item, m : Mrk) -> Option<@ast::item> {
1486-
fun_to_ident_folder(new_ident_marker(m)).fold_item(expr)
1501+
new_mark_folder(m).fold_item(expr)
14871502
}
14881503

14891504
#[cfg(test)]
@@ -1499,8 +1514,8 @@ mod test {
14991514
use print::pprust;
15001515
use std;
15011516
use std::vec;
1502-
use util::parser_testing::{string_to_crate_and_sess, string_to_item, string_to_pat};
1503-
use util::parser_testing::{strs_to_idents};
1517+
use util::parser_testing::{string_to_crate, string_to_crate_and_sess, string_to_item};
1518+
use util::parser_testing::{string_to_pat, strs_to_idents};
15041519
use visit;
15051520

15061521
// make sure that fail! is present
@@ -1601,30 +1616,31 @@ mod test {
16011616

16021617
#[test]
16031618
fn renaming () {
1604-
let item_ast = string_to_item(@"fn a() -> int { let b = 13; b }").unwrap();
1619+
let item_ast = string_to_crate(@"fn f() -> int { a }");
16051620
let a_name = intern("a");
16061621
let a2_name = gensym("a2");
1607-
let renamer = new_ident_renamer(ast::Ident{name:a_name,ctxt:EMPTY_CTXT},
1622+
let renamer = new_rename_folder(ast::Ident{name:a_name,ctxt:EMPTY_CTXT},
16081623
a2_name);
1609-
let renamed_ast = fun_to_ident_folder(renamer).fold_item(item_ast).unwrap();
1610-
let resolver = new_ident_resolver();
1611-
let resolver_fold = fun_to_ident_folder(resolver);
1612-
let resolved_ast = resolver_fold.fold_item(renamed_ast).unwrap();
1613-
let resolved_as_str = pprust::item_to_str(resolved_ast,
1614-
get_ident_interner());
1615-
assert_eq!(resolved_as_str,~"fn a2() -> int { let b = 13; b }");
1624+
let renamed_ast = renamer.fold_crate(item_ast);
1625+
let varrefs = @mut ~[];
1626+
visit::walk_crate(&mut new_path_finder(varrefs), &renamed_ast, ());
1627+
match varrefs {
1628+
@[Path{segments:[ref seg],_}] => assert_eq!(mtwt_resolve(seg.identifier),a2_name),
1629+
_ => assert_eq!(0,1)
1630+
}
16161631

16171632
// try a double-rename, with pending_renames.
16181633
let a3_name = gensym("a3");
16191634
let ctxt2 = new_rename(ast::Ident::new(a_name),a2_name,EMPTY_CTXT);
16201635
let pending_renames = @mut ~[(ast::Ident::new(a_name),a2_name),
16211636
(ast::Ident{name:a_name,ctxt:ctxt2},a3_name)];
1622-
let double_renamed = renames_to_fold(pending_renames).fold_item(item_ast).unwrap();
1623-
let resolved_again = resolver_fold.fold_item(double_renamed).unwrap();
1624-
let double_renamed_as_str = pprust::item_to_str(resolved_again,
1625-
get_ident_interner());
1626-
assert_eq!(double_renamed_as_str,~"fn a3() -> int { let b = 13; b }");
1627-
1637+
let double_renamed = renames_to_fold(pending_renames).fold_crate(item_ast);
1638+
let varrefs = @mut ~[];
1639+
visit::walk_crate(&mut new_path_finder(varrefs), &double_renamed, ());
1640+
match varrefs {
1641+
@[Path{segments:[ref seg],_}] => assert_eq!(mtwt_resolve(seg.identifier),a2_name),
1642+
_ => assert_eq!(0,1)
1643+
}
16281644
}
16291645

16301646
fn fake_print_crate(s: @pprust::ps, crate: &ast::Crate) {

src/libsyntax/fold.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -118,16 +118,16 @@ fn fold_mac_(m: &mac, fld: @ast_fold) -> mac {
118118
node: match m.node {
119119
mac_invoc_tt(ref p,ref tts,ctxt) =>
120120
mac_invoc_tt(fld.fold_path(p),
121-
fold_tts(*tts,|id|{fld.fold_ident(id)}),
121+
fold_tts(*tts,fld),
122122
ctxt)
123123
},
124124
span: fld.new_span(m.span)
125125
}
126126
}
127127

128-
// build a new vector of tts by appling the given function to
128+
// build a new vector of tts by appling the ast_fold's fold_ident to
129129
// all of the identifiers in the token trees.
130-
pub fn fold_tts(tts : &[token_tree], f: @fn(Ident)->Ident) -> ~[token_tree] {
130+
pub fn fold_tts(tts : &[token_tree], f : @ast_fold) -> ~[token_tree] {
131131
do tts.map |tt| {
132132
match *tt {
133133
tt_tok(span, ref tok) =>
@@ -140,16 +140,16 @@ pub fn fold_tts(tts : &[token_tree], f: @fn(Ident)->Ident) -> ~[token_tree] {
140140
sep.map(|tok|maybe_fold_ident(tok,f)),
141141
is_optional),
142142
tt_nonterminal(sp,ref ident) =>
143-
tt_nonterminal(sp,f(*ident))
143+
tt_nonterminal(sp,f.fold_ident(*ident))
144144
}
145145
}
146146
}
147147

148148
// apply ident folder if it's an ident, otherwise leave it alone
149-
fn maybe_fold_ident(t : &token::Token, f: @fn(Ident)->Ident) -> token::Token {
149+
fn maybe_fold_ident(t : &token::Token, f: @ast_fold) -> token::Token {
150150
match *t {
151151
token::IDENT(id,followed_by_colons) =>
152-
token::IDENT(f(id),followed_by_colons),
152+
token::IDENT(f.fold_ident(id),followed_by_colons),
153153
_ => (*t).clone()
154154
}
155155
}
@@ -948,6 +948,8 @@ impl AstFoldExtensions for @ast_fold {
948948
}
949949
}
950950

951+
// brson agrees with me that this function's existence is probably
952+
// not a good or useful thing.
951953
pub fn make_fold(afp: ast_fold_fns) -> @ast_fold {
952954
afp as @ast_fold
953955
}

0 commit comments

Comments
 (0)