mirror of
https://github.com/rust-lang/rust.git
synced 2024-12-15 18:15:01 +00:00
parent
09f84aa8f4
commit
c144752a2d
@ -48,14 +48,6 @@ pub fn strip_items(crate: ast::Crate,
|
|||||||
ctxt.fold_crate(crate)
|
ctxt.fold_crate(crate)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn filter_item(cx: &Context, item: @ast::item) -> Option<@ast::item> {
|
|
||||||
if item_in_cfg(cx, item) {
|
|
||||||
Some(item)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn filter_view_item<'r>(cx: &Context, view_item: &'r ast::view_item)
|
fn filter_view_item<'r>(cx: &Context, view_item: &'r ast::view_item)
|
||||||
-> Option<&'r ast::view_item> {
|
-> Option<&'r ast::view_item> {
|
||||||
if view_item_in_cfg(cx, view_item) {
|
if view_item_in_cfg(cx, view_item) {
|
||||||
@ -66,9 +58,10 @@ fn filter_view_item<'r>(cx: &Context, view_item: &'r ast::view_item)
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn fold_mod(cx: &Context, m: &ast::_mod) -> ast::_mod {
|
fn fold_mod(cx: &Context, m: &ast::_mod) -> ast::_mod {
|
||||||
let filtered_items = m.items.iter().filter_map(|a| {
|
let filtered_items = m.items.iter()
|
||||||
filter_item(cx, *a).and_then(|x| cx.fold_item(x))
|
.filter(|&a| item_in_cfg(cx, *a))
|
||||||
}).collect();
|
.flat_map(|&x| cx.fold_item(x).move_iter())
|
||||||
|
.collect();
|
||||||
let filtered_view_items = m.view_items.iter().filter_map(|a| {
|
let filtered_view_items = m.view_items.iter().filter_map(|a| {
|
||||||
filter_view_item(cx, a).map(|x| cx.fold_view_item(x))
|
filter_view_item(cx, a).map(|x| cx.fold_view_item(x))
|
||||||
}).collect();
|
}).collect();
|
||||||
@ -122,28 +115,25 @@ fn fold_item_underscore(cx: &Context, item: &ast::item_) -> ast::item_ {
|
|||||||
fold::noop_fold_item_underscore(&item, cx)
|
fold::noop_fold_item_underscore(&item, cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn filter_stmt(cx: &Context, stmt: @ast::Stmt) -> Option<@ast::Stmt> {
|
fn retain_stmt(cx: &Context, stmt: @ast::Stmt) -> bool {
|
||||||
match stmt.node {
|
match stmt.node {
|
||||||
ast::StmtDecl(decl, _) => {
|
ast::StmtDecl(decl, _) => {
|
||||||
match decl.node {
|
match decl.node {
|
||||||
ast::DeclItem(item) => {
|
ast::DeclItem(item) => {
|
||||||
if item_in_cfg(cx, item) {
|
item_in_cfg(cx, item)
|
||||||
Some(stmt)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_ => Some(stmt)
|
_ => true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => Some(stmt),
|
_ => true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fold_block(cx: &Context, b: &ast::Block) -> ast::Block {
|
fn fold_block(cx: &Context, b: &ast::Block) -> ast::Block {
|
||||||
let resulting_stmts = b.stmts.iter().filter_map(|a| {
|
let resulting_stmts = b.stmts.iter()
|
||||||
filter_stmt(cx, *a).and_then(|stmt| cx.fold_stmt(stmt))
|
.filter(|&a| retain_stmt(cx, *a))
|
||||||
}).collect();
|
.flat_map(|&stmt| cx.fold_stmt(stmt).move_iter())
|
||||||
|
.collect();
|
||||||
let filtered_view_items = b.view_items.iter().filter_map(|a| {
|
let filtered_view_items = b.view_items.iter().filter_map(|a| {
|
||||||
filter_view_item(cx, a).map(|x| cx.fold_view_item(x))
|
filter_view_item(cx, a).map(|x| cx.fold_view_item(x))
|
||||||
}).collect();
|
}).collect();
|
||||||
|
@ -19,6 +19,7 @@ use syntax::codemap;
|
|||||||
use syntax::fold::ast_fold;
|
use syntax::fold::ast_fold;
|
||||||
use syntax::fold;
|
use syntax::fold;
|
||||||
use syntax::opt_vec;
|
use syntax::opt_vec;
|
||||||
|
use syntax::util::small_vector::SmallVector;
|
||||||
|
|
||||||
static STD_VERSION: &'static str = "0.9-pre";
|
static STD_VERSION: &'static str = "0.9-pre";
|
||||||
|
|
||||||
@ -98,14 +99,14 @@ impl fold::ast_fold for StandardLibraryInjector {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fold_item(&self, item: @ast::item) -> Option<@ast::item> {
|
fn fold_item(&self, item: @ast::item) -> SmallVector<@ast::item> {
|
||||||
if !no_prelude(item.attrs) {
|
if !no_prelude(item.attrs) {
|
||||||
// only recur if there wasn't `#[no_implicit_prelude];`
|
// only recur if there wasn't `#[no_implicit_prelude];`
|
||||||
// on this item, i.e. this means that the prelude is not
|
// on this item, i.e. this means that the prelude is not
|
||||||
// implicitly imported though the whole subtree
|
// implicitly imported though the whole subtree
|
||||||
fold::noop_fold_item(item, self)
|
fold::noop_fold_item(item, self)
|
||||||
} else {
|
} else {
|
||||||
Some(item)
|
SmallVector::one(item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@ use syntax::fold;
|
|||||||
use syntax::opt_vec;
|
use syntax::opt_vec;
|
||||||
use syntax::print::pprust;
|
use syntax::print::pprust;
|
||||||
use syntax::{ast, ast_util};
|
use syntax::{ast, ast_util};
|
||||||
|
use syntax::util::small_vector::SmallVector;
|
||||||
|
|
||||||
struct Test {
|
struct Test {
|
||||||
span: Span,
|
span: Span,
|
||||||
@ -76,7 +77,7 @@ impl fold::ast_fold for TestHarnessGenerator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fold_item(&self, i: @ast::item) -> Option<@ast::item> {
|
fn fold_item(&self, i: @ast::item) -> SmallVector<@ast::item> {
|
||||||
self.cx.path.push(i.ident);
|
self.cx.path.push(i.ident);
|
||||||
debug!("current path: {}",
|
debug!("current path: {}",
|
||||||
ast_util::path_name_i(self.cx.path.clone()));
|
ast_util::path_name_i(self.cx.path.clone()));
|
||||||
@ -108,7 +109,7 @@ impl fold::ast_fold for TestHarnessGenerator {
|
|||||||
|
|
||||||
let res = fold::noop_fold_item(i, self);
|
let res = fold::noop_fold_item(i, self);
|
||||||
self.cx.path.pop();
|
self.cx.path.pop();
|
||||||
return res;
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fold_mod(&self, m: &ast::_mod) -> ast::_mod {
|
fn fold_mod(&self, m: &ast::_mod) -> ast::_mod {
|
||||||
|
@ -33,6 +33,7 @@ use syntax::codemap;
|
|||||||
use syntax::fold::*;
|
use syntax::fold::*;
|
||||||
use syntax::fold;
|
use syntax::fold;
|
||||||
use syntax::parse::token;
|
use syntax::parse::token;
|
||||||
|
use syntax::util::small_vector::SmallVector;
|
||||||
use syntax;
|
use syntax;
|
||||||
|
|
||||||
use std::at_vec;
|
use std::at_vec;
|
||||||
@ -347,13 +348,20 @@ fn simplify_ast(ii: &ast::inlined_item) -> ast::inlined_item {
|
|||||||
|
|
||||||
match *ii {
|
match *ii {
|
||||||
//hack: we're not dropping items
|
//hack: we're not dropping items
|
||||||
ast::ii_item(i) => ast::ii_item(fld.fold_item(i).unwrap()),
|
ast::ii_item(i) => ast::ii_item(get_only_one(fld.fold_item(i))),
|
||||||
ast::ii_method(d, is_provided, m) =>
|
ast::ii_method(d, is_provided, m) =>
|
||||||
ast::ii_method(d, is_provided, fld.fold_method(m)),
|
ast::ii_method(d, is_provided, fld.fold_method(m)),
|
||||||
ast::ii_foreign(i) => ast::ii_foreign(fld.fold_foreign_item(i))
|
ast::ii_foreign(i) => ast::ii_foreign(fld.fold_foreign_item(i))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_only_one<T>(mut v: SmallVector<T>) -> T {
|
||||||
|
if v.len() != 1 {
|
||||||
|
fail!("Attempting to extract unique member but there isn't one");
|
||||||
|
}
|
||||||
|
v.pop()
|
||||||
|
}
|
||||||
|
|
||||||
fn decode_ast(par_doc: ebml::Doc) -> ast::inlined_item {
|
fn decode_ast(par_doc: ebml::Doc) -> ast::inlined_item {
|
||||||
let chi_doc = par_doc.get(c::tag_tree as uint);
|
let chi_doc = par_doc.get(c::tag_tree as uint);
|
||||||
let mut d = reader::Decoder(chi_doc);
|
let mut d = reader::Decoder(chi_doc);
|
||||||
@ -379,7 +387,7 @@ fn renumber_ast(xcx: @ExtendedDecodeContext, ii: ast::inlined_item)
|
|||||||
xcx: xcx,
|
xcx: xcx,
|
||||||
};
|
};
|
||||||
match ii {
|
match ii {
|
||||||
ast::ii_item(i) => ast::ii_item(fld.fold_item(i).unwrap()),
|
ast::ii_item(i) => ast::ii_item(get_only_one(fld.fold_item(i))),
|
||||||
ast::ii_method(d, is_provided, m) =>
|
ast::ii_method(d, is_provided, m) =>
|
||||||
ast::ii_method(xcx.tr_def_id(d), is_provided, fld.fold_method(m)),
|
ast::ii_method(xcx.tr_def_id(d), is_provided, fld.fold_method(m)),
|
||||||
ast::ii_foreign(i) => ast::ii_foreign(fld.fold_foreign_item(i)),
|
ast::ii_foreign(i) => ast::ii_foreign(fld.fold_foreign_item(i)),
|
||||||
|
@ -22,6 +22,7 @@ use syntax::{ast, attr, codemap, diagnostic, fold, visit};
|
|||||||
use syntax::attr::AttrMetaMethods;
|
use syntax::attr::AttrMetaMethods;
|
||||||
use syntax::fold::ast_fold;
|
use syntax::fold::ast_fold;
|
||||||
use syntax::visit::Visitor;
|
use syntax::visit::Visitor;
|
||||||
|
use syntax::util::small_vector::SmallVector;
|
||||||
use rustc::back::link::output_type_exe;
|
use rustc::back::link::output_type_exe;
|
||||||
use rustc::back::link;
|
use rustc::back::link;
|
||||||
use rustc::driver::session::{lib_crate, bin_crate};
|
use rustc::driver::session::{lib_crate, bin_crate};
|
||||||
@ -99,7 +100,7 @@ fn fold_mod(_ctx: @mut ReadyCtx, m: &ast::_mod, fold: &CrateSetup)
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn fold_item(ctx: @mut ReadyCtx, item: @ast::item, fold: &CrateSetup)
|
fn fold_item(ctx: @mut ReadyCtx, item: @ast::item, fold: &CrateSetup)
|
||||||
-> Option<@ast::item> {
|
-> SmallVector<@ast::item> {
|
||||||
ctx.path.push(item.ident);
|
ctx.path.push(item.ident);
|
||||||
|
|
||||||
let mut cmds = ~[];
|
let mut cmds = ~[];
|
||||||
@ -142,7 +143,7 @@ struct CrateSetup {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl fold::ast_fold for CrateSetup {
|
impl fold::ast_fold for CrateSetup {
|
||||||
fn fold_item(&self, item: @ast::item) -> Option<@ast::item> {
|
fn fold_item(&self, item: @ast::item) -> SmallVector<@ast::item> {
|
||||||
fold_item(self.ctx, item, self)
|
fold_item(self.ctx, item, self)
|
||||||
}
|
}
|
||||||
fn fold_mod(&self, module: &ast::_mod) -> ast::_mod {
|
fn fold_mod(&self, module: &ast::_mod) -> ast::_mod {
|
||||||
|
@ -18,6 +18,7 @@ use ext::expand;
|
|||||||
use parse;
|
use parse;
|
||||||
use parse::token;
|
use parse::token;
|
||||||
use parse::token::{ident_to_str, intern, str_to_ident};
|
use parse::token::{ident_to_str, intern, str_to_ident};
|
||||||
|
use util::small_vector::SmallVector;
|
||||||
|
|
||||||
use std::hashmap::HashMap;
|
use std::hashmap::HashMap;
|
||||||
|
|
||||||
@ -131,7 +132,7 @@ pub type SyntaxExpanderTTItemFunNoCtxt =
|
|||||||
|
|
||||||
pub trait AnyMacro {
|
pub trait AnyMacro {
|
||||||
fn make_expr(&self) -> @ast::Expr;
|
fn make_expr(&self) -> @ast::Expr;
|
||||||
fn make_item(&self) -> Option<@ast::item>;
|
fn make_items(&self) -> SmallVector<@ast::item>;
|
||||||
fn make_stmt(&self) -> @ast::Stmt;
|
fn make_stmt(&self) -> @ast::Stmt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@ use parse::token;
|
|||||||
use parse::token::{fresh_mark, fresh_name, ident_to_str, intern};
|
use parse::token::{fresh_mark, fresh_name, ident_to_str, intern};
|
||||||
use visit;
|
use visit;
|
||||||
use visit::Visitor;
|
use visit::Visitor;
|
||||||
|
use util::small_vector::SmallVector;
|
||||||
|
|
||||||
use std::vec;
|
use std::vec;
|
||||||
|
|
||||||
@ -310,7 +311,7 @@ pub fn expand_item(extsbox: @mut SyntaxEnv,
|
|||||||
cx: @ExtCtxt,
|
cx: @ExtCtxt,
|
||||||
it: @ast::item,
|
it: @ast::item,
|
||||||
fld: &MacroExpander)
|
fld: &MacroExpander)
|
||||||
-> Option<@ast::item> {
|
-> SmallVector<@ast::item> {
|
||||||
match it.node {
|
match it.node {
|
||||||
ast::item_mac(*) => expand_item_mac(extsbox, cx, it, fld),
|
ast::item_mac(*) => expand_item_mac(extsbox, cx, it, fld),
|
||||||
ast::item_mod(_) | ast::item_foreign_mod(_) => {
|
ast::item_mod(_) | ast::item_foreign_mod(_) => {
|
||||||
@ -337,7 +338,7 @@ pub fn expand_item_mac(extsbox: @mut SyntaxEnv,
|
|||||||
cx: @ExtCtxt,
|
cx: @ExtCtxt,
|
||||||
it: @ast::item,
|
it: @ast::item,
|
||||||
fld: &MacroExpander)
|
fld: &MacroExpander)
|
||||||
-> Option<@ast::item> {
|
-> SmallVector<@ast::item> {
|
||||||
let (pth, tts, ctxt) = match it.node {
|
let (pth, tts, ctxt) = match it.node {
|
||||||
item_mac(codemap::Spanned {
|
item_mac(codemap::Spanned {
|
||||||
node: mac_invoc_tt(ref pth, ref tts, ctxt),
|
node: mac_invoc_tt(ref pth, ref tts, ctxt),
|
||||||
@ -396,28 +397,30 @@ pub fn expand_item_mac(extsbox: @mut SyntaxEnv,
|
|||||||
it.span, format!("{}! is not legal in item position", extnamestr))
|
it.span, format!("{}! is not legal in item position", extnamestr))
|
||||||
};
|
};
|
||||||
|
|
||||||
let maybe_it = match expanded {
|
let items = match expanded {
|
||||||
MRItem(it) => {
|
MRItem(it) => {
|
||||||
mark_item(it,fm)
|
mark_item(it,fm).move_iter()
|
||||||
.and_then(|i| fld.fold_item(i))
|
.flat_map(|i| fld.fold_item(i).move_iter())
|
||||||
|
.collect()
|
||||||
}
|
}
|
||||||
MRExpr(_) => {
|
MRExpr(_) => {
|
||||||
cx.span_fatal(pth.span, format!("expr macro in item position: {}", extnamestr))
|
cx.span_fatal(pth.span, format!("expr macro in item position: {}", extnamestr))
|
||||||
}
|
}
|
||||||
MRAny(any_macro) => {
|
MRAny(any_macro) => {
|
||||||
any_macro.make_item()
|
any_macro.make_items().move_iter()
|
||||||
.and_then(|i| mark_item(i,fm))
|
.flat_map(|i| mark_item(i, fm).move_iter())
|
||||||
.and_then(|i| fld.fold_item(i))
|
.flat_map(|i| fld.fold_item(i).move_iter())
|
||||||
|
.collect()
|
||||||
}
|
}
|
||||||
MRDef(ref mdef) => {
|
MRDef(ref mdef) => {
|
||||||
// yikes... no idea how to apply the mark to this. I'm afraid
|
// yikes... no idea how to apply the mark to this. I'm afraid
|
||||||
// we're going to have to wait-and-see on this one.
|
// we're going to have to wait-and-see on this one.
|
||||||
insert_macro(*extsbox,intern(mdef.name), @SE((*mdef).ext));
|
insert_macro(*extsbox,intern(mdef.name), @SE((*mdef).ext));
|
||||||
None
|
SmallVector::zero()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
cx.bt_pop();
|
cx.bt_pop();
|
||||||
return maybe_it;
|
return items;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -442,7 +445,7 @@ pub fn expand_stmt(extsbox: @mut SyntaxEnv,
|
|||||||
cx: @ExtCtxt,
|
cx: @ExtCtxt,
|
||||||
s: &Stmt,
|
s: &Stmt,
|
||||||
fld: &MacroExpander)
|
fld: &MacroExpander)
|
||||||
-> Option<@Stmt> {
|
-> SmallVector<@Stmt> {
|
||||||
// why the copying here and not in expand_expr?
|
// why the copying here and not in expand_expr?
|
||||||
// looks like classic changed-in-only-one-place
|
// looks like classic changed-in-only-one-place
|
||||||
let (pth, tts, semi, ctxt) = match s.node {
|
let (pth, tts, semi, ctxt) = match s.node {
|
||||||
@ -461,7 +464,7 @@ pub fn expand_stmt(extsbox: @mut SyntaxEnv,
|
|||||||
}
|
}
|
||||||
let extname = &pth.segments[0].identifier;
|
let extname = &pth.segments[0].identifier;
|
||||||
let extnamestr = ident_to_str(extname);
|
let extnamestr = ident_to_str(extname);
|
||||||
let fully_expanded: @ast::Stmt = match (*extsbox).find(&extname.name) {
|
let fully_expanded: SmallVector<@Stmt> = match (*extsbox).find(&extname.name) {
|
||||||
None => {
|
None => {
|
||||||
cx.span_fatal(pth.span, format!("macro undefined: '{}'", extnamestr))
|
cx.span_fatal(pth.span, format!("macro undefined: '{}'", extnamestr))
|
||||||
}
|
}
|
||||||
@ -501,22 +504,15 @@ pub fn expand_stmt(extsbox: @mut SyntaxEnv,
|
|||||||
let marked_after = mark_stmt(expanded,fm);
|
let marked_after = mark_stmt(expanded,fm);
|
||||||
|
|
||||||
// Keep going, outside-in.
|
// Keep going, outside-in.
|
||||||
let fully_expanded = match fld.fold_stmt(marked_after) {
|
let fully_expanded = fld.fold_stmt(marked_after);
|
||||||
Some(stmt) => {
|
if fully_expanded.is_empty() {
|
||||||
let fully_expanded = &stmt.node;
|
cx.span_fatal(pth.span,
|
||||||
cx.bt_pop();
|
"macro didn't expand to a statement");
|
||||||
@Spanned {
|
}
|
||||||
span: stmt.span,
|
cx.bt_pop();
|
||||||
node: (*fully_expanded).clone(),
|
fully_expanded.move_iter()
|
||||||
}
|
.map(|s| @Spanned { span: s.span, node: s.node.clone() })
|
||||||
}
|
.collect()
|
||||||
None => {
|
|
||||||
cx.span_fatal(pth.span,
|
|
||||||
"macro didn't expand to a statement")
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
fully_expanded
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => {
|
_ => {
|
||||||
@ -525,21 +521,23 @@ pub fn expand_stmt(extsbox: @mut SyntaxEnv,
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
match fully_expanded.node {
|
fully_expanded.move_iter().map(|s| {
|
||||||
StmtExpr(e, stmt_id) if semi => {
|
match s.node {
|
||||||
Some(@Spanned {
|
StmtExpr(e, stmt_id) if semi => {
|
||||||
span: fully_expanded.span,
|
@Spanned {
|
||||||
node: StmtSemi(e, stmt_id),
|
span: s.span,
|
||||||
})
|
node: StmtSemi(e, stmt_id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => s /* might already have a semi */
|
||||||
}
|
}
|
||||||
_ => Some(fully_expanded), /* might already have a semi */
|
}).collect()
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// expand a non-macro stmt. this is essentially the fallthrough for
|
// expand a non-macro stmt. this is essentially the fallthrough for
|
||||||
// expand_stmt, above.
|
// expand_stmt, above.
|
||||||
fn expand_non_macro_stmt(exts: SyntaxEnv, s: &Stmt, fld: &MacroExpander)
|
fn expand_non_macro_stmt(exts: SyntaxEnv, s: &Stmt, fld: &MacroExpander)
|
||||||
-> Option<@Stmt> {
|
-> SmallVector<@Stmt> {
|
||||||
// is it a let?
|
// is it a let?
|
||||||
match s.node {
|
match s.node {
|
||||||
StmtDecl(@Spanned {
|
StmtDecl(@Spanned {
|
||||||
@ -590,7 +588,7 @@ fn expand_non_macro_stmt(exts: SyntaxEnv, s: &Stmt, fld: &MacroExpander)
|
|||||||
id: id,
|
id: id,
|
||||||
span: span,
|
span: span,
|
||||||
};
|
};
|
||||||
Some(@Spanned {
|
SmallVector::one(@Spanned {
|
||||||
node: StmtDecl(@Spanned {
|
node: StmtDecl(@Spanned {
|
||||||
node: DeclLocal(rewritten_local),
|
node: DeclLocal(rewritten_local),
|
||||||
span: stmt_span
|
span: stmt_span
|
||||||
@ -679,13 +677,9 @@ pub fn expand_block_elts(exts: SyntaxEnv, b: &Block, fld: &MacroExpander)
|
|||||||
let pending_renames = block_info.pending_renames;
|
let pending_renames = block_info.pending_renames;
|
||||||
let rename_fld = renames_to_fold(pending_renames);
|
let rename_fld = renames_to_fold(pending_renames);
|
||||||
let new_view_items = b.view_items.map(|x| fld.fold_view_item(x));
|
let new_view_items = b.view_items.map(|x| fld.fold_view_item(x));
|
||||||
let mut new_stmts = ~[];
|
let new_stmts = b.stmts.iter()
|
||||||
for x in b.stmts.iter() {
|
.flat_map(|x| fld.fold_stmt(mustbeone(rename_fld.fold_stmt(*x))).move_iter())
|
||||||
match fld.fold_stmt(mustbesome(rename_fld.fold_stmt(*x))) {
|
.collect();
|
||||||
Some(s) => new_stmts.push(s),
|
|
||||||
None => ()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let new_expr = b.expr.map(|x| fld.fold_expr(rename_fld.fold_expr(x)));
|
let new_expr = b.expr.map(|x| fld.fold_expr(rename_fld.fold_expr(x)));
|
||||||
Block{
|
Block{
|
||||||
view_items: new_view_items,
|
view_items: new_view_items,
|
||||||
@ -697,13 +691,12 @@ pub fn expand_block_elts(exts: SyntaxEnv, b: &Block, fld: &MacroExpander)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// rename_fold should never return "None".
|
// rename_fold should never return anything other than one thing
|
||||||
// (basically, just .get() with a better message...)
|
fn mustbeone<T>(mut val : SmallVector<T>) -> T {
|
||||||
fn mustbesome<T>(val : Option<T>) -> T {
|
if val.len() != 1 {
|
||||||
match val {
|
fail!("rename_fold didn't return one value");
|
||||||
Some(v) => v,
|
|
||||||
None => fail!("rename_fold returned None")
|
|
||||||
}
|
}
|
||||||
|
val.pop()
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the (innermost) BlockInfo from an exts stack
|
// get the (innermost) BlockInfo from an exts stack
|
||||||
@ -741,10 +734,11 @@ pub fn renames_to_fold(renames: @mut ~[(ast::Ident,ast::Name)]) -> @ast_fold {
|
|||||||
|
|
||||||
// perform a bunch of renames
|
// perform a bunch of renames
|
||||||
fn apply_pending_renames(folder : @ast_fold, stmt : ast::Stmt) -> @ast::Stmt {
|
fn apply_pending_renames(folder : @ast_fold, stmt : ast::Stmt) -> @ast::Stmt {
|
||||||
match folder.fold_stmt(&stmt) {
|
let mut stmts = folder.fold_stmt(&stmt);
|
||||||
Some(s) => s,
|
if stmts.len() != 1 {
|
||||||
None => fail!("renaming of stmt produced None")
|
fail!("renaming of stmt did not produce one stmt");
|
||||||
}
|
}
|
||||||
|
stmts.pop()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1025,14 +1019,14 @@ impl ast_fold for MacroExpander {
|
|||||||
self)
|
self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fold_item(&self, item: @ast::item) -> Option<@ast::item> {
|
fn fold_item(&self, item: @ast::item) -> SmallVector<@ast::item> {
|
||||||
expand_item(self.extsbox,
|
expand_item(self.extsbox,
|
||||||
self.cx,
|
self.cx,
|
||||||
item,
|
item,
|
||||||
self)
|
self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fold_stmt(&self, stmt: &ast::Stmt) -> Option<@ast::Stmt> {
|
fn fold_stmt(&self, stmt: &ast::Stmt) -> SmallVector<@ast::Stmt> {
|
||||||
expand_stmt(self.extsbox,
|
expand_stmt(self.extsbox,
|
||||||
self.cx,
|
self.cx,
|
||||||
stmt,
|
stmt,
|
||||||
@ -1191,11 +1185,15 @@ fn mark_expr(expr : @ast::Expr, m : Mrk) -> @ast::Expr {
|
|||||||
|
|
||||||
// apply a given mark to the given stmt. Used following the expansion of a macro.
|
// apply a given mark to the given stmt. Used following the expansion of a macro.
|
||||||
fn mark_stmt(expr : &ast::Stmt, m : Mrk) -> @ast::Stmt {
|
fn mark_stmt(expr : &ast::Stmt, m : Mrk) -> @ast::Stmt {
|
||||||
new_mark_folder(m).fold_stmt(expr).unwrap()
|
let mut stmts = new_mark_folder(m).fold_stmt(expr);
|
||||||
|
if stmts.len() != 1 {
|
||||||
|
fail!("marking a stmt didn't return a stmt");
|
||||||
|
}
|
||||||
|
stmts.pop()
|
||||||
}
|
}
|
||||||
|
|
||||||
// apply a given mark to the given item. Used following the expansion of a macro.
|
// apply a given mark to the given item. Used following the expansion of a macro.
|
||||||
fn mark_item(expr : @ast::item, m : Mrk) -> Option<@ast::item> {
|
fn mark_item(expr : @ast::item, m : Mrk) -> SmallVector<@ast::item> {
|
||||||
new_mark_folder(m).fold_item(expr)
|
new_mark_folder(m).fold_item(expr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,6 +24,7 @@ use parse::attr::parser_attr;
|
|||||||
use parse::token::{get_ident_interner, special_idents, gensym_ident, ident_to_str};
|
use parse::token::{get_ident_interner, special_idents, gensym_ident, ident_to_str};
|
||||||
use parse::token::{FAT_ARROW, SEMI, nt_matchers, nt_tt, EOF};
|
use parse::token::{FAT_ARROW, SEMI, nt_matchers, nt_tt, EOF};
|
||||||
use print;
|
use print;
|
||||||
|
use util::small_vector::SmallVector;
|
||||||
|
|
||||||
struct ParserAnyMacro {
|
struct ParserAnyMacro {
|
||||||
parser: @Parser,
|
parser: @Parser,
|
||||||
@ -54,9 +55,15 @@ impl AnyMacro for ParserAnyMacro {
|
|||||||
self.ensure_complete_parse(true);
|
self.ensure_complete_parse(true);
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
fn make_item(&self) -> Option<@ast::item> {
|
fn make_items(&self) -> SmallVector<@ast::item> {
|
||||||
let attrs = self.parser.parse_outer_attributes();
|
let mut ret = SmallVector::zero();
|
||||||
let ret = self.parser.parse_item(attrs);
|
loop {
|
||||||
|
let attrs = self.parser.parse_outer_attributes();
|
||||||
|
match self.parser.parse_item(attrs) {
|
||||||
|
Some(item) => ret.push(item),
|
||||||
|
None => break
|
||||||
|
}
|
||||||
|
}
|
||||||
self.ensure_complete_parse(false);
|
self.ensure_complete_parse(false);
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ use ast;
|
|||||||
use codemap::{respan, Span, Spanned};
|
use codemap::{respan, Span, Spanned};
|
||||||
use parse::token;
|
use parse::token;
|
||||||
use opt_vec::OptVec;
|
use opt_vec::OptVec;
|
||||||
|
use util::small_vector::SmallVector;
|
||||||
|
|
||||||
// We may eventually want to be able to fold over type parameters, too.
|
// We may eventually want to be able to fold over type parameters, too.
|
||||||
pub trait ast_fold {
|
pub trait ast_fold {
|
||||||
@ -113,7 +114,7 @@ pub trait ast_fold {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fold_item(&self, i: @item) -> Option<@item> {
|
fn fold_item(&self, i: @item) -> SmallVector<@item> {
|
||||||
noop_fold_item(i, self)
|
noop_fold_item(i, self)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,7 +160,7 @@ pub trait ast_fold {
|
|||||||
noop_fold_block(b, self)
|
noop_fold_block(b, self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fold_stmt(&self, s: &Stmt) -> Option<@Stmt> {
|
fn fold_stmt(&self, s: &Stmt) -> SmallVector<@Stmt> {
|
||||||
noop_fold_stmt(s, self)
|
noop_fold_stmt(s, self)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -216,23 +217,20 @@ pub trait ast_fold {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fold_decl(&self, d: @Decl) -> Option<@Decl> {
|
fn fold_decl(&self, d: @Decl) -> SmallVector<@Decl> {
|
||||||
let node = match d.node {
|
let node = match d.node {
|
||||||
DeclLocal(ref l) => Some(DeclLocal(self.fold_local(*l))),
|
DeclLocal(ref l) => SmallVector::one(DeclLocal(self.fold_local(*l))),
|
||||||
DeclItem(it) => {
|
DeclItem(it) => {
|
||||||
match self.fold_item(it) {
|
self.fold_item(it).move_iter().map(|i| DeclItem(i)).collect()
|
||||||
Some(it_folded) => Some(DeclItem(it_folded)),
|
|
||||||
None => None,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
node.map(|node| {
|
node.move_iter().map(|node| {
|
||||||
@Spanned {
|
@Spanned {
|
||||||
node: node,
|
node: node,
|
||||||
span: d.span,
|
span: d.span,
|
||||||
}
|
}
|
||||||
})
|
}).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fold_expr(&self, e: @Expr) -> @Expr {
|
fn fold_expr(&self, e: @Expr) -> @Expr {
|
||||||
@ -618,13 +616,7 @@ fn fold_variant_arg_<T:ast_fold>(va: &variant_arg, folder: &T)
|
|||||||
|
|
||||||
pub fn noop_fold_block<T:ast_fold>(b: &Block, folder: &T) -> Block {
|
pub fn noop_fold_block<T:ast_fold>(b: &Block, folder: &T) -> Block {
|
||||||
let view_items = b.view_items.map(|x| folder.fold_view_item(x));
|
let view_items = b.view_items.map(|x| folder.fold_view_item(x));
|
||||||
let mut stmts = ~[];
|
let stmts = b.stmts.iter().flat_map(|s| folder.fold_stmt(*s).move_iter()).collect();
|
||||||
for stmt in b.stmts.iter() {
|
|
||||||
match folder.fold_stmt(*stmt) {
|
|
||||||
None => {}
|
|
||||||
Some(stmt) => stmts.push(stmt)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ast::Block {
|
ast::Block {
|
||||||
view_items: view_items,
|
view_items: view_items,
|
||||||
stmts: stmts,
|
stmts: stmts,
|
||||||
@ -711,7 +703,7 @@ pub fn noop_fold_mod<T:ast_fold>(m: &_mod, folder: &T) -> _mod {
|
|||||||
view_items: m.view_items
|
view_items: m.view_items
|
||||||
.iter()
|
.iter()
|
||||||
.map(|x| folder.fold_view_item(x)).collect(),
|
.map(|x| folder.fold_view_item(x)).collect(),
|
||||||
items: m.items.iter().filter_map(|x| folder.fold_item(*x)).collect(),
|
items: m.items.iter().flat_map(|x| folder.fold_item(*x).move_iter()).collect(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -728,10 +720,10 @@ pub fn noop_fold_crate<T:ast_fold>(c: Crate, folder: &T) -> Crate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn noop_fold_item<T:ast_fold>(i: @ast::item, folder: &T)
|
pub fn noop_fold_item<T:ast_fold>(i: @ast::item, folder: &T)
|
||||||
-> Option<@ast::item> {
|
-> SmallVector<@ast::item> {
|
||||||
let fold_attribute = |x| fold_attribute_(x, folder);
|
let fold_attribute = |x| fold_attribute_(x, folder);
|
||||||
|
|
||||||
Some(@ast::item {
|
SmallVector::one(@ast::item {
|
||||||
ident: folder.fold_ident(i.ident),
|
ident: folder.fold_ident(i.ident),
|
||||||
attrs: i.attrs.map(|e| fold_attribute(*e)),
|
attrs: i.attrs.map(|e| fold_attribute(*e)),
|
||||||
id: folder.new_id(i.id),
|
id: folder.new_id(i.id),
|
||||||
@ -867,27 +859,26 @@ pub fn noop_fold_expr<T:ast_fold>(e: @ast::Expr, folder: &T) -> @ast::Expr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn noop_fold_stmt<T:ast_fold>(s: &Stmt, folder: &T) -> Option<@Stmt> {
|
pub fn noop_fold_stmt<T:ast_fold>(s: &Stmt, folder: &T) -> SmallVector<@Stmt> {
|
||||||
let node = match s.node {
|
let nodes = match s.node {
|
||||||
StmtDecl(d, nid) => {
|
StmtDecl(d, nid) => {
|
||||||
match folder.fold_decl(d) {
|
folder.fold_decl(d).move_iter()
|
||||||
Some(d) => Some(StmtDecl(d, folder.new_id(nid))),
|
.map(|d| StmtDecl(d, folder.new_id(nid)))
|
||||||
None => None,
|
.collect()
|
||||||
}
|
|
||||||
}
|
}
|
||||||
StmtExpr(e, nid) => {
|
StmtExpr(e, nid) => {
|
||||||
Some(StmtExpr(folder.fold_expr(e), folder.new_id(nid)))
|
SmallVector::one(StmtExpr(folder.fold_expr(e), folder.new_id(nid)))
|
||||||
}
|
}
|
||||||
StmtSemi(e, nid) => {
|
StmtSemi(e, nid) => {
|
||||||
Some(StmtSemi(folder.fold_expr(e), folder.new_id(nid)))
|
SmallVector::one(StmtSemi(folder.fold_expr(e), folder.new_id(nid)))
|
||||||
}
|
}
|
||||||
StmtMac(ref mac, semi) => Some(StmtMac(folder.fold_mac(mac), semi))
|
StmtMac(ref mac, semi) => SmallVector::one(StmtMac(folder.fold_mac(mac), semi))
|
||||||
};
|
};
|
||||||
|
|
||||||
node.map(|node| @Spanned {
|
nodes.move_iter().map(|node| @Spanned {
|
||||||
node: node,
|
node: node,
|
||||||
span: folder.new_span(s.span),
|
span: folder.new_span(s.span),
|
||||||
})
|
}).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -73,6 +73,22 @@ impl<T> SmallVector<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn pop(&mut self) -> T {
|
||||||
|
match *self {
|
||||||
|
Zero => fail!("attempted to pop from an empty SmallVector"),
|
||||||
|
One(*) => {
|
||||||
|
let mut tmp = Zero;
|
||||||
|
util::swap(self, &mut tmp);
|
||||||
|
match tmp {
|
||||||
|
One(v) => v,
|
||||||
|
_ => unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Should this reduce to a One if possible?
|
||||||
|
Many(ref mut vs) => vs.pop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get<'a>(&'a self, idx: uint) -> &'a T {
|
pub fn get<'a>(&'a self, idx: uint) -> &'a T {
|
||||||
match *self {
|
match *self {
|
||||||
One(ref v) if idx == 0 => v,
|
One(ref v) if idx == 0 => v,
|
||||||
@ -176,6 +192,18 @@ mod test {
|
|||||||
assert_eq!(&3, v.get(2));
|
assert_eq!(&3, v.get(2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_pop() {
|
||||||
|
let mut v = SmallVector::one(1);
|
||||||
|
assert_eq!(1, v.pop());
|
||||||
|
assert_eq!(0, v.len());
|
||||||
|
|
||||||
|
let mut v= SmallVector::many(~[1, 2]);
|
||||||
|
assert_eq!(2, v.pop());
|
||||||
|
assert_eq!(1, v.pop());
|
||||||
|
assert_eq!(0, v.len());
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_from_iterator() {
|
fn test_from_iterator() {
|
||||||
let v: SmallVector<int> = (~[1, 2, 3]).move_iter().collect();
|
let v: SmallVector<int> = (~[1, 2, 3]).move_iter().collect();
|
||||||
|
@ -13,7 +13,8 @@
|
|||||||
macro_rules! ignored_item {
|
macro_rules! ignored_item {
|
||||||
() => {
|
() => {
|
||||||
fn foo() {}
|
fn foo() {}
|
||||||
fn bar() {} //~ ERROR macro expansion ignores token `fn`
|
fn bar() {}
|
||||||
|
, //~ ERROR macro expansion ignores token `,`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
29
src/test/run-pass/macro-multiple-items.rs
Normal file
29
src/test/run-pass/macro-multiple-items.rs
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
// xfail-pretty - token trees can't pretty print
|
||||||
|
|
||||||
|
#[feature(macro_rules)];
|
||||||
|
|
||||||
|
macro_rules! make_foo(
|
||||||
|
() => (
|
||||||
|
struct Foo;
|
||||||
|
|
||||||
|
impl Foo {
|
||||||
|
fn bar(&self) {}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
make_foo!()
|
||||||
|
|
||||||
|
pub fn main() {
|
||||||
|
Foo.bar()
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user