about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorJohn Clements <clements@racket-lang.org>2013-06-04 14:56:33 -0700
committerJohn Clements <clements@racket-lang.org>2013-06-05 12:01:40 -0700
commit5a158f1d19d93af4223fea2da49209e73a3ed002 (patch)
treef79fda064ff81ff3c3f5b7f7d69b9c1cf8fbad5b /src/libsyntax
parentecdb6e472218ea6f542e4b95e1e3ce48a7e78056 (diff)
downloadrust-5a158f1d19d93af4223fea2da49209e73a3ed002.tar.gz
rust-5a158f1d19d93af4223fea2da49209e73a3ed002.zip
add hygiene support functions
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/ext/base.rs10
-rw-r--r--src/libsyntax/ext/expand.rs58
-rw-r--r--src/libsyntax/parse/mod.rs34
-rw-r--r--src/libsyntax/util/parser_testing.rs3
4 files changed, 78 insertions, 27 deletions
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index cc819a00f7d..a3432a00edc 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -479,6 +479,15 @@ impl <K: Eq + Hash + IterBytes ,V: Copy> MapChain<K,V>{
         }
     }
 
+    fn find_in_topmost_frame(&self, key: &K) -> Option<@V> {
+        let map = match *self {
+            BaseMapChain(ref map) => map,
+            ConsMapChain(ref map,_) => map
+        };
+        // strip one layer of indirection off the pointer.
+        map.find(key).map(|r| {**r})
+    }
+
     // insert the binding into the top-level map
     fn insert (&mut self, key: K, ext: @V) -> bool {
         // can't abstract over get_map because of flow sensitivity...
@@ -512,6 +521,7 @@ impl <K: Eq + Hash + IterBytes ,V: Copy> MapChain<K,V>{
     }
 }
 
+// returns true if the binding for 'n' satisfies 'pred' in 'map'
 fn satisfies_pred<K : Eq + Hash + IterBytes,V>(map : &mut HashMap<K,V>,
                                                n: &K,
                                                pred: &fn(&V)->bool)
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index 47c22c438a8..f5edc50377e 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -11,8 +11,8 @@
 use core::prelude::*;
 
 use ast::{blk_, attribute_, attr_outer, meta_word};
-use ast::{crate, expr_, expr_mac, mac_invoc_tt};
-use ast::{item_mac, stmt_, stmt_mac, stmt_expr, stmt_semi};
+use ast::{crate, decl_local, expr_, expr_mac, mac_invoc_tt};
+use ast::{item_mac, local_, stmt_, stmt_decl, stmt_mac, stmt_expr, stmt_semi};
 use ast::{SCTable, illegal_ctxt};
 use ast;
 use ast_util::{new_rename, new_mark, resolve, new_sctable};
@@ -26,6 +26,8 @@ use fold::*;
 use parse;
 use parse::{parse_item_from_source_str};
 use parse::token::{ident_to_str, intern};
+use visit;
+use visit::{Visitor,mk_vt};
 
 use core::vec;
 
@@ -276,13 +278,13 @@ pub fn expand_item_mac(extsbox: @mut SyntaxEnv,
 // insert a macro into the innermost frame that doesn't have the
 // macro_escape tag.
 fn insert_macro(exts: SyntaxEnv, name: ast::Name, transformer: @Transformer) {
-    let block_err_msg = "special identifier ' block' was bound to a non-BlockInfo";
     let is_non_escaping_block =
         |t : &@Transformer| -> bool{
         match t {
             &@BlockInfo(BlockInfo {macros_escape:false,_}) => true,
             &@BlockInfo(BlockInfo {_}) => false,
-            _ => fail!(block_err_msg)
+            _ => fail!(fmt!("special identifier %? was bound to a non-BlockInfo",
+                            special_block_name))
         }
     };
     exts.insert_into_frame(name,transformer,intern(special_block_name),
@@ -365,6 +367,34 @@ pub fn expand_stmt(extsbox: @mut SyntaxEnv,
 
 }
 
+// return a visitor that extracts the pat_ident paths
+// from a given pattern and puts them in a mutable
+// array (passed in to the traversal
+pub fn new_name_finder() -> @Visitor<@mut ~[ast::ident]> {
+    let default_visitor = visit::default_visitor();
+    @Visitor{
+        visit_pat : |p:@ast::pat,ident_accum:@mut ~[ast::ident],v:visit::vt<@mut ~[ast::ident]>| {
+            match *p {
+                // we found a pat_ident!
+                ast::pat{id:_, node: ast::pat_ident(_,path,ref inner), span:_} => {
+                    match path {
+                        // a path of length one:
+                        @ast::Path{global: false,idents: [id], span:_,rp:_,types:_} =>
+                        ident_accum.push(id),
+                        // I believe these must be enums...
+                        _ => ()
+                    }
+                    // visit optional subpattern of pat_ident:
+                    for inner.each |subpat: &@ast::pat| { (v.visit_pat)(*subpat, ident_accum, v) }
+                }
+                // use the default traversal for non-pat_idents
+                _ => visit::visit_pat(p,ident_accum,v)
+            }
+        },
+        .. *default_visitor
+    }
+}
+
 
 
 pub fn expand_block(extsbox: @mut SyntaxEnv,
@@ -378,6 +408,17 @@ pub fn expand_block(extsbox: @mut SyntaxEnv,
     with_exts_frame!(extsbox,false,orig(blk,sp,fld))
 }
 
+
+// get the (innermost) BlockInfo from an exts stack
+fn get_block_info(exts : SyntaxEnv) -> BlockInfo {
+    match exts.find_in_topmost_frame(&intern(special_block_name)) {
+        Some(@BlockInfo(bi)) => bi,
+        _ => fail!(fmt!("special identifier %? was bound to a non-BlockInfo",
+                       @~" block"))
+    }
+}
+
+
 // given a mutable list of renames, return a tree-folder that applies those
 // renames.
 fn renames_to_fold(renames : @mut ~[(ast::ident,ast::Name)]) -> @ast_fold {
@@ -738,6 +779,7 @@ mod test {
     use core::io;
     use core::option::{None, Some};
     use util::parser_testing::{string_to_item, string_to_pat, strs_to_idents};
+    use visit::{mk_vt,Visitor};
 
     // make sure that fail! is present
     #[test] fn fail_exists_test () {
@@ -857,4 +899,12 @@ mod test {
         io::print(fmt!("ast: %?\n",resolved_ast))
     }
 
+    #[test]
+    fn pat_idents(){
+        let pat = string_to_pat(@~"(a,Foo{x:c @ (b,9),y:Bar(4,d)})");
+        let pat_idents = new_name_finder();
+        let idents = @mut ~[];
+        ((*pat_idents).visit_pat)(pat,idents, mk_vt(pat_idents));
+        assert_eq!(idents,@mut strs_to_idents(~["a","c","b","d"]));
+    }
 }
diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs
index 7f7e607d37f..d7248204e1c 100644
--- a/src/libsyntax/parse/mod.rs
+++ b/src/libsyntax/parse/mod.rs
@@ -347,7 +347,7 @@ mod test {
     use parse::token::{intern, str_to_ident};
     use util::parser_testing::{string_to_tts_and_sess, string_to_parser};
     use util::parser_testing::{string_to_expr, string_to_item};
-    use util::parser_testing::{string_to_stmt};
+    use util::parser_testing::{string_to_stmt, strs_to_idents};
 
     // map a string to tts, return the tt without its parsesess
     fn string_to_tts_only(source_str : @~str) -> ~[ast::token_tree] {
@@ -368,22 +368,12 @@ mod test {
         span{lo:BytePos(a),hi:BytePos(b),expn_info:None}
     }
 
-    // compose new_ident and intern:
-    fn intern_ident(str : &str) -> ast::ident {
-        new_ident(intern(str))
-    }
-
-    // convert a vector of uints to a vector of ast::idents
-    fn ints_to_idents(ids: ~[~str]) -> ~[ast::ident] {
-        ids.map(|u| intern_ident(*u))
-    }
-
     #[test] fn path_exprs_1 () {
         assert_eq!(string_to_expr(@~"a"),
                    @ast::expr{id:1,
                               node:ast::expr_path(@ast::Path {span:sp(0,1),
                                                               global:false,
-                                                              idents:~[intern_ident("a")],
+                                                              idents:~[str_to_ident("a")],
                                                               rp:None,
                                                               types:~[]}),
                               span:sp(0,1)})
@@ -395,7 +385,7 @@ mod test {
                                node:ast::expr_path(
                                    @ast::Path {span:sp(0,6),
                                                global:true,
-                                               idents:ints_to_idents(~[~"a",~"b"]),
+                                               idents:strs_to_idents(~["a","b"]),
                                                rp:None,
                                                types:~[]}),
                               span:sp(0,6)})
@@ -445,7 +435,7 @@ mod test {
                                                   node:ast::expr_path(
                                                       @ast::Path{span:sp(7,8),
                                                                  global:false,
-                                                                 idents:~[intern_ident("d")],
+                                                                 idents:~[str_to_ident("d")],
                                                                  rp:None,
                                                                  types:~[]
                                                                 }),
@@ -462,7 +452,7 @@ mod test {
                                @ast::Path{
                                    span:sp(0,1),
                                    global:false,
-                                   idents:~[intern_ident("b")],
+                                   idents:~[str_to_ident("b")],
                                    rp:None,
                                    types: ~[]}),
                            span: sp(0,1)},
@@ -483,7 +473,7 @@ mod test {
                                                   @ast::Path{
                                                       span:sp(0,1),
                                                       global:false,
-                                                      idents:~[intern_ident("b")],
+                                                      idents:~[str_to_ident("b")],
                                                       rp: None,
                                                       types: ~[]},
                                                   None // no idea
@@ -502,7 +492,7 @@ mod test {
                                         span:sp(4,4), // this is bizarre...
                                         // check this in the original parser?
                                         global:false,
-                                        idents:~[intern_ident("int")],
+                                        idents:~[str_to_ident("int")],
                                         rp: None,
                                         types: ~[]},
                                                        2),
@@ -512,7 +502,7 @@ mod test {
                                                            @ast::Path{
                                                                span:sp(0,1),
                                                                global:false,
-                                                               idents:~[intern_ident("b")],
+                                                               idents:~[str_to_ident("b")],
                                                                rp: None,
                                                                types: ~[]},
                                                            None // no idea
@@ -528,7 +518,7 @@ mod test {
         // assignment order of the node_ids.
         assert_eq!(string_to_item(@~"fn a (b : int) { b; }"),
                   Some(
-                      @ast::item{ident:intern_ident("a"),
+                      @ast::item{ident:str_to_ident("a"),
                             attrs:~[],
                             id: 9, // fixme
                             node: ast::item_fn(ast::fn_decl{
@@ -538,7 +528,7 @@ mod test {
                                                 node: ast::ty_path(@ast::Path{
                                         span:sp(10,13),
                                         global:false,
-                                        idents:~[intern_ident("int")],
+                                        idents:~[str_to_ident("int")],
                                         rp: None,
                                         types: ~[]},
                                                        2),
@@ -549,7 +539,7 @@ mod test {
                                                        @ast::Path{
                                                            span:sp(6,7),
                                                            global:false,
-                                                           idents:~[intern_ident("b")],
+                                                           idents:~[str_to_ident("b")],
                                                            rp: None,
                                                            types: ~[]},
                                                        None // no idea
@@ -579,7 +569,7 @@ mod test {
                                                         @ast::Path{
                                                             span:sp(17,18),
                                                             global:false,
-                                                            idents:~[intern_ident("b")],
+                                                            idents:~[str_to_ident("b")],
                                                             rp:None,
                                                             types: ~[]}),
                                                     span: sp(17,18)},
diff --git a/src/libsyntax/util/parser_testing.rs b/src/libsyntax/util/parser_testing.rs
index 2b74ef7fbea..c5528069926 100644
--- a/src/libsyntax/util/parser_testing.rs
+++ b/src/libsyntax/util/parser_testing.rs
@@ -54,7 +54,8 @@ pub fn string_to_item_and_sess (source_str : @~str) -> (Option<@ast::item>,@mut
     (p.parse_item(~[]),ps)
 }
 
-pub fn string_to_stmt (source_str : @~str) -> @ast::stmt {
+// parse a string, return a stmt
+pub fn string_to_stmt(source_str : @~str) -> @ast::stmt {
     string_to_parser(source_str).parse_stmt(~[])
 }