Skip to content

Commit f50bb86

Browse files
committed
---
yaml --- r: 79318 b: refs/heads/try c: 04070c9 h: refs/heads/master v: v3
1 parent 426ad08 commit f50bb86

File tree

6 files changed

+176
-61
lines changed

6 files changed

+176
-61
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
refs/heads/master: 3e6de6b7da8ee88bf84b0e217900051334be08da
33
refs/heads/snap-stage1: e33de59e47c5076a89eadeb38f4934f58a3618a6
44
refs/heads/snap-stage3: 60fba4d7d677ec098e6a43014132fe99f7547363
5-
refs/heads/try: 7b579c065a82ee00956ee26fddf48e84d8132936
5+
refs/heads/try: 04070c9bf271a2e225f0017fcf5d9796ae67beee
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/ndm: f3868061cd7988080c30d6d5bf352a5a5fe2460b
88
refs/heads/try2: 147ecfdd8221e4a4d4e090486829a06da1e0ca3c

branches/try/src/libsyntax/ast.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -560,7 +560,7 @@ pub enum token_tree {
560560
// These only make sense for right-hand-sides of MBE macros:
561561

562562
// a kleene-style repetition sequence with a span, a tt_forest,
563-
// an optional separator (?), and a boolean where true indicates
563+
// an optional separator, and a boolean where true indicates
564564
// zero or more (*), and false indicates one or more (+).
565565
tt_seq(Span, @mut ~[token_tree], Option<::parse::token::Token>, bool),
566566

branches/try/src/libsyntax/ast_util.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -825,9 +825,6 @@ pub fn pat_is_ident(pat: @ast::Pat) -> bool {
825825

826826
// HYGIENE FUNCTIONS
827827

828-
/// Construct an identifier with the given name and an empty context:
829-
pub fn new_ident(name: Name) -> Ident { Ident {name: name, ctxt: 0}}
830-
831828
/// Extend a syntax context with a given mark
832829
pub fn new_mark(m:Mrk, tail:SyntaxContext) -> SyntaxContext {
833830
new_mark_internal(m,tail,get_sctable())

branches/try/src/libsyntax/ext/expand.rs

Lines changed: 164 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use ast::{Block, Crate, NodeId, Expr_, ExprMac, Ident, mac_invoc_tt};
12-
use ast::{item_mac, Stmt_, StmtMac, StmtExpr, StmtSemi};
13-
use ast::{ILLEGAL_CTXT};
11+
use ast::{Block, Crate, NodeId, DeclLocal, Expr_, ExprMac, Local, Ident, mac_invoc_tt};
12+
use ast::{item_mac, Mrk, Stmt_, StmtDecl, StmtMac, StmtExpr, StmtSemi};
13+
use ast::{ILLEGAL_CTXT, SCTable, token_tree};
1414
use ast;
1515
use ast_util::{new_rename, new_mark, mtwt_resolve};
1616
use attr;
@@ -23,7 +23,7 @@ use opt_vec;
2323
use parse;
2424
use parse::{parse_item_from_source_str};
2525
use parse::token;
26-
use parse::token::{ident_to_str, intern};
26+
use parse::token::{fresh_name, ident_to_str, intern};
2727
use visit;
2828
use visit::Visitor;
2929

@@ -521,6 +521,71 @@ pub fn expand_stmt(extsbox: @mut SyntaxEnv,
521521

522522
}
523523

524+
// expand a non-macro stmt. this is essentially the fallthrough for
525+
// expand_stmt, above.
526+
fn expand_non_macro_stmt (exts: SyntaxEnv,
527+
s: &Stmt_,
528+
sp: Span,
529+
fld: @ast_fold,
530+
orig: @fn(&Stmt_, Span, @ast_fold) -> (Option<Stmt_>, Span))
531+
-> (Option<Stmt_>,Span) {
532+
// is it a let?
533+
match *s {
534+
StmtDecl(@Spanned{node: DeclLocal(ref local), span: stmt_span}, node_id) => {
535+
let block_info = get_block_info(exts);
536+
let pending_renames = block_info.pending_renames;
537+
538+
// take it apart:
539+
let @Local{is_mutbl:is_mutbl,
540+
ty:_,
541+
pat:pat,
542+
init:init,
543+
id:id,
544+
span:span
545+
} = *local;
546+
// types can't be copied automatically because of the owned ptr in ty_tup...
547+
let ty = local.ty.clone();
548+
// expand the pat (it might contain exprs... #:(o)>
549+
let expanded_pat = fld.fold_pat(pat);
550+
// find the pat_idents in the pattern:
551+
// oh dear heaven... this is going to include the enum names, as well....
552+
let idents = @mut ~[];
553+
let name_finder = new_name_finder(idents);
554+
name_finder.visit_pat(expanded_pat,());
555+
// generate fresh names, push them to a new pending list
556+
let new_pending_renames = @mut ~[];
557+
for ident in idents.iter() {
558+
let new_name = fresh_name(ident);
559+
new_pending_renames.push((*ident,new_name));
560+
}
561+
let mut rename_fld = renames_to_fold(new_pending_renames);
562+
// rewrite the pattern using the new names (the old ones
563+
// have already been applied):
564+
let rewritten_pat = rename_fld.fold_pat(expanded_pat);
565+
// add them to the existing pending renames:
566+
for pr in new_pending_renames.iter() {pending_renames.push(*pr)}
567+
// also, don't forget to expand the init:
568+
let new_init_opt = init.map(|e| fld.fold_expr(*e));
569+
let rewritten_local =
570+
@Local{is_mutbl:is_mutbl,
571+
ty:ty,
572+
pat:rewritten_pat,
573+
init:new_init_opt,
574+
id:id,
575+
span:span};
576+
(Some(StmtDecl(@Spanned{node:DeclLocal(rewritten_local),
577+
span: stmt_span},node_id)),
578+
sp)
579+
},
580+
_ => {
581+
orig(s, sp, fld)
582+
}
583+
}
584+
}
585+
586+
// a visitor that extracts the pat_ident paths
587+
// from a given pattern and puts them in a mutable
588+
// array (passed in to the traversal)
524589
#[deriving(Clone)]
525590
struct NewNameFinderContext {
526591
ident_accumulator: @mut ~[ast::Ident],
@@ -674,30 +739,10 @@ pub fn new_name_finder(idents: @mut ~[ast::Ident]) -> @mut Visitor<()> {
674739
context as @mut Visitor<()>
675740
}
676741

677-
pub fn expand_block(extsbox: @mut SyntaxEnv,
678-
_cx: @ExtCtxt,
679-
blk: &Block,
680-
fld: @ast_fold,
681-
orig: @fn(&Block, @ast_fold) -> Block)
682-
-> Block {
683-
// see note below about treatment of exts table
684-
with_exts_frame!(extsbox,false,orig(blk,fld))
685-
}
686-
687-
688-
// get the (innermost) BlockInfo from an exts stack
689-
fn get_block_info(exts : SyntaxEnv) -> BlockInfo {
690-
match exts.find_in_topmost_frame(&intern(special_block_name)) {
691-
Some(@BlockInfo(bi)) => bi,
692-
_ => fail!(fmt!("special identifier %? was bound to a non-BlockInfo",
693-
@" block"))
694-
}
695-
}
696-
697-
698742
// given a mutable list of renames, return a tree-folder that applies those
699743
// renames.
700-
fn renames_to_fold(renames : @mut ~[(ast::Ident,ast::Name)]) -> @ast_fold {
744+
// FIXME #4536: currently pub to allow testing
745+
pub fn renames_to_fold(renames : @mut ~[(ast::Ident,ast::Name)]) -> @ast_fold {
701746
let afp = default_ast_fold();
702747
let f_pre = @AstFoldFns {
703748
fold_ident: |id,_| {
@@ -713,15 +758,56 @@ fn renames_to_fold(renames : @mut ~[(ast::Ident,ast::Name)]) -> @ast_fold {
713758
make_fold(f_pre)
714759
}
715760

716-
// perform a bunch of renames
717-
fn apply_pending_renames(folder : @ast_fold, stmt : ast::Stmt) -> @ast::Stmt {
718-
match folder.fold_stmt(&stmt) {
719-
Some(s) => s,
720-
None => fail!(fmt!("renaming of stmt produced None"))
761+
pub fn expand_block(extsbox: @mut SyntaxEnv,
762+
_cx: @ExtCtxt,
763+
blk: &Block,
764+
fld: @ast_fold,
765+
orig: @fn(&Block, @ast_fold) -> Block)
766+
-> Block {
767+
// see note below about treatment of exts table
768+
with_exts_frame!(extsbox,false,orig(blk,fld))
769+
}
770+
771+
772+
pub fn expand_block_elts(exts: SyntaxEnv, b: &Block, fld: @ast_fold) -> Block {
773+
let block_info = get_block_info(exts);
774+
let pending_renames = block_info.pending_renames;
775+
let mut rename_fld = renames_to_fold(pending_renames);
776+
let new_view_items = b.view_items.map(|x| fld.fold_view_item(x));
777+
let mut new_stmts = ~[];
778+
for x in b.stmts.iter() {
779+
match fld.fold_stmt(mustbesome(rename_fld.fold_stmt(*x))) {
780+
Some(s) => new_stmts.push(s),
781+
None => ()
782+
}
783+
}
784+
let new_expr = b.expr.map(|x| fld.fold_expr(rename_fld.fold_expr(*x)));
785+
Block{
786+
view_items: new_view_items,
787+
stmts: new_stmts,
788+
expr: new_expr,
789+
id: fld.new_id(b.id),
790+
rules: b.rules,
791+
span: b.span,
721792
}
722793
}
723794

795+
// rename_fold should never return "None".
796+
fn mustbesome<T>(val : Option<T>) -> T {
797+
match val {
798+
Some(v) => v,
799+
None => fail!("rename_fold returned None")
800+
}
801+
}
724802

803+
// get the (innermost) BlockInfo from an exts stack
804+
fn get_block_info(exts : SyntaxEnv) -> BlockInfo {
805+
match exts.find_in_topmost_frame(&intern(special_block_name)) {
806+
Some(@BlockInfo(bi)) => bi,
807+
_ => fail!(fmt!("special identifier %? was bound to a non-BlockInfo",
808+
@" block"))
809+
}
810+
}
725811

726812
pub fn new_span(cx: @ExtCtxt, sp: Span) -> Span {
727813
/* this discards information in the case of macro-defining macros */
@@ -1228,12 +1314,15 @@ mod test {
12281314
use super::*;
12291315
use ast;
12301316
use ast::{Attribute_, AttrOuter, MetaWord, EMPTY_CTXT};
1317+
use ast_util::{get_sctable, new_rename};
12311318
use codemap;
12321319
use codemap::Spanned;
12331320
use parse;
1234-
use parse::token::{intern, get_ident_interner};
1321+
use parse::token::{gensym, intern, get_ident_interner};
12351322
use print::pprust;
1236-
use util::parser_testing::{string_to_item, string_to_pat, strs_to_idents};
1323+
use std;
1324+
use util::parser_testing::{string_to_crate_and_sess, string_to_item, string_to_pat};
1325+
use util::parser_testing::{strs_to_idents};
12371326

12381327
// make sure that fail! is present
12391328
#[test] fn fail_exists_test () {
@@ -1333,26 +1422,60 @@ mod test {
13331422

13341423
#[test]
13351424
fn renaming () {
1336-
let maybe_item_ast = string_to_item(@"fn a() -> int { let b = 13; b }");
1337-
let item_ast = match maybe_item_ast {
1338-
Some(x) => x,
1339-
None => fail!("test case fail")
1340-
};
1425+
let item_ast = string_to_item(@"fn a() -> int { let b = 13; b }").unwrap();
13411426
let a_name = intern("a");
1342-
let a2_name = intern("a2");
1427+
let a2_name = gensym("a2");
13431428
let renamer = new_ident_renamer(ast::Ident{name:a_name,ctxt:EMPTY_CTXT},
13441429
a2_name);
13451430
let renamed_ast = fun_to_ident_folder(renamer).fold_item(item_ast).unwrap();
13461431
let resolver = new_ident_resolver();
1347-
let resolved_ast = fun_to_ident_folder(resolver).fold_item(renamed_ast).unwrap();
1432+
let resolver_fold = fun_to_ident_folder(resolver);
1433+
let resolved_ast = resolver_fold.fold_item(renamed_ast).unwrap();
13481434
let resolved_as_str = pprust::item_to_str(resolved_ast,
13491435
get_ident_interner());
13501436
assert_eq!(resolved_as_str,~"fn a2() -> int { let b = 13; b }");
13511437
1438+
// try a double-rename, with pending_renames.
1439+
let a3_name = gensym("a3");
1440+
let ctxt2 = new_rename(ast::Ident::new(a_name),a2_name,EMPTY_CTXT);
1441+
let pending_renames = @mut ~[(ast::Ident::new(a_name),a2_name),
1442+
(ast::Ident{name:a_name,ctxt:ctxt2},a3_name)];
1443+
let double_renamed = renames_to_fold(pending_renames).fold_item(item_ast).unwrap();
1444+
let resolved_again = resolver_fold.fold_item(double_renamed).unwrap();
1445+
let double_renamed_as_str = pprust::item_to_str(resolved_again,
1446+
get_ident_interner());
1447+
assert_eq!(double_renamed_as_str,~"fn a3() -> int { let b = 13; b }");
1448+
1449+
}
13521450
1451+
fn fake_print_crate(s: @pprust::ps, crate: &ast::Crate) {
1452+
pprust::print_mod(s, &crate.module, crate.attrs);
13531453
}
13541454
1355-
// sigh... it looks like I have two different renaming mechanisms, now...
1455+
// "fn a() -> int { let b = 13; let c = b; b+c }" --> b & c should get new names, in the expr too.
1456+
// "macro_rules! f (($x:ident) => ($x + b)) fn a() -> int { let b = 13; f!(b)}" --> one should
1457+
// be renamed, one should not.
1458+
1459+
fn expand_and_resolve_and_pretty_print (crate_str : @str) -> ~str {
1460+
let resolver = new_ident_resolver();
1461+
let resolver_fold = fun_to_ident_folder(resolver);
1462+
let (crate_ast,ps) = string_to_crate_and_sess(crate_str);
1463+
// the cfg argument actually does matter, here...
1464+
let expanded_ast = expand_crate(ps,~[],crate_ast);
1465+
// std::io::println(fmt!("expanded: %?\n",expanded_ast));
1466+
let resolved_ast = resolver_fold.fold_crate(expanded_ast);
1467+
pprust::to_str(&resolved_ast,fake_print_crate,get_ident_interner())
1468+
}
1469+
1470+
#[test]
1471+
fn automatic_renaming () {
1472+
let teststrs =
1473+
~[@"fn a() -> int { let b = 13; let c = b; b+c }",
1474+
@"macro_rules! f (($x:ident) => ($x + b)) fn a() -> int { let b = 13; f!(b)}"];
1475+
for s in teststrs.iter() {
1476+
std::io::println(expand_and_resolve_and_pretty_print(*s));
1477+
}
1478+
}
13561479
13571480
#[test]
13581481
fn pat_idents(){

branches/try/src/libsyntax/parse/token.rs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -552,9 +552,9 @@ pub fn gensym_ident(str : &str) -> ast::Ident {
552552
// by using a gensym with a name that has a random number
553553
// at the end. So, the gensym guarantees the uniqueness,
554554
// and the int helps to avoid confusion.
555-
pub fn fresh_name(src_name : &str) -> Name {
555+
pub fn fresh_name(src_name : &ast::Ident) -> Name {
556556
let num = rand::rng().gen_uint_range(0,0xffff);
557-
gensym(fmt!("%s_%u",src_name,num))
557+
gensym(fmt!("%s_%u",ident_to_str(src_name),num))
558558
}
559559

560560
/**
@@ -697,9 +697,5 @@ pub fn is_reserved_keyword(tok: &Token) -> bool {
697697
#[cfg(test)]
698698
mod test {
699699
use super::*;
700-
#[test] fn t1() {
701-
let a = fresh_name("ghi");
702-
printfln!("interned name: %u,\ntextual name: %s\n",
703-
a, interner_get(a));
704-
}
700+
705701
}

branches/try/src/libsyntax/util/parser_testing.rs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,19 @@ fn with_error_checking_parse<T>(s: @str, f: &fn(&mut Parser) -> T) -> T {
4040
x
4141
}
4242

43+
// parse a string, return a crate.
4344
pub fn string_to_crate (source_str : @str) -> @ast::Crate {
4445
do with_error_checking_parse(source_str) |p| {
4546
p.parse_crate_mod()
4647
}
4748
}
4849

50+
// parse a string, return a crate and the ParseSess
51+
pub fn string_to_crate_and_sess (source_str : @str) -> (@ast::Crate,@mut ParseSess) {
52+
let (p,ps) = string_to_parser_and_sess(source_str);
53+
(p.parse_crate_mod(),ps)
54+
}
55+
4956
// parse a string, return an expr
5057
pub fn string_to_expr (source_str : @str) -> @ast::Expr {
5158
do with_error_checking_parse(source_str) |p| {
@@ -60,14 +67,6 @@ pub fn string_to_item (source_str : @str) -> Option<@ast::item> {
6067
}
6168
}
6269

63-
// parse a string, return an item and the ParseSess
64-
pub fn string_to_item_and_sess (source_str : @str) -> (Option<@ast::item>,@mut ParseSess) {
65-
let (p,ps) = string_to_parser_and_sess(source_str);
66-
let io = p.parse_item(~[]);
67-
p.abort_if_errors();
68-
(io,ps)
69-
}
70-
7170
// parse a string, return a stmt
7271
pub fn string_to_stmt(source_str : @str) -> @ast::Stmt {
7372
do with_error_checking_parse(source_str) |p| {

0 commit comments

Comments
 (0)