diff options
| author | Patrick Walton <pcwalton@mimiga.net> | 2014-05-28 22:26:56 -0700 |
|---|---|---|
| committer | Patrick Walton <pcwalton@mimiga.net> | 2014-07-18 09:01:37 -0700 |
| commit | 02adaca4dc7eb4594d8bda9a7e04bc0247fc2a74 (patch) | |
| tree | 2edb47de67e3c8a0d006f61217d7dffaab824b27 /src/libsyntax/parse/parser.rs | |
| parent | 5ddc7b4a252fbebee5f2ac87ed755139816d6823 (diff) | |
| download | rust-02adaca4dc7eb4594d8bda9a7e04bc0247fc2a74.tar.gz rust-02adaca4dc7eb4594d8bda9a7e04bc0247fc2a74.zip | |
librustc: Implement unboxed closures with mutable receivers
Diffstat (limited to 'src/libsyntax/parse/parser.rs')
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 119 |
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) } }; |
