diff options
| author | Alex Crichton <alex@alexcrichton.com> | 2018-01-25 12:48:49 -0600 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-01-25 12:48:49 -0600 |
| commit | 98b375483c44c68009d699a4cd4b7b0a3d5d97a3 (patch) | |
| tree | 1cba42b1aa98db0d012cbecfb36d7d2dea428232 /src/libsyntax | |
| parent | 304885d959cae6b1fd6cb9aa64b70df6269d04b4 (diff) | |
| parent | 2d56abfbebdc905dafc9cf9edc0a6f58e4de7cbd (diff) | |
| download | rust-98b375483c44c68009d699a4cd4b7b0a3d5d97a3.tar.gz rust-98b375483c44c68009d699a4cd4b7b0a3d5d97a3.zip | |
Rollup merge of #47502 - petrochenkov:label, r=eddyb
AST/HIR: Add a separate structure for labels
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/ast.rs | 24 | ||||
| -rw-r--r-- | src/libsyntax/fold.rs | 43 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 64 | ||||
| -rw-r--r-- | src/libsyntax/print/pprust.rs | 36 | ||||
| -rw-r--r-- | src/libsyntax/visit.rs | 58 |
5 files changed, 108 insertions, 117 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index d6e26057ea8..73810b3fe81 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -34,6 +34,18 @@ use std::rc::Rc; use std::u32; #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)] +pub struct Label { + pub ident: Ident, + pub span: Span, +} + +impl fmt::Debug for Label { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "label({:?})", self.ident) + } +} + +#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)] pub struct Lifetime { pub id: NodeId, pub span: Span, @@ -1078,23 +1090,23 @@ pub enum ExprKind { /// A while loop, with an optional label /// /// `'label: while expr { block }` - While(P<Expr>, P<Block>, Option<SpannedIdent>), + While(P<Expr>, P<Block>, Option<Label>), /// A while-let loop, with an optional label /// /// `'label: while let pat = expr { block }` /// /// This is desugared to a combination of `loop` and `match` expressions. - WhileLet(P<Pat>, P<Expr>, P<Block>, Option<SpannedIdent>), + WhileLet(P<Pat>, P<Expr>, P<Block>, Option<Label>), /// A for loop, with an optional label /// /// `'label: for pat in expr { block }` /// /// This is desugared to a combination of `loop` and `match` expressions. - ForLoop(P<Pat>, P<Expr>, P<Block>, Option<SpannedIdent>), + ForLoop(P<Pat>, P<Expr>, P<Block>, Option<Label>), /// Conditionless loop (can be exited with break, continue, or return) /// /// `'label: loop { block }` - Loop(P<Block>, Option<SpannedIdent>), + Loop(P<Block>, Option<Label>), /// A `match` block. Match(P<Expr>, Vec<Arm>), /// A closure (for example, `move |a, b, c| a + b + c`) @@ -1133,9 +1145,9 @@ pub enum ExprKind { /// A referencing operation (`&a` or `&mut a`) AddrOf(Mutability, P<Expr>), /// A `break`, with an optional label to break, and an optional expression - Break(Option<SpannedIdent>, Option<P<Expr>>), + Break(Option<Label>, Option<P<Expr>>), /// A `continue`, with an optional label - Continue(Option<SpannedIdent>), + Continue(Option<Label>), /// A `return`, with an optional value to be returned Ret(Option<P<Expr>>), diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 1e605ba3ecd..0f8fe57e380 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -193,6 +193,10 @@ pub trait Folder : Sized { noop_fold_macro_def(def, self) } + fn fold_label(&mut self, label: Label) -> Label { + noop_fold_label(label, self) + } + fn fold_lifetime(&mut self, l: Lifetime) -> Lifetime { noop_fold_lifetime(l, self) } @@ -696,6 +700,13 @@ pub fn noop_fold_generic_params<T: Folder>( params.move_map(|p| fld.fold_generic_param(p)) } +pub fn noop_fold_label<T: Folder>(label: Label, fld: &mut T) -> Label { + Label { + ident: fld.fold_ident(label.ident), + span: fld.new_span(label.span), + } +} + pub fn noop_fold_lifetime<T: Folder>(l: Lifetime, fld: &mut T) -> Lifetime { Lifetime { id: fld.new_id(l.id), @@ -1206,30 +1217,26 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span, attrs}: Expr, folder: &mu folder.fold_block(tr), fl.map(|x| folder.fold_expr(x))) } - ExprKind::While(cond, body, opt_ident) => { + ExprKind::While(cond, body, opt_label) => { ExprKind::While(folder.fold_expr(cond), folder.fold_block(body), - opt_ident.map(|label| respan(folder.new_span(label.span), - folder.fold_ident(label.node)))) + opt_label.map(|label| folder.fold_label(label))) } - ExprKind::WhileLet(pat, expr, body, opt_ident) => { + ExprKind::WhileLet(pat, expr, body, opt_label) => { ExprKind::WhileLet(folder.fold_pat(pat), folder.fold_expr(expr), folder.fold_block(body), - opt_ident.map(|label| respan(folder.new_span(label.span), - folder.fold_ident(label.node)))) + opt_label.map(|label| folder.fold_label(label))) } - ExprKind::ForLoop(pat, iter, body, opt_ident) => { + ExprKind::ForLoop(pat, iter, body, opt_label) => { ExprKind::ForLoop(folder.fold_pat(pat), folder.fold_expr(iter), folder.fold_block(body), - opt_ident.map(|label| respan(folder.new_span(label.span), - folder.fold_ident(label.node)))) + opt_label.map(|label| folder.fold_label(label))) } - ExprKind::Loop(body, opt_ident) => { + ExprKind::Loop(body, opt_label) => { ExprKind::Loop(folder.fold_block(body), - opt_ident.map(|label| respan(folder.new_span(label.span), - folder.fold_ident(label.node)))) + opt_label.map(|label| folder.fold_label(label))) } ExprKind::Match(expr, arms) => { ExprKind::Match(folder.fold_expr(expr), @@ -1278,15 +1285,13 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span, attrs}: Expr, folder: &mu }); ExprKind::Path(qself, folder.fold_path(path)) } - ExprKind::Break(opt_ident, opt_expr) => { - ExprKind::Break(opt_ident.map(|label| respan(folder.new_span(label.span), - folder.fold_ident(label.node))), + ExprKind::Break(opt_label, opt_expr) => { + ExprKind::Break(opt_label.map(|label| folder.fold_label(label)), opt_expr.map(|e| folder.fold_expr(e))) } - ExprKind::Continue(opt_ident) => ExprKind::Continue(opt_ident.map(|label| - respan(folder.new_span(label.span), - folder.fold_ident(label.node))) - ), + ExprKind::Continue(opt_label) => { + ExprKind::Continue(opt_label.map(|label| folder.fold_label(label))) + } ExprKind::Ret(e) => ExprKind::Ret(e.map(|x| folder.fold_expr(x))), ExprKind::InlineAsm(asm) => ExprKind::InlineAsm(asm.map(|asm| { InlineAsm { diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 8213d604b91..d393cab4718 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -23,7 +23,7 @@ use ast::{Field, FnDecl}; use ast::{ForeignItem, ForeignItemKind, FunctionRetTy}; use ast::GenericParam; use ast::{Ident, ImplItem, IsAuto, Item, ItemKind}; -use ast::{Lifetime, LifetimeDef, Lit, LitKind, UintTy}; +use ast::{Label, Lifetime, LifetimeDef, Lit, LitKind, UintTy}; use ast::Local; use ast::MacStmtStyle; use ast::Mac_; @@ -1325,15 +1325,17 @@ impl<'a> Parser<'a> { self.check_keyword(keywords::Extern) } - fn get_label(&mut self) -> ast::Ident { - match self.token { + fn eat_label(&mut self) -> Option<Label> { + let ident = match self.token { token::Lifetime(ref ident) => *ident, token::Interpolated(ref nt) => match nt.0 { token::NtLifetime(lifetime) => lifetime.ident, - _ => self.bug("not a lifetime"), + _ => return None, }, - _ => self.bug("not a lifetime"), - } + _ => return None, + }; + self.bump(); + Some(Label { ident, span: self.prev_span }) } /// parse a TyKind::BareFn type: @@ -2317,11 +2319,8 @@ impl<'a> Parser<'a> { let lo = self.prev_span; return self.parse_while_expr(None, lo, attrs); } - if self.token.is_lifetime() { - let label = Spanned { node: self.get_label(), - span: self.span }; - let lo = self.span; - self.bump(); + if let Some(label) = self.eat_label() { + let lo = label.span; self.expect(&token::Colon)?; if self.eat_keyword(keywords::While) { return self.parse_while_expr(Some(label), lo, attrs) @@ -2339,16 +2338,8 @@ impl<'a> Parser<'a> { return self.parse_loop_expr(None, lo, attrs); } if self.eat_keyword(keywords::Continue) { - let ex = if self.token.is_lifetime() { - let ex = ExprKind::Continue(Some(Spanned{ - node: self.get_label(), - span: self.span - })); - self.bump(); - ex - } else { - ExprKind::Continue(None) - }; + let label = self.eat_label(); + let ex = ExprKind::Continue(label); let hi = self.prev_span; return Ok(self.mk_expr(lo.to(hi), ex, attrs)); } @@ -2376,16 +2367,7 @@ impl<'a> Parser<'a> { ex = ExprKind::Ret(None); } } else if self.eat_keyword(keywords::Break) { - let lt = if self.token.is_lifetime() { - let spanned_lt = Spanned { - node: self.get_label(), - span: self.span - }; - self.bump(); - Some(spanned_lt) - } else { - None - }; + let label = self.eat_label(); let e = if self.token.can_begin_expr() && !(self.token == token::OpenDelim(token::Brace) && self.restrictions.contains( @@ -2394,7 +2376,7 @@ impl<'a> Parser<'a> { } else { None }; - ex = ExprKind::Break(lt, e); + ex = ExprKind::Break(label, e); hi = self.prev_span; } else if self.eat_keyword(keywords::Yield) { if self.token.can_begin_expr() { @@ -3291,7 +3273,7 @@ impl<'a> Parser<'a> { } /// Parse a 'for' .. 'in' expression ('for' token already eaten) - pub fn parse_for_expr(&mut self, opt_ident: Option<ast::SpannedIdent>, + pub fn parse_for_expr(&mut self, opt_label: Option<Label>, span_lo: Span, mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> { // Parse: `for <src_pat> in <src_expr> <src_loop_block>` @@ -3309,25 +3291,25 @@ impl<'a> Parser<'a> { attrs.extend(iattrs); let hi = self.prev_span; - Ok(self.mk_expr(span_lo.to(hi), ExprKind::ForLoop(pat, expr, loop_block, opt_ident), attrs)) + Ok(self.mk_expr(span_lo.to(hi), ExprKind::ForLoop(pat, expr, loop_block, opt_label), attrs)) } /// Parse a 'while' or 'while let' expression ('while' token already eaten) - pub fn parse_while_expr(&mut self, opt_ident: Option<ast::SpannedIdent>, + pub fn parse_while_expr(&mut self, opt_label: Option<Label>, span_lo: Span, mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> { if self.token.is_keyword(keywords::Let) { - return self.parse_while_let_expr(opt_ident, span_lo, attrs); + return self.parse_while_let_expr(opt_label, span_lo, attrs); } let cond = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?; let (iattrs, body) = self.parse_inner_attrs_and_block()?; attrs.extend(iattrs); let span = span_lo.to(body.span); - return Ok(self.mk_expr(span, ExprKind::While(cond, body, opt_ident), attrs)); + return Ok(self.mk_expr(span, ExprKind::While(cond, body, opt_label), attrs)); } /// Parse a 'while let' expression ('while' token already eaten) - pub fn parse_while_let_expr(&mut self, opt_ident: Option<ast::SpannedIdent>, + pub fn parse_while_let_expr(&mut self, opt_label: Option<Label>, span_lo: Span, mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> { self.expect_keyword(keywords::Let)?; @@ -3337,17 +3319,17 @@ impl<'a> Parser<'a> { let (iattrs, body) = self.parse_inner_attrs_and_block()?; attrs.extend(iattrs); let span = span_lo.to(body.span); - return Ok(self.mk_expr(span, ExprKind::WhileLet(pat, expr, body, opt_ident), attrs)); + return Ok(self.mk_expr(span, ExprKind::WhileLet(pat, expr, body, opt_label), attrs)); } // parse `loop {...}`, `loop` token already eaten - pub fn parse_loop_expr(&mut self, opt_ident: Option<ast::SpannedIdent>, + pub fn parse_loop_expr(&mut self, opt_label: Option<Label>, span_lo: Span, mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> { let (iattrs, body) = self.parse_inner_attrs_and_block()?; attrs.extend(iattrs); let span = span_lo.to(body.span); - Ok(self.mk_expr(span, ExprKind::Loop(body, opt_ident), attrs)) + Ok(self.mk_expr(span, ExprKind::Loop(body, opt_label), attrs)) } /// Parse a `do catch {...}` expression (`do catch` token already eaten) diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 345c592a011..ae459c668aa 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -2104,9 +2104,9 @@ impl<'a> State<'a> { ast::ExprKind::IfLet(ref pat, ref expr, ref blk, ref elseopt) => { self.print_if_let(pat, expr, blk, elseopt.as_ref().map(|e| &**e))?; } - ast::ExprKind::While(ref test, ref blk, opt_ident) => { - if let Some(ident) = opt_ident { - self.print_ident(ident.node)?; + ast::ExprKind::While(ref test, ref blk, opt_label) => { + if let Some(label) = opt_label { + self.print_ident(label.ident)?; self.word_space(":")?; } self.head("while")?; @@ -2114,9 +2114,9 @@ impl<'a> State<'a> { self.s.space()?; self.print_block_with_attrs(blk, attrs)?; } - ast::ExprKind::WhileLet(ref pat, ref expr, ref blk, opt_ident) => { - if let Some(ident) = opt_ident { - self.print_ident(ident.node)?; + ast::ExprKind::WhileLet(ref pat, ref expr, ref blk, opt_label) => { + if let Some(label) = opt_label { + self.print_ident(label.ident)?; self.word_space(":")?; } self.head("while let")?; @@ -2127,9 +2127,9 @@ impl<'a> State<'a> { self.s.space()?; self.print_block_with_attrs(blk, attrs)?; } - ast::ExprKind::ForLoop(ref pat, ref iter, ref blk, opt_ident) => { - if let Some(ident) = opt_ident { - self.print_ident(ident.node)?; + ast::ExprKind::ForLoop(ref pat, ref iter, ref blk, opt_label) => { + if let Some(label) = opt_label { + self.print_ident(label.ident)?; self.word_space(":")?; } self.head("for")?; @@ -2140,9 +2140,9 @@ impl<'a> State<'a> { self.s.space()?; self.print_block_with_attrs(blk, attrs)?; } - ast::ExprKind::Loop(ref blk, opt_ident) => { - if let Some(ident) = opt_ident { - self.print_ident(ident.node)?; + ast::ExprKind::Loop(ref blk, opt_label) => { + if let Some(label) = opt_label { + self.print_ident(label.ident)?; self.word_space(":")?; } self.head("loop")?; @@ -2238,11 +2238,11 @@ impl<'a> State<'a> { ast::ExprKind::Path(Some(ref qself), ref path) => { self.print_qpath(path, qself, true)? } - ast::ExprKind::Break(opt_ident, ref opt_expr) => { + ast::ExprKind::Break(opt_label, ref opt_expr) => { self.s.word("break")?; self.s.space()?; - if let Some(ident) = opt_ident { - self.print_ident(ident.node)?; + if let Some(label) = opt_label { + self.print_ident(label.ident)?; self.s.space()?; } if let Some(ref expr) = *opt_expr { @@ -2250,11 +2250,11 @@ impl<'a> State<'a> { self.s.space()?; } } - ast::ExprKind::Continue(opt_ident) => { + ast::ExprKind::Continue(opt_label) => { self.s.word("continue")?; self.s.space()?; - if let Some(ident) = opt_ident { - self.print_ident(ident.node)?; + if let Some(label) = opt_label { + self.print_ident(label.ident)?; self.s.space()? } } diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 8aeacf79cee..bbb123dab28 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -101,6 +101,9 @@ pub trait Visitor<'ast>: Sized { fn visit_variant(&mut self, v: &'ast Variant, g: &'ast Generics, item_id: NodeId) { walk_variant(self, v, g, item_id) } + fn visit_label(&mut self, label: &'ast Label) { + walk_label(self, label) + } fn visit_lifetime(&mut self, lifetime: &'ast Lifetime) { walk_lifetime(self, lifetime) } @@ -163,25 +166,6 @@ macro_rules! walk_list { } } -pub fn walk_opt_name<'a, V: Visitor<'a>>(visitor: &mut V, span: Span, opt_name: Option<Name>) { - if let Some(name) = opt_name { - visitor.visit_name(span, name); - } -} - -pub fn walk_opt_ident<'a, V: Visitor<'a>>(visitor: &mut V, span: Span, opt_ident: Option<Ident>) { - if let Some(ident) = opt_ident { - visitor.visit_ident(span, ident); - } -} - -pub fn walk_opt_sp_ident<'a, V: Visitor<'a>>(visitor: &mut V, - opt_sp_ident: &Option<Spanned<Ident>>) { - if let Some(ref sp_ident) = *opt_sp_ident { - visitor.visit_ident(sp_ident.span, sp_ident.node); - } -} - pub fn walk_ident<'a, V: Visitor<'a>>(visitor: &mut V, span: Span, ident: Ident) { visitor.visit_name(span, ident.name); } @@ -204,6 +188,10 @@ pub fn walk_local<'a, V: Visitor<'a>>(visitor: &mut V, local: &'a Local) { walk_list!(visitor, visit_expr, &local.init); } +pub fn walk_label<'a, V: Visitor<'a>>(visitor: &mut V, label: &'a Label) { + visitor.visit_ident(label.span, label.ident); +} + pub fn walk_lifetime<'a, V: Visitor<'a>>(visitor: &mut V, lifetime: &'a Lifetime) { visitor.visit_ident(lifetime.span, lifetime.ident); } @@ -226,7 +214,9 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) { visitor.visit_ident(item.span, item.ident); match item.node { ItemKind::ExternCrate(opt_name) => { - walk_opt_name(visitor, item.span, opt_name) + if let Some(name) = opt_name { + visitor.visit_name(item.span, name); + } } ItemKind::Use(ref use_tree) => { visitor.visit_use_tree(use_tree, item.id, false) @@ -622,7 +612,9 @@ pub fn walk_struct_def<'a, V: Visitor<'a>>(visitor: &mut V, struct_definition: & pub fn walk_struct_field<'a, V: Visitor<'a>>(visitor: &mut V, struct_field: &'a StructField) { visitor.visit_vis(&struct_field.vis); - walk_opt_ident(visitor, struct_field.span, struct_field.ident); + if let Some(ident) = struct_field.ident { + visitor.visit_ident(struct_field.span, ident); + } visitor.visit_ty(&struct_field.ty); walk_list!(visitor, visit_attribute, &struct_field.attrs); } @@ -708,10 +700,10 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) { visitor.visit_block(if_block); walk_list!(visitor, visit_expr, optional_else); } - ExprKind::While(ref subexpression, ref block, ref opt_sp_ident) => { + ExprKind::While(ref subexpression, ref block, ref opt_label) => { + walk_list!(visitor, visit_label, opt_label); visitor.visit_expr(subexpression); visitor.visit_block(block); - walk_opt_sp_ident(visitor, opt_sp_ident); } ExprKind::IfLet(ref pattern, ref subexpression, ref if_block, ref optional_else) => { visitor.visit_pat(pattern); @@ -719,21 +711,21 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) { visitor.visit_block(if_block); walk_list!(visitor, visit_expr, optional_else); } - ExprKind::WhileLet(ref pattern, ref subexpression, ref block, ref opt_sp_ident) => { + ExprKind::WhileLet(ref pattern, ref subexpression, ref block, ref opt_label) => { + walk_list!(visitor, visit_label, opt_label); visitor.visit_pat(pattern); visitor.visit_expr(subexpression); visitor.visit_block(block); - walk_opt_sp_ident(visitor, opt_sp_ident); } - ExprKind::ForLoop(ref pattern, ref subexpression, ref block, ref opt_sp_ident) => { + ExprKind::ForLoop(ref pattern, ref subexpression, ref block, ref opt_label) => { + walk_list!(visitor, visit_label, opt_label); visitor.visit_pat(pattern); visitor.visit_expr(subexpression); visitor.visit_block(block); - walk_opt_sp_ident(visitor, opt_sp_ident); } - ExprKind::Loop(ref block, ref opt_sp_ident) => { + ExprKind::Loop(ref block, ref opt_label) => { + walk_list!(visitor, visit_label, opt_label); visitor.visit_block(block); - walk_opt_sp_ident(visitor, opt_sp_ident); } ExprKind::Match(ref subexpression, ref arms) => { visitor.visit_expr(subexpression); @@ -775,12 +767,12 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) { } visitor.visit_path(path, expression.id) } - ExprKind::Break(ref opt_sp_ident, ref opt_expr) => { - walk_opt_sp_ident(visitor, opt_sp_ident); + ExprKind::Break(ref opt_label, ref opt_expr) => { + walk_list!(visitor, visit_label, opt_label); walk_list!(visitor, visit_expr, opt_expr); } - ExprKind::Continue(ref opt_sp_ident) => { - walk_opt_sp_ident(visitor, opt_sp_ident); + ExprKind::Continue(ref opt_label) => { + walk_list!(visitor, visit_label, opt_label); } ExprKind::Ret(ref optional_expression) => { walk_list!(visitor, visit_expr, optional_expression); |
