Skip to content

Commit 5a158f1

Browse files
committed
add hygiene support functions
1 parent ecdb6e4 commit 5a158f1

File tree

4 files changed

+78
-27
lines changed

4 files changed

+78
-27
lines changed

src/libsyntax/ext/base.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,15 @@ impl <K: Eq + Hash + IterBytes ,V: Copy> MapChain<K,V>{
479479
}
480480
}
481481

482+
fn find_in_topmost_frame(&self, key: &K) -> Option<@V> {
483+
let map = match *self {
484+
BaseMapChain(ref map) => map,
485+
ConsMapChain(ref map,_) => map
486+
};
487+
// strip one layer of indirection off the pointer.
488+
map.find(key).map(|r| {**r})
489+
}
490+
482491
// insert the binding into the top-level map
483492
fn insert (&mut self, key: K, ext: @V) -> bool {
484493
// can't abstract over get_map because of flow sensitivity...
@@ -512,6 +521,7 @@ impl <K: Eq + Hash + IterBytes ,V: Copy> MapChain<K,V>{
512521
}
513522
}
514523
524+
// returns true if the binding for 'n' satisfies 'pred' in 'map'
515525
fn satisfies_pred<K : Eq + Hash + IterBytes,V>(map : &mut HashMap<K,V>,
516526
n: &K,
517527
pred: &fn(&V)->bool)

src/libsyntax/ext/expand.rs

Lines changed: 54 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
use core::prelude::*;
1212

1313
use ast::{blk_, attribute_, attr_outer, meta_word};
14-
use ast::{crate, expr_, expr_mac, mac_invoc_tt};
15-
use ast::{item_mac, stmt_, stmt_mac, stmt_expr, stmt_semi};
14+
use ast::{crate, decl_local, expr_, expr_mac, mac_invoc_tt};
15+
use ast::{item_mac, local_, stmt_, stmt_decl, stmt_mac, stmt_expr, stmt_semi};
1616
use ast::{SCTable, illegal_ctxt};
1717
use ast;
1818
use ast_util::{new_rename, new_mark, resolve, new_sctable};
@@ -26,6 +26,8 @@ use fold::*;
2626
use parse;
2727
use parse::{parse_item_from_source_str};
2828
use parse::token::{ident_to_str, intern};
29+
use visit;
30+
use visit::{Visitor,mk_vt};
2931

3032
use core::vec;
3133

@@ -276,13 +278,13 @@ pub fn expand_item_mac(extsbox: @mut SyntaxEnv,
276278
// insert a macro into the innermost frame that doesn't have the
277279
// macro_escape tag.
278280
fn insert_macro(exts: SyntaxEnv, name: ast::Name, transformer: @Transformer) {
279-
let block_err_msg = "special identifier ' block' was bound to a non-BlockInfo";
280281
let is_non_escaping_block =
281282
|t : &@Transformer| -> bool{
282283
match t {
283284
&@BlockInfo(BlockInfo {macros_escape:false,_}) => true,
284285
&@BlockInfo(BlockInfo {_}) => false,
285-
_ => fail!(block_err_msg)
286+
_ => fail!(fmt!("special identifier %? was bound to a non-BlockInfo",
287+
special_block_name))
286288
}
287289
};
288290
exts.insert_into_frame(name,transformer,intern(special_block_name),
@@ -365,6 +367,34 @@ pub fn expand_stmt(extsbox: @mut SyntaxEnv,
365367

366368
}
367369

370+
// return a visitor that extracts the pat_ident paths
371+
// from a given pattern and puts them in a mutable
372+
// array (passed in to the traversal
373+
pub fn new_name_finder() -> @Visitor<@mut ~[ast::ident]> {
374+
let default_visitor = visit::default_visitor();
375+
@Visitor{
376+
visit_pat : |p:@ast::pat,ident_accum:@mut ~[ast::ident],v:visit::vt<@mut ~[ast::ident]>| {
377+
match *p {
378+
// we found a pat_ident!
379+
ast::pat{id:_, node: ast::pat_ident(_,path,ref inner), span:_} => {
380+
match path {
381+
// a path of length one:
382+
@ast::Path{global: false,idents: [id], span:_,rp:_,types:_} =>
383+
ident_accum.push(id),
384+
// I believe these must be enums...
385+
_ => ()
386+
}
387+
// visit optional subpattern of pat_ident:
388+
for inner.each |subpat: &@ast::pat| { (v.visit_pat)(*subpat, ident_accum, v) }
389+
}
390+
// use the default traversal for non-pat_idents
391+
_ => visit::visit_pat(p,ident_accum,v)
392+
}
393+
},
394+
.. *default_visitor
395+
}
396+
}
397+
368398

369399

370400
pub fn expand_block(extsbox: @mut SyntaxEnv,
@@ -378,6 +408,17 @@ pub fn expand_block(extsbox: @mut SyntaxEnv,
378408
with_exts_frame!(extsbox,false,orig(blk,sp,fld))
379409
}
380410

411+
412+
// get the (innermost) BlockInfo from an exts stack
413+
fn get_block_info(exts : SyntaxEnv) -> BlockInfo {
414+
match exts.find_in_topmost_frame(&intern(special_block_name)) {
415+
Some(@BlockInfo(bi)) => bi,
416+
_ => fail!(fmt!("special identifier %? was bound to a non-BlockInfo",
417+
@~" block"))
418+
}
419+
}
420+
421+
381422
// given a mutable list of renames, return a tree-folder that applies those
382423
// renames.
383424
fn renames_to_fold(renames : @mut ~[(ast::ident,ast::Name)]) -> @ast_fold {
@@ -738,6 +779,7 @@ mod test {
738779
use core::io;
739780
use core::option::{None, Some};
740781
use util::parser_testing::{string_to_item, string_to_pat, strs_to_idents};
782+
use visit::{mk_vt,Visitor};
741783

742784
// make sure that fail! is present
743785
#[test] fn fail_exists_test () {
@@ -857,4 +899,12 @@ mod test {
857899
io::print(fmt!("ast: %?\n",resolved_ast))
858900
}
859901

902+
#[test]
903+
fn pat_idents(){
904+
let pat = string_to_pat(@~"(a,Foo{x:c @ (b,9),y:Bar(4,d)})");
905+
let pat_idents = new_name_finder();
906+
let idents = @mut ~[];
907+
((*pat_idents).visit_pat)(pat,idents, mk_vt(pat_idents));
908+
assert_eq!(idents,@mut strs_to_idents(~["a","c","b","d"]));
909+
}
860910
}

src/libsyntax/parse/mod.rs

Lines changed: 12 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,7 @@ mod test {
347347
use parse::token::{intern, str_to_ident};
348348
use util::parser_testing::{string_to_tts_and_sess, string_to_parser};
349349
use util::parser_testing::{string_to_expr, string_to_item};
350-
use util::parser_testing::{string_to_stmt};
350+
use util::parser_testing::{string_to_stmt, strs_to_idents};
351351

352352
// map a string to tts, return the tt without its parsesess
353353
fn string_to_tts_only(source_str : @~str) -> ~[ast::token_tree] {
@@ -368,22 +368,12 @@ mod test {
368368
span{lo:BytePos(a),hi:BytePos(b),expn_info:None}
369369
}
370370

371-
// compose new_ident and intern:
372-
fn intern_ident(str : &str) -> ast::ident {
373-
new_ident(intern(str))
374-
}
375-
376-
// convert a vector of uints to a vector of ast::idents
377-
fn ints_to_idents(ids: ~[~str]) -> ~[ast::ident] {
378-
ids.map(|u| intern_ident(*u))
379-
}
380-
381371
#[test] fn path_exprs_1 () {
382372
assert_eq!(string_to_expr(@~"a"),
383373
@ast::expr{id:1,
384374
node:ast::expr_path(@ast::Path {span:sp(0,1),
385375
global:false,
386-
idents:~[intern_ident("a")],
376+
idents:~[str_to_ident("a")],
387377
rp:None,
388378
types:~[]}),
389379
span:sp(0,1)})
@@ -395,7 +385,7 @@ mod test {
395385
node:ast::expr_path(
396386
@ast::Path {span:sp(0,6),
397387
global:true,
398-
idents:ints_to_idents(~[~"a",~"b"]),
388+
idents:strs_to_idents(~["a","b"]),
399389
rp:None,
400390
types:~[]}),
401391
span:sp(0,6)})
@@ -445,7 +435,7 @@ mod test {
445435
node:ast::expr_path(
446436
@ast::Path{span:sp(7,8),
447437
global:false,
448-
idents:~[intern_ident("d")],
438+
idents:~[str_to_ident("d")],
449439
rp:None,
450440
types:~[]
451441
}),
@@ -462,7 +452,7 @@ mod test {
462452
@ast::Path{
463453
span:sp(0,1),
464454
global:false,
465-
idents:~[intern_ident("b")],
455+
idents:~[str_to_ident("b")],
466456
rp:None,
467457
types: ~[]}),
468458
span: sp(0,1)},
@@ -483,7 +473,7 @@ mod test {
483473
@ast::Path{
484474
span:sp(0,1),
485475
global:false,
486-
idents:~[intern_ident("b")],
476+
idents:~[str_to_ident("b")],
487477
rp: None,
488478
types: ~[]},
489479
None // no idea
@@ -502,7 +492,7 @@ mod test {
502492
span:sp(4,4), // this is bizarre...
503493
// check this in the original parser?
504494
global:false,
505-
idents:~[intern_ident("int")],
495+
idents:~[str_to_ident("int")],
506496
rp: None,
507497
types: ~[]},
508498
2),
@@ -512,7 +502,7 @@ mod test {
512502
@ast::Path{
513503
span:sp(0,1),
514504
global:false,
515-
idents:~[intern_ident("b")],
505+
idents:~[str_to_ident("b")],
516506
rp: None,
517507
types: ~[]},
518508
None // no idea
@@ -528,7 +518,7 @@ mod test {
528518
// assignment order of the node_ids.
529519
assert_eq!(string_to_item(@~"fn a (b : int) { b; }"),
530520
Some(
531-
@ast::item{ident:intern_ident("a"),
521+
@ast::item{ident:str_to_ident("a"),
532522
attrs:~[],
533523
id: 9, // fixme
534524
node: ast::item_fn(ast::fn_decl{
@@ -538,7 +528,7 @@ mod test {
538528
node: ast::ty_path(@ast::Path{
539529
span:sp(10,13),
540530
global:false,
541-
idents:~[intern_ident("int")],
531+
idents:~[str_to_ident("int")],
542532
rp: None,
543533
types: ~[]},
544534
2),
@@ -549,7 +539,7 @@ mod test {
549539
@ast::Path{
550540
span:sp(6,7),
551541
global:false,
552-
idents:~[intern_ident("b")],
542+
idents:~[str_to_ident("b")],
553543
rp: None,
554544
types: ~[]},
555545
None // no idea
@@ -579,7 +569,7 @@ mod test {
579569
@ast::Path{
580570
span:sp(17,18),
581571
global:false,
582-
idents:~[intern_ident("b")],
572+
idents:~[str_to_ident("b")],
583573
rp:None,
584574
types: ~[]}),
585575
span: sp(17,18)},

src/libsyntax/util/parser_testing.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@ pub fn string_to_item_and_sess (source_str : @~str) -> (Option<@ast::item>,@mut
5454
(p.parse_item(~[]),ps)
5555
}
5656

57-
pub fn string_to_stmt (source_str : @~str) -> @ast::stmt {
57+
// parse a string, return a stmt
58+
pub fn string_to_stmt(source_str : @~str) -> @ast::stmt {
5859
string_to_parser(source_str).parse_stmt(~[])
5960
}
6061

0 commit comments

Comments
 (0)