mirror of
https://github.com/rust-lang/rust.git
synced 2025-06-06 04:08:40 +00:00
Support an alternate for syntax that calls a higher-order function
The last argument of the call must be a block, and the type of this argument must a function returning bool. `break` and `cont` are supported in the body of the block, and return `false` or `true` from the function. When the end of the function is reached, `true` is implicitly returned. for vec::all([1, 2, 3]) {|elt| if elt == 2 { break; } log(error, elt); } Issue #1619
This commit is contained in:
parent
9638e7fece
commit
f6e3738b9c
@ -156,7 +156,7 @@ fn compile_upto(sess: session, cfg: ast::crate_cfg,
|
|||||||
time(time_passes, "block-use checking",
|
time(time_passes, "block-use checking",
|
||||||
bind middle::block_use::check_crate(ty_cx, crate));
|
bind middle::block_use::check_crate(ty_cx, crate));
|
||||||
time(time_passes, "loop checking",
|
time(time_passes, "loop checking",
|
||||||
bind middle::check_loop::check_crate(sess, crate));
|
bind middle::check_loop::check_crate(ty_cx, crate));
|
||||||
time(time_passes, "function usage",
|
time(time_passes, "function usage",
|
||||||
bind fn_usage::check_crate_fn_usage(ty_cx, crate));
|
bind fn_usage::check_crate_fn_usage(ty_cx, crate));
|
||||||
time(time_passes, "alt checking",
|
time(time_passes, "alt checking",
|
||||||
|
@ -33,6 +33,10 @@ fn visit_expr(ex: @expr, cx: ctx, v: visit::vt<ctx>) {
|
|||||||
i += 1u;
|
i += 1u;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
expr_loop_body(body) {
|
||||||
|
cx.allow_block = true;
|
||||||
|
v.visit_expr(body, cx, v);
|
||||||
|
}
|
||||||
_ {
|
_ {
|
||||||
cx.allow_block = false;
|
cx.allow_block = false;
|
||||||
visit::visit_expr(ex, cx, v);
|
visit::visit_expr(ex, cx, v);
|
||||||
|
@ -4,7 +4,7 @@ import driver::session::session;
|
|||||||
|
|
||||||
type ctx = {in_loop: bool, can_ret: bool};
|
type ctx = {in_loop: bool, can_ret: bool};
|
||||||
|
|
||||||
fn check_crate(sess: session, crate: @crate) {
|
fn check_crate(tcx: ty::ctxt, crate: @crate) {
|
||||||
visit::visit_crate(*crate, {in_loop: false,can_ret: true}, visit::mk_vt(@{
|
visit::visit_crate(*crate, {in_loop: false,can_ret: true}, visit::mk_vt(@{
|
||||||
visit_item: {|i, _cx, v|
|
visit_item: {|i, _cx, v|
|
||||||
visit::visit_item(i, {in_loop: false, can_ret: true}, v);
|
visit::visit_item(i, {in_loop: false, can_ret: true}, v);
|
||||||
@ -21,28 +21,31 @@ fn check_crate(sess: session, crate: @crate) {
|
|||||||
expr_fn(_, _, _, _) {
|
expr_fn(_, _, _, _) {
|
||||||
visit::visit_expr(e, {in_loop: false, can_ret: true}, v);
|
visit::visit_expr(e, {in_loop: false, can_ret: true}, v);
|
||||||
}
|
}
|
||||||
expr_fn_block(fn_decl, blk) {
|
expr_fn_block(_, b) {
|
||||||
visit::visit_expr(e, {in_loop: false, can_ret: false}, v);
|
v.visit_block(b, {in_loop: false, can_ret: false}, v);
|
||||||
|
}
|
||||||
|
expr_loop_body(@{node: expr_fn_block(_, b), _}) {
|
||||||
|
v.visit_block(b, {in_loop: true, can_ret: false}, v);
|
||||||
}
|
}
|
||||||
expr_break {
|
expr_break {
|
||||||
if !cx.in_loop {
|
if !cx.in_loop {
|
||||||
sess.span_err(e.span, "`break` outside of loop");
|
tcx.sess.span_err(e.span, "`break` outside of loop");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
expr_cont {
|
expr_cont {
|
||||||
if !cx.in_loop {
|
if !cx.in_loop {
|
||||||
sess.span_err(e.span, "`cont` outside of loop");
|
tcx.sess.span_err(e.span, "`cont` outside of loop");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
expr_ret(oe) {
|
expr_ret(oe) {
|
||||||
if !cx.can_ret {
|
if !cx.can_ret {
|
||||||
sess.span_err(e.span, "`ret` in block function");
|
tcx.sess.span_err(e.span, "`ret` in block function");
|
||||||
}
|
}
|
||||||
visit::visit_expr_opt(oe, cx, v);
|
visit::visit_expr_opt(oe, cx, v);
|
||||||
}
|
}
|
||||||
expr_be(re) {
|
expr_be(re) {
|
||||||
if !cx.can_ret {
|
if !cx.can_ret {
|
||||||
sess.span_err(e.span, "`be` in block function");
|
tcx.sess.span_err(e.span, "`be` in block function");
|
||||||
}
|
}
|
||||||
v.visit_expr(re, cx, v);
|
v.visit_expr(re, cx, v);
|
||||||
}
|
}
|
||||||
|
@ -2990,20 +2990,24 @@ fn trans_expr(bcx: block, e: @ast::expr, dest: dest) -> block {
|
|||||||
}
|
}
|
||||||
ast::expr_addr_of(_, x) { ret trans_addr_of(bcx, x, dest); }
|
ast::expr_addr_of(_, x) { ret trans_addr_of(bcx, x, dest); }
|
||||||
ast::expr_fn(proto, decl, body, cap_clause) {
|
ast::expr_fn(proto, decl, body, cap_clause) {
|
||||||
ret closure::trans_expr_fn(
|
ret closure::trans_expr_fn(bcx, proto, decl, body, e.span, e.id,
|
||||||
bcx, proto, decl, body, e.span, e.id, *cap_clause, dest);
|
*cap_clause, false, dest);
|
||||||
}
|
}
|
||||||
ast::expr_fn_block(decl, body) {
|
ast::expr_fn_block(decl, body) {
|
||||||
alt ty::get(expr_ty(bcx, e)).struct {
|
alt check ty::get(expr_ty(bcx, e)).struct {
|
||||||
ty::ty_fn({proto, _}) {
|
ty::ty_fn({proto, _}) {
|
||||||
#debug("translating fn_block %s with type %s",
|
#debug("translating fn_block %s with type %s",
|
||||||
expr_to_str(e), ty_to_str(tcx, expr_ty(bcx, e)));
|
expr_to_str(e), ty_to_str(tcx, expr_ty(bcx, e)));
|
||||||
let cap_clause = { copies: [], moves: [] };
|
ret closure::trans_expr_fn(bcx, proto, decl, body, e.span, e.id,
|
||||||
ret closure::trans_expr_fn(
|
{copies: [], moves: []}, false, dest);
|
||||||
bcx, proto, decl, body, e.span, e.id, cap_clause, dest);
|
|
||||||
}
|
}
|
||||||
_ {
|
}
|
||||||
fail "type of fn block is not a function!";
|
}
|
||||||
|
ast::expr_loop_body(b@@{node: ast::expr_fn_block(decl, body), _}) {
|
||||||
|
alt check ty::get(expr_ty(bcx, e)).struct {
|
||||||
|
ty::ty_fn({proto, _}) {
|
||||||
|
ret closure::trans_expr_fn(bcx, proto, decl, body, e.span, b.id,
|
||||||
|
{copies: [], moves: []}, true, dest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3375,7 +3379,16 @@ fn trans_break_cont(bcx: block, to_end: bool)
|
|||||||
}
|
}
|
||||||
_ {}
|
_ {}
|
||||||
}
|
}
|
||||||
unwind = alt check unwind.parent { parent_some(cx) { cx } };
|
unwind = alt unwind.parent {
|
||||||
|
parent_some(cx) { cx }
|
||||||
|
// This is a return from a loop body block
|
||||||
|
parent_none {
|
||||||
|
Store(bcx, C_bool(!to_end), bcx.fcx.llretptr);
|
||||||
|
cleanup_and_leave(bcx, none, some(bcx.fcx.llreturn));
|
||||||
|
Unreachable(bcx);
|
||||||
|
ret bcx;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
cleanup_and_Br(bcx, unwind, target.llbb);
|
cleanup_and_Br(bcx, unwind, target.llbb);
|
||||||
Unreachable(bcx);
|
Unreachable(bcx);
|
||||||
@ -3895,7 +3908,8 @@ fn trans_closure(ccx: @crate_ctxt, path: path, decl: ast::fn_decl,
|
|||||||
ty_self: self_arg,
|
ty_self: self_arg,
|
||||||
param_substs: option<param_substs>,
|
param_substs: option<param_substs>,
|
||||||
id: ast::node_id,
|
id: ast::node_id,
|
||||||
maybe_load_env: fn(fn_ctxt)) {
|
maybe_load_env: fn(fn_ctxt),
|
||||||
|
finish: fn(block)) {
|
||||||
let _icx = ccx.insn_ctxt("trans_closure");
|
let _icx = ccx.insn_ctxt("trans_closure");
|
||||||
set_uwtable(llfndecl);
|
set_uwtable(llfndecl);
|
||||||
|
|
||||||
@ -3932,6 +3946,7 @@ fn trans_closure(ccx: @crate_ctxt, path: path, decl: ast::fn_decl,
|
|||||||
} else {
|
} else {
|
||||||
bcx = trans_block(bcx, body, save_in(fcx.llretptr));
|
bcx = trans_block(bcx, body, save_in(fcx.llretptr));
|
||||||
}
|
}
|
||||||
|
finish(bcx);
|
||||||
cleanup_and_Br(bcx, bcx_top, fcx.llreturn);
|
cleanup_and_Br(bcx, bcx_top, fcx.llreturn);
|
||||||
|
|
||||||
// Insert the mandatory first few basic blocks before lltop.
|
// Insert the mandatory first few basic blocks before lltop.
|
||||||
@ -3957,7 +3972,7 @@ fn trans_fn(ccx: @crate_ctxt,
|
|||||||
if ccx.sess.opts.extra_debuginfo {
|
if ccx.sess.opts.extra_debuginfo {
|
||||||
debuginfo::create_function(fcx);
|
debuginfo::create_function(fcx);
|
||||||
}
|
}
|
||||||
});
|
}, {|_bcx|});
|
||||||
if do_time {
|
if do_time {
|
||||||
let end = time::get_time();
|
let end = time::get_time();
|
||||||
log_fn_time(ccx, path_str(path), start, end);
|
log_fn_time(ccx, path_str(path), start, end);
|
||||||
|
@ -367,6 +367,7 @@ fn trans_expr_fn(bcx: block,
|
|||||||
sp: span,
|
sp: span,
|
||||||
id: ast::node_id,
|
id: ast::node_id,
|
||||||
cap_clause: ast::capture_clause,
|
cap_clause: ast::capture_clause,
|
||||||
|
is_loop_body: bool,
|
||||||
dest: dest) -> block {
|
dest: dest) -> block {
|
||||||
let _icx = bcx.insn_ctxt("closure::trans_expr_fn");
|
let _icx = bcx.insn_ctxt("closure::trans_expr_fn");
|
||||||
if dest == ignore { ret bcx; }
|
if dest == ignore { ret bcx; }
|
||||||
@ -385,6 +386,8 @@ fn trans_expr_fn(bcx: block,
|
|||||||
trans_closure(ccx, sub_path, decl, body, llfn, no_self,
|
trans_closure(ccx, sub_path, decl, body, llfn, no_self,
|
||||||
bcx.fcx.param_substs, id, {|fcx|
|
bcx.fcx.param_substs, id, {|fcx|
|
||||||
load_environment(fcx, cdata_ty, cap_vars, ck);
|
load_environment(fcx, cdata_ty, cap_vars, ck);
|
||||||
|
}, {|bcx|
|
||||||
|
if is_loop_body { Store(bcx, C_bool(true), bcx.fcx.llretptr); }
|
||||||
});
|
});
|
||||||
llbox
|
llbox
|
||||||
};
|
};
|
||||||
@ -395,7 +398,7 @@ fn trans_expr_fn(bcx: block,
|
|||||||
ast::proto_uniq { trans_closure_env(ty::ck_uniq) }
|
ast::proto_uniq { trans_closure_env(ty::ck_uniq) }
|
||||||
ast::proto_bare {
|
ast::proto_bare {
|
||||||
trans_closure(ccx, sub_path, decl, body, llfn, no_self, none,
|
trans_closure(ccx, sub_path, decl, body, llfn, no_self, none,
|
||||||
id, {|_fcx|});
|
id, {|_fcx|}, {|_bcx|});
|
||||||
C_null(T_opaque_box_ptr(ccx))
|
C_null(T_opaque_box_ptr(ccx))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -718,9 +718,7 @@ fn C_nil() -> ValueRef {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn C_bool(b: bool) -> ValueRef {
|
fn C_bool(b: bool) -> ValueRef {
|
||||||
if b {
|
C_integral(T_bool(), if b { 1u64 } else { 0u64 }, False)
|
||||||
ret C_integral(T_bool(), 1u64, False);
|
|
||||||
} else { ret C_integral(T_bool(), 0u64, False); }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn C_i32(i: i32) -> ValueRef {
|
fn C_i32(i: i32) -> ValueRef {
|
||||||
|
@ -190,7 +190,7 @@ fn mark_for_expr(cx: ctx, e: @expr) {
|
|||||||
expr_fail(_) | expr_break | expr_cont | expr_unary(_, _) |
|
expr_fail(_) | expr_break | expr_cont | expr_unary(_, _) |
|
||||||
expr_lit(_) | expr_assert(_) | expr_check(_, _) |
|
expr_lit(_) | expr_assert(_) | expr_check(_, _) |
|
||||||
expr_if_check(_, _, _) | expr_mac(_) | expr_addr_of(_, _) |
|
expr_if_check(_, _, _) | expr_mac(_) | expr_addr_of(_, _) |
|
||||||
expr_ret(_) | expr_loop(_) | expr_bind(_, _) {}
|
expr_ret(_) | expr_loop(_) | expr_bind(_, _) | expr_loop_body(_) {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -360,10 +360,6 @@ fn find_pre_post_expr(fcx: fn_ctxt, e: @expr) {
|
|||||||
find_pre_post_exprs(fcx, es, e.id);
|
find_pre_post_exprs(fcx, es, e.id);
|
||||||
}
|
}
|
||||||
expr_tup(elts) { find_pre_post_exprs(fcx, elts, e.id); }
|
expr_tup(elts) { find_pre_post_exprs(fcx, elts, e.id); }
|
||||||
expr_copy(a) {
|
|
||||||
find_pre_post_expr(fcx, a);
|
|
||||||
copy_pre_post(fcx.ccx, e.id, a);
|
|
||||||
}
|
|
||||||
expr_move(lhs, rhs) { handle_update(fcx, e, lhs, rhs, oper_move); }
|
expr_move(lhs, rhs) { handle_update(fcx, e, lhs, rhs, oper_move); }
|
||||||
expr_swap(lhs, rhs) { handle_update(fcx, e, lhs, rhs, oper_swap); }
|
expr_swap(lhs, rhs) { handle_update(fcx, e, lhs, rhs, oper_swap); }
|
||||||
expr_assign(lhs, rhs) { handle_update(fcx, e, lhs, rhs, oper_assign); }
|
expr_assign(lhs, rhs) { handle_update(fcx, e, lhs, rhs, oper_assign); }
|
||||||
@ -408,17 +404,10 @@ fn find_pre_post_expr(fcx: fn_ctxt, e: @expr) {
|
|||||||
expr_postcond(fcx.ccx, l));
|
expr_postcond(fcx.ccx, l));
|
||||||
} else { find_pre_post_exprs(fcx, [l, r], e.id); }
|
} else { find_pre_post_exprs(fcx, [l, r], e.id); }
|
||||||
}
|
}
|
||||||
expr_unary(_, operand) {
|
expr_addr_of(_, x) | expr_cast(x, _) | expr_unary(_, x) |
|
||||||
find_pre_post_expr(fcx, operand);
|
expr_loop_body(x) | expr_assert(x) | expr_copy(x) {
|
||||||
copy_pre_post(fcx.ccx, e.id, operand);
|
find_pre_post_expr(fcx, x);
|
||||||
}
|
copy_pre_post(fcx.ccx, e.id, x);
|
||||||
expr_addr_of(_, operand) {
|
|
||||||
find_pre_post_expr(fcx, operand);
|
|
||||||
copy_pre_post(fcx.ccx, e.id, operand);
|
|
||||||
}
|
|
||||||
expr_cast(operand, _) {
|
|
||||||
find_pre_post_expr(fcx, operand);
|
|
||||||
copy_pre_post(fcx.ccx, e.id, operand);
|
|
||||||
}
|
}
|
||||||
expr_while(test, body) {
|
expr_while(test, body) {
|
||||||
find_pre_post_expr(fcx, test);
|
find_pre_post_expr(fcx, test);
|
||||||
@ -512,10 +501,6 @@ fn find_pre_post_expr(fcx: fn_ctxt, e: @expr) {
|
|||||||
then everything is true! */
|
then everything is true! */
|
||||||
prestate, false_postcond(num_local_vars));
|
prestate, false_postcond(num_local_vars));
|
||||||
}
|
}
|
||||||
expr_assert(p) {
|
|
||||||
find_pre_post_expr(fcx, p);
|
|
||||||
copy_pre_post(fcx.ccx, e.id, p);
|
|
||||||
}
|
|
||||||
expr_check(_, p) {
|
expr_check(_, p) {
|
||||||
find_pre_post_expr(fcx, p);
|
find_pre_post_expr(fcx, p);
|
||||||
copy_pre_post(fcx.ccx, e.id, p);
|
copy_pre_post(fcx.ccx, e.id, p);
|
||||||
@ -527,12 +512,6 @@ fn find_pre_post_expr(fcx: fn_ctxt, e: @expr) {
|
|||||||
expr_if_check(p, conseq, maybe_alt) {
|
expr_if_check(p, conseq, maybe_alt) {
|
||||||
join_then_else(fcx, p, conseq, maybe_alt, e.id, if_check);
|
join_then_else(fcx, p, conseq, maybe_alt, e.id, if_check);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
expr_bind(operator, maybe_args) {
|
expr_bind(operator, maybe_args) {
|
||||||
let mut args = [];
|
let mut args = [];
|
||||||
let mut cmodes = callee_modes(fcx, operator.id);
|
let mut cmodes = callee_modes(fcx, operator.id);
|
||||||
|
@ -422,7 +422,6 @@ fn find_pre_post_state_expr(fcx: fn_ctxt, pres: prestate, e: @expr) -> bool {
|
|||||||
init_assign), elts,
|
init_assign), elts,
|
||||||
return_val);
|
return_val);
|
||||||
}
|
}
|
||||||
expr_copy(a) { ret find_pre_post_state_sub(fcx, pres, a, e.id, none); }
|
|
||||||
expr_move(lhs, rhs) {
|
expr_move(lhs, rhs) {
|
||||||
ret find_pre_post_state_two(fcx, pres, lhs, rhs, e.id, oper_move);
|
ret find_pre_post_state_two(fcx, pres, lhs, rhs, e.id, oper_move);
|
||||||
}
|
}
|
||||||
@ -598,17 +597,10 @@ fn find_pre_post_state_expr(fcx: fn_ctxt, pres: prestate, e: @expr) -> bool {
|
|||||||
}
|
}
|
||||||
ret changed | set_poststate_ann(fcx.ccx, e.id, a_post);
|
ret changed | set_poststate_ann(fcx.ccx, e.id, a_post);
|
||||||
}
|
}
|
||||||
expr_field(val, _, _) {
|
expr_field(x, _, _) | expr_loop_body(x) | expr_unary(_, x) |
|
||||||
ret find_pre_post_state_sub(fcx, pres, val, e.id, none);
|
expr_addr_of(_, x) | expr_assert(x) | expr_cast(x, _) |
|
||||||
}
|
expr_copy(x) {
|
||||||
expr_unary(_, operand) {
|
ret find_pre_post_state_sub(fcx, pres, x, e.id, none);
|
||||||
ret find_pre_post_state_sub(fcx, pres, operand, e.id, none);
|
|
||||||
}
|
|
||||||
expr_addr_of(_, operand) {
|
|
||||||
ret find_pre_post_state_sub(fcx, pres, operand, e.id, none);
|
|
||||||
}
|
|
||||||
expr_cast(operand, _) {
|
|
||||||
ret find_pre_post_state_sub(fcx, pres, operand, e.id, none);
|
|
||||||
}
|
}
|
||||||
expr_fail(maybe_fail_val) {
|
expr_fail(maybe_fail_val) {
|
||||||
// FIXME Should factor out this code,
|
// FIXME Should factor out this code,
|
||||||
@ -622,9 +614,6 @@ fn find_pre_post_state_expr(fcx: fn_ctxt, pres: prestate, e: @expr) -> bool {
|
|||||||
option::maybe(maybe_fail_val, false, {|fail_val|
|
option::maybe(maybe_fail_val, false, {|fail_val|
|
||||||
find_pre_post_state_expr(fcx, pres, fail_val)});
|
find_pre_post_state_expr(fcx, pres, fail_val)});
|
||||||
}
|
}
|
||||||
expr_assert(p) {
|
|
||||||
ret find_pre_post_state_sub(fcx, pres, p, e.id, none);
|
|
||||||
}
|
|
||||||
expr_check(_, p) {
|
expr_check(_, p) {
|
||||||
/* predicate p holds after this expression executes */
|
/* predicate p holds after this expression executes */
|
||||||
let c: sp_constr = expr_to_constr(fcx.ccx.tcx, p);
|
let c: sp_constr = expr_to_constr(fcx.ccx.tcx, p);
|
||||||
|
@ -2910,6 +2910,24 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
|
|||||||
check_expr_fn_with_unifier(fcx, expr, proto, decl, body,
|
check_expr_fn_with_unifier(fcx, expr, proto, decl, body,
|
||||||
unify, expected);
|
unify, expected);
|
||||||
}
|
}
|
||||||
|
ast::expr_loop_body(block) {
|
||||||
|
let rty = structurally_resolved_type(fcx, expr.span, expected);
|
||||||
|
let inner_ty = alt check ty::get(rty).struct {
|
||||||
|
ty::ty_fn(fty) {
|
||||||
|
demand::simple(fcx, expr.span, fty.output, ty::mk_bool(tcx));
|
||||||
|
ty::mk_fn(tcx, {output: ty::mk_nil(tcx) with fty})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
check_expr_with(fcx, block, inner_ty);
|
||||||
|
let block_ty = structurally_resolved_type(
|
||||||
|
fcx, expr.span, ty::node_id_to_type(tcx, block.id));
|
||||||
|
alt check ty::get(block_ty).struct {
|
||||||
|
ty::ty_fn(fty) {
|
||||||
|
write_ty(tcx, expr.id, ty::mk_fn(tcx, {output: ty::mk_bool(tcx)
|
||||||
|
with fty}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
ast::expr_block(b) {
|
ast::expr_block(b) {
|
||||||
// If this is an unchecked block, turn off purity-checking
|
// If this is an unchecked block, turn off purity-checking
|
||||||
bot = check_block(fcx, b);
|
bot = check_block(fcx, b);
|
||||||
|
@ -303,6 +303,7 @@ enum expr_ {
|
|||||||
expr_alt(@expr, [arm], alt_mode),
|
expr_alt(@expr, [arm], alt_mode),
|
||||||
expr_fn(proto, fn_decl, blk, @capture_clause),
|
expr_fn(proto, fn_decl, blk, @capture_clause),
|
||||||
expr_fn_block(fn_decl, blk),
|
expr_fn_block(fn_decl, blk),
|
||||||
|
expr_loop_body(@expr),
|
||||||
expr_block(blk),
|
expr_block(blk),
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -407,6 +407,7 @@ fn noop_fold_expr(e: expr_, fld: ast_fold) -> expr_ {
|
|||||||
expr_binary(binop, fld.fold_expr(lhs), fld.fold_expr(rhs))
|
expr_binary(binop, fld.fold_expr(lhs), fld.fold_expr(rhs))
|
||||||
}
|
}
|
||||||
expr_unary(binop, ohs) { expr_unary(binop, fld.fold_expr(ohs)) }
|
expr_unary(binop, ohs) { expr_unary(binop, fld.fold_expr(ohs)) }
|
||||||
|
expr_loop_body(f) { expr_loop_body(fld.fold_expr(f)) }
|
||||||
expr_lit(_) { e }
|
expr_lit(_) { e }
|
||||||
expr_cast(expr, ty) { expr_cast(fld.fold_expr(expr), ty) }
|
expr_cast(expr, ty) { expr_cast(fld.fold_expr(expr), ty) }
|
||||||
expr_addr_of(m, ohs) { expr_addr_of(m, fld.fold_expr(ohs)) }
|
expr_addr_of(m, ohs) { expr_addr_of(m, fld.fold_expr(ohs)) }
|
||||||
|
@ -1403,13 +1403,37 @@ fn parse_else_expr(p: parser) -> @ast::expr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn parse_for_expr(p: parser) -> @ast::expr {
|
fn parse_for_expr(p: parser) -> @ast::expr {
|
||||||
let lo = p.last_span.lo;
|
let lo = p.last_span;
|
||||||
|
// FIXME remove this kludge after migration and snapshotting (#1619)
|
||||||
|
let new_style = alt p.token {
|
||||||
|
token::IDENT(_, false) { alt p.look_ahead(1u) {
|
||||||
|
token::DOT | token::LPAREN { true }
|
||||||
|
_ { false }
|
||||||
|
} }
|
||||||
|
token::IDENT(_, true) { true }
|
||||||
|
_ { false }
|
||||||
|
};
|
||||||
|
if new_style {
|
||||||
|
let call = parse_expr(p);
|
||||||
|
alt call.node {
|
||||||
|
ast::expr_call(f, args, true) {
|
||||||
|
let b_arg = vec::last(args);
|
||||||
|
let last = mk_expr(p, b_arg.span.lo, b_arg.span.hi,
|
||||||
|
ast::expr_loop_body(b_arg));
|
||||||
|
@{node: ast::expr_call(f, vec::init(args) + [last], true)
|
||||||
|
with *call}
|
||||||
|
}
|
||||||
|
_ {
|
||||||
|
p.span_fatal(lo, "`for` must be followed by a block call");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
let decl = parse_local(p, false, false);
|
let decl = parse_local(p, false, false);
|
||||||
expect_word(p, "in");
|
expect_word(p, "in");
|
||||||
let seq = parse_expr(p);
|
let seq = parse_expr(p);
|
||||||
let body = parse_block_no_value(p);
|
let body = parse_block_no_value(p);
|
||||||
let mut hi = body.span.hi;
|
mk_expr(p, lo.lo, body.span.hi, ast::expr_for(decl, seq, body))
|
||||||
ret mk_expr(p, lo, hi, ast::expr_for(decl, seq, body));
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_while_expr(p: parser) -> @ast::expr {
|
fn parse_while_expr(p: parser) -> @ast::expr {
|
||||||
|
@ -855,9 +855,16 @@ fn print_expr(s: ps, &&expr: @ast::expr) {
|
|||||||
pclose(s);
|
pclose(s);
|
||||||
}
|
}
|
||||||
ast::expr_call(func, args, has_block) {
|
ast::expr_call(func, args, has_block) {
|
||||||
|
let mut base_args = args;
|
||||||
|
let blk = if has_block {
|
||||||
|
let blk_arg = vec::pop(base_args);
|
||||||
|
alt blk_arg.node {
|
||||||
|
ast::expr_loop_body(_) { word_nbsp(s, "for"); }
|
||||||
|
_ {}
|
||||||
|
}
|
||||||
|
some(blk_arg)
|
||||||
|
} else { none };
|
||||||
print_expr_parens_if_not_bot(s, func);
|
print_expr_parens_if_not_bot(s, func);
|
||||||
let mut base_args = args, blk = none;
|
|
||||||
if has_block { blk = some(vec::pop(base_args)); }
|
|
||||||
if !has_block || vec::len(base_args) > 0u {
|
if !has_block || vec::len(base_args) > 0u {
|
||||||
popen(s);
|
popen(s);
|
||||||
commasep_exprs(s, inconsistent, base_args);
|
commasep_exprs(s, inconsistent, base_args);
|
||||||
@ -989,6 +996,9 @@ fn print_expr(s: ps, &&expr: @ast::expr) {
|
|||||||
print_fn_block_args(s, decl);
|
print_fn_block_args(s, decl);
|
||||||
print_possibly_embedded_block(s, body, block_block_fn, indent_unit);
|
print_possibly_embedded_block(s, body, block_block_fn, indent_unit);
|
||||||
}
|
}
|
||||||
|
ast::expr_loop_body(body) {
|
||||||
|
print_expr(s, body);
|
||||||
|
}
|
||||||
ast::expr_block(blk) {
|
ast::expr_block(blk) {
|
||||||
// containing cbox, will be closed by print-block at }
|
// containing cbox, will be closed by print-block at }
|
||||||
cbox(s, indent_unit);
|
cbox(s, indent_unit);
|
||||||
|
@ -338,10 +338,12 @@ fn visit_expr<E>(ex: @expr, e: E, v: vt<E>) {
|
|||||||
for eo: option<@expr> in args { visit_expr_opt(eo, e, v); }
|
for eo: option<@expr> in args { visit_expr_opt(eo, e, v); }
|
||||||
}
|
}
|
||||||
expr_binary(_, a, b) { v.visit_expr(a, e, v); v.visit_expr(b, e, v); }
|
expr_binary(_, a, b) { v.visit_expr(a, e, v); v.visit_expr(b, e, v); }
|
||||||
expr_unary(_, a) { v.visit_expr(a, e, v); }
|
expr_addr_of(_, x) | expr_unary(_, x) | expr_loop_body(x) |
|
||||||
|
expr_check(_, x) | expr_assert(x) {
|
||||||
|
v.visit_expr(x, e, v);
|
||||||
|
}
|
||||||
expr_lit(_) { }
|
expr_lit(_) { }
|
||||||
expr_cast(x, t) { v.visit_expr(x, e, v); v.visit_ty(t, e, v); }
|
expr_cast(x, t) { v.visit_expr(x, e, v); v.visit_ty(t, e, v); }
|
||||||
expr_addr_of(_, x) { v.visit_expr(x, e, v); }
|
|
||||||
expr_if(x, b, eo) {
|
expr_if(x, b, eo) {
|
||||||
v.visit_expr(x, e, v);
|
v.visit_expr(x, e, v);
|
||||||
v.visit_block(b, e, v);
|
v.visit_block(b, e, v);
|
||||||
@ -394,8 +396,6 @@ fn visit_expr<E>(ex: @expr, e: E, v: vt<E>) {
|
|||||||
v.visit_expr(lv, e, v);
|
v.visit_expr(lv, e, v);
|
||||||
v.visit_expr(x, e, v);
|
v.visit_expr(x, e, v);
|
||||||
}
|
}
|
||||||
expr_check(_, x) { v.visit_expr(x, e, v); }
|
|
||||||
expr_assert(x) { v.visit_expr(x, e, v); }
|
|
||||||
expr_mac(mac) { visit_mac(mac, e, v); }
|
expr_mac(mac) { visit_mac(mac, e, v); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user