diff options
| author | John Kåre Alsaker <john.kare.alsaker@gmail.com> | 2016-12-26 14:34:03 +0100 |
|---|---|---|
| committer | John Kåre Alsaker <john.kare.alsaker@gmail.com> | 2017-07-28 15:46:23 +0200 |
| commit | d861982ca6a1fa5773373362771aa08b9f732de0 (patch) | |
| tree | 06d990dc877d7a629a152185b1c039edb073c4ec /src/libsyntax | |
| parent | 6f815ca771b59fe652a5f88f198810b5dc37a4c9 (diff) | |
Generator literal support
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/ast.rs | 6 | ||||
| -rw-r--r-- | src/libsyntax/feature_gate.rs | 14 | ||||
| -rw-r--r-- | src/libsyntax/fold.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 22 | ||||
| -rw-r--r-- | src/libsyntax/parse/token.rs | 1 | ||||
| -rw-r--r-- | src/libsyntax/print/pprust.rs | 15 | ||||
| -rw-r--r-- | src/libsyntax/visit.rs | 4 |
7 files changed, 63 insertions, 1 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 4fc73787353..1a2299bcf1f 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -981,6 +981,12 @@ pub enum ExprKind { /// `expr?` Try(P<Expr>), + + /// A `yield`, with an optional value to be yielded + Yield(Option<P<Expr>>), + + /// A reference to the implicit argument of a generator + ImplArg, } /// The explicit Self type in a "qualified path". The actual diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index e8de8cf41c9..0f99761968a 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -361,6 +361,10 @@ declare_features! ( // Allows unsized tuple coercion. (active, unsized_tuple_coercion, "1.20.0", Some(42877)), + // Generators + (active, generators, "1.21.0", None), + + // global allocators and their internals (active, global_allocator, "1.20.0", None), (active, allocator_internals, "1.20.0", None), @@ -1326,6 +1330,16 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { ast::ExprKind::InPlace(..) => { gate_feature_post!(&self, placement_in_syntax, e.span, EXPLAIN_PLACEMENT_IN); } + ast::ExprKind::Yield(..) => { + gate_feature_post!(&self, generators, + e.span, + "yield syntax is experimental"); + } + ast::ExprKind::ImplArg => { + gate_feature_post!(&self, generators, + e.span, + "gen arg syntax is experimental"); + } ast::ExprKind::Lit(ref lit) => { if let ast::LitKind::Int(_, ref ty) = lit.node { match *ty { diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 8c616df858a..4a86008bb33 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -1303,6 +1303,8 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span, attrs}: Expr, folder: &mu attrs: fold_attrs(attrs.into(), folder).into(), }; } + ExprKind::Yield(ex) => ExprKind::Yield(ex.map(|x| folder.fold_expr(x))), + ExprKind::ImplArg => ExprKind::ImplArg, ExprKind::Try(ex) => ExprKind::Try(folder.fold_expr(ex)), ExprKind::Catch(body) => ExprKind::Catch(folder.fold_block(body)), }, diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index d1591a219b3..c377a77d87f 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2146,6 +2146,12 @@ impl<'a> Parser<'a> { assert!(self.eat_keyword(keywords::Catch)); return self.parse_catch_expr(lo, attrs); } + if self.is_gen_arg() { + assert!(self.eat_keyword(keywords::Gen)); + assert!(self.eat_keyword(keywords::Arg)); + let hi = self.prev_span; + return Ok(self.mk_expr(lo.to(hi), ExprKind::ImplArg, attrs)); + } if self.eat_keyword(keywords::Return) { if self.token.can_begin_expr() { let e = self.parse_expr()?; @@ -2175,6 +2181,14 @@ impl<'a> Parser<'a> { }; ex = ExprKind::Break(lt, e); hi = self.prev_span; + } else if self.eat_keyword(keywords::Yield) { + if self.token.can_begin_expr() { + let e = self.parse_expr()?; + hi = e.span; + ex = ExprKind::Yield(Some(e)); + } else { + ex = ExprKind::Yield(None); + } } else if self.token.is_keyword(keywords::Let) { // Catch this syntax error here, instead of in `parse_ident`, so // that we can explicitly mention that let is not to be used as an expression @@ -3696,6 +3710,11 @@ impl<'a> Parser<'a> { self.look_ahead(1, |t| t.is_ident() && !t.is_reserved_ident()) } + fn is_gen_arg(&self) -> bool { + self.token.is_keyword(keywords::Gen) && + self.look_ahead(1, |t| t.is_keyword(keywords::Arg)) + } + fn is_defaultness(&self) -> bool { // `pub` is included for better error messages self.token.is_keyword(keywords::Default) && @@ -3799,7 +3818,8 @@ impl<'a> Parser<'a> { // Starts like a simple path, but not a union item. } else if self.token.is_path_start() && !self.token.is_qpath_start() && - !self.is_union_item() { + !self.is_union_item() && + !self.is_gen_arg() { let pth = self.parse_path(PathStyle::Expr)?; if !self.eat(&token::Not) { diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 834ac38af98..d39f11bc3ee 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -106,6 +106,7 @@ fn ident_can_begin_expr(ident: ast::Ident) -> bool { keywords::True.name(), keywords::Unsafe.name(), keywords::While.name(), + keywords::Yield.name(), ].contains(&ident.name) } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index b052b2cdbbb..114cabe26d1 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -2280,6 +2280,21 @@ impl<'a> State<'a> { self.print_expr(e)?; self.pclose()?; }, + ast::ExprKind::Yield(ref e) => { + word(&mut self.s, "yield")?; + match *e { + Some(ref expr) => { + word(&mut self.s, " ")?; + self.print_expr(&expr)?; + } + _ => () + } + } + ast::ExprKind::ImplArg => { + word(&mut self.s, "impl")?; + space(&mut self.s)?; + word(&mut self.s, "arg")?; + } ast::ExprKind::Try(ref e) => { self.print_expr(e)?; self.s.word("?")? diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index f4ac7e341ce..cd8a2f1534b 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -784,6 +784,10 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) { visitor.visit_expr(&output.expr) } } + ExprKind::Yield(ref optional_expression) => { + walk_list!(visitor, visit_expr, optional_expression); + } + ExprKind::ImplArg => (), ExprKind::Try(ref subexpression) => { visitor.visit_expr(subexpression) } |
