auto merge of #10132 : pcwalton/rust/proc, r=pcwalton
the feature gate for `once fn` if used with the `~` sigil. r? @brson
This commit is contained in:
commit
fed48cc861
29 changed files with 250 additions and 70 deletions
|
@ -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,
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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, ());
|
||||
}
|
||||
|
|
|
@ -409,6 +409,7 @@ impl CFGBuilder {
|
|||
ast::ExprInlineAsm(*) |
|
||||
ast::ExprSelf |
|
||||
ast::ExprFnBlock(*) |
|
||||
ast::ExprProc(*) |
|
||||
ast::ExprLit(*) |
|
||||
ast::ExprPath(*) => {
|
||||
self.straightline(expr, pred, [])
|
||||
|
|
|
@ -49,7 +49,7 @@ impl Visitor<Context> 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(_) => {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -47,7 +47,7 @@ impl Visitor<int> 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 => {
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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(*) |
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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| {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -3263,6 +3263,7 @@ pub fn expr_kind(tcx: ctxt,
|
|||
ast::ExprIf(*) |
|
||||
ast::ExprMatch(*) |
|
||||
ast::ExprFnBlock(*) |
|
||||
ast::ExprProc(*) |
|
||||
ast::ExprDoBody(*) |
|
||||
ast::ExprBlock(*) |
|
||||
ast::ExprRepeat(*) |
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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(*) |
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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(":");
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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),
|
||||
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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 },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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), _ => () }
|
||||
|
|
|
@ -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());
|
||||
|
|
27
src/test/run-pass/closure-reform.rs
Normal file
27
src/test/run-pass/closure-reform.rs
Normal file
|
@ -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
|
||||
});
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue