about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorJohn Kåre Alsaker <john.kare.alsaker@gmail.com>2016-12-26 14:34:03 +0100
committerJohn Kåre Alsaker <john.kare.alsaker@gmail.com>2017-07-28 15:46:23 +0200
commitd861982ca6a1fa5773373362771aa08b9f732de0 (patch)
tree06d990dc877d7a629a152185b1c039edb073c4ec /src/libsyntax
parent6f815ca771b59fe652a5f88f198810b5dc37a4c9 (diff)
Generator literal support
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/ast.rs6
-rw-r--r--src/libsyntax/feature_gate.rs14
-rw-r--r--src/libsyntax/fold.rs2
-rw-r--r--src/libsyntax/parse/parser.rs22
-rw-r--r--src/libsyntax/parse/token.rs1
-rw-r--r--src/libsyntax/print/pprust.rs15
-rw-r--r--src/libsyntax/visit.rs4
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)
         }