Rollup merge of #34316 - jseyfried:refactor_ast_stmt, r=eddyb

Refactor away `ast::Decl`, refactor `ast::Stmt`, and rename `ast::ExprKind::Again` to `ast::ExprKind::Continue`.
This commit is contained in:
Jeffrey Seyfried 2016-06-26 02:16:55 +00:00
commit 8748cd92d0
23 changed files with 331 additions and 409 deletions

View File

@ -238,19 +238,6 @@ impl<'a> LoweringContext<'a> {
}
}
fn lower_decl(&mut self, d: &Decl) -> P<hir::Decl> {
match d.node {
DeclKind::Local(ref l) => P(Spanned {
node: hir::DeclLocal(self.lower_local(l)),
span: d.span,
}),
DeclKind::Item(ref it) => P(Spanned {
node: hir::DeclItem(self.lower_item_id(it)),
span: d.span,
}),
}
}
fn lower_ty_binding(&mut self, b: &TypeBinding) -> hir::TypeBinding {
hir::TypeBinding {
id: b.id,
@ -1225,7 +1212,7 @@ impl<'a> LoweringContext<'a> {
hir::ExprPath(hir_qself, self.lower_path(path))
}
ExprKind::Break(opt_ident) => hir::ExprBreak(self.lower_opt_sp_ident(opt_ident)),
ExprKind::Again(opt_ident) => hir::ExprAgain(self.lower_opt_sp_ident(opt_ident)),
ExprKind::Continue(opt_ident) => hir::ExprAgain(self.lower_opt_sp_ident(opt_ident)),
ExprKind::Ret(ref e) => hir::ExprRet(e.as_ref().map(|x| self.lower_expr(x))),
ExprKind::InlineAsm(InlineAsm {
ref inputs,
@ -1581,21 +1568,29 @@ impl<'a> LoweringContext<'a> {
fn lower_stmt(&mut self, s: &Stmt) -> hir::Stmt {
match s.node {
StmtKind::Decl(ref d, id) => {
StmtKind::Local(ref l) => Spanned {
node: hir::StmtDecl(P(Spanned {
node: hir::DeclLocal(self.lower_local(l)),
span: s.span,
}), s.id),
span: s.span,
},
StmtKind::Item(ref it) => Spanned {
node: hir::StmtDecl(P(Spanned {
node: hir::DeclItem(self.lower_item_id(it)),
span: s.span,
}), s.id),
span: s.span,
},
StmtKind::Expr(ref e) => {
Spanned {
node: hir::StmtDecl(self.lower_decl(d), id),
node: hir::StmtExpr(self.lower_expr(e), s.id),
span: s.span,
}
}
StmtKind::Expr(ref e, id) => {
StmtKind::Semi(ref e) => {
Spanned {
node: hir::StmtExpr(self.lower_expr(e), id),
span: s.span,
}
}
StmtKind::Semi(ref e, id) => {
Spanned {
node: hir::StmtSemi(self.lower_expr(e), id),
node: hir::StmtSemi(self.lower_expr(e), s.id),
span: s.span,
}
}

View File

@ -1005,11 +1005,6 @@ impl<'a> ast_visit::Visitor for EarlyContext<'a> {
ast_visit::walk_arm(self, a);
}
fn visit_decl(&mut self, d: &ast::Decl) {
run_lints!(self, check_decl, early_passes, d);
ast_visit::walk_decl(self, d);
}
fn visit_expr_post(&mut self, e: &ast::Expr) {
run_lints!(self, check_expr_post, early_passes, e);
}

View File

@ -195,7 +195,6 @@ pub trait EarlyLintPass: LintPass {
fn check_stmt(&mut self, _: &EarlyContext, _: &ast::Stmt) { }
fn check_arm(&mut self, _: &EarlyContext, _: &ast::Arm) { }
fn check_pat(&mut self, _: &EarlyContext, _: &ast::Pat) { }
fn check_decl(&mut self, _: &EarlyContext, _: &ast::Decl) { }
fn check_expr(&mut self, _: &EarlyContext, _: &ast::Expr) { }
fn check_expr_post(&mut self, _: &EarlyContext, _: &ast::Expr) { }
fn check_ty(&mut self, _: &EarlyContext, _: &ast::Ty) { }

View File

@ -365,14 +365,11 @@ impl EarlyLintPass for UnusedParens {
fn check_stmt(&mut self, cx: &EarlyContext, s: &ast::Stmt) {
let (value, msg) = match s.node {
ast::StmtKind::Decl(ref decl, _) => match decl.node {
ast::DeclKind::Local(ref local) => match local.init {
ast::StmtKind::Local(ref local) => match local.init {
Some(ref value) => (value, "assigned value"),
None => return
},
_ => return
},
_ => return
};
self.check_unused_parens_core(cx, &value, msg, false);
}

View File

@ -73,7 +73,7 @@ impl<'a> Visitor for AstValidator<'a> {
match expr.node {
ExprKind::While(_, _, Some(ident)) | ExprKind::Loop(_, Some(ident)) |
ExprKind::WhileLet(_, _, _, Some(ident)) | ExprKind::ForLoop(_, _, _, Some(ident)) |
ExprKind::Break(Some(ident)) | ExprKind::Again(Some(ident)) => {
ExprKind::Break(Some(ident)) | ExprKind::Continue(Some(ident)) => {
self.check_label(ident.node, ident.span, expr.id);
}
_ => {}

View File

@ -30,10 +30,10 @@ use syntax::ast::Name;
use syntax::attr;
use syntax::parse::token;
use syntax::ast::{Block, Crate, DeclKind};
use syntax::ast::{Block, Crate};
use syntax::ast::{ForeignItem, ForeignItemKind, Item, ItemKind};
use syntax::ast::{Mutability, PathListItemKind};
use syntax::ast::{Stmt, StmtKind, TraitItemKind};
use syntax::ast::{StmtKind, TraitItemKind};
use syntax::ast::{Variant, ViewPathGlob, ViewPathList, ViewPathSimple};
use syntax::visit::{self, Visitor};
@ -85,17 +85,11 @@ impl<'b> Resolver<'b> {
}
fn block_needs_anonymous_module(&mut self, block: &Block) -> bool {
fn is_item(statement: &Stmt) -> bool {
if let StmtKind::Decl(ref declaration, _) = statement.node {
if let DeclKind::Item(_) = declaration.node {
return true;
}
}
false
}
// If any statements are items, we need to create an anonymous module
block.stmts.iter().any(is_item)
block.stmts.iter().any(|statement| match statement.node {
StmtKind::Item(_) => true,
_ => false,
})
}
/// Constructs the reduced graph for one item.

View File

@ -2951,7 +2951,7 @@ impl<'a> Resolver<'a> {
})
}
ExprKind::Break(Some(label)) | ExprKind::Again(Some(label)) => {
ExprKind::Break(Some(label)) | ExprKind::Continue(Some(label)) => {
match self.search_label(mtwt::resolve(label.node)) {
None => {
self.record_def(expr.id, err_path_resolution());

View File

@ -1423,8 +1423,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor for DumpVisitor<'l, 'tcx, 'll, D>
}
fn visit_stmt(&mut self, s: &ast::Stmt) {
let id = s.node.id();
self.process_macro_use(s.span, id.unwrap());
self.process_macro_use(s.span, s.id);
visit::walk_stmt(self, s)
}

View File

@ -27,7 +27,6 @@ use tokenstream::{TokenTree};
use std::fmt;
use std::rc::Rc;
use std::borrow::Cow;
use std::hash::{Hash, Hasher};
use serialize::{Encodable, Decodable, Encoder, Decoder};
@ -811,41 +810,35 @@ impl UnOp {
}
/// A statement
pub type Stmt = Spanned<StmtKind>;
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash)]
pub struct Stmt {
pub id: NodeId,
pub node: StmtKind,
pub span: Span,
}
impl fmt::Debug for Stmt {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "stmt({}: {})",
self.node.id()
.map_or(Cow::Borrowed("<macro>"),|id|Cow::Owned(id.to_string())),
pprust::stmt_to_string(self))
write!(f, "stmt({}: {})", self.id.to_string(), pprust::stmt_to_string(self))
}
}
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash)]
pub enum StmtKind {
/// Could be an item or a local (let) binding:
Decl(P<Decl>, NodeId),
/// A local (let) binding.
Local(P<Local>),
/// Expr without trailing semi-colon (must have unit type):
Expr(P<Expr>, NodeId),
/// An item definition.
Item(P<Item>),
/// Expr with trailing semi-colon (may have any type):
Semi(P<Expr>, NodeId),
/// Expr without trailing semi-colon (must have unit type).
Expr(P<Expr>),
Mac(P<Mac>, MacStmtStyle, ThinAttributes),
}
/// Expr with trailing semi-colon (may have any type).
Semi(P<Expr>),
impl StmtKind {
pub fn id(&self) -> Option<NodeId> {
match *self {
StmtKind::Decl(_, id) => Some(id),
StmtKind::Expr(_, id) => Some(id),
StmtKind::Semi(_, id) => Some(id),
StmtKind::Mac(..) => None,
}
}
Mac(P<(Mac, MacStmtStyle, ThinAttributes)>),
}
#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
@ -875,16 +868,6 @@ pub struct Local {
pub attrs: ThinAttributes,
}
pub type Decl = Spanned<DeclKind>;
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub enum DeclKind {
/// A local (let) binding:
Local(P<Local>),
/// An item binding:
Item(P<Item>),
}
/// An arm of a 'match'.
///
/// E.g. `0...10 => { println!("match!") }` as in
@ -1053,7 +1036,7 @@ pub enum ExprKind {
/// A `break`, with an optional label to break
Break(Option<SpannedIdent>),
/// A `continue`, with an optional label
Again(Option<SpannedIdent>),
Continue(Option<SpannedIdent>),
/// A `return`, with an optional value to be returned
Ret(Option<P<Expr>>),

View File

@ -16,8 +16,7 @@ pub use self::IntType::*;
use ast;
use ast::{AttrId, Attribute, Attribute_, MetaItem, MetaItemKind};
use ast::{Stmt, StmtKind, DeclKind};
use ast::{Expr, Item, Local, Decl};
use ast::{Expr, Item, Local, Stmt, StmtKind};
use codemap::{spanned, dummy_spanned, Spanned};
use syntax_pos::{Span, BytePos};
use errors::Handler;
@ -909,38 +908,28 @@ impl<T: HasAttrs + 'static> HasAttrs for P<T> {
}
}
impl HasAttrs for DeclKind {
fn attrs(&self) -> &[Attribute] {
match *self {
DeclKind::Local(ref local) => local.attrs(),
DeclKind::Item(ref item) => item.attrs(),
}
}
fn map_attrs<F: FnOnce(Vec<Attribute>) -> Vec<Attribute>>(self, f: F) -> Self {
match self {
DeclKind::Local(local) => DeclKind::Local(local.map_attrs(f)),
DeclKind::Item(item) => DeclKind::Item(item.map_attrs(f)),
}
}
}
impl HasAttrs for StmtKind {
fn attrs(&self) -> &[Attribute] {
match *self {
StmtKind::Decl(ref decl, _) => decl.attrs(),
StmtKind::Expr(ref expr, _) | StmtKind::Semi(ref expr, _) => expr.attrs(),
StmtKind::Mac(_, _, ref attrs) => attrs.attrs(),
StmtKind::Local(ref local) => local.attrs(),
StmtKind::Item(ref item) => item.attrs(),
StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => expr.attrs(),
StmtKind::Mac(ref mac) => {
let (_, _, ref attrs) = **mac;
attrs.attrs()
}
}
}
fn map_attrs<F: FnOnce(Vec<Attribute>) -> Vec<Attribute>>(self, f: F) -> Self {
match self {
StmtKind::Decl(decl, id) => StmtKind::Decl(decl.map_attrs(f), id),
StmtKind::Expr(expr, id) => StmtKind::Expr(expr.map_attrs(f), id),
StmtKind::Semi(expr, id) => StmtKind::Semi(expr.map_attrs(f), id),
StmtKind::Mac(mac, style, attrs) =>
StmtKind::Mac(mac, style, attrs.map_attrs(f)),
StmtKind::Local(local) => StmtKind::Local(local.map_attrs(f)),
StmtKind::Item(item) => StmtKind::Item(item.map_attrs(f)),
StmtKind::Expr(expr) => StmtKind::Expr(expr.map_attrs(f)),
StmtKind::Semi(expr) => StmtKind::Semi(expr.map_attrs(f)),
StmtKind::Mac(mac) => StmtKind::Mac(mac.map(|(mac, style, attrs)| {
(mac, style, attrs.map_attrs(f))
})),
}
}
}
@ -967,4 +956,4 @@ derive_has_attrs_from_field! {
Item, Expr, Local, ast::ForeignItem, ast::StructField, ast::ImplItem, ast::TraitItem, ast::Arm
}
derive_has_attrs_from_field! { Decl: .node, Stmt: .node, ast::Variant: .node.attrs }
derive_has_attrs_from_field! { Stmt: .node, ast::Variant: .node.attrs }

View File

@ -213,17 +213,10 @@ impl<'a> fold::Folder for StripUnconfigured<'a> {
}
fn fold_stmt(&mut self, stmt: ast::Stmt) -> SmallVector<ast::Stmt> {
let is_item = match stmt.node {
ast::StmtKind::Decl(ref decl, _) => match decl.node {
ast::DeclKind::Item(_) => true,
_ => false,
},
_ => false,
};
// avoid calling `visit_stmt_or_expr_attrs` on items
if !is_item {
self.visit_stmt_or_expr_attrs(stmt.attrs());
match stmt.node {
ast::StmtKind::Item(_) => {}
_ => self.visit_stmt_or_expr_attrs(stmt.attrs()),
}
self.configure(stmt).map(|stmt| fold::noop_fold_stmt(stmt, self))

View File

@ -221,10 +221,11 @@ impl<F> IdentMacroExpander for F
// Use a macro because forwarding to a simple function has type system issues
macro_rules! make_stmts_default {
($me:expr) => {
$me.make_expr().map(|e| {
SmallVector::one(codemap::respan(
e.span, ast::StmtKind::Expr(e, ast::DUMMY_NODE_ID)))
})
$me.make_expr().map(|e| SmallVector::one(ast::Stmt {
id: ast::DUMMY_NODE_ID,
span: e.span,
node: ast::StmtKind::Expr(e),
}))
}
}
@ -436,10 +437,11 @@ impl MacResult for DummyResult {
}
fn make_stmts(self: Box<DummyResult>) -> Option<SmallVector<ast::Stmt>> {
Some(SmallVector::one(
codemap::respan(self.span,
ast::StmtKind::Expr(DummyResult::raw_expr(self.span),
ast::DUMMY_NODE_ID))))
Some(SmallVector::one(ast::Stmt {
id: ast::DUMMY_NODE_ID,
node: ast::StmtKind::Expr(DummyResult::raw_expr(self.span)),
span: self.span,
}))
}
}

View File

@ -509,7 +509,11 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
}
fn stmt_expr(&self, expr: P<ast::Expr>) -> ast::Stmt {
respan(expr.span, ast::StmtKind::Semi(expr, ast::DUMMY_NODE_ID))
ast::Stmt {
id: ast::DUMMY_NODE_ID,
span: expr.span,
node: ast::StmtKind::Semi(expr),
}
}
fn stmt_let(&self, sp: Span, mutbl: bool, ident: ast::Ident,
@ -528,8 +532,11 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
span: sp,
attrs: None,
});
let decl = respan(sp, ast::DeclKind::Local(local));
respan(sp, ast::StmtKind::Decl(P(decl), ast::DUMMY_NODE_ID))
ast::Stmt {
id: ast::DUMMY_NODE_ID,
node: ast::StmtKind::Local(local),
span: sp,
}
}
fn stmt_let_typed(&self,
@ -553,8 +560,11 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
span: sp,
attrs: None,
});
let decl = respan(sp, ast::DeclKind::Local(local));
P(respan(sp, ast::StmtKind::Decl(P(decl), ast::DUMMY_NODE_ID)))
P(ast::Stmt {
id: ast::DUMMY_NODE_ID,
node: ast::StmtKind::Local(local),
span: sp,
})
}
fn block(&self, span: Span, stmts: Vec<ast::Stmt>,
@ -563,8 +573,11 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
}
fn stmt_item(&self, sp: Span, item: P<ast::Item>) -> ast::Stmt {
let decl = respan(sp, ast::DeclKind::Item(item));
respan(sp, ast::StmtKind::Decl(P(decl), ast::DUMMY_NODE_ID))
ast::Stmt {
id: ast::DUMMY_NODE_ID,
node: ast::StmtKind::Item(item),
span: sp,
}
}
fn block_expr(&self, expr: P<ast::Expr>) -> P<ast::Block> {

View File

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use ast::{Block, Crate, DeclKind, PatKind};
use ast::{Block, Crate, PatKind};
use ast::{Local, Ident, Mac_, Name, SpannedIdent};
use ast::{MacStmtStyle, Mrk, Stmt, StmtKind, ItemKind};
use ast;
@ -439,25 +439,25 @@ fn expand_stmt(stmt: Stmt, fld: &mut MacroExpander) -> SmallVector<Stmt> {
};
let (mac, style, attrs) = match stmt.node {
StmtKind::Mac(mac, style, attrs) => (mac, style, attrs),
StmtKind::Mac(mac) => mac.unwrap(),
_ => return expand_non_macro_stmt(stmt, fld)
};
let mut fully_expanded: SmallVector<ast::Stmt> =
expand_mac_invoc(mac.unwrap(), None, attrs.into_attr_vec(), stmt.span, fld);
expand_mac_invoc(mac, None, attrs.into_attr_vec(), stmt.span, fld);
// If this is a macro invocation with a semicolon, then apply that
// semicolon to the final statement produced by expansion.
if style == MacStmtStyle::Semicolon {
if let Some(stmt) = fully_expanded.pop() {
let new_stmt = Spanned {
fully_expanded.push(Stmt {
id: stmt.id,
node: match stmt.node {
StmtKind::Expr(e, stmt_id) => StmtKind::Semi(e, stmt_id),
StmtKind::Expr(expr) => StmtKind::Semi(expr),
_ => stmt.node /* might already have a semi */
},
span: stmt.span
};
fully_expanded.push(new_stmt);
span: stmt.span,
});
}
}
@ -466,12 +466,11 @@ fn expand_stmt(stmt: Stmt, fld: &mut MacroExpander) -> SmallVector<Stmt> {
// expand a non-macro stmt. this is essentially the fallthrough for
// expand_stmt, above.
fn expand_non_macro_stmt(Spanned {node, span: stmt_span}: Stmt, fld: &mut MacroExpander)
fn expand_non_macro_stmt(stmt: Stmt, fld: &mut MacroExpander)
-> SmallVector<Stmt> {
// is it a let?
match node {
StmtKind::Decl(decl, node_id) => decl.and_then(|Spanned {node: decl, span}| match decl {
DeclKind::Local(local) => {
match stmt.node {
StmtKind::Local(local) => {
// take it apart:
let rewritten_local = local.map(|Local {id, pat, ty, init, span, attrs}| {
// expand the ty since TyKind::FixedLengthVec contains an Expr
@ -507,32 +506,13 @@ fn expand_non_macro_stmt(Spanned {node, span: stmt_span}: Stmt, fld: &mut MacroE
attrs: fold::fold_thin_attrs(attrs, fld),
}
});
SmallVector::one(Spanned {
node: StmtKind::Decl(P(Spanned {
node: DeclKind::Local(rewritten_local),
span: span
}),
node_id),
span: stmt_span
SmallVector::one(Stmt {
id: stmt.id,
node: StmtKind::Local(rewritten_local),
span: stmt.span,
})
}
_ => {
noop_fold_stmt(Spanned {
node: StmtKind::Decl(P(Spanned {
node: decl,
span: span
}),
node_id),
span: stmt_span
}, fld)
}
}),
_ => {
noop_fold_stmt(Spanned {
node: node,
span: stmt_span
}, fld)
}
_ => noop_fold_stmt(stmt, fld),
}
}

View File

@ -102,10 +102,6 @@ pub trait Folder : Sized {
noop_fold_pat(p, self)
}
fn fold_decl(&mut self, d: P<Decl>) -> SmallVector<P<Decl>> {
noop_fold_decl(d, self)
}
fn fold_expr(&mut self, e: P<Expr>) -> P<Expr> {
e.map(|e| noop_fold_expr(e, self))
}
@ -349,19 +345,6 @@ pub fn noop_fold_arm<T: Folder>(Arm {attrs, pats, guard, body}: Arm, fld: &mut T
}
}
pub fn noop_fold_decl<T: Folder>(d: P<Decl>, fld: &mut T) -> SmallVector<P<Decl>> {
d.and_then(|Spanned {node, span}| match node {
DeclKind::Local(l) => SmallVector::one(P(Spanned {
node: DeclKind::Local(fld.fold_local(l)),
span: fld.new_span(span)
})),
DeclKind::Item(it) => fld.fold_item(it).into_iter().map(|i| P(Spanned {
node: DeclKind::Item(i),
span: fld.new_span(span)
})).collect()
})
}
pub fn noop_fold_ty_binding<T: Folder>(b: TypeBinding, fld: &mut T) -> TypeBinding {
TypeBinding {
id: fld.new_id(b.id),
@ -1248,7 +1231,7 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span, attrs}: Expr, folder: &mu
respan(folder.new_span(label.span),
folder.fold_ident(label.node)))
),
ExprKind::Again(opt_ident) => ExprKind::Again(opt_ident.map(|label|
ExprKind::Continue(opt_ident) => ExprKind::Continue(opt_ident.map(|label|
respan(folder.new_span(label.span),
folder.fold_ident(label.node)))
),
@ -1305,44 +1288,52 @@ pub fn noop_fold_exprs<T: Folder>(es: Vec<P<Expr>>, folder: &mut T) -> Vec<P<Exp
es.move_flat_map(|e| folder.fold_opt_expr(e))
}
pub fn noop_fold_stmt<T: Folder>(Spanned {node, span}: Stmt, folder: &mut T)
pub fn noop_fold_stmt<T: Folder>(Stmt {node, span, id}: Stmt, folder: &mut T)
-> SmallVector<Stmt> {
let id = folder.new_id(id);
let span = folder.new_span(span);
match node {
StmtKind::Decl(d, id) => {
let id = folder.new_id(id);
folder.fold_decl(d).into_iter().map(|d| Spanned {
node: StmtKind::Decl(d, id),
span: span
}).collect()
}
StmtKind::Expr(e, id) => {
let id = folder.new_id(id);
if let Some(e) = folder.fold_opt_expr(e) {
SmallVector::one(Spanned {
node: StmtKind::Expr(e, id),
span: span
StmtKind::Local(local) => SmallVector::one(Stmt {
id: id,
node: StmtKind::Local(folder.fold_local(local)),
span: span,
}),
StmtKind::Item(item) => folder.fold_item(item).into_iter().map(|item| Stmt {
id: id,
node: StmtKind::Item(item),
span: span,
}).collect(),
StmtKind::Expr(expr) => {
if let Some(expr) = folder.fold_opt_expr(expr) {
SmallVector::one(Stmt {
id: id,
node: StmtKind::Expr(expr),
span: span,
})
} else {
SmallVector::zero()
}
}
StmtKind::Semi(e, id) => {
let id = folder.new_id(id);
if let Some(e) = folder.fold_opt_expr(e) {
SmallVector::one(Spanned {
node: StmtKind::Semi(e, id),
span: span
StmtKind::Semi(expr) => {
if let Some(expr) = folder.fold_opt_expr(expr) {
SmallVector::one(Stmt {
id: id,
node: StmtKind::Semi(expr),
span: span,
})
} else {
SmallVector::zero()
}
}
StmtKind::Mac(mac, semi, attrs) => SmallVector::one(Spanned {
node: StmtKind::Mac(mac.map(|m| folder.fold_mac(m)),
semi,
attrs.map_thin_attrs(|v| fold_attrs(v, folder))),
span: span
StmtKind::Mac(mac) => SmallVector::one(Stmt {
id: id,
node: StmtKind::Mac(mac.map(|(mac, semi, attrs)| {
let mac = folder.fold_mac(mac);
let attrs = attrs.map_thin_attrs(|attrs| fold_attrs(attrs, folder));
(mac, semi, attrs)
})),
span: span,
})
}
}

View File

@ -47,13 +47,9 @@ pub fn expr_is_simple_block(e: &ast::Expr) -> bool {
/// seen the semicolon, and thus don't need another.
pub fn stmt_ends_with_semi(stmt: &ast::StmtKind) -> bool {
match *stmt {
ast::StmtKind::Decl(ref d, _) => {
match d.node {
ast::DeclKind::Local(_) => true,
ast::DeclKind::Item(_) => false,
}
}
ast::StmtKind::Expr(ref e, _) => expr_requires_semi_to_be_stmt(e),
ast::StmtKind::Local(_) => true,
ast::StmtKind::Item(_) => false,
ast::StmtKind::Expr(ref e) => expr_requires_semi_to_be_stmt(e),
ast::StmtKind::Semi(..) => false,
ast::StmtKind::Mac(..) => false,
}

View File

@ -844,7 +844,7 @@ mod tests {
#[test] fn parse_stmt_1 () {
assert!(string_to_stmt("b;".to_string()) ==
Some(Spanned{
Some(ast::Stmt {
node: ast::StmtKind::Expr(P(ast::Expr {
id: ast::DUMMY_NODE_ID,
node: ast::ExprKind::Path(None, ast::Path {
@ -858,8 +858,8 @@ mod tests {
),
}),
span: sp(0,1),
attrs: None}),
ast::DUMMY_NODE_ID),
attrs: None})),
id: ast::DUMMY_NODE_ID,
span: sp(0,1)}))
}
@ -935,7 +935,7 @@ mod tests {
}
},
P(ast::Block {
stmts: vec!(Spanned{
stmts: vec!(ast::Stmt {
node: ast::StmtKind::Semi(P(ast::Expr{
id: ast::DUMMY_NODE_ID,
node: ast::ExprKind::Path(None,
@ -953,8 +953,8 @@ mod tests {
),
}),
span: sp(17,18),
attrs: None,}),
ast::DUMMY_NODE_ID),
attrs: None,})),
id: ast::DUMMY_NODE_ID,
span: sp(17,19)}),
expr: None,
id: ast::DUMMY_NODE_ID,

View File

@ -16,7 +16,7 @@ use ast::{Mod, Arg, Arm, Attribute, BindingMode, TraitItemKind};
use ast::Block;
use ast::{BlockCheckMode, CaptureBy};
use ast::{Constness, Crate, CrateConfig};
use ast::{Decl, DeclKind, Defaultness};
use ast::Defaultness;
use ast::EnumDef;
use ast::{Expr, ExprKind, RangeLimits};
use ast::{Field, FnDecl};
@ -2312,14 +2312,14 @@ impl<'a> Parser<'a> {
}
if self.eat_keyword(keywords::Continue) {
let ex = if self.token.is_lifetime() {
let ex = ExprKind::Again(Some(Spanned{
let ex = ExprKind::Continue(Some(Spanned{
node: self.get_lifetime(),
span: self.span
}));
self.bump();
ex
} else {
ExprKind::Again(None)
ExprKind::Continue(None)
};
let hi = self.last_span.hi;
return Ok(self.mk_expr(lo, hi, ex, attrs));
@ -3826,13 +3826,6 @@ impl<'a> Parser<'a> {
}))
}
/// Parse a "let" stmt
fn parse_let(&mut self, attrs: ThinAttributes) -> PResult<'a, P<Decl>> {
let lo = self.span.lo;
let local = self.parse_local(attrs)?;
Ok(P(spanned(lo, self.last_span.hi, DeclKind::Local(local))))
}
/// Parse a structure field
fn parse_name_and_ty(&mut self, pr: Visibility,
attrs: Vec<Attribute> ) -> PResult<'a, StructField> {
@ -3945,12 +3938,12 @@ impl<'a> Parser<'a> {
let attrs = self.parse_outer_attributes()?;
let lo = self.span.lo;
Ok(Some(if self.check_keyword(keywords::Let) {
self.expect_keyword(keywords::Let)?;
let decl = self.parse_let(attrs.into_thin_attrs())?;
let hi = decl.span.hi;
let stmt = StmtKind::Decl(decl, ast::DUMMY_NODE_ID);
spanned(lo, hi, stmt)
Ok(Some(if self.eat_keyword(keywords::Let) {
Stmt {
id: ast::DUMMY_NODE_ID,
node: StmtKind::Local(self.parse_local(attrs.into_thin_attrs())?),
span: mk_sp(lo, self.last_span.hi),
}
} else if self.token.is_ident()
&& !self.token.is_any_keyword()
&& self.look_ahead(1, |t| *t == token::Not) {
@ -4001,9 +3994,12 @@ impl<'a> Parser<'a> {
};
if id.name == keywords::Invalid.name() {
let mac = P(spanned(lo, hi, Mac_ { path: pth, tts: tts }));
let stmt = StmtKind::Mac(mac, style, attrs.into_thin_attrs());
spanned(lo, hi, stmt)
let mac = spanned(lo, hi, Mac_ { path: pth, tts: tts });
Stmt {
id: ast::DUMMY_NODE_ID,
node: StmtKind::Mac(P((mac, style, attrs.into_thin_attrs()))),
span: mk_sp(lo, hi),
}
} else {
// if it has a special ident, it's definitely an item
//
@ -4017,25 +4013,28 @@ impl<'a> Parser<'a> {
followed by a semicolon");
}
}
spanned(lo, hi, StmtKind::Decl(
P(spanned(lo, hi, DeclKind::Item(
Stmt {
id: ast::DUMMY_NODE_ID,
span: mk_sp(lo, hi),
node: StmtKind::Item({
self.mk_item(
lo, hi, id /*id is good here*/,
ItemKind::Mac(spanned(lo, hi,
Mac_ { path: pth, tts: tts })),
Visibility::Inherited, attrs)))),
ast::DUMMY_NODE_ID))
ItemKind::Mac(spanned(lo, hi, Mac_ { path: pth, tts: tts })),
Visibility::Inherited,
attrs)
}),
}
}
} else {
// FIXME: Bad copy of attrs
let restrictions = self.restrictions | Restrictions::NO_NONINLINE_MOD;
match self.with_res(restrictions,
|this| this.parse_item_(attrs.clone(), false, true))? {
Some(i) => {
let hi = i.span.hi;
let decl = P(spanned(lo, hi, DeclKind::Item(i)));
spanned(lo, hi, StmtKind::Decl(decl, ast::DUMMY_NODE_ID))
}
Some(i) => Stmt {
id: ast::DUMMY_NODE_ID,
span: mk_sp(lo, i.span.hi),
node: StmtKind::Item(i),
},
None => {
let unused_attrs = |attrs: &[_], s: &mut Self| {
if attrs.len() > 0 {
@ -4059,9 +4058,11 @@ impl<'a> Parser<'a> {
// Remainder are line-expr stmts.
let e = self.parse_expr_res(
Restrictions::RESTRICTION_STMT_EXPR, Some(attrs.into_thin_attrs()))?;
let hi = e.span.hi;
let stmt = StmtKind::Expr(e, ast::DUMMY_NODE_ID);
spanned(lo, hi, stmt)
Stmt {
id: ast::DUMMY_NODE_ID,
span: mk_sp(lo, e.span.hi),
node: StmtKind::Expr(e),
}
}
}
}))
@ -4107,7 +4108,7 @@ impl<'a> Parser<'a> {
let mut expr = None;
while !self.eat(&token::CloseDelim(token::Brace)) {
let Spanned {node, span} = if let Some(s) = self.parse_stmt_() {
let Stmt {node, span, ..} = if let Some(s) = self.parse_stmt_() {
s
} else if self.token == token::Eof {
break;
@ -4115,60 +4116,13 @@ impl<'a> Parser<'a> {
// Found only `;` or `}`.
continue;
};
match node {
StmtKind::Expr(e, _) => {
StmtKind::Expr(e) => {
self.handle_expression_like_statement(e, span, &mut stmts, &mut expr)?;
}
StmtKind::Mac(mac, MacStmtStyle::NoBraces, attrs) => {
// statement macro without braces; might be an
// expr depending on whether a semicolon follows
match self.token {
token::Semi => {
stmts.push(Spanned {
node: StmtKind::Mac(mac, MacStmtStyle::Semicolon, attrs),
span: mk_sp(span.lo, self.span.hi),
});
self.bump();
}
_ => {
let e = self.mk_mac_expr(span.lo, span.hi,
mac.and_then(|m| m.node),
None);
let lo = e.span.lo;
let e = self.parse_dot_or_call_expr_with(e, lo, attrs)?;
let e = self.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(e))?;
self.handle_expression_like_statement(
e,
span,
&mut stmts,
&mut expr)?;
}
}
}
StmtKind::Mac(m, style, attrs) => {
// statement macro; might be an expr
match self.token {
token::Semi => {
stmts.push(Spanned {
node: StmtKind::Mac(m, MacStmtStyle::Semicolon, attrs),
span: mk_sp(span.lo, self.span.hi),
});
self.bump();
}
token::CloseDelim(token::Brace) => {
// if a block ends in `m!(arg)` without
// a `;`, it must be an expr
expr = Some(self.mk_mac_expr(span.lo, span.hi,
m.and_then(|x| x.node),
attrs));
}
_ => {
stmts.push(Spanned {
node: StmtKind::Mac(m, style, attrs),
span: span
});
}
}
StmtKind::Mac(mac) => {
self.handle_macro_in_block(mac.unwrap(), span, &mut stmts, &mut expr)?;
}
_ => { // all other kinds of statements:
let mut hi = span.hi;
@ -4177,7 +4131,8 @@ impl<'a> Parser<'a> {
hi = self.last_span.hi;
}
stmts.push(Spanned {
stmts.push(Stmt {
id: ast::DUMMY_NODE_ID,
node: node,
span: mk_sp(span.lo, hi)
});
@ -4194,6 +4149,60 @@ impl<'a> Parser<'a> {
}))
}
fn handle_macro_in_block(&mut self,
(mac, style, attrs): (ast::Mac, MacStmtStyle, ThinAttributes),
span: Span,
stmts: &mut Vec<Stmt>,
last_block_expr: &mut Option<P<Expr>>)
-> PResult<'a, ()> {
if style == MacStmtStyle::NoBraces {
// statement macro without braces; might be an
// expr depending on whether a semicolon follows
match self.token {
token::Semi => {
stmts.push(Stmt {
id: ast::DUMMY_NODE_ID,
node: StmtKind::Mac(P((mac, MacStmtStyle::Semicolon, attrs))),
span: mk_sp(span.lo, self.span.hi),
});
self.bump();
}
_ => {
let e = self.mk_mac_expr(span.lo, span.hi, mac.node, None);
let lo = e.span.lo;
let e = self.parse_dot_or_call_expr_with(e, lo, attrs)?;
let e = self.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(e))?;
self.handle_expression_like_statement(e, span, stmts, last_block_expr)?;
}
}
} else {
// statement macro; might be an expr
match self.token {
token::Semi => {
stmts.push(Stmt {
id: ast::DUMMY_NODE_ID,
node: StmtKind::Mac(P((mac, MacStmtStyle::Semicolon, attrs))),
span: mk_sp(span.lo, self.span.hi),
});
self.bump();
}
token::CloseDelim(token::Brace) => {
// if a block ends in `m!(arg)` without
// a `;`, it must be an expr
*last_block_expr = Some(self.mk_mac_expr(span.lo, span.hi, mac.node, attrs));
}
_ => {
stmts.push(Stmt {
id: ast::DUMMY_NODE_ID,
node: StmtKind::Mac(P((mac, style, attrs))),
span: span
});
}
}
}
Ok(())
}
fn handle_expression_like_statement(&mut self,
e: P<Expr>,
span: Span,
@ -4219,15 +4228,17 @@ impl<'a> Parser<'a> {
hi: self.last_span.hi,
expn_id: span.expn_id,
};
stmts.push(Spanned {
node: StmtKind::Semi(e, ast::DUMMY_NODE_ID),
stmts.push(Stmt {
id: ast::DUMMY_NODE_ID,
node: StmtKind::Semi(e),
span: span_with_semi,
});
}
token::CloseDelim(token::Brace) => *last_block_expr = Some(e),
_ => {
stmts.push(Spanned {
node: StmtKind::Expr(e, ast::DUMMY_NODE_ID),
stmts.push(Stmt {
id: ast::DUMMY_NODE_ID,
node: StmtKind::Expr(e),
span: span
});
}

View File

@ -1606,19 +1606,34 @@ impl<'a> State<'a> {
pub fn print_stmt(&mut self, st: &ast::Stmt) -> io::Result<()> {
try!(self.maybe_print_comment(st.span.lo));
match st.node {
ast::StmtKind::Decl(ref decl, _) => {
try!(self.print_decl(&decl));
ast::StmtKind::Local(ref loc) => {
try!(self.print_outer_attributes(loc.attrs.as_attr_slice()));
try!(self.space_if_not_bol());
try!(self.ibox(INDENT_UNIT));
try!(self.word_nbsp("let"));
try!(self.ibox(INDENT_UNIT));
try!(self.print_local_decl(&loc));
try!(self.end());
if let Some(ref init) = loc.init {
try!(self.nbsp());
try!(self.word_space("="));
try!(self.print_expr(&init));
}
ast::StmtKind::Expr(ref expr, _) => {
self.end()?;
}
ast::StmtKind::Item(ref item) => self.print_item(&item)?,
ast::StmtKind::Expr(ref expr) => {
try!(self.space_if_not_bol());
try!(self.print_expr_outer_attr_style(&expr, false));
}
ast::StmtKind::Semi(ref expr, _) => {
ast::StmtKind::Semi(ref expr) => {
try!(self.space_if_not_bol());
try!(self.print_expr_outer_attr_style(&expr, false));
try!(word(&mut self.s, ";"));
}
ast::StmtKind::Mac(ref mac, style, ref attrs) => {
ast::StmtKind::Mac(ref mac) => {
let (ref mac, style, ref attrs) = **mac;
try!(self.space_if_not_bol());
try!(self.print_outer_attributes(attrs.as_attr_slice()));
let delim = match style {
@ -2183,7 +2198,7 @@ impl<'a> State<'a> {
try!(space(&mut self.s));
}
}
ast::ExprKind::Again(opt_ident) => {
ast::ExprKind::Continue(opt_ident) => {
try!(word(&mut self.s, "continue"));
try!(space(&mut self.s));
if let Some(ident) = opt_ident {
@ -2291,29 +2306,6 @@ impl<'a> State<'a> {
Ok(())
}
pub fn print_decl(&mut self, decl: &ast::Decl) -> io::Result<()> {
try!(self.maybe_print_comment(decl.span.lo));
match decl.node {
ast::DeclKind::Local(ref loc) => {
try!(self.print_outer_attributes(loc.attrs.as_attr_slice()));
try!(self.space_if_not_bol());
try!(self.ibox(INDENT_UNIT));
try!(self.word_nbsp("let"));
try!(self.ibox(INDENT_UNIT));
try!(self.print_local_decl(&loc));
try!(self.end());
if let Some(ref init) = loc.init {
try!(self.nbsp());
try!(self.word_space("="));
try!(self.print_expr(&init));
}
self.end()
}
ast::DeclKind::Item(ref item) => self.print_item(&item)
}
}
pub fn print_ident(&mut self, ident: ast::Ident) -> io::Result<()> {
try!(word(&mut self.s, &ident.name.as_str()));
self.ann.post(self, NodeIdent(&ident))

View File

@ -63,10 +63,6 @@ impl Visitor for NodeCounter {
self.count += 1;
walk_pat(self, p)
}
fn visit_decl(&mut self, d: &Decl) {
self.count += 1;
walk_decl(self, d)
}
fn visit_expr(&mut self, ex: &Expr) {
self.count += 1;
walk_expr(self, ex)

View File

@ -65,7 +65,6 @@ pub trait Visitor: Sized {
fn visit_stmt(&mut self, s: &Stmt) { walk_stmt(self, s) }
fn visit_arm(&mut self, a: &Arm) { walk_arm(self, a) }
fn visit_pat(&mut self, p: &Pat) { walk_pat(self, p) }
fn visit_decl(&mut self, d: &Decl) { walk_decl(self, d) }
fn visit_expr(&mut self, ex: &Expr) { walk_expr(self, ex) }
fn visit_expr_post(&mut self, _ex: &Expr) { }
fn visit_ty(&mut self, t: &Ty) { walk_ty(self, t) }
@ -597,11 +596,13 @@ pub fn walk_block<V: Visitor>(visitor: &mut V, block: &Block) {
pub fn walk_stmt<V: Visitor>(visitor: &mut V, statement: &Stmt) {
match statement.node {
StmtKind::Decl(ref declaration, _) => visitor.visit_decl(declaration),
StmtKind::Expr(ref expression, _) | StmtKind::Semi(ref expression, _) => {
StmtKind::Local(ref local) => visitor.visit_local(local),
StmtKind::Item(ref item) => visitor.visit_item(item),
StmtKind::Expr(ref expression) | StmtKind::Semi(ref expression) => {
visitor.visit_expr(expression)
}
StmtKind::Mac(ref mac, _, ref attrs) => {
StmtKind::Mac(ref mac) => {
let (ref mac, _, ref attrs) = **mac;
visitor.visit_mac(mac);
for attr in attrs.as_attr_slice() {
visitor.visit_attribute(attr);
@ -610,13 +611,6 @@ pub fn walk_stmt<V: Visitor>(visitor: &mut V, statement: &Stmt) {
}
}
pub fn walk_decl<V: Visitor>(visitor: &mut V, declaration: &Decl) {
match declaration.node {
DeclKind::Local(ref local) => visitor.visit_local(local),
DeclKind::Item(ref item) => visitor.visit_item(item),
}
}
pub fn walk_mac<V: Visitor>(_: &mut V, _: &Mac) {
// Empty!
}
@ -745,7 +739,7 @@ pub fn walk_expr<V: Visitor>(visitor: &mut V, expression: &Expr) {
}
visitor.visit_path(path, expression.id)
}
ExprKind::Break(ref opt_sp_ident) | ExprKind::Again(ref opt_sp_ident) => {
ExprKind::Break(ref opt_sp_ident) | ExprKind::Continue(ref opt_sp_ident) => {
walk_opt_sp_ident(visitor, opt_sp_ident);
}
ExprKind::Ret(ref optional_expression) => {

View File

@ -13,7 +13,6 @@ use deriving::generic::ty::*;
use syntax::ast;
use syntax::ast::{MetaItem, Expr};
use syntax::codemap::respan;
use syntax::ext::base::{ExtCtxt, Annotatable};
use syntax::ext::build::AstBuilder;
use syntax::parse::token;
@ -152,6 +151,9 @@ fn stmt_let_undescore(cx: &mut ExtCtxt,
span: sp,
attrs: None,
});
let decl = respan(sp, ast::DeclKind::Local(local));
respan(sp, ast::StmtKind::Decl(P(decl), ast::DUMMY_NODE_ID))
ast::Stmt {
id: ast::DUMMY_NODE_ID,
node: ast::StmtKind::Local(local),
span: sp,
}
}

View File

@ -14,7 +14,6 @@ use self::Position::*;
use fmt_macros as parse;
use syntax::ast;
use syntax::codemap::respan;
use syntax::ext::base::*;
use syntax::ext::base;
use syntax::ext::build::AstBuilder;
@ -443,12 +442,14 @@ impl<'a, 'b> Context<'a, 'b> {
let name = ecx.ident_of(name);
let item = ecx.item(sp, name, vec![], st);
let decl = respan(sp, ast::DeclKind::Item(item));
let stmt = ast::Stmt {
id: ast::DUMMY_NODE_ID,
node: ast::StmtKind::Item(item),
span: sp,
};
// Wrap the declaration in a block so that it forms a single expression.
ecx.expr_block(ecx.block(sp,
vec![respan(sp, ast::StmtKind::Decl(P(decl), ast::DUMMY_NODE_ID))],
Some(ecx.expr_ident(sp, name))))
ecx.expr_block(ecx.block(sp, vec![stmt], Some(ecx.expr_ident(sp, name))))
}
/// Actually builds the expression which the iformat! block will be expanded