add hygiene support functions
This commit is contained in:
parent
ecdb6e4722
commit
5a158f1d19
|
@ -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
|
// insert the binding into the top-level map
|
||||||
fn insert (&mut self, key: K, ext: @V) -> bool {
|
fn insert (&mut self, key: K, ext: @V) -> bool {
|
||||||
// can't abstract over get_map because of flow sensitivity...
|
// 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>,
|
fn satisfies_pred<K : Eq + Hash + IterBytes,V>(map : &mut HashMap<K,V>,
|
||||||
n: &K,
|
n: &K,
|
||||||
pred: &fn(&V)->bool)
|
pred: &fn(&V)->bool)
|
||||||
|
|
|
@ -11,8 +11,8 @@
|
||||||
use core::prelude::*;
|
use core::prelude::*;
|
||||||
|
|
||||||
use ast::{blk_, attribute_, attr_outer, meta_word};
|
use ast::{blk_, attribute_, attr_outer, meta_word};
|
||||||
use ast::{crate, expr_, expr_mac, mac_invoc_tt};
|
use ast::{crate, decl_local, expr_, expr_mac, mac_invoc_tt};
|
||||||
use ast::{item_mac, stmt_, stmt_mac, stmt_expr, stmt_semi};
|
use ast::{item_mac, local_, stmt_, stmt_decl, stmt_mac, stmt_expr, stmt_semi};
|
||||||
use ast::{SCTable, illegal_ctxt};
|
use ast::{SCTable, illegal_ctxt};
|
||||||
use ast;
|
use ast;
|
||||||
use ast_util::{new_rename, new_mark, resolve, new_sctable};
|
use ast_util::{new_rename, new_mark, resolve, new_sctable};
|
||||||
|
@ -26,6 +26,8 @@ use fold::*;
|
||||||
use parse;
|
use parse;
|
||||||
use parse::{parse_item_from_source_str};
|
use parse::{parse_item_from_source_str};
|
||||||
use parse::token::{ident_to_str, intern};
|
use parse::token::{ident_to_str, intern};
|
||||||
|
use visit;
|
||||||
|
use visit::{Visitor,mk_vt};
|
||||||
|
|
||||||
use core::vec;
|
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
|
// insert a macro into the innermost frame that doesn't have the
|
||||||
// macro_escape tag.
|
// macro_escape tag.
|
||||||
fn insert_macro(exts: SyntaxEnv, name: ast::Name, transformer: @Transformer) {
|
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 =
|
let is_non_escaping_block =
|
||||||
|t : &@Transformer| -> bool{
|
|t : &@Transformer| -> bool{
|
||||||
match t {
|
match t {
|
||||||
&@BlockInfo(BlockInfo {macros_escape:false,_}) => true,
|
&@BlockInfo(BlockInfo {macros_escape:false,_}) => true,
|
||||||
&@BlockInfo(BlockInfo {_}) => false,
|
&@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),
|
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,
|
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))
|
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
|
// given a mutable list of renames, return a tree-folder that applies those
|
||||||
// renames.
|
// renames.
|
||||||
fn renames_to_fold(renames : @mut ~[(ast::ident,ast::Name)]) -> @ast_fold {
|
fn renames_to_fold(renames : @mut ~[(ast::ident,ast::Name)]) -> @ast_fold {
|
||||||
|
@ -738,6 +779,7 @@ mod test {
|
||||||
use core::io;
|
use core::io;
|
||||||
use core::option::{None, Some};
|
use core::option::{None, Some};
|
||||||
use util::parser_testing::{string_to_item, string_to_pat, strs_to_idents};
|
use util::parser_testing::{string_to_item, string_to_pat, strs_to_idents};
|
||||||
|
use visit::{mk_vt,Visitor};
|
||||||
|
|
||||||
// make sure that fail! is present
|
// make sure that fail! is present
|
||||||
#[test] fn fail_exists_test () {
|
#[test] fn fail_exists_test () {
|
||||||
|
@ -857,4 +899,12 @@ mod test {
|
||||||
io::print(fmt!("ast: %?\n",resolved_ast))
|
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"]));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -347,7 +347,7 @@ mod test {
|
||||||
use parse::token::{intern, str_to_ident};
|
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_tts_and_sess, string_to_parser};
|
||||||
use util::parser_testing::{string_to_expr, string_to_item};
|
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
|
// map a string to tts, return the tt without its parsesess
|
||||||
fn string_to_tts_only(source_str : @~str) -> ~[ast::token_tree] {
|
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}
|
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 () {
|
#[test] fn path_exprs_1 () {
|
||||||
assert_eq!(string_to_expr(@~"a"),
|
assert_eq!(string_to_expr(@~"a"),
|
||||||
@ast::expr{id:1,
|
@ast::expr{id:1,
|
||||||
node:ast::expr_path(@ast::Path {span:sp(0,1),
|
node:ast::expr_path(@ast::Path {span:sp(0,1),
|
||||||
global:false,
|
global:false,
|
||||||
idents:~[intern_ident("a")],
|
idents:~[str_to_ident("a")],
|
||||||
rp:None,
|
rp:None,
|
||||||
types:~[]}),
|
types:~[]}),
|
||||||
span:sp(0,1)})
|
span:sp(0,1)})
|
||||||
|
@ -395,7 +385,7 @@ mod test {
|
||||||
node:ast::expr_path(
|
node:ast::expr_path(
|
||||||
@ast::Path {span:sp(0,6),
|
@ast::Path {span:sp(0,6),
|
||||||
global:true,
|
global:true,
|
||||||
idents:ints_to_idents(~[~"a",~"b"]),
|
idents:strs_to_idents(~["a","b"]),
|
||||||
rp:None,
|
rp:None,
|
||||||
types:~[]}),
|
types:~[]}),
|
||||||
span:sp(0,6)})
|
span:sp(0,6)})
|
||||||
|
@ -445,7 +435,7 @@ mod test {
|
||||||
node:ast::expr_path(
|
node:ast::expr_path(
|
||||||
@ast::Path{span:sp(7,8),
|
@ast::Path{span:sp(7,8),
|
||||||
global:false,
|
global:false,
|
||||||
idents:~[intern_ident("d")],
|
idents:~[str_to_ident("d")],
|
||||||
rp:None,
|
rp:None,
|
||||||
types:~[]
|
types:~[]
|
||||||
}),
|
}),
|
||||||
|
@ -462,7 +452,7 @@ mod test {
|
||||||
@ast::Path{
|
@ast::Path{
|
||||||
span:sp(0,1),
|
span:sp(0,1),
|
||||||
global:false,
|
global:false,
|
||||||
idents:~[intern_ident("b")],
|
idents:~[str_to_ident("b")],
|
||||||
rp:None,
|
rp:None,
|
||||||
types: ~[]}),
|
types: ~[]}),
|
||||||
span: sp(0,1)},
|
span: sp(0,1)},
|
||||||
|
@ -483,7 +473,7 @@ mod test {
|
||||||
@ast::Path{
|
@ast::Path{
|
||||||
span:sp(0,1),
|
span:sp(0,1),
|
||||||
global:false,
|
global:false,
|
||||||
idents:~[intern_ident("b")],
|
idents:~[str_to_ident("b")],
|
||||||
rp: None,
|
rp: None,
|
||||||
types: ~[]},
|
types: ~[]},
|
||||||
None // no idea
|
None // no idea
|
||||||
|
@ -502,7 +492,7 @@ mod test {
|
||||||
span:sp(4,4), // this is bizarre...
|
span:sp(4,4), // this is bizarre...
|
||||||
// check this in the original parser?
|
// check this in the original parser?
|
||||||
global:false,
|
global:false,
|
||||||
idents:~[intern_ident("int")],
|
idents:~[str_to_ident("int")],
|
||||||
rp: None,
|
rp: None,
|
||||||
types: ~[]},
|
types: ~[]},
|
||||||
2),
|
2),
|
||||||
|
@ -512,7 +502,7 @@ mod test {
|
||||||
@ast::Path{
|
@ast::Path{
|
||||||
span:sp(0,1),
|
span:sp(0,1),
|
||||||
global:false,
|
global:false,
|
||||||
idents:~[intern_ident("b")],
|
idents:~[str_to_ident("b")],
|
||||||
rp: None,
|
rp: None,
|
||||||
types: ~[]},
|
types: ~[]},
|
||||||
None // no idea
|
None // no idea
|
||||||
|
@ -528,7 +518,7 @@ mod test {
|
||||||
// assignment order of the node_ids.
|
// assignment order of the node_ids.
|
||||||
assert_eq!(string_to_item(@~"fn a (b : int) { b; }"),
|
assert_eq!(string_to_item(@~"fn a (b : int) { b; }"),
|
||||||
Some(
|
Some(
|
||||||
@ast::item{ident:intern_ident("a"),
|
@ast::item{ident:str_to_ident("a"),
|
||||||
attrs:~[],
|
attrs:~[],
|
||||||
id: 9, // fixme
|
id: 9, // fixme
|
||||||
node: ast::item_fn(ast::fn_decl{
|
node: ast::item_fn(ast::fn_decl{
|
||||||
|
@ -538,7 +528,7 @@ mod test {
|
||||||
node: ast::ty_path(@ast::Path{
|
node: ast::ty_path(@ast::Path{
|
||||||
span:sp(10,13),
|
span:sp(10,13),
|
||||||
global:false,
|
global:false,
|
||||||
idents:~[intern_ident("int")],
|
idents:~[str_to_ident("int")],
|
||||||
rp: None,
|
rp: None,
|
||||||
types: ~[]},
|
types: ~[]},
|
||||||
2),
|
2),
|
||||||
|
@ -549,7 +539,7 @@ mod test {
|
||||||
@ast::Path{
|
@ast::Path{
|
||||||
span:sp(6,7),
|
span:sp(6,7),
|
||||||
global:false,
|
global:false,
|
||||||
idents:~[intern_ident("b")],
|
idents:~[str_to_ident("b")],
|
||||||
rp: None,
|
rp: None,
|
||||||
types: ~[]},
|
types: ~[]},
|
||||||
None // no idea
|
None // no idea
|
||||||
|
@ -579,7 +569,7 @@ mod test {
|
||||||
@ast::Path{
|
@ast::Path{
|
||||||
span:sp(17,18),
|
span:sp(17,18),
|
||||||
global:false,
|
global:false,
|
||||||
idents:~[intern_ident("b")],
|
idents:~[str_to_ident("b")],
|
||||||
rp:None,
|
rp:None,
|
||||||
types: ~[]}),
|
types: ~[]}),
|
||||||
span: sp(17,18)},
|
span: sp(17,18)},
|
||||||
|
|
|
@ -54,7 +54,8 @@ pub fn string_to_item_and_sess (source_str : @~str) -> (Option<@ast::item>,@mut
|
||||||
(p.parse_item(~[]),ps)
|
(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(~[])
|
string_to_parser(source_str).parse_stmt(~[])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue