diff --git a/src/compiletest/procsrv.rs b/src/compiletest/procsrv.rs index 829916117d2..f8123d7b05c 100644 --- a/src/compiletest/procsrv.rs +++ b/src/compiletest/procsrv.rs @@ -48,7 +48,7 @@ pub fn run(lib_path: &str, input: Option<~str>) -> Result { let env = env + target_env(lib_path, prog); - let mut proc = run::Process::new(prog, args, run::ProcessOptions { + let mut process = run::Process::new(prog, args, run::ProcessOptions { env: Some(env), dir: None, in_fd: None, @@ -57,9 +57,9 @@ pub fn run(lib_path: &str, }); for input in input.iter() { - proc.input().write(input.as_bytes()); + process.input().write(input.as_bytes()); } - let output = proc.finish_with_output(); + let output = process.finish_with_output(); Result { status: output.status, diff --git a/src/librustc/front/feature_gate.rs b/src/librustc/front/feature_gate.rs index 6de94936d15..c17d6cabfed 100644 --- a/src/librustc/front/feature_gate.rs +++ b/src/librustc/front/feature_gate.rs @@ -132,7 +132,8 @@ impl Visitor<()> for Context { fn visit_ty(&mut self, t: &ast::Ty, _: ()) { match t.node { - ast::ty_closure(closure) if closure.onceness == ast::Once => { + ast::ty_closure(closure) if closure.onceness == ast::Once && + closure.sigil != ast::OwnedSigil => { self.gate_feature("once_fns", t.span, "once functions are \ experimental and likely to be removed"); diff --git a/src/librustc/middle/borrowck/check_loans.rs b/src/librustc/middle/borrowck/check_loans.rs index b05bdaa2032..77dec4ede10 100644 --- a/src/librustc/middle/borrowck/check_loans.rs +++ b/src/librustc/middle/borrowck/check_loans.rs @@ -656,7 +656,7 @@ impl<'self> CheckLoanCtxt<'self> { fn check_move_out_from_expr(&self, expr: @ast::Expr) { match expr.node { - ast::ExprFnBlock(*) => { + ast::ExprFnBlock(*) | ast::ExprProc(*) => { // moves due to capture clauses are checked // in `check_loans_in_fn`, so that we can // give a better error message diff --git a/src/librustc/middle/borrowck/gather_loans/mod.rs b/src/librustc/middle/borrowck/gather_loans/mod.rs index 36a49de8778..dd161b189da 100644 --- a/src/librustc/middle/borrowck/gather_loans/mod.rs +++ b/src/librustc/middle/borrowck/gather_loans/mod.rs @@ -307,7 +307,7 @@ fn gather_loans_in_expr(this: &mut GatherLoanCtxt, this.pop_repeating_id(body.id); } - ast::ExprFnBlock(*) => { + ast::ExprFnBlock(*) | ast::ExprProc(*) => { gather_moves::gather_captures(this.bccx, this.move_data, ex); visit::walk_expr(this, ex, ()); } diff --git a/src/librustc/middle/cfg/construct.rs b/src/librustc/middle/cfg/construct.rs index 27fbecb5979..fce318f173e 100644 --- a/src/librustc/middle/cfg/construct.rs +++ b/src/librustc/middle/cfg/construct.rs @@ -409,6 +409,7 @@ impl CFGBuilder { ast::ExprInlineAsm(*) | ast::ExprSelf | ast::ExprFnBlock(*) | + ast::ExprProc(*) | ast::ExprLit(*) | ast::ExprPath(*) => { self.straightline(expr, pred, []) diff --git a/src/librustc/middle/check_loop.rs b/src/librustc/middle/check_loop.rs index cc3511aa51f..a6aab151e5a 100644 --- a/src/librustc/middle/check_loop.rs +++ b/src/librustc/middle/check_loop.rs @@ -49,7 +49,7 @@ impl Visitor for CheckLoopVisitor { ExprLoop(ref b, _) => { self.visit_block(b, Context { in_loop: true,.. cx }); } - ExprFnBlock(_, ref b) => { + ExprFnBlock(_, ref b) | ExprProc(_, ref b) => { self.visit_block(b, Context { in_loop: false, can_ret: false }); } ExprBreak(_) => { diff --git a/src/librustc/middle/dataflow.rs b/src/librustc/middle/dataflow.rs index 7ad55936b9e..299aa65897e 100644 --- a/src/librustc/middle/dataflow.rs +++ b/src/librustc/middle/dataflow.rs @@ -431,7 +431,8 @@ impl<'self, O:DataFlowOperator> PropagationContext<'self, O> { self.merge_with_entry_set(expr.id, in_out); match expr.node { - ast::ExprFnBlock(ref decl, ref body) => { + ast::ExprFnBlock(ref decl, ref body) | + ast::ExprProc(ref decl, ref body) => { if self.dfcx.oper.walk_closures() { // In the absence of once fns, we must assume that // every function body will execute more than diff --git a/src/librustc/middle/freevars.rs b/src/librustc/middle/freevars.rs index 9aaddab69a1..7b0bb80eb28 100644 --- a/src/librustc/middle/freevars.rs +++ b/src/librustc/middle/freevars.rs @@ -47,7 +47,7 @@ impl Visitor for CollectFreevarsVisitor { fn visit_expr(&mut self, expr:@ast::Expr, depth:int) { match expr.node { - ast::ExprFnBlock(*) => { + ast::ExprFnBlock(*) | ast::ExprProc(*) => { visit::walk_expr(self, expr, depth + 1) } ast::ExprPath(*) | ast::ExprSelf => { diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index e9e416124af..a370da2893a 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -485,7 +485,7 @@ fn visit_expr(v: &mut LivenessVisitor, expr: @Expr, this: @mut IrMaps) { } visit::walk_expr(v, expr, this); } - ExprFnBlock(*) => { + ExprFnBlock(*) | ExprProc(*) => { // Interesting control flow (for loops can contain labeled // breaks or continues) this.add_live_node_for_node(expr.id, ExprNode(expr.span)); @@ -1023,8 +1023,8 @@ impl Liveness { self.propagate_through_expr(e, succ) } - ExprFnBlock(_, ref blk) => { - debug!("{} is an expr_fn_block", + ExprFnBlock(_, ref blk) | ExprProc(_, ref blk) => { + debug!("{} is an ExprFnBlock or ExprProc", expr_to_str(expr, self.tcx.sess.intr())); /* @@ -1498,7 +1498,8 @@ fn check_expr(this: &mut Liveness, expr: @Expr) { ExprCast(*) | ExprUnary(*) | ExprRet(*) | ExprBreak(*) | ExprAgain(*) | ExprLit(_) | ExprBlock(*) | ExprMac(*) | ExprAddrOf(*) | ExprStruct(*) | ExprRepeat(*) | - ExprParen(*) | ExprFnBlock(*) | ExprPath(*) | ExprSelf(*) => { + ExprParen(*) | ExprFnBlock(*) | ExprProc(*) | ExprPath(*) | + ExprSelf(*) => { visit::walk_expr(this, expr, ()); } ExprForLoop(*) => fail!("non-desugared expr_for_loop") diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 5e26201522c..bd2f69a1d03 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -424,7 +424,7 @@ impl mem_categorization_ctxt { ast::ExprAddrOf(*) | ast::ExprCall(*) | ast::ExprAssign(*) | ast::ExprAssignOp(*) | - ast::ExprFnBlock(*) | ast::ExprRet(*) | + ast::ExprFnBlock(*) | ast::ExprProc(*) | ast::ExprRet(*) | ast::ExprDoBody(*) | ast::ExprUnary(*) | ast::ExprMethodCall(*) | ast::ExprCast(*) | ast::ExprVstore(*) | ast::ExprVec(*) | ast::ExprTup(*) | ast::ExprIf(*) | diff --git a/src/librustc/middle/moves.rs b/src/librustc/middle/moves.rs index 6317e3a1abc..36a47578e27 100644 --- a/src/librustc/middle/moves.rs +++ b/src/librustc/middle/moves.rs @@ -555,7 +555,8 @@ impl VisitContext { self.use_expr(base, comp_mode); } - ExprFnBlock(ref decl, ref body) => { + ExprFnBlock(ref decl, ref body) | + ExprProc(ref decl, ref body) => { for a in decl.inputs.iter() { self.use_pat(a.pat); } diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index c16c39b5a09..8c5deeb94d5 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -5043,7 +5043,8 @@ impl Resolver { visit::walk_expr(self, expr, ()); } - ExprFnBlock(ref fn_decl, ref block) => { + ExprFnBlock(ref fn_decl, ref block) | + ExprProc(ref fn_decl, ref block) => { self.resolve_function(FunctionRibKind(expr.id, block.id), Some(fn_decl), NoTypeParameters, diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index 2138afd2e9b..cea39c8e3d2 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -569,7 +569,8 @@ pub fn create_function_debug_context(cx: &mut CrateContext, } ast_map::node_expr(ref expr) => { match expr.node { - ast::ExprFnBlock(ref fn_decl, ref top_level_block) => { + ast::ExprFnBlock(ref fn_decl, ref top_level_block) | + ast::ExprProc(ref fn_decl, ref top_level_block) => { let name = format!("fn{}", token::gensym("fn")); let name = token::str_to_ident(name); (name, fn_decl, @@ -2579,7 +2580,8 @@ fn populate_scope_map(cx: &mut CrateContext, } } - ast::ExprFnBlock(ast::fn_decl { inputs: ref inputs, _ }, ref block) => { + ast::ExprFnBlock(ast::fn_decl { inputs: ref inputs, _ }, ref block) | + ast::ExprProc(ast::fn_decl { inputs: ref inputs, _ }, ref block) => { do with_new_scope(cx, block.span, scope_stack, scope_map) |cx, scope_stack, scope_map| { diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs index 1c856f04b06..ca1bd2d8a95 100644 --- a/src/librustc/middle/trans/expr.rs +++ b/src/librustc/middle/trans/expr.rs @@ -717,10 +717,11 @@ fn trans_rvalue_dps_unadjusted(bcx: @mut Block, expr: &ast::Expr, ast::ExprVec(*) | ast::ExprRepeat(*) => { return tvec::trans_fixed_vstore(bcx, expr, expr, dest); } - ast::ExprFnBlock(ref decl, ref body) => { + ast::ExprFnBlock(ref decl, ref body) | + ast::ExprProc(ref decl, ref body) => { let expr_ty = expr_ty(bcx, expr); let sigil = ty::ty_closure_sigil(expr_ty); - debug!("translating fn_block {} with type {}", + debug!("translating block function {} with type {}", expr_to_str(expr, tcx.sess.intr()), expr_ty.repr(tcx)); return closure::trans_expr_fn(bcx, sigil, decl, body, diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 39aa6c5e396..fbfac3b7518 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -3263,6 +3263,7 @@ pub fn expr_kind(tcx: ctxt, ast::ExprIf(*) | ast::ExprMatch(*) | ast::ExprFnBlock(*) | + ast::ExprProc(*) | ast::ExprDoBody(*) | ast::ExprBlock(*) | ast::ExprRepeat(*) | diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index d71aa776689..ab6ed65d542 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -1408,6 +1408,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, for (i, arg) in args.iter().enumerate() { let is_block = match arg.node { ast::ExprFnBlock(*) | + ast::ExprProc(*) | ast::ExprDoBody(*) => true, _ => false }; @@ -2592,6 +2593,15 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, check_expr_fn(fcx, expr, None, decl, body, Vanilla, expected); } + ast::ExprProc(ref decl, ref body) => { + check_expr_fn(fcx, + expr, + Some(ast::OwnedSigil), + decl, + body, + Vanilla, + expected); + } ast::ExprDoBody(b) => { let expected_sty = unpack_expected(fcx, expected, diff --git a/src/librustc/middle/typeck/check/regionck.rs b/src/librustc/middle/typeck/check/regionck.rs index 09fc7b5c15c..c0aa669d920 100644 --- a/src/librustc/middle/typeck/check/regionck.rs +++ b/src/librustc/middle/typeck/check/regionck.rs @@ -427,7 +427,7 @@ fn visit_expr(rcx: &mut Rcx, expr: @ast::Expr) { visit::walk_expr(rcx, expr, ()); } - ast::ExprFnBlock(*) => { + ast::ExprFnBlock(*) | ast::ExprProc(*) => { check_expr_fn_block(rcx, expr); } @@ -457,7 +457,7 @@ fn check_expr_fn_block(rcx: &mut Rcx, expr: @ast::Expr) { let tcx = rcx.fcx.tcx(); match expr.node { - ast::ExprFnBlock(_, ref body) => { + ast::ExprFnBlock(_, ref body) | ast::ExprProc(_, ref body) => { let function_type = rcx.resolve_node_type(expr.id); match ty::get(function_type).sty { ty::ty_closure( @@ -1027,6 +1027,7 @@ pub mod guarantor { ast::ExprIf(*) | ast::ExprMatch(*) | ast::ExprFnBlock(*) | + ast::ExprProc(*) | ast::ExprDoBody(*) | ast::ExprBlock(*) | ast::ExprRepeat(*) | diff --git a/src/librustc/middle/typeck/check/writeback.rs b/src/librustc/middle/typeck/check/writeback.rs index 46c7968a0a4..1d724e22de9 100644 --- a/src/librustc/middle/typeck/check/writeback.rs +++ b/src/librustc/middle/typeck/check/writeback.rs @@ -245,7 +245,7 @@ fn visit_expr(e: @ast::Expr, wbcx: &mut WbCtxt) { } match e.node { - ast::ExprFnBlock(ref decl, _) => { + ast::ExprFnBlock(ref decl, _) | ast::ExprProc(ref decl, _) => { for input in decl.inputs.iter() { let _ = resolve_type_vars_for_node(wbcx, e.span, input.id); } diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index d5219ed0867..2f8c1f6f97d 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -337,7 +337,14 @@ pub fn ty_to_str(cx: ctxt, typ: t) -> ~str { } fn closure_to_str(cx: ctxt, cty: &ty::ClosureTy) -> ~str { - let mut s = cty.sigil.to_str(); + let is_proc = + (cty.sigil, cty.onceness) == (ast::OwnedSigil, ast::Once); + + let mut s = if is_proc { + ~"" + } else { + cty.sigil.to_str() + }; match (cty.sigil, cty.region) { (ast::ManagedSigil, ty::re_static) | @@ -356,15 +363,19 @@ pub fn ty_to_str(cx: ctxt, typ: t) -> ~str { } }; - match cty.onceness { - ast::Many => {} - ast::Once => { - s.push_str(cty.onceness.to_str()); - s.push_char(' '); - } - }; + if is_proc { + s.push_str("proc"); + } else { + match cty.onceness { + ast::Many => {} + ast::Once => { + s.push_str(cty.onceness.to_str()); + s.push_char(' '); + } + }; - s.push_str("fn"); + s.push_str("fn"); + } if !cty.bounds.is_empty() { s.push_str(":"); diff --git a/src/libstd/rt/io/native/process.rs b/src/libstd/rt/io/native/process.rs index 91fff6d9263..0fa454b94d0 100644 --- a/src/libstd/rt/io/native/process.rs +++ b/src/libstd/rt/io/native/process.rs @@ -649,23 +649,25 @@ fn waitpid(pid: pid_t) -> int { unsafe { - let proc = OpenProcess(SYNCHRONIZE | PROCESS_QUERY_INFORMATION, FALSE, pid as DWORD); - if proc.is_null() { + let process = OpenProcess(SYNCHRONIZE | PROCESS_QUERY_INFORMATION, + FALSE, + pid as DWORD); + if process.is_null() { fail!("failure in OpenProcess: {}", os::last_os_error()); } loop { let mut status = 0; - if GetExitCodeProcess(proc, &mut status) == FALSE { - CloseHandle(proc); + if GetExitCodeProcess(process, &mut status) == FALSE { + CloseHandle(process); fail!("failure in GetExitCodeProcess: {}", os::last_os_error()); } if status != STILL_ACTIVE { - CloseHandle(proc); + CloseHandle(process); return status as int; } - if WaitForSingleObject(proc, INFINITE) == WAIT_FAILED { - CloseHandle(proc); + if WaitForSingleObject(process, INFINITE) == WAIT_FAILED { + CloseHandle(process); fail!("failure in WaitForSingleObject: {}", os::last_os_error()); } } diff --git a/src/libstd/run.rs b/src/libstd/run.rs index 973e866e335..9e6fdf2ba4c 100644 --- a/src/libstd/run.rs +++ b/src/libstd/run.rs @@ -413,7 +413,7 @@ mod tests { let pipe_out = os::pipe(); let pipe_err = os::pipe(); - let mut proc = run::Process::new("cat", [], run::ProcessOptions { + let mut process = run::Process::new("cat", [], run::ProcessOptions { dir: None, env: None, in_fd: Some(pipe_in.input), @@ -430,7 +430,7 @@ mod tests { } let actual = readclose(pipe_out.input); readclose(pipe_err.input); - proc.finish(); + process.finish(); assert_eq!(~"test", actual); } 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), 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(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 + "proc", // 65 - "be", // 65 - "pure", // 66 - "yield", // 67 - "typeof", // 68 - "alignof", // 69 - "offsetof", // 70 - "sizeof", // 71 + "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 }, + Proc => Ident { name: 65, 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 }, + 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, 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>(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()); diff --git a/src/test/run-pass/closure-reform.rs b/src/test/run-pass/closure-reform.rs new file mode 100644 index 00000000000..c765ebe9643 --- /dev/null +++ b/src/test/run-pass/closure-reform.rs @@ -0,0 +1,27 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +fn call_it(f: proc(~str) -> ~str) { + println(f(~"Fred")) +} + +pub fn main() { + let greeting = ~"Hi "; + do call_it |s| { + greeting + s + } + + let greeting = ~"Hello "; + call_it(proc(s) { + greeting + s + }); + + let greeting = ~"Goodbye "; + call_it(proc(s) greeting + s); + + let greeting = ~"How's life, "; + call_it(proc(s: ~str) -> ~str { + greeting + s + }); +} + diff --git a/src/test/run-pass/core-run-destroy.rs b/src/test/run-pass/core-run-destroy.rs index 4ff184b4483..aee4c7e40bc 100644 --- a/src/test/run-pass/core-run-destroy.rs +++ b/src/test/run-pass/core-run-destroy.rs @@ -64,14 +64,14 @@ fn test_destroy_actually_kills(force: bool) { use std::libc::consts::os::extra::{FALSE, PROCESS_QUERY_INFORMATION, STILL_ACTIVE }; unsafe { - let proc = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid as DWORD); - if proc.is_null() { + let process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid as DWORD); + if process.is_null() { return false; } - // proc will be non-null if the process is alive, or if it died recently + // process will be non-null if the process is alive, or if it died recently let mut status = 0; - GetExitCodeProcess(proc, &mut status); - CloseHandle(proc); + GetExitCodeProcess(process, &mut status); + CloseHandle(process); return status == STILL_ACTIVE; } }