Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit b9c39c6

Browse files
committedJan 3, 2014
auto merge of #11228 : sfackler/rust/syntaxenv, r=pcwalton
I'd really like to be able to do something like ```rust struct MapChain<'next, K, V> { info: BlockInfo, map: HashMap<K, V>, next: Option<&'next mut MapChain<'next, K, V> } ``` but I can't get the lifetimes to work out.
2 parents bfde029 + b74613b commit b9c39c6

File tree

2 files changed

+129
-247
lines changed

2 files changed

+129
-247
lines changed
 

‎src/libsyntax/ext/base.rs

Lines changed: 88 additions & 178 deletions
Original file line numberDiff line numberDiff line change
@@ -155,57 +155,48 @@ pub enum SyntaxExtension {
155155
// The SyntaxEnv is the environment that's threaded through the expansion
156156
// of macros. It contains bindings for macros, and also a special binding
157157
// for " block" (not a legal identifier) that maps to a BlockInfo
158-
pub type SyntaxEnv = @mut MapChain<Name, Transformer>;
159-
160-
// Transformer : the codomain of SyntaxEnvs
161-
162-
pub enum Transformer {
163-
// this identifier maps to a syntax extension or macro
164-
SE(SyntaxExtension),
165-
// blockinfo : this is ... well, it's simpler than threading
166-
// another whole data stack-structured data structure through
167-
// expansion. Basically, there's an invariant that every
168-
// map must contain a binding for " block".
169-
BlockInfo(BlockInfo)
170-
}
158+
pub type SyntaxEnv = MapChain<Name, SyntaxExtension>;
171159

172160
pub struct BlockInfo {
173161
// should macros escape from this scope?
174162
macros_escape : bool,
175163
// what are the pending renames?
176-
pending_renames : @mut RenameList
164+
pending_renames : RenameList
165+
}
166+
167+
impl BlockInfo {
168+
pub fn new() -> BlockInfo {
169+
BlockInfo {
170+
macros_escape: false,
171+
pending_renames: ~[]
172+
}
173+
}
177174
}
178175

179176
// a list of ident->name renamings
180-
type RenameList = ~[(ast::Ident,Name)];
177+
pub type RenameList = ~[(ast::Ident,Name)];
181178

182179
// The base map of methods for expanding syntax extension
183180
// AST nodes into full ASTs
184181
pub fn syntax_expander_table() -> SyntaxEnv {
185182
// utility function to simplify creating NormalTT syntax extensions
186183
fn builtin_normal_tt_no_ctxt(f: SyntaxExpanderTTFunNoCtxt)
187-
-> @Transformer {
188-
@SE(NormalTT(@SyntaxExpanderTT{
184+
-> SyntaxExtension {
185+
NormalTT(@SyntaxExpanderTT{
189186
expander: SyntaxExpanderTTExpanderWithoutContext(f),
190187
span: None,
191188
} as @SyntaxExpanderTTTrait,
192-
None))
189+
None)
193190
}
194191

195-
let mut syntax_expanders = HashMap::new();
196-
// NB identifier starts with space, and can't conflict with legal idents
197-
syntax_expanders.insert(intern(&" block"),
198-
@BlockInfo(BlockInfo{
199-
macros_escape : false,
200-
pending_renames : @mut ~[]
201-
}));
192+
let mut syntax_expanders = MapChain::new();
202193
syntax_expanders.insert(intern(&"macro_rules"),
203-
@SE(IdentTT(@SyntaxExpanderTTItem {
194+
IdentTT(@SyntaxExpanderTTItem {
204195
expander: SyntaxExpanderTTItemExpanderWithContext(
205196
ext::tt::macro_rules::add_new_extension),
206197
span: None,
207198
} as @SyntaxExpanderTTItemTrait,
208-
None)));
199+
None));
209200
syntax_expanders.insert(intern(&"fmt"),
210201
builtin_normal_tt_no_ctxt(
211202
ext::fmt::expand_syntax_ext));
@@ -231,8 +222,7 @@ pub fn syntax_expander_table() -> SyntaxEnv {
231222
builtin_normal_tt_no_ctxt(
232223
ext::log_syntax::expand_syntax_ext));
233224
syntax_expanders.insert(intern(&"deriving"),
234-
@SE(ItemDecorator(
235-
ext::deriving::expand_meta_deriving)));
225+
ItemDecorator(ext::deriving::expand_meta_deriving));
236226

237227
// Quasi-quoting expanders
238228
syntax_expanders.insert(intern(&"quote_tokens"),
@@ -287,7 +277,7 @@ pub fn syntax_expander_table() -> SyntaxEnv {
287277
syntax_expanders.insert(intern(&"trace_macros"),
288278
builtin_normal_tt_no_ctxt(
289279
ext::trace_macros::expand_trace_macros));
290-
MapChain::new(~syntax_expanders)
280+
syntax_expanders
291281
}
292282

293283
// One of these is made during expansion and incrementally updated as we go;
@@ -298,11 +288,6 @@ pub struct ExtCtxt {
298288
cfg: ast::CrateConfig,
299289
backtrace: Option<@ExpnInfo>,
300290

301-
// These two @mut's should really not be here,
302-
// but the self types for CtxtRepr are all wrong
303-
// and there are bugs in the code for object
304-
// types that make this hard to get right at the
305-
// moment. - nmatsakis
306291
mod_path: ~[ast::Ident],
307292
trace_mac: bool
308293
}
@@ -324,7 +309,7 @@ impl ExtCtxt {
324309
match e.node {
325310
ast::ExprMac(..) => {
326311
let mut expander = expand::MacroExpander {
327-
extsbox: @mut syntax_expander_table(),
312+
extsbox: syntax_expander_table(),
328313
cx: self,
329314
};
330315
e = expand::expand_expr(e, &mut expander);
@@ -459,11 +444,7 @@ pub fn get_exprs_from_tts(cx: &ExtCtxt,
459444
// we want to implement the notion of a transformation
460445
// environment.
461446

462-
// This environment maps Names to Transformers.
463-
// Initially, this includes macro definitions and
464-
// block directives.
465-
466-
447+
// This environment maps Names to SyntaxExtensions.
467448

468449
// Actually, the following implementation is parameterized
469450
// by both key and value types.
@@ -478,169 +459,98 @@ pub fn get_exprs_from_tts(cx: &ExtCtxt,
478459
// able to refer to a macro that was added to an enclosing
479460
// scope lexically later than the deeper scope.
480461

481-
// Note on choice of representation: I've been pushed to
482-
// use a top-level managed pointer by some difficulties
483-
// with pushing and popping functionally, and the ownership
484-
// issues. As a result, the values returned by the table
485-
// also need to be managed; the &'a ... type that Maps
486-
// return won't work for things that need to get outside
487-
// of that managed pointer. The easiest way to do this
488-
// is just to insist that the values in the tables are
489-
// managed to begin with.
490-
491-
// a transformer env is either a base map or a map on top
492-
// of another chain.
493-
pub enum MapChain<K,V> {
494-
BaseMapChain(~HashMap<K,@V>),
495-
ConsMapChain(~HashMap<K,@V>,@mut MapChain<K,V>)
462+
// Only generic to make it easy to test
463+
struct MapChainFrame<K, V> {
464+
info: BlockInfo,
465+
map: HashMap<K, V>,
496466
}
497467

468+
// Only generic to make it easy to test
469+
pub struct MapChain<K, V> {
470+
priv chain: ~[MapChainFrame<K, V>],
471+
}
498472

499-
// get the map from an env frame
500-
impl <K: Eq + Hash + IterBytes + 'static, V: 'static> MapChain<K,V>{
501-
// Constructor. I don't think we need a zero-arg one.
502-
pub fn new(init: ~HashMap<K,@V>) -> @mut MapChain<K,V> {
503-
@mut BaseMapChain(init)
473+
impl<K: Hash+Eq, V> MapChain<K, V> {
474+
pub fn new() -> MapChain<K, V> {
475+
let mut map = MapChain { chain: ~[] };
476+
map.push_frame();
477+
map
504478
}
505479

506-
// add a new frame to the environment (functionally)
507-
pub fn push_frame (@mut self) -> @mut MapChain<K,V> {
508-
@mut ConsMapChain(~HashMap::new() ,self)
480+
pub fn push_frame(&mut self) {
481+
self.chain.push(MapChainFrame {
482+
info: BlockInfo::new(),
483+
map: HashMap::new(),
484+
});
509485
}
510486

511-
// no need for pop, it'll just be functional.
512-
513-
// utility fn...
514-
515-
// ugh: can't get this to compile with mut because of the
516-
// lack of flow sensitivity.
517-
pub fn get_map<'a>(&'a self) -> &'a HashMap<K,@V> {
518-
match *self {
519-
BaseMapChain (~ref map) => map,
520-
ConsMapChain (~ref map,_) => map
521-
}
487+
pub fn pop_frame(&mut self) {
488+
assert!(self.chain.len() > 1, "too many pops on MapChain!");
489+
self.chain.pop();
522490
}
523491

524-
// traits just don't work anywhere...?
525-
//impl Map<Name,SyntaxExtension> for MapChain {
526-
527-
pub fn contains_key (&self, key: &K) -> bool {
528-
match *self {
529-
BaseMapChain (ref map) => map.contains_key(key),
530-
ConsMapChain (ref map,ref rest) =>
531-
(map.contains_key(key)
532-
|| rest.contains_key(key))
492+
fn find_escape_frame<'a>(&'a mut self) -> &'a mut MapChainFrame<K, V> {
493+
for (i, frame) in self.chain.mut_iter().enumerate().invert() {
494+
if !frame.info.macros_escape || i == 0 {
495+
return frame
496+
}
533497
}
534-
}
535-
// should each_key and each_value operate on shadowed
536-
// names? I think not.
537-
// delaying implementing this....
538-
pub fn each_key (&self, _f: |&K| -> bool) {
539-
fail!("unimplemented 2013-02-15T10:01");
540-
}
541-
542-
pub fn each_value (&self, _f: |&V| -> bool) {
543-
fail!("unimplemented 2013-02-15T10:02");
498+
unreachable!()
544499
}
545500

546-
// Returns a copy of the value that the name maps to.
547-
// Goes down the chain 'til it finds one (or bottom out).
548-
pub fn find (&self, key: &K) -> Option<@V> {
549-
match self.get_map().find (key) {
550-
Some(ref v) => Some(**v),
551-
None => match *self {
552-
BaseMapChain (_) => None,
553-
ConsMapChain (_,ref rest) => rest.find(key)
501+
pub fn find<'a>(&'a self, k: &K) -> Option<&'a V> {
502+
for frame in self.chain.iter().invert() {
503+
match frame.map.find(k) {
504+
Some(v) => return Some(v),
505+
None => {}
554506
}
555507
}
508+
None
556509
}
557510

558-
pub fn find_in_topmost_frame(&self, key: &K) -> Option<@V> {
559-
let map = match *self {
560-
BaseMapChain(ref map) => map,
561-
ConsMapChain(ref map,_) => map
562-
};
563-
// strip one layer of indirection off the pointer.
564-
map.find(key).map(|r| {*r})
565-
}
566-
567-
// insert the binding into the top-level map
568-
pub fn insert (&mut self, key: K, ext: @V) -> bool {
569-
// can't abstract over get_map because of flow sensitivity...
570-
match *self {
571-
BaseMapChain (~ref mut map) => map.insert(key, ext),
572-
ConsMapChain (~ref mut map,_) => map.insert(key,ext)
573-
}
511+
pub fn insert(&mut self, k: K, v: V) {
512+
self.find_escape_frame().map.insert(k, v);
574513
}
575-
// insert the binding into the topmost frame for which the binding
576-
// associated with 'n' exists and satisfies pred
577-
// ... there are definitely some opportunities for abstraction
578-
// here that I'm ignoring. (e.g., manufacturing a predicate on
579-
// the maps in the chain, and using an abstract "find".
580-
pub fn insert_into_frame(&mut self,
581-
key: K,
582-
ext: @V,
583-
n: K,
584-
pred: |&@V| -> bool) {
585-
match *self {
586-
BaseMapChain (~ref mut map) => {
587-
if satisfies_pred(map,&n,pred) {
588-
map.insert(key,ext);
589-
} else {
590-
fail!("expected map chain containing satisfying frame")
591-
}
592-
},
593-
ConsMapChain (~ref mut map, rest) => {
594-
if satisfies_pred(map,&n,|v|pred(v)) {
595-
map.insert(key,ext);
596-
} else {
597-
rest.insert_into_frame(key,ext,n,pred)
598-
}
599-
}
600-
}
601-
}
602-
}
603514

604-
// returns true if the binding for 'n' satisfies 'pred' in 'map'
605-
fn satisfies_pred<K:Eq + Hash + IterBytes,
606-
V>(
607-
map: &mut HashMap<K,V>,
608-
n: &K,
609-
pred: |&V| -> bool)
610-
-> bool {
611-
match map.find(n) {
612-
Some(ref v) => (pred(*v)),
613-
None => false
515+
pub fn info<'a>(&'a mut self) -> &'a mut BlockInfo {
516+
&mut self.chain[self.chain.len()-1].info
614517
}
615518
}
616519

617520
#[cfg(test)]
618521
mod test {
619522
use super::MapChain;
620-
use std::hashmap::HashMap;
621523

622524
#[test]
623525
fn testenv() {
624-
let mut a = HashMap::new();
625-
a.insert (@"abc",@15);
626-
let m = MapChain::new(~a);
627-
m.insert (@"def",@16);
628-
assert_eq!(m.find(&@"abc"),Some(@15));
629-
assert_eq!(m.find(&@"def"),Some(@16));
630-
assert_eq!(*(m.find(&@"abc").unwrap()),15);
631-
assert_eq!(*(m.find(&@"def").unwrap()),16);
632-
let n = m.push_frame();
633-
// old bindings are still present:
634-
assert_eq!(*(n.find(&@"abc").unwrap()),15);
635-
assert_eq!(*(n.find(&@"def").unwrap()),16);
636-
n.insert (@"def",@17);
637-
// n shows the new binding
638-
assert_eq!(*(n.find(&@"abc").unwrap()),15);
639-
assert_eq!(*(n.find(&@"def").unwrap()),17);
640-
// ... but m still has the old ones
641-
assert_eq!(m.find(&@"abc"),Some(@15));
642-
assert_eq!(m.find(&@"def"),Some(@16));
643-
assert_eq!(*(m.find(&@"abc").unwrap()),15);
644-
assert_eq!(*(m.find(&@"def").unwrap()),16);
526+
let mut m = MapChain::new();
527+
let (a,b,c,d) = ("a", "b", "c", "d");
528+
m.insert(1, a);
529+
assert_eq!(Some(&a), m.find(&1));
530+
531+
m.push_frame();
532+
m.info().macros_escape = true;
533+
m.insert(2, b);
534+
assert_eq!(Some(&a), m.find(&1));
535+
assert_eq!(Some(&b), m.find(&2));
536+
m.pop_frame();
537+
538+
assert_eq!(Some(&a), m.find(&1));
539+
assert_eq!(Some(&b), m.find(&2));
540+
541+
m.push_frame();
542+
m.push_frame();
543+
m.info().macros_escape = true;
544+
m.insert(3, c);
545+
assert_eq!(Some(&c), m.find(&3));
546+
m.pop_frame();
547+
assert_eq!(Some(&c), m.find(&3));
548+
m.pop_frame();
549+
assert_eq!(None, m.find(&3));
550+
551+
m.push_frame();
552+
m.insert(4, d);
553+
m.pop_frame();
554+
assert_eq!(None, m.find(&4));
645555
}
646556
}

‎src/libsyntax/ext/expand.rs

Lines changed: 41 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,13 @@ pub fn expand_expr(e: @ast::Expr, fld: &mut MacroExpander) -> @ast::Expr {
5353
let extname = &pth.segments[0].identifier;
5454
let extnamestr = ident_to_str(extname);
5555
// leaving explicit deref here to highlight unbox op:
56-
match (*fld.extsbox).find(&extname.name) {
56+
match fld.extsbox.find(&extname.name) {
5757
None => {
5858
fld.cx.span_fatal(
5959
pth.span,
6060
format!("macro undefined: '{}'", extnamestr))
6161
}
62-
Some(@SE(NormalTT(expandfun, exp_span))) => {
62+
Some(&NormalTT(expandfun, exp_span)) => {
6363
fld.cx.bt_push(ExpnInfo {
6464
call_site: e.span,
6565
callee: NameAndSpan {
@@ -221,8 +221,8 @@ pub fn expand_mod_items(module_: &ast::_mod, fld: &mut MacroExpander) -> ast::_m
221221
item.attrs.rev_iter().fold(~[*item], |items, attr| {
222222
let mname = attr.name();
223223

224-
match (*fld.extsbox).find(&intern(mname)) {
225-
Some(@SE(ItemDecorator(dec_fn))) => {
224+
match fld.extsbox.find(&intern(mname)) {
225+
Some(&ItemDecorator(dec_fn)) => {
226226
fld.cx.bt_push(ExpnInfo {
227227
call_site: attr.span,
228228
callee: NameAndSpan {
@@ -249,19 +249,14 @@ pub fn expand_mod_items(module_: &ast::_mod, fld: &mut MacroExpander) -> ast::_m
249249
// eval $e with a new exts frame:
250250
macro_rules! with_exts_frame (
251251
($extsboxexpr:expr,$macros_escape:expr,$e:expr) =>
252-
({let extsbox = $extsboxexpr;
253-
let oldexts = *extsbox;
254-
*extsbox = oldexts.push_frame();
255-
extsbox.insert(intern(special_block_name),
256-
@BlockInfo(BlockInfo{macros_escape:$macros_escape,pending_renames:@mut ~[]}));
252+
({$extsboxexpr.push_frame();
253+
$extsboxexpr.info().macros_escape = $macros_escape;
257254
let result = $e;
258-
*extsbox = oldexts;
255+
$extsboxexpr.pop_frame();
259256
result
260257
})
261258
)
262259

263-
static special_block_name : &'static str = " block";
264-
265260
// When we enter a module, record it, for the sake of `module!`
266261
pub fn expand_item(it: @ast::item, fld: &mut MacroExpander)
267262
-> SmallVector<@ast::item> {
@@ -302,11 +297,11 @@ pub fn expand_item_mac(it: @ast::item, fld: &mut MacroExpander)
302297
let extname = &pth.segments[0].identifier;
303298
let extnamestr = ident_to_str(extname);
304299
let fm = fresh_mark();
305-
let expanded = match (*fld.extsbox).find(&extname.name) {
300+
let expanded = match fld.extsbox.find(&extname.name) {
306301
None => fld.cx.span_fatal(pth.span,
307302
format!("macro undefined: '{}!'", extnamestr)),
308303

309-
Some(@SE(NormalTT(expander, span))) => {
304+
Some(&NormalTT(expander, span)) => {
310305
if it.ident.name != parse::token::special_idents::invalid.name {
311306
fld.cx.span_fatal(pth.span,
312307
format!("macro {}! expects no ident argument, \
@@ -326,7 +321,7 @@ pub fn expand_item_mac(it: @ast::item, fld: &mut MacroExpander)
326321
let marked_ctxt = new_mark(fm,ctxt);
327322
expander.expand(fld.cx, it.span, marked_before, marked_ctxt)
328323
}
329-
Some(@SE(IdentTT(expander, span))) => {
324+
Some(&IdentTT(expander, span)) => {
330325
if it.ident.name == parse::token::special_idents::invalid.name {
331326
fld.cx.span_fatal(pth.span,
332327
format!("macro {}! expects an ident argument",
@@ -369,31 +364,14 @@ pub fn expand_item_mac(it: @ast::item, fld: &mut MacroExpander)
369364
MRDef(ref mdef) => {
370365
// yikes... no idea how to apply the mark to this. I'm afraid
371366
// we're going to have to wait-and-see on this one.
372-
insert_macro(*fld.extsbox,intern(mdef.name), @SE((*mdef).ext));
367+
fld.extsbox.insert(intern(mdef.name), (*mdef).ext);
373368
SmallVector::zero()
374369
}
375370
};
376371
fld.cx.bt_pop();
377372
return items;
378373
}
379374

380-
381-
// insert a macro into the innermost frame that doesn't have the
382-
// macro_escape tag.
383-
fn insert_macro(exts: SyntaxEnv, name: ast::Name, transformer: @Transformer) {
384-
let is_non_escaping_block =
385-
|t : &@Transformer| -> bool{
386-
match t {
387-
&@BlockInfo(BlockInfo {macros_escape:false,..}) => true,
388-
&@BlockInfo(BlockInfo {..}) => false,
389-
_ => fail!("special identifier {:?} was bound to a non-BlockInfo",
390-
special_block_name)
391-
}
392-
};
393-
exts.insert_into_frame(name,transformer,intern(special_block_name),
394-
is_non_escaping_block)
395-
}
396-
397375
// expand a stmt
398376
pub fn expand_stmt(s: &Stmt, fld: &mut MacroExpander) -> SmallVector<@Stmt> {
399377
// why the copying here and not in expand_expr?
@@ -414,12 +392,12 @@ pub fn expand_stmt(s: &Stmt, fld: &mut MacroExpander) -> SmallVector<@Stmt> {
414392
}
415393
let extname = &pth.segments[0].identifier;
416394
let extnamestr = ident_to_str(extname);
417-
let fully_expanded: SmallVector<@Stmt> = match (*fld.extsbox).find(&extname.name) {
395+
let fully_expanded: SmallVector<@Stmt> = match fld.extsbox.find(&extname.name) {
418396
None => {
419397
fld.cx.span_fatal(pth.span, format!("macro undefined: '{}'", extnamestr))
420398
}
421399

422-
Some(@SE(NormalTT(expandfun, exp_span))) => {
400+
Some(&NormalTT(expandfun, exp_span)) => {
423401
fld.cx.bt_push(ExpnInfo {
424402
call_site: s.span,
425403
callee: NameAndSpan {
@@ -497,8 +475,6 @@ fn expand_non_macro_stmt(s: &Stmt, fld: &mut MacroExpander)
497475
span: stmt_span
498476
},
499477
node_id) => {
500-
let block_info = get_block_info(*fld.extsbox);
501-
let pending_renames = block_info.pending_renames;
502478

503479
// take it apart:
504480
let @Local {
@@ -522,12 +498,16 @@ fn expand_non_macro_stmt(s: &Stmt, fld: &mut MacroExpander)
522498
let new_name = fresh_name(ident);
523499
new_pending_renames.push((*ident,new_name));
524500
}
525-
let mut rename_fld = renames_to_fold(new_pending_renames);
526-
// rewrite the pattern using the new names (the old ones
527-
// have already been applied):
528-
let rewritten_pat = rename_fld.fold_pat(expanded_pat);
501+
let rewritten_pat = {
502+
let mut rename_fld = renames_to_fold(new_pending_renames);
503+
// rewrite the pattern using the new names (the old ones
504+
// have already been applied):
505+
rename_fld.fold_pat(expanded_pat)
506+
};
529507
// add them to the existing pending renames:
530-
for pr in new_pending_renames.iter() {pending_renames.push(*pr)}
508+
for pr in new_pending_renames.iter() {
509+
fld.extsbox.info().pending_renames.push(*pr)
510+
}
531511
// also, don't forget to expand the init:
532512
let new_init_opt = init.map(|e| fld.fold_expr(e));
533513
let rewritten_local =
@@ -618,16 +598,23 @@ pub fn expand_block(blk: &Block, fld: &mut MacroExpander) -> P<Block> {
618598

619599
// expand the elements of a block.
620600
pub fn expand_block_elts(b: &Block, fld: &mut MacroExpander) -> P<Block> {
621-
let block_info = get_block_info(*fld.extsbox);
622-
let pending_renames = block_info.pending_renames;
623-
let mut rename_fld = renames_to_fold(pending_renames);
624601
let new_view_items = b.view_items.map(|x| fld.fold_view_item(x));
625602
let new_stmts = b.stmts.iter()
626-
.map(|x| rename_fld.fold_stmt(*x)
627-
.expect_one("rename_fold didn't return one value"))
603+
.map(|x| {
604+
let pending_renames = &mut fld.extsbox.info().pending_renames;
605+
let mut rename_fld = renames_to_fold(pending_renames);
606+
rename_fld.fold_stmt(*x).expect_one("rename_fold didn't return one value")
607+
})
628608
.flat_map(|x| fld.fold_stmt(x).move_iter())
629609
.collect();
630-
let new_expr = b.expr.map(|x| fld.fold_expr(rename_fld.fold_expr(x)));
610+
let new_expr = b.expr.map(|x| {
611+
let expr = {
612+
let pending_renames = &mut fld.extsbox.info().pending_renames;
613+
let mut rename_fld = renames_to_fold(pending_renames);
614+
rename_fld.fold_expr(x)
615+
};
616+
fld.fold_expr(expr)
617+
});
631618
P(Block {
632619
view_items: new_view_items,
633620
stmts: new_stmts,
@@ -638,20 +625,11 @@ pub fn expand_block_elts(b: &Block, fld: &mut MacroExpander) -> P<Block> {
638625
})
639626
}
640627

641-
// get the (innermost) BlockInfo from an exts stack
642-
fn get_block_info(exts : SyntaxEnv) -> BlockInfo {
643-
match exts.find_in_topmost_frame(&intern(special_block_name)) {
644-
Some(@BlockInfo(bi)) => bi,
645-
_ => fail!("special identifier {:?} was bound to a non-BlockInfo",
646-
@" block")
647-
}
648-
}
649-
650-
struct IdentRenamer {
651-
renames: @mut ~[(ast::Ident,ast::Name)],
628+
struct IdentRenamer<'a> {
629+
renames: &'a mut RenameList,
652630
}
653631

654-
impl ast_fold for IdentRenamer {
632+
impl<'a> ast_fold for IdentRenamer<'a> {
655633
fn fold_ident(&mut self, id: ast::Ident) -> ast::Ident {
656634
let new_ctxt = self.renames.iter().fold(id.ctxt, |ctxt, &(from, to)| {
657635
new_rename(from, to, ctxt)
@@ -665,7 +643,7 @@ impl ast_fold for IdentRenamer {
665643

666644
// given a mutable list of renames, return a tree-folder that applies those
667645
// renames.
668-
pub fn renames_to_fold(renames: @mut ~[(ast::Ident,ast::Name)]) -> IdentRenamer {
646+
pub fn renames_to_fold<'a>(renames: &'a mut RenameList) -> IdentRenamer<'a> {
669647
IdentRenamer {
670648
renames: renames,
671649
}
@@ -931,7 +909,7 @@ pub fn inject_std_macros(parse_sess: @mut parse::ParseSess,
931909
}
932910

933911
pub struct MacroExpander<'a> {
934-
extsbox: @mut SyntaxEnv,
912+
extsbox: SyntaxEnv,
935913
cx: &'a mut ExtCtxt,
936914
}
937915

@@ -964,15 +942,9 @@ impl<'a> ast_fold for MacroExpander<'a> {
964942
pub fn expand_crate(parse_sess: @mut parse::ParseSess,
965943
cfg: ast::CrateConfig,
966944
c: Crate) -> Crate {
967-
// adding *another* layer of indirection here so that the block
968-
// visitor can swap out one exts table for another for the duration
969-
// of the block. The cleaner alternative would be to thread the
970-
// exts table through the fold, but that would require updating
971-
// every method/element of AstFoldFns in fold.rs.
972-
let extsbox = syntax_expander_table();
973945
let mut cx = ExtCtxt::new(parse_sess, cfg.clone());
974946
let mut expander = MacroExpander {
975-
extsbox: @mut extsbox,
947+
extsbox: syntax_expander_table(),
976948
cx: &mut cx,
977949
};
978950

0 commit comments

Comments
 (0)
Please sign in to comment.