Change the way block calls are parsed, mark them as block-calls.
This makes it possible to omit the semicolon after the block, and will cause the pretty-printer to properly print such calls (if pretty-printing of blocks wasn't so broken). Block calls (with the block outside of the parentheses) can now only occur at statement level, and their value can not be used. When calling a block-style function that returns a useful value, the block must be put insde the parentheses. Issue #1054
This commit is contained in:
parent
0ce40f60e7
commit
7114702496
@ -302,7 +302,7 @@ fn mk_test_wrapper(cx: test_ctxt,
|
||||
span: span) -> @ast::expr {
|
||||
let call_expr: ast::expr = {
|
||||
id: cx.next_node_id(),
|
||||
node: ast::expr_call(@fn_path_expr, []),
|
||||
node: ast::expr_call(@fn_path_expr, [], false),
|
||||
span: span
|
||||
};
|
||||
|
||||
@ -401,7 +401,7 @@ fn mk_test_main_call(cx: test_ctxt) -> @ast::expr {
|
||||
let test_path_expr: ast::expr =
|
||||
{id: cx.next_node_id(), node: test_path_expr_, span: dummy_sp()};
|
||||
|
||||
let test_call_expr_: ast::expr_ = ast::expr_call(@test_path_expr, []);
|
||||
let test_call_expr_ = ast::expr_call(@test_path_expr, [], false);
|
||||
|
||||
let test_call_expr: ast::expr =
|
||||
{id: cx.next_node_id(), node: test_call_expr_, span: dummy_sp()};
|
||||
@ -419,7 +419,7 @@ fn mk_test_main_call(cx: test_ctxt) -> @ast::expr {
|
||||
|
||||
let test_main_call_expr_: ast::expr_ =
|
||||
ast::expr_call(@test_main_path_expr,
|
||||
[@args_path_expr, @test_call_expr]);
|
||||
[@args_path_expr, @test_call_expr], false);
|
||||
|
||||
let test_main_call_expr: ast::expr =
|
||||
{id: cx.next_node_id(), node: test_main_call_expr_, span: dummy_sp()};
|
||||
|
@ -93,7 +93,7 @@ fn visit_fn(cx: @ctx, f: ast::_fn, _tp: [ast::ty_param], sp: span,
|
||||
fn visit_expr(cx: @ctx, ex: @ast::expr, sc: scope, v: vt<scope>) {
|
||||
let handled = true;
|
||||
alt ex.node {
|
||||
ast::expr_call(f, args) {
|
||||
ast::expr_call(f, args, _) {
|
||||
check_call(*cx, f, args);
|
||||
handled = false;
|
||||
}
|
||||
@ -667,7 +667,7 @@ fn expr_root(cx: ctx, ex: @ast::expr, autoderef: bool)
|
||||
}
|
||||
if is_none(path_def_id(cx, base_root.ex)) {
|
||||
alt base_root.ex.node {
|
||||
ast::expr_call(f, args) {
|
||||
ast::expr_call(f, args, _) {
|
||||
let fty = ty::expr_ty(cx.tcx, f);
|
||||
alt ty::ty_fn_ret_style(cx.tcx, fty) {
|
||||
ast::return_ref(mut, arg_n) {
|
||||
|
@ -42,7 +42,7 @@ fn fn_usage_expr(expr: @ast::expr,
|
||||
}
|
||||
}
|
||||
|
||||
ast::expr_call(f, args) {
|
||||
ast::expr_call(f, args, _) {
|
||||
let f_ctx = {unsafe_fn_legal: true,
|
||||
generic_bare_fn_legal: true with ctx};
|
||||
v.visit_expr(f, f_ctx, v);
|
||||
|
@ -174,7 +174,7 @@ fn need_shared_or_pinned_ctor(tcx: ty::ctxt, a: @ast::expr, descr: str) {
|
||||
fn pinned_ctor(a: @ast::expr) -> bool {
|
||||
// FIXME: Technically a lambda block is also a pinned ctor
|
||||
alt a.node {
|
||||
ast::expr_call(cexpr, _) {
|
||||
ast::expr_call(cexpr, _, _) {
|
||||
// Assuming that if it's a call that it's safe to move in, mostly
|
||||
// because I don't know offhand how to ensure that it's a call
|
||||
// specifically to a resource constructor
|
||||
@ -224,7 +224,7 @@ fn check_expr(tcx: ty::ctxt, e: @ast::expr) {
|
||||
ast::expr_fail(option::some(a)) {
|
||||
need_expr_kind(tcx, a, ast::kind_shared, "'fail' operand");
|
||||
}
|
||||
ast::expr_call(callee, _) {
|
||||
ast::expr_call(callee, _, _) {
|
||||
let tpt = ty::expr_ty_params_and_ty(tcx, callee);
|
||||
|
||||
// If we have typarams, we're calling an item; we need to check
|
||||
|
@ -150,7 +150,7 @@ fn visit_decl(cx: @ctx, d: @decl, &&e: (), v: visit::vt<()>) {
|
||||
|
||||
fn visit_expr(cx: @ctx, ex: @expr, &&e: (), v: visit::vt<()>) {
|
||||
alt ex.node {
|
||||
expr_call(f, args) { check_call(cx, f, args); }
|
||||
expr_call(f, args, _) { check_call(cx, f, args); }
|
||||
expr_swap(lhs, rhs) {
|
||||
check_lval(cx, lhs, msg_assign);
|
||||
check_lval(cx, rhs, msg_assign);
|
||||
|
@ -3147,7 +3147,7 @@ fn expr_is_lval(tcx: ty::ctxt, e: @ast::expr) -> bool {
|
||||
ty::ty_rec(_) { true }
|
||||
}
|
||||
}
|
||||
ast::expr_call(f, _) {
|
||||
ast::expr_call(f, _, _) {
|
||||
let fty = ty::expr_ty(tcx, f);
|
||||
ast_util::ret_by_ref(ty::ty_fn_ret_style(tcx, fty))
|
||||
}
|
||||
@ -3198,7 +3198,7 @@ fn trans_lval(cx: @block_ctxt, e: @ast::expr) -> lval_result {
|
||||
ret lval_owned(sub.bcx, val);
|
||||
}
|
||||
// This is a by-ref returning call. Regular calls are not lval
|
||||
ast::expr_call(f, args) {
|
||||
ast::expr_call(f, args, _) {
|
||||
let cell = empty_dest_cell();
|
||||
let bcx = trans_call(cx, f, args, e.id, by_val(cell));
|
||||
ret lval_owned(bcx, *cell);
|
||||
@ -4175,7 +4175,7 @@ fn trans_expr(bcx: @block_ctxt, e: @ast::expr, dest: dest) -> @block_ctxt {
|
||||
ast::expr_anon_obj(anon_obj) {
|
||||
ret trans_anon_obj(bcx, e.span, anon_obj, e.id, dest);
|
||||
}
|
||||
ast::expr_call(f, args) {
|
||||
ast::expr_call(f, args, _) {
|
||||
ret trans_call(bcx, f, args, e.id, dest);
|
||||
}
|
||||
ast::expr_field(_, _) {
|
||||
|
@ -607,7 +607,7 @@ fn exprs_to_constr_args(tcx: ty::ctxt, args: [@expr]) -> [@constr_arg_use] {
|
||||
|
||||
fn expr_to_constr(tcx: ty::ctxt, e: @expr) -> sp_constr {
|
||||
alt e.node {
|
||||
expr_call(operator, args) {
|
||||
expr_call(operator, args, _) {
|
||||
alt operator.node {
|
||||
expr_path(p) {
|
||||
ret respan(e.span,
|
||||
|
@ -32,7 +32,7 @@ fn collect_pred(e: @expr, cx: ctxt, v: visit::vt<ctxt>) {
|
||||
|
||||
// If it's a call, generate appropriate instances of the
|
||||
// call's constraints.
|
||||
expr_call(operator, operands) {
|
||||
expr_call(operator, operands, _) {
|
||||
for c: @ty::constr in constraints_expr(cx.tcx, operator) {
|
||||
let ct: sp_constr =
|
||||
respan(c.span,
|
||||
|
@ -309,7 +309,7 @@ fn find_pre_post_expr(fcx: fn_ctxt, e: @expr) {
|
||||
|
||||
|
||||
alt e.node {
|
||||
expr_call(operator, operands) {
|
||||
expr_call(operator, operands, _) {
|
||||
/* copy */
|
||||
|
||||
let args = operands;
|
||||
|
@ -335,7 +335,7 @@ fn find_pre_post_state_expr(fcx: fn_ctxt, pres: prestate, e: @expr) -> bool {
|
||||
vec::len(elts)), elts,
|
||||
return_val);
|
||||
}
|
||||
expr_call(operator, operands) {
|
||||
expr_call(operator, operands, _) {
|
||||
ret find_pre_post_state_call(fcx, pres, operator, e.id,
|
||||
callee_arg_init_ops(fcx, operator.id),
|
||||
operands,
|
||||
|
@ -2072,7 +2072,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
|
||||
out_args, rt, cf, constrs);
|
||||
write::ty_only_fixup(fcx, id, ft);
|
||||
}
|
||||
ast::expr_call(f, args) {
|
||||
ast::expr_call(f, args, _) {
|
||||
bot = check_call_full(fcx, expr.span, f, args, expr.id);
|
||||
}
|
||||
ast::expr_self_method(ident) {
|
||||
@ -2535,7 +2535,7 @@ fn check_pred_expr(fcx: @fn_ctxt, e: @ast::expr) -> bool {
|
||||
/* e must be a call expr where all arguments are either
|
||||
literals or slots */
|
||||
alt e.node {
|
||||
ast::expr_call(operator, operands) {
|
||||
ast::expr_call(operator, operands, _) {
|
||||
if !ty::is_pred_ty(fcx.ccx.tcx, expr_ty(fcx.ccx.tcx, operator)) {
|
||||
fcx.ccx.tcx.sess.span_err
|
||||
(operator.span,
|
||||
@ -2632,7 +2632,7 @@ fn check_constraints(fcx: @fn_ctxt, cs: [@ast::constr], args: [ast::arg]) {
|
||||
let call_expr_id = fcx.ccx.tcx.sess.next_node_id();
|
||||
let call_expr =
|
||||
@{id: call_expr_id,
|
||||
node: ast::expr_call(oper, c_args),
|
||||
node: ast::expr_call(oper, c_args, false),
|
||||
span: c.span};
|
||||
check_pred_expr(fcx, call_expr);
|
||||
}
|
||||
|
@ -184,7 +184,7 @@ type expr = {id: node_id, node: expr_, span: span};
|
||||
tag expr_ {
|
||||
expr_vec([@expr], mutability);
|
||||
expr_rec([field], option::t<@expr>);
|
||||
expr_call(@expr, [@expr]);
|
||||
expr_call(@expr, [@expr], bool);
|
||||
expr_tup([@expr]);
|
||||
expr_self_method(ident);
|
||||
expr_bind(@expr, [option::t<@expr>]);
|
||||
|
@ -163,7 +163,7 @@ fn is_exported(i: ident, m: _mod) -> bool {
|
||||
}
|
||||
|
||||
pure fn is_call_expr(e: @expr) -> bool {
|
||||
alt e.node { expr_call(_, _) { true } _ { false } }
|
||||
alt e.node { expr_call(_, _, _) { true } _ { false } }
|
||||
}
|
||||
|
||||
fn is_constraint_arg(e: @expr) -> bool {
|
||||
|
@ -79,7 +79,7 @@ fn pieces_to_expr(cx: ext_ctxt, sp: span, pieces: [piece], args: [@ast::expr])
|
||||
fn make_call(cx: ext_ctxt, sp: span, fn_path: [ast::ident],
|
||||
args: [@ast::expr]) -> @ast::expr {
|
||||
let pathexpr = make_path_expr(cx, sp, fn_path);
|
||||
let callexpr = ast::expr_call(pathexpr, args);
|
||||
let callexpr = ast::expr_call(pathexpr, args, false);
|
||||
ret @{id: cx.next_id(), node: callexpr, span: sp};
|
||||
}
|
||||
fn make_rec_expr(cx: ext_ctxt, sp: span,
|
||||
|
@ -348,8 +348,9 @@ fn noop_fold_expr(e: expr_, fld: ast_fold) -> expr_ {
|
||||
option::map(fld.fold_expr, maybe_expr))
|
||||
}
|
||||
expr_tup(elts) { expr_tup(vec::map(fld.fold_expr, elts)) }
|
||||
expr_call(f, args) {
|
||||
expr_call(fld.fold_expr(f), fld.map_exprs(fld.fold_expr, args))
|
||||
expr_call(f, args, blk) {
|
||||
expr_call(fld.fold_expr(f), fld.map_exprs(fld.fold_expr, args),
|
||||
blk)
|
||||
}
|
||||
expr_self_method(id) { expr_self_method(fld.fold_ident(id)) }
|
||||
expr_bind(f, args) {
|
||||
|
@ -977,7 +977,7 @@ fn parse_bottom_expr(p: parser) -> @ast::expr {
|
||||
parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA),
|
||||
parse_expr, p);
|
||||
hi = es.span.hi;
|
||||
ex = ast::expr_call(f, es.node);
|
||||
ex = ast::expr_call(f, es.node, false);
|
||||
} else if p.peek() == token::MOD_SEP ||
|
||||
is_ident(p.peek()) && !is_word(p, "true") &&
|
||||
!is_word(p, "false") {
|
||||
@ -1051,7 +1051,7 @@ fn parse_dot_or_call_expr_with(p: parser, e: @ast::expr) -> @ast::expr {
|
||||
let es = parse_seq(token::LPAREN, token::RPAREN,
|
||||
some(token::COMMA), parse_expr, p);
|
||||
hi = es.span.hi;
|
||||
let nd = ast::expr_call(e, es.node);
|
||||
let nd = ast::expr_call(e, es.node, false);
|
||||
e = mk_expr(p, lo, hi, nd);
|
||||
}
|
||||
}
|
||||
@ -1073,19 +1073,6 @@ fn parse_dot_or_call_expr_with(p: parser, e: @ast::expr) -> @ast::expr {
|
||||
t { unexpected(p, t); }
|
||||
}
|
||||
}
|
||||
token::LBRACE. when is_bar(p.look_ahead(1u)) {
|
||||
p.bump();
|
||||
let blk = parse_fn_block_expr(p);
|
||||
alt e.node {
|
||||
ast::expr_call(f, args) {
|
||||
e = @{node: ast::expr_call(f, args + [blk]) with *e};
|
||||
}
|
||||
_ {
|
||||
e = mk_expr(p, lo, p.get_last_hi_pos(),
|
||||
ast::expr_call(e, [blk]));
|
||||
}
|
||||
}
|
||||
}
|
||||
_ { ret e; }
|
||||
}
|
||||
}
|
||||
@ -1569,7 +1556,6 @@ fn parse_source_stmt(p: parser) -> @ast::stmt {
|
||||
let decl = parse_let(p);
|
||||
ret @spanned(lo, decl.span.hi, ast::stmt_decl(decl, p.get_id()));
|
||||
} else {
|
||||
|
||||
let item_attrs;
|
||||
alt parse_outer_attrs_or_ext(p) {
|
||||
none. { item_attrs = []; }
|
||||
@ -1589,7 +1575,6 @@ fn parse_source_stmt(p: parser) -> @ast::stmt {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
alt maybe_item {
|
||||
some(i) {
|
||||
let hi = i.span.hi;
|
||||
@ -1599,6 +1584,21 @@ fn parse_source_stmt(p: parser) -> @ast::stmt {
|
||||
none. {
|
||||
// Remainder are line-expr stmts.
|
||||
let e = parse_expr(p);
|
||||
// See if it is a block call
|
||||
if p.peek() == token::LBRACE && is_bar(p.look_ahead(1u)) {
|
||||
p.bump();
|
||||
let blk = parse_fn_block_expr(p);
|
||||
alt e.node {
|
||||
ast::expr_call(f, args, false) {
|
||||
e = @{node: ast::expr_call(f, args + [blk], true)
|
||||
with *e};
|
||||
}
|
||||
_ {
|
||||
e = mk_expr(p, lo, p.get_last_hi_pos(),
|
||||
ast::expr_call(e, [blk], true));
|
||||
}
|
||||
}
|
||||
}
|
||||
ret @spanned(lo, e.span.hi, ast::stmt_expr(e, p.get_id()));
|
||||
}
|
||||
_ { p.fatal("expected statement"); }
|
||||
@ -1624,6 +1624,7 @@ fn expr_has_value(e: @ast::expr) -> bool {
|
||||
ast::expr_for(_, _, blk) | ast::expr_do_while(blk, _) {
|
||||
!option::is_none(blk.node.expr)
|
||||
}
|
||||
ast::expr_call(_, _, true) { false }
|
||||
_ { true }
|
||||
}
|
||||
}
|
||||
|
@ -727,11 +727,19 @@ fn print_expr(s: ps, &&expr: @ast::expr) {
|
||||
commasep_exprs(s, inconsistent, exprs);
|
||||
pclose(s);
|
||||
}
|
||||
ast::expr_call(func, args) {
|
||||
ast::expr_call(func, args, has_block) {
|
||||
print_expr_parens_if_not_bot(s, func);
|
||||
popen(s);
|
||||
commasep_exprs(s, inconsistent, args);
|
||||
pclose(s);
|
||||
let base_args = args, blk = none;
|
||||
if has_block { blk = some(vec::pop(base_args)); }
|
||||
if !has_block || vec::len(base_args) > 0u {
|
||||
popen(s);
|
||||
commasep_exprs(s, inconsistent, base_args);
|
||||
pclose(s);
|
||||
}
|
||||
if has_block {
|
||||
nbsp(s);
|
||||
print_expr(s, option::get(blk));
|
||||
}
|
||||
}
|
||||
ast::expr_self_method(ident) {
|
||||
word(s.s, "self.");
|
||||
|
@ -245,7 +245,7 @@ fn visit_expr<E>(ex: @expr, e: E, v: vt<E>) {
|
||||
visit_expr_opt(base, e, v);
|
||||
}
|
||||
expr_tup(elts) { for el in elts { v.visit_expr(el, e, v); } }
|
||||
expr_call(callee, args) {
|
||||
expr_call(callee, args, _) {
|
||||
visit_exprs(args, e, v);
|
||||
v.visit_expr(callee, e, v);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user