add hygiene support functions
This commit is contained in:
parent
ecdb6e4722
commit
5a158f1d19
@ -479,6 +479,15 @@ fn find (&self, key: &K) -> Option<@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 @@ fn insert_into_frame(&mut self, key: K, ext: @V, n: K, pred: &fn(&@V)->bool) {
|
||||
}
|
||||
}
|
||||
|
||||
// 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)
|
||||
|
@ -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 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 @@ fn renaming () {
|
||||
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 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 @@ fn sp (a: uint, b: uint) -> span {
|
||||
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 @@ fn ints_to_idents(ids: ~[~str]) -> ~[ast::ident] {
|
||||
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 @@ fn ints_to_idents(ids: ~[~str]) -> ~[ast::ident] {
|
||||
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 @@ fn ints_to_idents(ids: ~[~str]) -> ~[ast::ident] {
|
||||
@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 @@ fn parser_done(p: Parser){
|
||||
@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 @@ fn parser_done(p: Parser){
|
||||
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 @@ fn parser_done(p: Parser){
|
||||
@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 @@ fn parser_done(p: Parser){
|
||||
// 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 @@ fn parser_done(p: Parser){
|
||||
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 @@ fn parser_done(p: Parser){
|
||||
@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 @@ fn parser_done(p: Parser){
|
||||
@ast::Path{
|
||||
span:sp(17,18),
|
||||
global:false,
|
||||
idents:~[intern_ident("b")],
|
||||
idents:~[str_to_ident("b")],
|
||||
rp:None,
|
||||
types: ~[]}),
|
||||
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)
|
||||
}
|
||||
|
||||
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(~[])
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user