Moved syntax::ext::base::SyntaxEnv
into syntax::ext::base::ExtCtx
This commit is contained in:
parent
df68c6f3c3
commit
94d92e6830
2 changed files with 213 additions and 201 deletions
|
@ -23,6 +23,7 @@ use ext::mtwt;
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::gc::{Gc, GC};
|
use std::gc::{Gc, GC};
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
// new-style macro! tt code:
|
// new-style macro! tt code:
|
||||||
//
|
//
|
||||||
|
@ -104,9 +105,9 @@ pub type IdentMacroExpanderFn =
|
||||||
/// just into the compiler's internal macro table, for `make_def`).
|
/// just into the compiler's internal macro table, for `make_def`).
|
||||||
pub trait MacResult {
|
pub trait MacResult {
|
||||||
/// Define a new macro.
|
/// Define a new macro.
|
||||||
// this particular flavor should go away; the idea that a macro might
|
// this should go away; the idea that a macro might expand into
|
||||||
// expand into either a macro definition or an expression, depending
|
// either a macro definition or an expression, depending on what
|
||||||
// on what the context wants, is kind of silly.
|
// the context wants, is kind of silly.
|
||||||
fn make_def(&self) -> Option<MacroDef> {
|
fn make_def(&self) -> Option<MacroDef> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -314,7 +315,7 @@ impl BlockInfo {
|
||||||
|
|
||||||
/// The base map of methods for expanding syntax extension
|
/// The base map of methods for expanding syntax extension
|
||||||
/// AST nodes into full ASTs
|
/// AST nodes into full ASTs
|
||||||
pub fn syntax_expander_table() -> SyntaxEnv {
|
fn initial_syntax_expander_table() -> SyntaxEnv {
|
||||||
// utility function to simplify creating NormalTT syntax extensions
|
// utility function to simplify creating NormalTT syntax extensions
|
||||||
fn builtin_normal_expander(f: MacroExpanderFn) -> SyntaxExtension {
|
fn builtin_normal_expander(f: MacroExpanderFn) -> SyntaxExtension {
|
||||||
NormalTT(box BasicMacroExpander {
|
NormalTT(box BasicMacroExpander {
|
||||||
|
@ -431,7 +432,9 @@ pub struct ExtCtxt<'a> {
|
||||||
|
|
||||||
pub mod_path: Vec<ast::Ident> ,
|
pub mod_path: Vec<ast::Ident> ,
|
||||||
pub trace_mac: bool,
|
pub trace_mac: bool,
|
||||||
pub exported_macros: Vec<Gc<ast::Item>>
|
pub exported_macros: Vec<Gc<ast::Item>>,
|
||||||
|
|
||||||
|
pub syntax_env: SyntaxEnv,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ExtCtxt<'a> {
|
impl<'a> ExtCtxt<'a> {
|
||||||
|
@ -445,6 +448,7 @@ impl<'a> ExtCtxt<'a> {
|
||||||
ecfg: ecfg,
|
ecfg: ecfg,
|
||||||
trace_mac: false,
|
trace_mac: false,
|
||||||
exported_macros: Vec::new(),
|
exported_macros: Vec::new(),
|
||||||
|
syntax_env: initial_syntax_expander_table(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -453,7 +457,6 @@ impl<'a> ExtCtxt<'a> {
|
||||||
match e.node {
|
match e.node {
|
||||||
ast::ExprMac(..) => {
|
ast::ExprMac(..) => {
|
||||||
let mut expander = expand::MacroExpander {
|
let mut expander = expand::MacroExpander {
|
||||||
extsbox: syntax_expander_table(),
|
|
||||||
cx: self,
|
cx: self,
|
||||||
};
|
};
|
||||||
e = expand::expand_expr(e, &mut expander);
|
e = expand::expand_expr(e, &mut expander);
|
||||||
|
@ -642,10 +645,13 @@ pub fn get_exprs_from_tts(cx: &mut ExtCtxt,
|
||||||
/// In order to have some notion of scoping for macros,
|
/// In order to have some notion of scoping for macros,
|
||||||
/// we want to implement the notion of a transformation
|
/// we want to implement the notion of a transformation
|
||||||
/// environment.
|
/// environment.
|
||||||
|
///
|
||||||
/// This environment maps Names to SyntaxExtensions.
|
/// This environment maps Names to SyntaxExtensions.
|
||||||
|
pub struct SyntaxEnv {
|
||||||
|
chain: Vec<MapChainFrame> ,
|
||||||
|
}
|
||||||
|
|
||||||
//impl question: how to implement it? Initially, the
|
// impl question: how to implement it? Initially, the
|
||||||
// env will contain only macros, so it might be painful
|
// env will contain only macros, so it might be painful
|
||||||
// to add an empty frame for every context. Let's just
|
// to add an empty frame for every context. Let's just
|
||||||
// get it working, first....
|
// get it working, first....
|
||||||
|
@ -657,15 +663,11 @@ pub fn get_exprs_from_tts(cx: &mut ExtCtxt,
|
||||||
|
|
||||||
struct MapChainFrame {
|
struct MapChainFrame {
|
||||||
info: BlockInfo,
|
info: BlockInfo,
|
||||||
map: HashMap<Name, SyntaxExtension>,
|
map: HashMap<Name, Rc<SyntaxExtension>>,
|
||||||
}
|
|
||||||
|
|
||||||
pub struct SyntaxEnv {
|
|
||||||
chain: Vec<MapChainFrame> ,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SyntaxEnv {
|
impl SyntaxEnv {
|
||||||
pub fn new() -> SyntaxEnv {
|
fn new() -> SyntaxEnv {
|
||||||
let mut map = SyntaxEnv { chain: Vec::new() };
|
let mut map = SyntaxEnv { chain: Vec::new() };
|
||||||
map.push_frame();
|
map.push_frame();
|
||||||
map
|
map
|
||||||
|
@ -692,10 +694,10 @@ impl SyntaxEnv {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn find<'a>(&'a self, k: &Name) -> Option<&'a SyntaxExtension> {
|
pub fn find(&self, k: &Name) -> Option<Rc<SyntaxExtension>> {
|
||||||
for frame in self.chain.iter().rev() {
|
for frame in self.chain.iter().rev() {
|
||||||
match frame.map.find(k) {
|
match frame.map.find(k) {
|
||||||
Some(v) => return Some(v),
|
Some(v) => return Some(v.clone()),
|
||||||
None => {}
|
None => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -703,7 +705,7 @@ impl SyntaxEnv {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert(&mut self, k: Name, v: SyntaxExtension) {
|
pub fn insert(&mut self, k: Name, v: SyntaxExtension) {
|
||||||
self.find_escape_frame().map.insert(k, v);
|
self.find_escape_frame().map.insert(k, Rc::new(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn info<'a>(&'a mut self) -> &'a mut BlockInfo {
|
pub fn info<'a>(&'a mut self) -> &'a mut BlockInfo {
|
||||||
|
|
|
@ -208,7 +208,7 @@ fn expand_mac_invoc<T>(mac: &ast::Mac, span: &codemap::Span,
|
||||||
}
|
}
|
||||||
let extname = pth.segments.get(0).identifier;
|
let extname = pth.segments.get(0).identifier;
|
||||||
let extnamestr = token::get_ident(extname);
|
let extnamestr = token::get_ident(extname);
|
||||||
match fld.extsbox.find(&extname.name) {
|
match fld.cx.syntax_env.find(&extname.name) {
|
||||||
None => {
|
None => {
|
||||||
fld.cx.span_err(
|
fld.cx.span_err(
|
||||||
pth.span,
|
pth.span,
|
||||||
|
@ -218,46 +218,48 @@ fn expand_mac_invoc<T>(mac: &ast::Mac, span: &codemap::Span,
|
||||||
// let compilation continue
|
// let compilation continue
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
Some(&NormalTT(ref expandfun, exp_span)) => {
|
Some(rc) => match *rc {
|
||||||
fld.cx.bt_push(ExpnInfo {
|
NormalTT(ref expandfun, exp_span) => {
|
||||||
call_site: *span,
|
fld.cx.bt_push(ExpnInfo {
|
||||||
callee: NameAndSpan {
|
call_site: *span,
|
||||||
name: extnamestr.get().to_string(),
|
callee: NameAndSpan {
|
||||||
format: MacroBang,
|
name: extnamestr.get().to_string(),
|
||||||
span: exp_span,
|
format: MacroBang,
|
||||||
},
|
span: exp_span,
|
||||||
});
|
},
|
||||||
let fm = fresh_mark();
|
});
|
||||||
let marked_before = mark_tts(tts.as_slice(), fm);
|
let fm = fresh_mark();
|
||||||
|
let marked_before = mark_tts(tts.as_slice(), fm);
|
||||||
|
|
||||||
// The span that we pass to the expanders we want to
|
// The span that we pass to the expanders we want to
|
||||||
// be the root of the call stack. That's the most
|
// be the root of the call stack. That's the most
|
||||||
// relevant span and it's the actual invocation of
|
// relevant span and it's the actual invocation of
|
||||||
// the macro.
|
// the macro.
|
||||||
let mac_span = original_span(fld.cx);
|
let mac_span = original_span(fld.cx);
|
||||||
|
|
||||||
let expanded = expandfun.expand(fld.cx,
|
let expanded = expandfun.expand(fld.cx,
|
||||||
mac_span.call_site,
|
mac_span.call_site,
|
||||||
marked_before.as_slice());
|
marked_before.as_slice());
|
||||||
let parsed = match parse_thunk(expanded) {
|
let parsed = match parse_thunk(expanded) {
|
||||||
Some(e) => e,
|
Some(e) => e,
|
||||||
None => {
|
None => {
|
||||||
fld.cx.span_err(
|
fld.cx.span_err(
|
||||||
pth.span,
|
pth.span,
|
||||||
format!("non-expression macro in expression position: {}",
|
format!("non-expression macro in expression position: {}",
|
||||||
extnamestr.get().as_slice()
|
extnamestr.get().as_slice()
|
||||||
).as_slice());
|
).as_slice());
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Some(mark_thunk(parsed,fm))
|
Some(mark_thunk(parsed,fm))
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
fld.cx.span_err(
|
fld.cx.span_err(
|
||||||
pth.span,
|
pth.span,
|
||||||
format!("'{}' is not a tt-style macro",
|
format!("'{}' is not a tt-style macro",
|
||||||
extnamestr.get()).as_slice());
|
extnamestr.get()).as_slice());
|
||||||
None
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -288,10 +290,10 @@ fn expand_loop_block(loop_block: P<Block>,
|
||||||
// The rename *must* be added to the enclosed syntax context for
|
// The rename *must* be added to the enclosed syntax context for
|
||||||
// `break` or `continue` to pick up because by definition they are
|
// `break` or `continue` to pick up because by definition they are
|
||||||
// in a block enclosed by loop head.
|
// in a block enclosed by loop head.
|
||||||
fld.extsbox.push_frame();
|
fld.cx.syntax_env.push_frame();
|
||||||
fld.extsbox.info().pending_renames.push(rename);
|
fld.cx.syntax_env.info().pending_renames.push(rename);
|
||||||
let expanded_block = expand_block_elts(&*loop_block, fld);
|
let expanded_block = expand_block_elts(&*loop_block, fld);
|
||||||
fld.extsbox.pop_frame();
|
fld.cx.syntax_env.pop_frame();
|
||||||
|
|
||||||
(expanded_block, Some(renamed_ident))
|
(expanded_block, Some(renamed_ident))
|
||||||
}
|
}
|
||||||
|
@ -321,29 +323,32 @@ fn expand_item(it: Gc<ast::Item>, fld: &mut MacroExpander)
|
||||||
for attr in it.attrs.iter() {
|
for attr in it.attrs.iter() {
|
||||||
let mname = attr.name();
|
let mname = attr.name();
|
||||||
|
|
||||||
match fld.extsbox.find(&intern(mname.get())) {
|
match fld.cx.syntax_env.find(&intern(mname.get())) {
|
||||||
Some(&ItemDecorator(dec_fn)) => {
|
Some(rc) => match *rc {
|
||||||
attr::mark_used(attr);
|
ItemDecorator(dec_fn) => {
|
||||||
|
attr::mark_used(attr);
|
||||||
|
|
||||||
fld.cx.bt_push(ExpnInfo {
|
fld.cx.bt_push(ExpnInfo {
|
||||||
call_site: attr.span,
|
call_site: attr.span,
|
||||||
callee: NameAndSpan {
|
callee: NameAndSpan {
|
||||||
name: mname.get().to_string(),
|
name: mname.get().to_string(),
|
||||||
format: MacroAttribute,
|
format: MacroAttribute,
|
||||||
span: None
|
span: None
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// we'd ideally decorator_items.push_all(expand_item(item, fld)),
|
// we'd ideally decorator_items.push_all(expand_item(item, fld)),
|
||||||
// but that double-mut-borrows fld
|
// but that double-mut-borrows fld
|
||||||
let mut items: SmallVector<Gc<ast::Item>> = SmallVector::zero();
|
let mut items: SmallVector<Gc<ast::Item>> = SmallVector::zero();
|
||||||
dec_fn(fld.cx, attr.span, attr.node.value, it,
|
dec_fn(fld.cx, attr.span, attr.node.value, it,
|
||||||
|item| items.push(item));
|
|item| items.push(item));
|
||||||
decorator_items.extend(items.move_iter()
|
decorator_items.extend(items.move_iter()
|
||||||
.flat_map(|item| expand_item(item, fld).move_iter()));
|
.flat_map(|item| expand_item(item, fld).move_iter()));
|
||||||
|
|
||||||
fld.cx.bt_pop();
|
fld.cx.bt_pop();
|
||||||
}
|
}
|
||||||
|
_ => new_attrs.push((*attr).clone()),
|
||||||
|
},
|
||||||
_ => new_attrs.push((*attr).clone()),
|
_ => new_attrs.push((*attr).clone()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -353,7 +358,7 @@ fn expand_item(it: Gc<ast::Item>, fld: &mut MacroExpander)
|
||||||
ast::ItemMod(_) | ast::ItemForeignMod(_) => {
|
ast::ItemMod(_) | ast::ItemForeignMod(_) => {
|
||||||
fld.cx.mod_push(it.ident);
|
fld.cx.mod_push(it.ident);
|
||||||
let macro_escape = contains_macro_escape(new_attrs.as_slice());
|
let macro_escape = contains_macro_escape(new_attrs.as_slice());
|
||||||
let result = with_exts_frame!(fld.extsbox,
|
let result = with_exts_frame!(fld.cx.syntax_env,
|
||||||
macro_escape,
|
macro_escape,
|
||||||
noop_fold_item(&*it, fld));
|
noop_fold_item(&*it, fld));
|
||||||
fld.cx.mod_pop();
|
fld.cx.mod_pop();
|
||||||
|
@ -377,8 +382,8 @@ fn expand_item_modifiers(mut it: Gc<ast::Item>, fld: &mut MacroExpander)
|
||||||
-> Gc<ast::Item> {
|
-> Gc<ast::Item> {
|
||||||
// partition the attributes into ItemModifiers and others
|
// partition the attributes into ItemModifiers and others
|
||||||
let (modifiers, other_attrs) = it.attrs.partitioned(|attr| {
|
let (modifiers, other_attrs) = it.attrs.partitioned(|attr| {
|
||||||
match fld.extsbox.find(&intern(attr.name().get())) {
|
match fld.cx.syntax_env.find(&intern(attr.name().get())) {
|
||||||
Some(&ItemModifier(_)) => true,
|
Some(rc) => match *rc { ItemModifier(_) => true, _ => false },
|
||||||
_ => false
|
_ => false
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -395,20 +400,23 @@ fn expand_item_modifiers(mut it: Gc<ast::Item>, fld: &mut MacroExpander)
|
||||||
for attr in modifiers.iter() {
|
for attr in modifiers.iter() {
|
||||||
let mname = attr.name();
|
let mname = attr.name();
|
||||||
|
|
||||||
match fld.extsbox.find(&intern(mname.get())) {
|
match fld.cx.syntax_env.find(&intern(mname.get())) {
|
||||||
Some(&ItemModifier(dec_fn)) => {
|
Some(rc) => match *rc {
|
||||||
attr::mark_used(attr);
|
ItemModifier(dec_fn) => {
|
||||||
fld.cx.bt_push(ExpnInfo {
|
attr::mark_used(attr);
|
||||||
call_site: attr.span,
|
fld.cx.bt_push(ExpnInfo {
|
||||||
callee: NameAndSpan {
|
call_site: attr.span,
|
||||||
name: mname.get().to_string(),
|
callee: NameAndSpan {
|
||||||
format: MacroAttribute,
|
name: mname.get().to_string(),
|
||||||
span: None,
|
format: MacroAttribute,
|
||||||
}
|
span: None,
|
||||||
});
|
}
|
||||||
it = dec_fn(fld.cx, attr.span, attr.node.value, it);
|
});
|
||||||
fld.cx.bt_pop();
|
it = dec_fn(fld.cx, attr.span, attr.node.value, it);
|
||||||
}
|
fld.cx.bt_pop();
|
||||||
|
}
|
||||||
|
_ => unreachable!()
|
||||||
|
},
|
||||||
_ => unreachable!()
|
_ => unreachable!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -452,7 +460,7 @@ fn expand_item_mac(it: Gc<ast::Item>, fld: &mut MacroExpander)
|
||||||
let extname = pth.segments.get(0).identifier;
|
let extname = pth.segments.get(0).identifier;
|
||||||
let extnamestr = token::get_ident(extname);
|
let extnamestr = token::get_ident(extname);
|
||||||
let fm = fresh_mark();
|
let fm = fresh_mark();
|
||||||
let expanded = match fld.extsbox.find(&extname.name) {
|
let expanded = match fld.cx.syntax_env.find(&extname.name) {
|
||||||
None => {
|
None => {
|
||||||
fld.cx.span_err(pth.span,
|
fld.cx.span_err(pth.span,
|
||||||
format!("macro undefined: '{}!'",
|
format!("macro undefined: '{}!'",
|
||||||
|
@ -461,70 +469,72 @@ fn expand_item_mac(it: Gc<ast::Item>, fld: &mut MacroExpander)
|
||||||
return SmallVector::zero();
|
return SmallVector::zero();
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(&NormalTT(ref expander, span)) => {
|
Some(rc) => match *rc {
|
||||||
if it.ident.name != parse::token::special_idents::invalid.name {
|
NormalTT(ref expander, span) => {
|
||||||
fld.cx
|
if it.ident.name != parse::token::special_idents::invalid.name {
|
||||||
.span_err(pth.span,
|
fld.cx
|
||||||
format!("macro {}! expects no ident argument, \
|
.span_err(pth.span,
|
||||||
given '{}'",
|
format!("macro {}! expects no ident argument, \
|
||||||
extnamestr,
|
given '{}'",
|
||||||
token::get_ident(it.ident)).as_slice());
|
extnamestr,
|
||||||
return SmallVector::zero();
|
token::get_ident(it.ident)).as_slice());
|
||||||
}
|
return SmallVector::zero();
|
||||||
fld.cx.bt_push(ExpnInfo {
|
|
||||||
call_site: it.span,
|
|
||||||
callee: NameAndSpan {
|
|
||||||
name: extnamestr.get().to_string(),
|
|
||||||
format: MacroBang,
|
|
||||||
span: span
|
|
||||||
}
|
}
|
||||||
});
|
fld.cx.bt_push(ExpnInfo {
|
||||||
// mark before expansion:
|
call_site: it.span,
|
||||||
let marked_before = mark_tts(tts.as_slice(), fm);
|
callee: NameAndSpan {
|
||||||
expander.expand(fld.cx, it.span, marked_before.as_slice())
|
name: extnamestr.get().to_string(),
|
||||||
}
|
format: MacroBang,
|
||||||
Some(&IdentTT(ref expander, span)) => {
|
span: span
|
||||||
if it.ident.name == parse::token::special_idents::invalid.name {
|
}
|
||||||
fld.cx.span_err(pth.span,
|
});
|
||||||
format!("macro {}! expects an ident argument",
|
// mark before expansion:
|
||||||
|
let marked_before = mark_tts(tts.as_slice(), fm);
|
||||||
|
expander.expand(fld.cx, it.span, marked_before.as_slice())
|
||||||
|
}
|
||||||
|
IdentTT(ref expander, span) => {
|
||||||
|
if it.ident.name == parse::token::special_idents::invalid.name {
|
||||||
|
fld.cx.span_err(pth.span,
|
||||||
|
format!("macro {}! expects an ident argument",
|
||||||
|
extnamestr.get()).as_slice());
|
||||||
|
return SmallVector::zero();
|
||||||
|
}
|
||||||
|
fld.cx.bt_push(ExpnInfo {
|
||||||
|
call_site: it.span,
|
||||||
|
callee: NameAndSpan {
|
||||||
|
name: extnamestr.get().to_string(),
|
||||||
|
format: MacroBang,
|
||||||
|
span: span
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// mark before expansion:
|
||||||
|
let marked_tts = mark_tts(tts.as_slice(), fm);
|
||||||
|
expander.expand(fld.cx, it.span, it.ident, marked_tts)
|
||||||
|
}
|
||||||
|
LetSyntaxTT(ref expander, span) => {
|
||||||
|
if it.ident.name == parse::token::special_idents::invalid.name {
|
||||||
|
fld.cx.span_err(pth.span,
|
||||||
|
format!("macro {}! expects an ident argument",
|
||||||
|
extnamestr.get()).as_slice());
|
||||||
|
return SmallVector::zero();
|
||||||
|
}
|
||||||
|
fld.cx.bt_push(ExpnInfo {
|
||||||
|
call_site: it.span,
|
||||||
|
callee: NameAndSpan {
|
||||||
|
name: extnamestr.get().to_string(),
|
||||||
|
format: MacroBang,
|
||||||
|
span: span
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// DON'T mark before expansion:
|
||||||
|
expander.expand(fld.cx, it.span, it.ident, tts)
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
fld.cx.span_err(it.span,
|
||||||
|
format!("{}! is not legal in item position",
|
||||||
extnamestr.get()).as_slice());
|
extnamestr.get()).as_slice());
|
||||||
return SmallVector::zero();
|
return SmallVector::zero();
|
||||||
}
|
}
|
||||||
fld.cx.bt_push(ExpnInfo {
|
|
||||||
call_site: it.span,
|
|
||||||
callee: NameAndSpan {
|
|
||||||
name: extnamestr.get().to_string(),
|
|
||||||
format: MacroBang,
|
|
||||||
span: span
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// mark before expansion:
|
|
||||||
let marked_tts = mark_tts(tts.as_slice(), fm);
|
|
||||||
expander.expand(fld.cx, it.span, it.ident, marked_tts)
|
|
||||||
}
|
|
||||||
Some(&LetSyntaxTT(ref expander, span)) => {
|
|
||||||
if it.ident.name == parse::token::special_idents::invalid.name {
|
|
||||||
fld.cx.span_err(pth.span,
|
|
||||||
format!("macro {}! expects an ident argument",
|
|
||||||
extnamestr.get()).as_slice());
|
|
||||||
return SmallVector::zero();
|
|
||||||
}
|
|
||||||
fld.cx.bt_push(ExpnInfo {
|
|
||||||
call_site: it.span,
|
|
||||||
callee: NameAndSpan {
|
|
||||||
name: extnamestr.get().to_string(),
|
|
||||||
format: MacroBang,
|
|
||||||
span: span
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// DON'T mark before expansion:
|
|
||||||
expander.expand(fld.cx, it.span, it.ident, tts)
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
fld.cx.span_err(it.span,
|
|
||||||
format!("{}! is not legal in item position",
|
|
||||||
extnamestr.get()).as_slice());
|
|
||||||
return SmallVector::zero();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -534,7 +544,7 @@ fn expand_item_mac(it: Gc<ast::Item>, fld: &mut MacroExpander)
|
||||||
// result of expanding a LetSyntaxTT, and thus doesn't
|
// result of expanding a LetSyntaxTT, and thus doesn't
|
||||||
// need to be marked. Not that it could be marked anyway.
|
// need to be marked. Not that it could be marked anyway.
|
||||||
// create issue to recommend refactoring here?
|
// create issue to recommend refactoring here?
|
||||||
fld.extsbox.insert(intern(name.as_slice()), ext);
|
fld.cx.syntax_env.insert(intern(name.as_slice()), ext);
|
||||||
if attr::contains_name(it.attrs.as_slice(), "macro_export") {
|
if attr::contains_name(it.attrs.as_slice(), "macro_export") {
|
||||||
fld.cx.exported_macros.push(it);
|
fld.cx.exported_macros.push(it);
|
||||||
}
|
}
|
||||||
|
@ -641,7 +651,7 @@ fn expand_non_macro_stmt(s: &Stmt, fld: &mut MacroExpander)
|
||||||
rename_fld.fold_pat(expanded_pat)
|
rename_fld.fold_pat(expanded_pat)
|
||||||
};
|
};
|
||||||
// add them to the existing pending renames:
|
// add them to the existing pending renames:
|
||||||
fld.extsbox.info().pending_renames.push_all_move(new_pending_renames);
|
fld.cx.syntax_env.info().pending_renames.push_all_move(new_pending_renames);
|
||||||
// also, don't forget to expand the init:
|
// also, don't forget to expand the init:
|
||||||
let new_init_opt = init.map(|e| fld.fold_expr(e));
|
let new_init_opt = init.map(|e| fld.fold_expr(e));
|
||||||
let rewritten_local =
|
let rewritten_local =
|
||||||
|
@ -742,7 +752,7 @@ fn fn_decl_arg_bindings(fn_decl: &ast::FnDecl) -> Vec<ast::Ident> {
|
||||||
// expand a block. pushes a new exts_frame, then calls expand_block_elts
|
// expand a block. pushes a new exts_frame, then calls expand_block_elts
|
||||||
fn expand_block(blk: &Block, fld: &mut MacroExpander) -> P<Block> {
|
fn expand_block(blk: &Block, fld: &mut MacroExpander) -> P<Block> {
|
||||||
// see note below about treatment of exts table
|
// see note below about treatment of exts table
|
||||||
with_exts_frame!(fld.extsbox,false,
|
with_exts_frame!(fld.cx.syntax_env,false,
|
||||||
expand_block_elts(blk, fld))
|
expand_block_elts(blk, fld))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -753,7 +763,7 @@ fn expand_block_elts(b: &Block, fld: &mut MacroExpander) -> P<Block> {
|
||||||
b.stmts.iter().flat_map(|x| {
|
b.stmts.iter().flat_map(|x| {
|
||||||
// perform all pending renames
|
// perform all pending renames
|
||||||
let renamed_stmt = {
|
let renamed_stmt = {
|
||||||
let pending_renames = &mut fld.extsbox.info().pending_renames;
|
let pending_renames = &mut fld.cx.syntax_env.info().pending_renames;
|
||||||
let mut rename_fld = IdentRenamer{renames:pending_renames};
|
let mut rename_fld = IdentRenamer{renames:pending_renames};
|
||||||
rename_fld.fold_stmt(&**x).expect_one("rename_fold didn't return one value")
|
rename_fld.fold_stmt(&**x).expect_one("rename_fold didn't return one value")
|
||||||
};
|
};
|
||||||
|
@ -762,7 +772,7 @@ fn expand_block_elts(b: &Block, fld: &mut MacroExpander) -> P<Block> {
|
||||||
}).collect();
|
}).collect();
|
||||||
let new_expr = b.expr.map(|x| {
|
let new_expr = b.expr.map(|x| {
|
||||||
let expr = {
|
let expr = {
|
||||||
let pending_renames = &mut fld.extsbox.info().pending_renames;
|
let pending_renames = &mut fld.cx.syntax_env.info().pending_renames;
|
||||||
let mut rename_fld = IdentRenamer{renames:pending_renames};
|
let mut rename_fld = IdentRenamer{renames:pending_renames};
|
||||||
rename_fld.fold_expr(x)
|
rename_fld.fold_expr(x)
|
||||||
};
|
};
|
||||||
|
@ -795,7 +805,7 @@ fn expand_pat(p: Gc<ast::Pat>, fld: &mut MacroExpander) -> Gc<ast::Pat> {
|
||||||
}
|
}
|
||||||
let extname = pth.segments.get(0).identifier;
|
let extname = pth.segments.get(0).identifier;
|
||||||
let extnamestr = token::get_ident(extname);
|
let extnamestr = token::get_ident(extname);
|
||||||
let marked_after = match fld.extsbox.find(&extname.name) {
|
let marked_after = match fld.cx.syntax_env.find(&extname.name) {
|
||||||
None => {
|
None => {
|
||||||
fld.cx.span_err(pth.span,
|
fld.cx.span_err(pth.span,
|
||||||
format!("macro undefined: '{}!'",
|
format!("macro undefined: '{}!'",
|
||||||
|
@ -804,43 +814,45 @@ fn expand_pat(p: Gc<ast::Pat>, fld: &mut MacroExpander) -> Gc<ast::Pat> {
|
||||||
return DummyResult::raw_pat(p.span);
|
return DummyResult::raw_pat(p.span);
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(&NormalTT(ref expander, span)) => {
|
Some(rc) => match *rc {
|
||||||
fld.cx.bt_push(ExpnInfo {
|
NormalTT(ref expander, span) => {
|
||||||
call_site: p.span,
|
fld.cx.bt_push(ExpnInfo {
|
||||||
callee: NameAndSpan {
|
call_site: p.span,
|
||||||
name: extnamestr.get().to_string(),
|
callee: NameAndSpan {
|
||||||
format: MacroBang,
|
name: extnamestr.get().to_string(),
|
||||||
span: span
|
format: MacroBang,
|
||||||
}
|
span: span
|
||||||
});
|
}
|
||||||
|
});
|
||||||
|
|
||||||
let fm = fresh_mark();
|
let fm = fresh_mark();
|
||||||
let marked_before = mark_tts(tts.as_slice(), fm);
|
let marked_before = mark_tts(tts.as_slice(), fm);
|
||||||
let mac_span = original_span(fld.cx);
|
let mac_span = original_span(fld.cx);
|
||||||
let expanded = match expander.expand(fld.cx,
|
let expanded = match expander.expand(fld.cx,
|
||||||
mac_span.call_site,
|
mac_span.call_site,
|
||||||
marked_before.as_slice()).make_pat() {
|
marked_before.as_slice()).make_pat() {
|
||||||
Some(e) => e,
|
Some(e) => e,
|
||||||
None => {
|
None => {
|
||||||
fld.cx.span_err(
|
fld.cx.span_err(
|
||||||
pth.span,
|
pth.span,
|
||||||
format!(
|
format!(
|
||||||
"non-pattern macro in pattern position: {}",
|
"non-pattern macro in pattern position: {}",
|
||||||
extnamestr.get()
|
extnamestr.get()
|
||||||
).as_slice()
|
).as_slice()
|
||||||
);
|
);
|
||||||
return DummyResult::raw_pat(p.span);
|
return DummyResult::raw_pat(p.span);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// mark after:
|
// mark after:
|
||||||
mark_pat(expanded,fm)
|
mark_pat(expanded,fm)
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
fld.cx.span_err(p.span,
|
fld.cx.span_err(p.span,
|
||||||
format!("{}! is not legal in pattern position",
|
format!("{}! is not legal in pattern position",
|
||||||
extnamestr.get()).as_slice());
|
extnamestr.get()).as_slice());
|
||||||
return DummyResult::raw_pat(p.span);
|
return DummyResult::raw_pat(p.span);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -975,7 +987,6 @@ fn expand_and_rename_fn_decl_and_block(fn_decl: &ast::FnDecl, block: Gc<ast::Blo
|
||||||
|
|
||||||
/// A tree-folder that performs macro expansion
|
/// A tree-folder that performs macro expansion
|
||||||
pub struct MacroExpander<'a, 'b> {
|
pub struct MacroExpander<'a, 'b> {
|
||||||
pub extsbox: SyntaxEnv,
|
|
||||||
pub cx: &'a mut ExtCtxt<'b>,
|
pub cx: &'a mut ExtCtxt<'b>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1044,7 +1055,6 @@ pub fn expand_crate(parse_sess: &parse::ParseSess,
|
||||||
c: Crate) -> Crate {
|
c: Crate) -> Crate {
|
||||||
let mut cx = ExtCtxt::new(parse_sess, c.config.clone(), cfg);
|
let mut cx = ExtCtxt::new(parse_sess, c.config.clone(), cfg);
|
||||||
let mut expander = MacroExpander {
|
let mut expander = MacroExpander {
|
||||||
extsbox: syntax_expander_table(),
|
|
||||||
cx: &mut cx,
|
cx: &mut cx,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1063,7 +1073,7 @@ pub fn expand_crate(parse_sess: &parse::ParseSess,
|
||||||
}
|
}
|
||||||
|
|
||||||
for (name, extension) in user_exts.move_iter() {
|
for (name, extension) in user_exts.move_iter() {
|
||||||
expander.extsbox.insert(name, extension);
|
expander.cx.syntax_env.insert(name, extension);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut ret = expander.fold_crate(c);
|
let mut ret = expander.fold_crate(c);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue