diff options
| author | bors <bors@rust-lang.org> | 2013-10-29 10:52:25 -0700 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2013-10-29 10:52:25 -0700 |
| commit | fed48cc861fd858762c1e9b498675bfa4dee2d38 (patch) | |
| tree | 01c61601be0db74a12ff9504f6eace70add85385 /src/libsyntax | |
| parent | 52f42f16387d0142944f376ea31c554c9caa2189 (diff) | |
| parent | 7e77bf17694e31c741fe3a31c7eca5437d9cb6d5 (diff) | |
| download | rust-fed48cc861fd858762c1e9b498675bfa4dee2d38.tar.gz rust-fed48cc861fd858762c1e9b498675bfa4dee2d38.zip | |
auto merge of #10132 : pcwalton/rust/proc, r=pcwalton
the feature gate for `once fn` if used with the `~` sigil. r? @brson
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/ast.rs | 1 | ||||
| -rw-r--r-- | src/libsyntax/fold.rs | 3 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 57 | ||||
| -rw-r--r-- | src/libsyntax/parse/token.rs | 41 | ||||
| -rw-r--r-- | src/libsyntax/print/pprust.rs | 61 | ||||
| -rw-r--r-- | src/libsyntax/visit.rs | 8 |
6 files changed, 145 insertions, 26 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 3467e1aaadc..cf72455a83a 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -537,6 +537,7 @@ pub enum Expr_ { ExprLoop(Block, Option<Ident>), ExprMatch(@Expr, ~[Arm]), ExprFnBlock(fn_decl, Block), + ExprProc(fn_decl, Block), ExprDoBody(@Expr), ExprBlock(Block), diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index fddf674a846..d579e7dd2c7 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -786,6 +786,9 @@ pub fn noop_fold_expr<T:ast_fold>(e: @ast::Expr, folder: &T) -> @ast::Expr { folder.fold_block(body) ) } + ExprProc(ref decl, ref body) => { + ExprProc(fold_fn_decl(decl, folder), folder.fold_block(body)) + } ExprBlock(ref blk) => ExprBlock(folder.fold_block(blk)), ExprAssign(el, er) => { ExprAssign(folder.fold_expr(el), folder.fold_expr(er)) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 8b399266676..716fb5040f6 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -27,7 +27,7 @@ use ast::{ExprAssign, ExprAssignOp, ExprBinary, ExprBlock}; use ast::{ExprBreak, ExprCall, ExprCast, ExprDoBody}; use ast::{ExprField, ExprFnBlock, ExprIf, ExprIndex}; use ast::{ExprLit, ExprLogLevel, ExprLoop, ExprMac}; -use ast::{ExprMethodCall, ExprParen, ExprPath, ExprRepeat}; +use ast::{ExprMethodCall, ExprParen, ExprPath, ExprProc, ExprRepeat}; use ast::{ExprRet, ExprSelf, ExprStruct, ExprTup, ExprUnary}; use ast::{ExprVec, ExprVstore, ExprVstoreMutBox}; use ast::{ExprVstoreSlice, ExprVstoreBox}; @@ -814,6 +814,21 @@ impl Parser { }); } + // Parses a procedure type (`proc`). The initial `proc` keyword must + // already have been parsed. + pub fn parse_proc_type(&self) -> ty_ { + let (decl, lifetimes) = self.parse_ty_fn_decl(); + ty_closure(@TyClosure { + sigil: OwnedSigil, + region: None, + purity: impure_fn, + onceness: Once, + bounds: None, + decl: decl, + lifetimes: lifetimes, + }) + } + // parse a ty_closure type pub fn parse_ty_closure(&self, sigil: ast::Sigil, @@ -1123,6 +1138,8 @@ impl Parser { let e = self.parse_expr(); self.expect(&token::RPAREN); ty_typeof(e) + } else if self.eat_keyword(keywords::Proc) { + self.parse_proc_type() } else if *self.token == token::MOD_SEP || is_ident_or_path(self.token) { // NAMED TYPE @@ -1672,6 +1689,19 @@ impl Parser { ExprBlock(blk)); } else if token::is_bar(&*self.token) { return self.parse_lambda_expr(); + } else if self.eat_keyword(keywords::Proc) { + let decl = self.parse_proc_decl(); + let body = self.parse_expr(); + let fakeblock = ast::Block { + view_items: ~[], + stmts: ~[], + expr: Some(body), + id: ast::DUMMY_NODE_ID, + rules: DefaultBlock, + span: body.span, + }; + + return self.mk_expr(lo, body.span.hi, ExprProc(decl, fakeblock)); } else if self.eat_keyword(keywords::Self) { ex = ExprSelf; hi = self.span.hi; @@ -3616,6 +3646,31 @@ impl Parser { } } + // Parses the `(arg, arg) -> return_type` header on a procedure. + fn parse_proc_decl(&self) -> fn_decl { + let inputs = + self.parse_unspanned_seq(&token::LPAREN, + &token::RPAREN, + seq_sep_trailing_allowed(token::COMMA), + |p| p.parse_fn_block_arg()); + + let output = if self.eat(&token::RARROW) { + self.parse_ty(false) + } else { + Ty { + id: ast::DUMMY_NODE_ID, + node: ty_infer, + span: *self.span, + } + }; + + ast::fn_decl { + inputs: inputs, + output: output, + cf: return_val, + } + } + // parse the name and optional generic types of a function header. fn parse_fn_header(&self) -> (Ident, ast::Generics) { let id = self.parse_ident(); diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 27747d94b66..3d8fa1b6728 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -486,14 +486,15 @@ fn mk_fresh_ident_interner() -> @ident_interner { "while", // 62 "in", // 63 "continue", // 64 - - "be", // 65 - "pure", // 66 - "yield", // 67 - "typeof", // 68 - "alignof", // 69 - "offsetof", // 70 - "sizeof", // 71 + "proc", // 65 + + "be", // 66 + "pure", // 67 + "yield", // 68 + "typeof", // 69 + "alignof", // 70 + "offsetof", // 71 + "sizeof", // 72 ]; @interner::StrInterner::prefill(init_vec) @@ -502,9 +503,9 @@ fn mk_fresh_ident_interner() -> @ident_interner { static SELF_KEYWORD_NAME: uint = 8; static STATIC_KEYWORD_NAME: uint = 27; static STRICT_KEYWORD_START: uint = 32; -static STRICT_KEYWORD_FINAL: uint = 64; -static RESERVED_KEYWORD_START: uint = 65; -static RESERVED_KEYWORD_FINAL: uint = 71; +static STRICT_KEYWORD_FINAL: uint = 65; +static RESERVED_KEYWORD_START: uint = 66; +static RESERVED_KEYWORD_FINAL: uint = 72; // if an interner exists in TLS, return it. Otherwise, prepare a // fresh one. @@ -645,6 +646,7 @@ pub mod keywords { Use, While, Continue, + Proc, // Reserved keywords Alignof, @@ -694,14 +696,15 @@ pub mod keywords { Use => Ident { name: 61, ctxt: 0 }, While => Ident { name: 62, ctxt: 0 }, Continue => Ident { name: 64, ctxt: 0 }, - - Alignof => Ident { name: 69, ctxt: 0 }, - Be => Ident { name: 65, ctxt: 0 }, - Offsetof => Ident { name: 70, ctxt: 0 }, - Pure => Ident { name: 66, ctxt: 0 }, - Sizeof => Ident { name: 71, ctxt: 0 }, - Typeof => Ident { name: 68, ctxt: 0 }, - Yield => Ident { name: 67, ctxt: 0 }, + Proc => Ident { name: 65, ctxt: 0 }, + + Alignof => Ident { name: 70, ctxt: 0 }, + Be => Ident { name: 66, ctxt: 0 }, + Offsetof => Ident { name: 71, ctxt: 0 }, + Pure => Ident { name: 67, ctxt: 0 }, + Sizeof => Ident { name: 72, ctxt: 0 }, + Typeof => Ident { name: 69, ctxt: 0 }, + Yield => Ident { name: 68, ctxt: 0 }, } } } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index f3090c7dd16..33bdcdd1b03 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1350,6 +1350,33 @@ pub fn print_expr(s: @ps, expr: &ast::Expr) { // empty box to satisfy the close. ibox(s, 0); } + ast::ExprProc(ref decl, ref body) => { + // 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. + // + // if !decl.inputs.is_empty() { + print_proc_args(s, decl); + space(s.s); + // } + assert!(body.stmts.is_empty()); + assert!(body.expr.is_some()); + // we extract the block, so as not to create another set of boxes + match body.expr.unwrap().node { + ast::ExprBlock(ref blk) => { + print_block_unclosed(s, blk); + } + _ => { + // this is a bare expression + print_expr(s, body.expr.unwrap()); + end(s); // need to close a box + } + } + // a box will be closed by print_expr, but we didn't want an overall + // wrapper so we closed the corresponding opening. so create an + // empty box to satisfy the close. + ibox(s, 0); + } ast::ExprDoBody(body) => { print_expr(s, body); } @@ -1777,6 +1804,24 @@ pub fn print_fn_block_args(s: @ps, decl: &ast::fn_decl) { maybe_print_comment(s, decl.output.span.lo); } +pub fn print_proc_args(s: @ps, decl: &ast::fn_decl) { + word(s.s, "proc"); + word(s.s, "("); + print_fn_args(s, decl, None); + word(s.s, ")"); + + match decl.output.node { + ast::ty_infer => {} + _ => { + space_if_not_bol(s); + word_space(s, "->"); + print_type(s, &decl.output); + } + } + + maybe_print_comment(s, decl.output.span.lo); +} + pub fn print_bounds(s: @ps, bounds: &OptVec<ast::TyParamBound>, print_colon_anyway: bool) { if !bounds.is_empty() { @@ -1968,12 +2013,16 @@ pub fn print_ty_fn(s: @ps, // Duplicates the logic in `print_fn_header_info()`. This is because that // function prints the sigil in the wrong place. That should be fixed. - print_extern_opt_abis(s, opt_abis); - print_opt_sigil(s, opt_sigil); - print_opt_lifetime(s, opt_region); - print_purity(s, purity); - print_onceness(s, onceness); - word(s.s, "fn"); + if opt_sigil == Some(ast::OwnedSigil) && onceness == ast::Once { + word(s.s, "proc"); + } else { + print_extern_opt_abis(s, opt_abis); + print_opt_sigil(s, opt_sigil); + print_opt_lifetime(s, opt_region); + print_purity(s, purity); + print_onceness(s, onceness); + word(s.s, "fn"); + } match id { Some(id) => { word(s.s, " "); print_ident(s, id); } _ => () } do opt_bounds.as_ref().map |bounds| { print_bounds(s, bounds, true); }; match generics { Some(g) => print_generics(s, g), _ => () } diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index e879d67fbf2..09ee87d1701 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -560,6 +560,14 @@ pub fn walk_expr<E:Clone, V:Visitor<E>>(visitor: &mut V, expression: @Expr, env: expression.id, env.clone()) } + ExprProc(ref function_declaration, ref body) => { + visitor.visit_fn(&fk_fn_block, + function_declaration, + body, + expression.span, + expression.id, + env.clone()) + } ExprBlock(ref block) => visitor.visit_block(block, env.clone()), ExprAssign(left_hand_expression, right_hand_expression) => { visitor.visit_expr(right_hand_expression, env.clone()); |
