diff options
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/ast.rs | 10 | ||||
| -rw-r--r-- | src/libsyntax/ast_map/blocks.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax/ext/build.rs | 4 | ||||
| -rw-r--r-- | src/libsyntax/ext/expand.rs | 6 | ||||
| -rw-r--r-- | src/libsyntax/fold.rs | 10 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 17 | ||||
| -rw-r--r-- | src/libsyntax/print/pprust.rs | 16 | ||||
| -rw-r--r-- | src/libsyntax/visit.rs | 4 |
8 files changed, 50 insertions, 19 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 0ea57e41b0f..46039a70fb2 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -526,9 +526,9 @@ pub enum Expr_ { // FIXME #6993: change to Option<Name> ... or not, if these are hygienic. ExprLoop(P<Block>, Option<Ident>), ExprMatch(Gc<Expr>, Vec<Arm>), - ExprFnBlock(P<FnDecl>, P<Block>), + ExprFnBlock(CaptureClause, P<FnDecl>, P<Block>), ExprProc(P<FnDecl>, P<Block>), - ExprUnboxedFn(P<FnDecl>, P<Block>), + ExprUnboxedFn(CaptureClause, P<FnDecl>, P<Block>), ExprBlock(P<Block>), ExprAssign(Gc<Expr>, Gc<Expr>), @@ -559,6 +559,12 @@ pub enum Expr_ { ExprParen(Gc<Expr>) } +#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +pub enum CaptureClause { + CaptureByValue, + CaptureByRef, +} + /// When the main rust parser encounters a syntax-extension invocation, it /// parses the arguments to the invocation as a token-tree. This is a very /// loose structure, such that all sorts of different AST-fragments can diff --git a/src/libsyntax/ast_map/blocks.rs b/src/libsyntax/ast_map/blocks.rs index a522f805543..83af390c4ed 100644 --- a/src/libsyntax/ast_map/blocks.rs +++ b/src/libsyntax/ast_map/blocks.rs @@ -206,7 +206,7 @@ impl FnLikeNode { }, ast_map::NodeMethod(ref m) => method(&**m), ast_map::NodeExpr(ref e) => match e.node { - ast::ExprFnBlock(ref decl, ref block) => + ast::ExprFnBlock(_, ref decl, ref block) => closure(ClosureParts::new(*decl, *block, e.id, e.span)), ast::ExprProc(ref decl, ref block) => closure(ClosureParts::new(*decl, *block, e.id, e.span)), diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 0e687c02c1d..f7eddca4b7a 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -876,14 +876,14 @@ impl<'a> AstBuilder for ExtCtxt<'a> { fn lambda_fn_decl(&self, span: Span, fn_decl: P<ast::FnDecl>, blk: P<ast::Block>) -> Gc<ast::Expr> { - self.expr(span, ast::ExprFnBlock(fn_decl, blk)) + self.expr(span, ast::ExprFnBlock(ast::CaptureByRef, fn_decl, blk)) } fn lambda(&self, span: Span, ids: Vec<ast::Ident> , blk: P<ast::Block>) -> Gc<ast::Expr> { let fn_decl = self.fn_decl( ids.iter().map(|id| self.arg(span, *id, self.ty_infer(span))).collect(), self.ty_infer(span)); - self.expr(span, ast::ExprFnBlock(fn_decl, blk)) + self.expr(span, ast::ExprFnBlock(ast::CaptureByRef, fn_decl, blk)) } fn lambda0(&self, span: Span, blk: P<ast::Block>) -> Gc<ast::Expr> { self.lambda(span, Vec::new(), blk) diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 808532d55bb..d918b28d4dc 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -74,10 +74,12 @@ fn expand_expr(e: Gc<ast::Expr>, fld: &mut MacroExpander) -> Gc<ast::Expr> { fld.cx.expr(e.span, ast::ExprForLoop(pat, head, body, opt_ident)) } - ast::ExprFnBlock(fn_decl, block) => { + ast::ExprFnBlock(capture_clause, fn_decl, block) => { let (rewritten_fn_decl, rewritten_block) = expand_and_rename_fn_decl_and_block(&*fn_decl, block, fld); - let new_node = ast::ExprFnBlock(rewritten_fn_decl, rewritten_block); + let new_node = ast::ExprFnBlock(capture_clause, + rewritten_fn_decl, + rewritten_block); box(GC) ast::Expr{id:e.id, node: new_node, span: fld.new_span(e.span)} } diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 80325c64349..02f1f4646a4 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -1094,16 +1094,18 @@ pub fn noop_fold_expr<T: Folder>(e: Gc<Expr>, folder: &mut T) -> Gc<Expr> { ExprMatch(folder.fold_expr(expr), arms.iter().map(|x| folder.fold_arm(x)).collect()) } - ExprFnBlock(ref decl, ref body) => { - ExprFnBlock(folder.fold_fn_decl(&**decl), + ExprFnBlock(capture_clause, ref decl, ref body) => { + ExprFnBlock(capture_clause, + folder.fold_fn_decl(&**decl), folder.fold_block(body.clone())) } ExprProc(ref decl, ref body) => { ExprProc(folder.fold_fn_decl(&**decl), folder.fold_block(body.clone())) } - ExprUnboxedFn(ref decl, ref body) => { - ExprUnboxedFn(folder.fold_fn_decl(&**decl), + ExprUnboxedFn(capture_clause, ref decl, ref body) => { + ExprUnboxedFn(capture_clause, + folder.fold_fn_decl(&**decl), folder.fold_block(*body)) } ExprBlock(ref blk) => ExprBlock(folder.fold_block(*blk)), diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 08d96f5b008..f0920603ad1 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -17,6 +17,7 @@ use ast::{Provided, Public, FnStyle}; use ast::{Mod, BiAdd, Arg, Arm, Attribute, BindByRef, BindByValue}; use ast::{BiBitAnd, BiBitOr, BiBitXor, Block}; use ast::{BlockCheckMode, UnBox}; +use ast::{CaptureByRef, CaptureByValue, CaptureClause}; use ast::{Crate, CrateConfig, Decl, DeclItem}; use ast::{DeclLocal, DefaultBlock, UnDeref, BiDiv, EMPTY_CTXT, EnumDef, ExplicitSelf}; use ast::{Expr, Expr_, ExprAddrOf, ExprMatch, ExprAgain}; @@ -1985,7 +1986,7 @@ impl<'a> Parser<'a> { ExprBlock(blk)); }, token::BINOP(token::OR) | token::OROR => { - return self.parse_lambda_expr(); + return self.parse_lambda_expr(CaptureByValue); }, // FIXME #13626: Should be able to stick in // token::SELF_KEYWORD_NAME @@ -2036,6 +2037,9 @@ impl<'a> Parser<'a> { hi = self.last_span.hi; }, _ => { + if self.eat_keyword(keywords::Ref) { + return self.parse_lambda_expr(CaptureByRef); + } if self.eat_keyword(keywords::Proc) { let decl = self.parse_proc_decl(); let body = self.parse_expr(); @@ -2696,7 +2700,8 @@ impl<'a> Parser<'a> { } // `|args| expr` - pub fn parse_lambda_expr(&mut self) -> Gc<Expr> { + pub fn parse_lambda_expr(&mut self, capture_clause: CaptureClause) + -> Gc<Expr> { let lo = self.span.lo; let (decl, is_unboxed) = self.parse_fn_block_decl(); let body = self.parse_expr(); @@ -2710,9 +2715,13 @@ impl<'a> Parser<'a> { }); if is_unboxed { - self.mk_expr(lo, body.span.hi, ExprUnboxedFn(decl, fakeblock)) + self.mk_expr(lo, + body.span.hi, + ExprUnboxedFn(capture_clause, decl, fakeblock)) } else { - self.mk_expr(lo, body.span.hi, ExprFnBlock(decl, fakeblock)) + self.mk_expr(lo, + body.span.hi, + ExprFnBlock(capture_clause, decl, fakeblock)) } } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 9c1b97f94a8..ed285e2aa44 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1473,7 +1473,9 @@ impl<'a> State<'a> { } try!(self.bclose_(expr.span, indent_unit)); } - ast::ExprFnBlock(ref decl, ref body) => { + ast::ExprFnBlock(capture_clause, ref decl, ref body) => { + try!(self.print_capture_clause(capture_clause)); + // in do/for blocks we don't want to show an empty // argument list, but at this point we don't know which // we are inside. @@ -1503,7 +1505,9 @@ impl<'a> State<'a> { // empty box to satisfy the close. try!(self.ibox(0)); } - ast::ExprUnboxedFn(ref decl, ref body) => { + ast::ExprUnboxedFn(capture_clause, ref decl, ref body) => { + try!(self.print_capture_clause(capture_clause)); + // in do/for blocks we don't want to show an empty // argument list, but at this point we don't know which // we are inside. @@ -2071,6 +2075,14 @@ impl<'a> State<'a> { self.maybe_print_comment(decl.output.span.lo) } + pub fn print_capture_clause(&mut self, capture_clause: ast::CaptureClause) + -> IoResult<()> { + match capture_clause { + ast::CaptureByValue => Ok(()), + ast::CaptureByRef => self.word_space("ref"), + } + } + pub fn print_proc_args(&mut self, decl: &ast::FnDecl) -> IoResult<()> { try!(word(&mut self.s, "proc")); try!(word(&mut self.s, "(")); diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 647e81db1f1..372cee9ad09 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -787,7 +787,7 @@ pub fn walk_expr<E: Clone, V: Visitor<E>>(visitor: &mut V, expression: &Expr, en visitor.visit_arm(arm, env.clone()) } } - ExprFnBlock(ref function_declaration, ref body) => { + ExprFnBlock(_, ref function_declaration, ref body) => { visitor.visit_fn(&FkFnBlock, &**function_declaration, &**body, @@ -795,7 +795,7 @@ pub fn walk_expr<E: Clone, V: Visitor<E>>(visitor: &mut V, expression: &Expr, en expression.id, env.clone()) } - ExprUnboxedFn(ref function_declaration, ref body) => { + ExprUnboxedFn(_, ref function_declaration, ref body) => { visitor.visit_fn(&FkFnBlock, &**function_declaration, &**body, |
