about summary refs log tree commit diff
path: root/src/libsyntax/parse/parser.rs
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2013-07-31 03:58:21 -0700
committerbors <bors@rust-lang.org>2013-07-31 03:58:21 -0700
commit6296dc0d73527301f18ef55b5f2d07c3241b8a00 (patch)
tree9ca1c483e62e852fb33db8aee766ba4c7e798eb9 /src/libsyntax/parse/parser.rs
parent8b7e241e02bb9f82d7b931033afde477d03ff4f2 (diff)
parenta696f0fecb9d11204f64d310eb66e095f64bd04a (diff)
downloadrust-6296dc0d73527301f18ef55b5f2d07c3241b8a00.tar.gz
rust-6296dc0d73527301f18ef55b5f2d07c3241b8a00.zip
auto merge of #8141 : graydon/rust/foreach-in-sketch, r=brson
This is a preliminary implementation of `for ... in ... { ...}` using a transitionary keyword `foreach`. Codesize seems to be a little bit down (10% or less non-opt) and otherwise it seems quite trivial to rewrite lambda-based loops to use it. Once we've rewritten the codebase away from lambda-based `for` we can retarget that word at the same production, snapshot, rewrite the keywords in one go, and expire `foreach`.

Feedback welcome. It's a desugaring-based approach which is arguably something we should have been doing for other constructs before. I apologize both for the laziness associated with doing it this way and with any sense that I'm bending rules I put in place previously concerning "never doing desugarings". I put the expansion in `expand.rs` and would be amenable to the argument that the code there needs better factoring / more helpers / to move to a submodule or helper function. It does seem to work at this point, though, and I gather we'd like to get the shift done relatively quickly.

Diffstat (limited to 'src/libsyntax/parse/parser.rs')
-rw-r--r--src/libsyntax/parse/parser.rs19
1 files changed, 18 insertions, 1 deletions
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 61dc6f47549..6ff4b91ec97 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -29,7 +29,7 @@ use ast::{expr_method_call, expr_paren, expr_path, expr_repeat};
 use ast::{expr_ret, expr_self, expr_struct, expr_tup, expr_unary};
 use ast::{expr_vec, expr_vstore, expr_vstore_mut_box};
 use ast::{expr_vstore_slice, expr_vstore_box};
-use ast::{expr_vstore_mut_slice, expr_while, extern_fn, Field, fn_decl};
+use ast::{expr_vstore_mut_slice, expr_while, expr_for_loop, extern_fn, Field, fn_decl};
 use ast::{expr_vstore_uniq, Onceness, Once, Many};
 use ast::{foreign_item, foreign_item_static, foreign_item_fn, foreign_mod};
 use ast::{ident, impure_fn, inherited, item, item_, item_static};
@@ -1622,6 +1622,8 @@ impl Parser {
             hi = self.span.hi;
         } else if self.eat_keyword(keywords::If) {
             return self.parse_if_expr();
+        } else if self.eat_keyword(keywords::ForEach) {
+            return self.parse_for_expr();
         } else if self.eat_keyword(keywords::For) {
             return self.parse_sugary_call_expr(lo, ~"for", ForSugar,
                                                expr_loop_body);
@@ -2323,6 +2325,21 @@ impl Parser {
         }
     }
 
+    // parse a 'foreach' .. 'in' expression ('foreach' token already eaten)
+    pub fn parse_for_expr(&self) -> @expr {
+        // Parse: `foreach <src_pat> in <src_expr> <src_loop_block>`
+
+        let lo = self.last_span.lo;
+        let pat = self.parse_pat();
+        self.expect_keyword(keywords::In);
+        let expr = self.parse_expr();
+        let loop_block = self.parse_block();
+        let hi = self.span.hi;
+
+        self.mk_expr(lo, hi, expr_for_loop(pat, expr, loop_block))
+    }
+
+
     // parse a 'for' or 'do'.
     // the 'for' and 'do' expressions parse as calls, but look like
     // function calls followed by a closure expression.