about summary refs log tree commit diff
path: root/src/libsyntax/parse
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2014-05-28 22:26:56 -0700
committerPatrick Walton <pcwalton@mimiga.net>2014-07-18 09:01:37 -0700
commit02adaca4dc7eb4594d8bda9a7e04bc0247fc2a74 (patch)
tree2edb47de67e3c8a0d006f61217d7dffaab824b27 /src/libsyntax/parse
parent5ddc7b4a252fbebee5f2ac87ed755139816d6823 (diff)
downloadrust-02adaca4dc7eb4594d8bda9a7e04bc0247fc2a74.tar.gz
rust-02adaca4dc7eb4594d8bda9a7e04bc0247fc2a74.zip
librustc: Implement unboxed closures with mutable receivers
Diffstat (limited to 'src/libsyntax/parse')
-rw-r--r--src/libsyntax/parse/parser.rs119
1 files changed, 63 insertions, 56 deletions
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index a77f24f98f8..394288bd9f2 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -25,7 +25,7 @@ use ast::{ExprBreak, ExprCall, ExprCast};
 use ast::{ExprField, ExprFnBlock, ExprIf, ExprIndex};
 use ast::{ExprLit, ExprLoop, ExprMac};
 use ast::{ExprMethodCall, ExprParen, ExprPath, ExprProc};
-use ast::{ExprRepeat, ExprRet, ExprStruct, ExprTup, ExprUnary};
+use ast::{ExprRepeat, ExprRet, ExprStruct, ExprTup, ExprUnary, ExprUnboxedFn};
 use ast::{ExprVec, ExprVstore, ExprVstoreSlice};
 use ast::{ExprVstoreMutSlice, ExprWhile, ExprForLoop, Field, FnDecl};
 use ast::{ExprVstoreUniq, Once, Many};
@@ -59,6 +59,7 @@ use ast::Visibility;
 use ast;
 use ast_util::{as_prec, ident_to_path, lit_is_str, operator_prec};
 use ast_util;
+use attr;
 use codemap::{Span, BytePos, Spanned, spanned, mk_sp};
 use codemap;
 use parse;
@@ -1217,6 +1218,16 @@ impl<'a> Parser<'a> {
             // NB: at the moment, trait methods are public by default; this
             // could change.
             let vis = p.parse_visibility();
+            let abi = if p.eat_keyword(keywords::Extern) {
+                p.parse_opt_abi().unwrap_or(abi::C)
+            } else if attr::contains_name(attrs.as_slice(),
+                                          "rust_call_abi_hack") {
+                // FIXME(stage0, pcwalton): Remove this awful hack after a
+                // snapshot, and change to `extern "rust-call" fn`.
+                abi::RustCall
+            } else {
+                abi::Rust
+            };
             let style = p.parse_fn_style();
             let ident = p.parse_ident();
 
@@ -1239,6 +1250,7 @@ impl<'a> Parser<'a> {
                     fn_style: style,
                     decl: d,
                     generics: generics,
+                    abi: abi,
                     explicit_self: explicit_self,
                     id: ast::DUMMY_NODE_ID,
                     span: mk_sp(lo, hi),
@@ -1254,7 +1266,14 @@ impl<'a> Parser<'a> {
                     attrs: attrs,
                     id: ast::DUMMY_NODE_ID,
                     span: mk_sp(lo, hi),
-                    node: ast::MethDecl(ident, generics, explicit_self, style, d, body, vis)
+                    node: ast::MethDecl(ident,
+                                        generics,
+                                        abi,
+                                        explicit_self,
+                                        style,
+                                        d,
+                                        body,
+                                        vis)
                 })
               }
 
@@ -2620,51 +2639,11 @@ impl<'a> Parser<'a> {
         self.mk_expr(lo, hi, ExprIf(cond, thn, els))
     }
 
-    /// `|args| { ... }` or `{ ...}` like in `do` expressions
-    pub fn parse_lambda_block_expr(&mut self) -> Gc<Expr> {
-        self.parse_lambda_expr_(
-            |p| {
-                match p.token {
-                    token::BINOP(token::OR) | token::OROR => {
-                        p.parse_fn_block_decl()
-                    }
-                    _ => {
-                        // No argument list - `do foo {`
-                        P(FnDecl {
-                            inputs: Vec::new(),
-                            output: P(Ty {
-                                id: ast::DUMMY_NODE_ID,
-                                node: TyInfer,
-                                span: p.span
-                            }),
-                            cf: Return,
-                            variadic: false
-                        })
-                    }
-                }
-            },
-            |p| {
-                let blk = p.parse_block();
-                p.mk_expr(blk.span.lo, blk.span.hi, ExprBlock(blk))
-            })
-    }
-
-    /// `|args| expr`
+    // `|args| expr`
     pub fn parse_lambda_expr(&mut self) -> Gc<Expr> {
-        self.parse_lambda_expr_(|p| p.parse_fn_block_decl(),
-                                |p| p.parse_expr())
-    }
-
-    /// parse something of the form |args| expr
-    /// this is used both in parsing a lambda expr
-    /// and in parsing a block expr as e.g. in for...
-    pub fn parse_lambda_expr_(&mut self,
-                              parse_decl: |&mut Parser| -> P<FnDecl>,
-                              parse_body: |&mut Parser| -> Gc<Expr>)
-                              -> Gc<Expr> {
         let lo = self.span.lo;
-        let decl = parse_decl(self);
-        let body = parse_body(self);
+        let (decl, is_unboxed) = self.parse_fn_block_decl();
+        let body = self.parse_expr();
         let fakeblock = P(ast::Block {
             view_items: Vec::new(),
             stmts: Vec::new(),
@@ -2674,7 +2653,11 @@ impl<'a> Parser<'a> {
             span: body.span,
         });
 
-        return self.mk_expr(lo, body.span.hi, ExprFnBlock(decl, fakeblock));
+        if is_unboxed {
+            self.mk_expr(lo, body.span.hi, ExprUnboxedFn(decl, fakeblock))
+        } else {
+            self.mk_expr(lo, body.span.hi, ExprFnBlock(decl, fakeblock))
+        }
     }
 
     pub fn parse_else_expr(&mut self) -> Gc<Expr> {
@@ -3955,18 +3938,30 @@ impl<'a> Parser<'a> {
         (spanned(lo, hi, explicit_self), fn_decl)
     }
 
-    /// Parse the |arg, arg| header on a lambda
-    fn parse_fn_block_decl(&mut self) -> P<FnDecl> {
-        let inputs_captures = {
+    // parse the |arg, arg| header on a lambda
+    fn parse_fn_block_decl(&mut self) -> (P<FnDecl>, bool) {
+        let (is_unboxed, inputs_captures) = {
             if self.eat(&token::OROR) {
-                Vec::new()
+                (false, Vec::new())
             } else {
-                self.parse_unspanned_seq(
-                    &token::BINOP(token::OR),
+                self.expect(&token::BINOP(token::OR));
+                let is_unboxed = self.token == token::BINOP(token::AND) &&
+                    self.look_ahead(1, |t| {
+                        token::is_keyword(keywords::Mut, t)
+                    }) &&
+                    self.look_ahead(2, |t| *t == token::COLON);
+                if is_unboxed {
+                    self.bump();
+                    self.bump();
+                    self.bump();
+                }
+                let args = self.parse_seq_to_before_end(
                     &token::BINOP(token::OR),
                     seq_sep_trailing_disallowed(token::COMMA),
                     |p| p.parse_fn_block_arg()
-                )
+                );
+                self.bump();
+                (is_unboxed, args)
             }
         };
         let output = if self.eat(&token::RARROW) {
@@ -3979,12 +3974,12 @@ impl<'a> Parser<'a> {
             })
         };
 
-        P(FnDecl {
+        (P(FnDecl {
             inputs: inputs_captures,
             output: output,
             cf: Return,
             variadic: false
-        })
+        }), is_unboxed)
     }
 
     /// Parses the `(arg, arg) -> return_type` header on a procedure.
@@ -4079,6 +4074,11 @@ impl<'a> Parser<'a> {
                 (ast::MethMac(m), self.span.hi, attrs)
             } else {
                 let visa = self.parse_visibility();
+                let abi = if self.eat_keyword(keywords::Extern) {
+                    self.parse_opt_abi().unwrap_or(abi::C)
+                } else {
+                    abi::Rust
+                };
                 let fn_style = self.parse_fn_style();
                 let ident = self.parse_ident();
                 let generics = self.parse_generics();
@@ -4087,7 +4087,14 @@ impl<'a> Parser<'a> {
                     });
                 let (inner_attrs, body) = self.parse_inner_attrs_and_block();
                 let new_attrs = attrs.append(inner_attrs.as_slice());
-                (ast::MethDecl(ident, generics, explicit_self, fn_style, decl, body, visa),
+                (ast::MethDecl(ident,
+                               generics,
+                               abi,
+                               explicit_self,
+                               fn_style,
+                               decl,
+                               body,
+                               visa),
                  body.span.hi, new_attrs)
             }
         };