change to newer macro escape mechanism, using uints in more places
This commit is contained in:
parent
77c2c0900f
commit
d7638f9dba
5 changed files with 166 additions and 128 deletions
|
|
@ -11,6 +11,7 @@
|
|||
use core::prelude::*;
|
||||
|
||||
use ast;
|
||||
use ast::Name;
|
||||
use codemap;
|
||||
use codemap::{CodeMap, span, ExpnInfo, ExpandedFrom};
|
||||
use codemap::CallInfo;
|
||||
|
|
@ -18,6 +19,7 @@ use diagnostic::span_handler;
|
|||
use ext;
|
||||
use parse;
|
||||
use parse::token;
|
||||
use parse::token::{intern};
|
||||
|
||||
use core::hashmap::HashMap;
|
||||
use core::vec;
|
||||
|
|
@ -91,29 +93,33 @@ pub enum SyntaxExtension {
|
|||
IdentTT(SyntaxExpanderTTItem),
|
||||
}
|
||||
|
||||
// The SyntaxEnv is the environment that's threaded through the expansion
|
||||
// of macros. It contains bindings for macros, and also a special binding
|
||||
// for " block" (not a legal identifier) that maps to a BlockInfo
|
||||
pub type SyntaxEnv = @mut MapChain<Name, Transformer>;
|
||||
|
||||
// Name : the domain of SyntaxEnvs
|
||||
// want to change these to uints....
|
||||
// note that we use certain strings that are not legal as identifiers
|
||||
// to indicate, for instance, how blocks are supposed to behave.
|
||||
type Name = @~str;
|
||||
|
||||
// Transformer : the codomain of SyntaxEnvs
|
||||
|
||||
// NB: it may seem crazy to lump both of these into one environment;
|
||||
// what would it mean to bind "foo" to BlockLimit(true)? The idea
|
||||
// is that this follows the lead of MTWT, and accommodates growth
|
||||
// toward a more uniform syntax syntax (sorry) where blocks are just
|
||||
// another kind of transformer.
|
||||
|
||||
pub enum Transformer {
|
||||
// this identifier maps to a syntax extension or macro
|
||||
SE(SyntaxExtension),
|
||||
// should blocks occurring here limit macro scopes?
|
||||
ScopeMacros(bool)
|
||||
// blockinfo : this is ... well, it's simpler than threading
|
||||
// another whole data stack-structured data structure through
|
||||
// expansion. Basically, there's an invariant that every
|
||||
// map must contain a binding for " block".
|
||||
BlockInfo(BlockInfo)
|
||||
}
|
||||
|
||||
pub struct BlockInfo {
|
||||
// should macros escape from this scope?
|
||||
macros_escape : bool,
|
||||
// what are the pending renames?
|
||||
pending_renames : @mut RenameList
|
||||
}
|
||||
|
||||
// a list of ident->name renamings
|
||||
type RenameList = ~[(ast::ident,Name)];
|
||||
|
||||
// The base map of methods for expanding syntax extension
|
||||
// AST nodes into full ASTs
|
||||
pub fn syntax_expander_table() -> SyntaxEnv {
|
||||
|
|
@ -127,77 +133,80 @@ pub fn syntax_expander_table() -> SyntaxEnv {
|
|||
}
|
||||
let mut syntax_expanders = HashMap::new();
|
||||
// NB identifier starts with space, and can't conflict with legal idents
|
||||
syntax_expanders.insert(@~" block",
|
||||
@ScopeMacros(true));
|
||||
syntax_expanders.insert(@~"macro_rules",
|
||||
syntax_expanders.insert(intern(&" block"),
|
||||
@BlockInfo(BlockInfo{
|
||||
macros_escape : false,
|
||||
pending_renames : @mut ~[]
|
||||
}));
|
||||
syntax_expanders.insert(intern(&"macro_rules"),
|
||||
builtin_item_tt(
|
||||
ext::tt::macro_rules::add_new_extension));
|
||||
syntax_expanders.insert(@~"fmt",
|
||||
syntax_expanders.insert(intern(&"fmt"),
|
||||
builtin_normal_tt(ext::fmt::expand_syntax_ext));
|
||||
syntax_expanders.insert(
|
||||
@~"auto_encode",
|
||||
intern(&"auto_encode"),
|
||||
@SE(ItemDecorator(ext::auto_encode::expand_auto_encode)));
|
||||
syntax_expanders.insert(
|
||||
@~"auto_decode",
|
||||
intern(&"auto_decode"),
|
||||
@SE(ItemDecorator(ext::auto_encode::expand_auto_decode)));
|
||||
syntax_expanders.insert(@~"env",
|
||||
syntax_expanders.insert(intern(&"env"),
|
||||
builtin_normal_tt(ext::env::expand_syntax_ext));
|
||||
syntax_expanders.insert(@~"bytes",
|
||||
syntax_expanders.insert(intern("bytes"),
|
||||
builtin_normal_tt(ext::bytes::expand_syntax_ext));
|
||||
syntax_expanders.insert(@~"concat_idents",
|
||||
syntax_expanders.insert(intern("concat_idents"),
|
||||
builtin_normal_tt(
|
||||
ext::concat_idents::expand_syntax_ext));
|
||||
syntax_expanders.insert(@~"log_syntax",
|
||||
syntax_expanders.insert(intern(&"log_syntax"),
|
||||
builtin_normal_tt(
|
||||
ext::log_syntax::expand_syntax_ext));
|
||||
syntax_expanders.insert(@~"deriving",
|
||||
syntax_expanders.insert(intern(&"deriving"),
|
||||
@SE(ItemDecorator(
|
||||
ext::deriving::expand_meta_deriving)));
|
||||
|
||||
// Quasi-quoting expanders
|
||||
syntax_expanders.insert(@~"quote_tokens",
|
||||
syntax_expanders.insert(intern(&"quote_tokens"),
|
||||
builtin_normal_tt(ext::quote::expand_quote_tokens));
|
||||
syntax_expanders.insert(@~"quote_expr",
|
||||
syntax_expanders.insert(intern(&"quote_expr"),
|
||||
builtin_normal_tt(ext::quote::expand_quote_expr));
|
||||
syntax_expanders.insert(@~"quote_ty",
|
||||
syntax_expanders.insert(intern(&"quote_ty"),
|
||||
builtin_normal_tt(ext::quote::expand_quote_ty));
|
||||
syntax_expanders.insert(@~"quote_item",
|
||||
syntax_expanders.insert(intern(&"quote_item"),
|
||||
builtin_normal_tt(ext::quote::expand_quote_item));
|
||||
syntax_expanders.insert(@~"quote_pat",
|
||||
syntax_expanders.insert(intern(&"quote_pat"),
|
||||
builtin_normal_tt(ext::quote::expand_quote_pat));
|
||||
syntax_expanders.insert(@~"quote_stmt",
|
||||
syntax_expanders.insert(intern(&"quote_stmt"),
|
||||
builtin_normal_tt(ext::quote::expand_quote_stmt));
|
||||
|
||||
syntax_expanders.insert(@~"line",
|
||||
syntax_expanders.insert(intern(&"line"),
|
||||
builtin_normal_tt(
|
||||
ext::source_util::expand_line));
|
||||
syntax_expanders.insert(@~"col",
|
||||
syntax_expanders.insert(intern(&"col"),
|
||||
builtin_normal_tt(
|
||||
ext::source_util::expand_col));
|
||||
syntax_expanders.insert(@~"file",
|
||||
syntax_expanders.insert(intern(&"file"),
|
||||
builtin_normal_tt(
|
||||
ext::source_util::expand_file));
|
||||
syntax_expanders.insert(@~"stringify",
|
||||
syntax_expanders.insert(intern(&"stringify"),
|
||||
builtin_normal_tt(
|
||||
ext::source_util::expand_stringify));
|
||||
syntax_expanders.insert(@~"include",
|
||||
syntax_expanders.insert(intern(&"include"),
|
||||
builtin_normal_tt(
|
||||
ext::source_util::expand_include));
|
||||
syntax_expanders.insert(@~"include_str",
|
||||
syntax_expanders.insert(intern(&"include_str"),
|
||||
builtin_normal_tt(
|
||||
ext::source_util::expand_include_str));
|
||||
syntax_expanders.insert(@~"include_bin",
|
||||
syntax_expanders.insert(intern(&"include_bin"),
|
||||
builtin_normal_tt(
|
||||
ext::source_util::expand_include_bin));
|
||||
syntax_expanders.insert(@~"module_path",
|
||||
syntax_expanders.insert(intern(&"module_path"),
|
||||
builtin_normal_tt(
|
||||
ext::source_util::expand_mod));
|
||||
syntax_expanders.insert(@~"proto",
|
||||
syntax_expanders.insert(intern(&"proto"),
|
||||
builtin_item_tt(ext::pipes::expand_proto));
|
||||
syntax_expanders.insert(@~"asm",
|
||||
syntax_expanders.insert(intern(&"asm"),
|
||||
builtin_normal_tt(ext::asm::expand_asm));
|
||||
syntax_expanders.insert(
|
||||
@~"trace_macros",
|
||||
intern(&"trace_macros"),
|
||||
builtin_normal_tt(ext::trace_macros::expand_trace_macros));
|
||||
MapChain::new(~syntax_expanders)
|
||||
}
|
||||
|
|
@ -478,7 +487,39 @@ impl <K: Eq + Hash + IterBytes ,V: Copy> MapChain<K,V>{
|
|||
ConsMapChain (~ref mut map,_) => map.insert(key,ext)
|
||||
}
|
||||
}
|
||||
// insert the binding into the topmost frame for which the binding
|
||||
// associated with 'n' exists and satisfies pred
|
||||
// ... there are definitely some opportunities for abstraction
|
||||
// here that I'm ignoring. (e.g., manufacturing a predicate on
|
||||
// the maps in the chain, and using an abstract "find".
|
||||
fn insert_into_frame(&mut self, key: K, ext: @V, n: K, pred: &fn(&@V)->bool) {
|
||||
match *self {
|
||||
BaseMapChain (~ref mut map) => {
|
||||
if satisfies_pred(map,&n,pred) {
|
||||
map.insert(key,ext);
|
||||
} else {
|
||||
fail!(~"expected map chain containing satisfying frame")
|
||||
}
|
||||
},
|
||||
ConsMapChain (~ref mut map, rest) => {
|
||||
if satisfies_pred(map,&n,pred) {
|
||||
map.insert(key,ext);
|
||||
} else {
|
||||
rest.insert_into_frame(key,ext,n,pred)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn satisfies_pred<K : Eq + Hash + IterBytes,V>(map : &mut HashMap<K,V>,
|
||||
n: &K,
|
||||
pred: &fn(&V)->bool)
|
||||
-> bool {
|
||||
match map.find(n) {
|
||||
Some(ref v) => (pred(*v)),
|
||||
None => false
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ use ext::base::*;
|
|||
use fold::*;
|
||||
use parse;
|
||||
use parse::{parse_item_from_source_str};
|
||||
use parse::token::{get_ident_interner,intern};
|
||||
|
||||
use core::vec;
|
||||
|
||||
|
|
@ -48,15 +49,14 @@ pub fn expand_expr(extsbox: @mut SyntaxEnv,
|
|||
fmt!("expected macro name without module \
|
||||
separators"));
|
||||
}
|
||||
/* using idents and token::special_idents would make the
|
||||
the macro names be hygienic */
|
||||
let extname = cx.parse_sess().interner.get(pth.idents[0]);
|
||||
let extname = pth.idents[0];
|
||||
let extnamestr = get_ident_interner().get(extname);
|
||||
// leaving explicit deref here to highlight unbox op:
|
||||
match (*extsbox).find(&extname) {
|
||||
match (*extsbox).find(&extname.repr) {
|
||||
None => {
|
||||
cx.span_fatal(
|
||||
pth.span,
|
||||
fmt!("macro undefined: '%s'", *extname))
|
||||
fmt!("macro undefined: '%s'", *extnamestr))
|
||||
}
|
||||
Some(@SE(NormalTT(SyntaxExpanderTT{
|
||||
expander: exp,
|
||||
|
|
@ -65,7 +65,7 @@ pub fn expand_expr(extsbox: @mut SyntaxEnv,
|
|||
cx.bt_push(ExpandedFrom(CallInfo {
|
||||
call_site: s,
|
||||
callee: NameAndSpan {
|
||||
name: copy *extname,
|
||||
name: copy *extnamestr,
|
||||
span: exp_sp,
|
||||
},
|
||||
}));
|
||||
|
|
@ -78,7 +78,7 @@ pub fn expand_expr(extsbox: @mut SyntaxEnv,
|
|||
pth.span,
|
||||
fmt!(
|
||||
"non-expr macro in expr pos: %s",
|
||||
*extname
|
||||
*extnamestr
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
@ -94,7 +94,7 @@ pub fn expand_expr(extsbox: @mut SyntaxEnv,
|
|||
_ => {
|
||||
cx.span_fatal(
|
||||
pth.span,
|
||||
fmt!("'%s' is not a tt-style macro", *extname)
|
||||
fmt!("'%s' is not a tt-style macro", *extnamestr)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -131,7 +131,7 @@ pub fn expand_mod_items(extsbox: @mut SyntaxEnv,
|
|||
do vec::foldr(item.attrs, ~[*item]) |attr, items| {
|
||||
let mname = attr::get_attr_name(attr);
|
||||
|
||||
match (*extsbox).find(&mname) {
|
||||
match (*extsbox).find(&intern(*mname)) {
|
||||
Some(@SE(ItemDecorator(dec_fn))) => {
|
||||
cx.bt_push(ExpandedFrom(CallInfo {
|
||||
call_site: attr.span,
|
||||
|
|
@ -155,16 +155,20 @@ pub fn expand_mod_items(extsbox: @mut SyntaxEnv,
|
|||
|
||||
// eval $e with a new exts frame:
|
||||
macro_rules! with_exts_frame (
|
||||
($extsboxexpr:expr,$e:expr) =>
|
||||
($extsboxexpr:expr,$macros_escape:expr,$e:expr) =>
|
||||
({let extsbox = $extsboxexpr;
|
||||
let oldexts = *extsbox;
|
||||
*extsbox = oldexts.push_frame();
|
||||
extsbox.insert(intern(special_block_name),
|
||||
@BlockInfo(BlockInfo{macros_escape:$macros_escape,pending_renames:@mut ~[]}));
|
||||
let result = $e;
|
||||
*extsbox = oldexts;
|
||||
result
|
||||
})
|
||||
)
|
||||
|
||||
static special_block_name : &'static str = " block";
|
||||
|
||||
// When we enter a module, record it, for the sake of `module!`
|
||||
pub fn expand_item(extsbox: @mut SyntaxEnv,
|
||||
cx: @ExtCtxt,
|
||||
|
|
@ -182,14 +186,8 @@ pub fn expand_item(extsbox: @mut SyntaxEnv,
|
|||
match it.node {
|
||||
ast::item_mod(_) | ast::item_foreign_mod(_) => {
|
||||
cx.mod_push(it.ident);
|
||||
let result =
|
||||
// don't push a macro scope for macro_escape:
|
||||
if contains_macro_escape(it.attrs) {
|
||||
orig(it,fld)
|
||||
} else {
|
||||
// otherwise, push a scope:
|
||||
with_exts_frame!(extsbox,orig(it,fld))
|
||||
};
|
||||
let macro_escape = contains_macro_escape(it.attrs);
|
||||
let result = with_exts_frame!(extsbox,macro_escape,orig(it,fld));
|
||||
cx.mod_pop();
|
||||
result
|
||||
}
|
||||
|
|
@ -205,31 +203,6 @@ pub fn contains_macro_escape (attrs: &[ast::attribute]) -> bool {
|
|||
attrs.any(|attr| "macro_escape" == *attr::get_attr_name(attr))
|
||||
}
|
||||
|
||||
// this macro disables (one layer of) macro
|
||||
// scoping, to allow a block to add macro bindings
|
||||
// to its parent env
|
||||
macro_rules! without_macro_scoping(
|
||||
($extsexpr:expr,$exp:expr) =>
|
||||
({
|
||||
// only evaluate this once:
|
||||
let exts = $extsexpr;
|
||||
// capture the existing binding:
|
||||
let existingBlockBinding =
|
||||
match exts.find(&@~" block"){
|
||||
Some(binding) => binding,
|
||||
None => cx.bug("expected to find \" block\" binding")
|
||||
};
|
||||
// this prevents the block from limiting the macros' scope:
|
||||
exts.insert(@~" block",@ScopeMacros(false));
|
||||
let result = $exp;
|
||||
// reset the block binding. Note that since the original
|
||||
// one may have been inherited, this procedure may wind
|
||||
// up introducing a block binding where one didn't exist
|
||||
// before.
|
||||
exts.insert(@~" block",existingBlockBinding);
|
||||
result
|
||||
}))
|
||||
|
||||
// Support for item-position macro invocations, exactly the same
|
||||
// logic as for expression-position macro invocations.
|
||||
pub fn expand_item_mac(extsbox: @mut SyntaxEnv,
|
||||
|
|
@ -243,22 +216,24 @@ pub fn expand_item_mac(extsbox: @mut SyntaxEnv,
|
|||
_ => cx.span_bug(it.span, "invalid item macro invocation")
|
||||
};
|
||||
|
||||
let extname = cx.parse_sess().interner.get(pth.idents[0]);
|
||||
let expanded = match (*extsbox).find(&extname) {
|
||||
let extname = pth.idents[0];
|
||||
let interner = get_ident_interner();
|
||||
let extnamestr = interner.get(extname);
|
||||
let expanded = match (*extsbox).find(&extname.repr) {
|
||||
None => cx.span_fatal(pth.span,
|
||||
fmt!("macro undefined: '%s!'", *extname)),
|
||||
fmt!("macro undefined: '%s!'", *extnamestr)),
|
||||
|
||||
Some(@SE(NormalTT(ref expand))) => {
|
||||
if it.ident != parse::token::special_idents::invalid {
|
||||
cx.span_fatal(pth.span,
|
||||
fmt!("macro %s! expects no ident argument, \
|
||||
given '%s'", *extname,
|
||||
*cx.parse_sess().interner.get(it.ident)));
|
||||
given '%s'", *extnamestr,
|
||||
*interner.get(it.ident)));
|
||||
}
|
||||
cx.bt_push(ExpandedFrom(CallInfo {
|
||||
call_site: it.span,
|
||||
callee: NameAndSpan {
|
||||
name: copy *extname,
|
||||
name: copy *extnamestr,
|
||||
span: expand.span
|
||||
}
|
||||
}));
|
||||
|
|
@ -268,29 +243,29 @@ pub fn expand_item_mac(extsbox: @mut SyntaxEnv,
|
|||
if it.ident == parse::token::special_idents::invalid {
|
||||
cx.span_fatal(pth.span,
|
||||
fmt!("macro %s! expects an ident argument",
|
||||
*extname));
|
||||
*extnamestr));
|
||||
}
|
||||
cx.bt_push(ExpandedFrom(CallInfo {
|
||||
call_site: it.span,
|
||||
callee: NameAndSpan {
|
||||
name: copy *extname,
|
||||
name: copy *extnamestr,
|
||||
span: expand.span
|
||||
}
|
||||
}));
|
||||
((*expand).expander)(cx, it.span, it.ident, tts)
|
||||
}
|
||||
_ => cx.span_fatal(
|
||||
it.span, fmt!("%s! is not legal in item position", *extname))
|
||||
it.span, fmt!("%s! is not legal in item position", *extnamestr))
|
||||
};
|
||||
|
||||
let maybe_it = match expanded {
|
||||
MRItem(it) => fld.fold_item(it),
|
||||
MRExpr(_) => cx.span_fatal(pth.span,
|
||||
~"expr macro in item position: "
|
||||
+ *extname),
|
||||
+ *extnamestr),
|
||||
MRAny(_, item_maker, _) => item_maker().chain(|i| {fld.fold_item(i)}),
|
||||
MRDef(ref mdef) => {
|
||||
extsbox.insert(@/*bad*/ copy mdef.name, @SE((*mdef).ext));
|
||||
insert_macro(*extsbox,intern(mdef.name), @SE((*mdef).ext));
|
||||
None
|
||||
}
|
||||
};
|
||||
|
|
@ -298,6 +273,23 @@ pub fn expand_item_mac(extsbox: @mut SyntaxEnv,
|
|||
return maybe_it;
|
||||
}
|
||||
|
||||
|
||||
// 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)
|
||||
}
|
||||
};
|
||||
exts.insert_into_frame(name,transformer,intern(special_block_name),
|
||||
is_non_escaping_block)
|
||||
}
|
||||
|
||||
// expand a stmt
|
||||
pub fn expand_stmt(extsbox: @mut SyntaxEnv,
|
||||
cx: @ExtCtxt,
|
||||
|
|
@ -323,16 +315,17 @@ pub fn expand_stmt(extsbox: @mut SyntaxEnv,
|
|||
fmt!("expected macro name without module \
|
||||
separators"));
|
||||
}
|
||||
let extname = cx.parse_sess().interner.get(pth.idents[0]);
|
||||
let (fully_expanded, sp) = match (*extsbox).find(&extname) {
|
||||
let extname = pth.idents[0];
|
||||
let extnamestr = get_ident_interner().get(extname);
|
||||
let (fully_expanded, sp) = match (*extsbox).find(&extname.repr) {
|
||||
None =>
|
||||
cx.span_fatal(pth.span, fmt!("macro undefined: '%s'", *extname)),
|
||||
cx.span_fatal(pth.span, fmt!("macro undefined: '%s'", *extnamestr)),
|
||||
|
||||
Some(@SE(NormalTT(
|
||||
SyntaxExpanderTT{expander: exp, span: exp_sp}))) => {
|
||||
cx.bt_push(ExpandedFrom(CallInfo {
|
||||
call_site: sp,
|
||||
callee: NameAndSpan { name: copy *extname, span: exp_sp }
|
||||
callee: NameAndSpan { name: copy *extnamestr, span: exp_sp }
|
||||
}));
|
||||
let expanded = match exp(cx, mac.span, tts) {
|
||||
MRExpr(e) =>
|
||||
|
|
@ -341,7 +334,7 @@ pub fn expand_stmt(extsbox: @mut SyntaxEnv,
|
|||
MRAny(_,_,stmt_mkr) => stmt_mkr(),
|
||||
_ => cx.span_fatal(
|
||||
pth.span,
|
||||
fmt!("non-stmt macro in stmt pos: %s", *extname))
|
||||
fmt!("non-stmt macro in stmt pos: %s", *extnamestr))
|
||||
};
|
||||
|
||||
//keep going, outside-in
|
||||
|
|
@ -362,7 +355,7 @@ pub fn expand_stmt(extsbox: @mut SyntaxEnv,
|
|||
|
||||
_ => {
|
||||
cx.span_fatal(pth.span,
|
||||
fmt!("'%s' is not a tt-style macro", *extname))
|
||||
fmt!("'%s' is not a tt-style macro", *extnamestr))
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -382,19 +375,8 @@ pub fn expand_block(extsbox: @mut SyntaxEnv,
|
|||
fld: @ast_fold,
|
||||
orig: @fn(&blk_, span, @ast_fold) -> (blk_, span))
|
||||
-> (blk_, span) {
|
||||
match (*extsbox).find(&@~" block") {
|
||||
// no scope limit on macros in this block, no need
|
||||
// to push an exts frame:
|
||||
Some(@ScopeMacros(false)) => {
|
||||
orig (blk,sp,fld)
|
||||
},
|
||||
// this block should limit the scope of its macros:
|
||||
Some(@ScopeMacros(true)) => {
|
||||
// see note below about treatment of exts table
|
||||
with_exts_frame!(extsbox,orig(blk,sp,fld))
|
||||
},
|
||||
_ => cx.span_bug(sp, "expected ScopeMacros binding for \" block\"")
|
||||
}
|
||||
// see note below about treatment of exts table
|
||||
with_exts_frame!(extsbox,false,orig(blk,sp,fld))
|
||||
}
|
||||
|
||||
// given a mutable list of renames, return a tree-folder that applies those
|
||||
|
|
|
|||
|
|
@ -351,6 +351,7 @@ mod test {
|
|||
use codemap::{span, BytePos, spanned};
|
||||
use opt_vec;
|
||||
use ast;
|
||||
use ast_util::new_ident;
|
||||
use abi;
|
||||
use parse::parser::Parser;
|
||||
use parse::token::intern;
|
||||
|
|
@ -377,9 +378,14 @@ 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(*u))
|
||||
ids.map(|u| intern_ident(*u))
|
||||
}
|
||||
|
||||
#[test] fn path_exprs_1 () {
|
||||
|
|
@ -387,7 +393,7 @@ mod test {
|
|||
@ast::expr{id:1,
|
||||
node:ast::expr_path(@ast::Path {span:sp(0,1),
|
||||
global:false,
|
||||
idents:~[intern("a")],
|
||||
idents:~[intern_ident("a")],
|
||||
rp:None,
|
||||
types:~[]}),
|
||||
span:sp(0,1)})
|
||||
|
|
@ -449,7 +455,7 @@ mod test {
|
|||
node:ast::expr_path(
|
||||
@ast::Path{span:sp(7,8),
|
||||
global:false,
|
||||
idents:~[intern("d")],
|
||||
idents:~[intern_ident("d")],
|
||||
rp:None,
|
||||
types:~[]
|
||||
}),
|
||||
|
|
@ -466,7 +472,7 @@ mod test {
|
|||
@ast::Path{
|
||||
span:sp(0,1),
|
||||
global:false,
|
||||
idents:~[intern("b")],
|
||||
idents:~[intern_ident("b")],
|
||||
rp:None,
|
||||
types: ~[]}),
|
||||
span: sp(0,1)},
|
||||
|
|
@ -487,7 +493,7 @@ mod test {
|
|||
@ast::Path{
|
||||
span:sp(0,1),
|
||||
global:false,
|
||||
idents:~[intern("b")],
|
||||
idents:~[intern_ident("b")],
|
||||
rp: None,
|
||||
types: ~[]},
|
||||
None // no idea
|
||||
|
|
@ -506,7 +512,7 @@ mod test {
|
|||
span:sp(4,4), // this is bizarre...
|
||||
// check this in the original parser?
|
||||
global:false,
|
||||
idents:~[intern("int")],
|
||||
idents:~[intern_ident("int")],
|
||||
rp: None,
|
||||
types: ~[]},
|
||||
2),
|
||||
|
|
@ -516,7 +522,7 @@ mod test {
|
|||
@ast::Path{
|
||||
span:sp(0,1),
|
||||
global:false,
|
||||
idents:~[intern("b")],
|
||||
idents:~[intern_ident("b")],
|
||||
rp: None,
|
||||
types: ~[]},
|
||||
None // no idea
|
||||
|
|
@ -532,7 +538,7 @@ mod test {
|
|||
// assignment order of the node_ids.
|
||||
assert_eq!(string_to_item(@~"fn a (b : int) { b; }"),
|
||||
Some(
|
||||
@ast::item{ident:intern("a"),
|
||||
@ast::item{ident:intern_ident("a"),
|
||||
attrs:~[],
|
||||
id: 9, // fixme
|
||||
node: ast::item_fn(ast::fn_decl{
|
||||
|
|
@ -542,7 +548,7 @@ mod test {
|
|||
node: ast::ty_path(@ast::Path{
|
||||
span:sp(10,13),
|
||||
global:false,
|
||||
idents:~[intern("int")],
|
||||
idents:~[intern_ident("int")],
|
||||
rp: None,
|
||||
types: ~[]},
|
||||
2),
|
||||
|
|
@ -553,7 +559,7 @@ mod test {
|
|||
@ast::Path{
|
||||
span:sp(6,7),
|
||||
global:false,
|
||||
idents:~[intern("b")],
|
||||
idents:~[intern_ident("b")],
|
||||
rp: None,
|
||||
types: ~[]},
|
||||
None // no idea
|
||||
|
|
@ -583,7 +589,7 @@ mod test {
|
|||
@ast::Path{
|
||||
span:sp(17,18),
|
||||
global:false,
|
||||
idents:~[intern("b")],
|
||||
idents:~[intern_ident("b")],
|
||||
rp:None,
|
||||
types: ~[]}),
|
||||
span: sp(17,18)},
|
||||
|
|
|
|||
|
|
@ -2628,6 +2628,13 @@ impl Parser {
|
|||
// to the macro clause of parse_item_or_view_item. This
|
||||
// could use some cleanup, it appears to me.
|
||||
|
||||
// whoops! I now have a guess: I'm guessing the "parens-only"
|
||||
// rule here is deliberate, to allow macro users to use parens
|
||||
// for things that should be parsed as stmt_mac, and braces
|
||||
// for things that should expand into items. Tricky, and
|
||||
// somewhat awkward... and probably undocumented. Of course,
|
||||
// I could just be wrong.
|
||||
|
||||
check_expected_item(self, item_attrs);
|
||||
|
||||
// Potential trouble: if we allow macros with paths instead of
|
||||
|
|
|
|||
|
|
@ -394,6 +394,8 @@ pub struct ident_interner {
|
|||
}
|
||||
|
||||
impl ident_interner {
|
||||
// I'm torn as to whether these should produce idents or
|
||||
// just uints.
|
||||
pub fn intern(&self, val: &str) -> ast::ident {
|
||||
ast::ident { repr: self.interner.intern(val), ctxt: 0 }
|
||||
}
|
||||
|
|
@ -530,9 +532,9 @@ pub fn mk_fake_ident_interner() -> @ident_interner {
|
|||
}
|
||||
|
||||
// maps a string to its interned representation
|
||||
pub fn intern(str : &str) -> ast::ident {
|
||||
pub fn intern(str : &str) -> uint {
|
||||
let interner = get_ident_interner();
|
||||
interner.intern(str)
|
||||
interner.intern(str).repr
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue