Handle fail as an argument; parse fail expressions unambiguously

An expression like:

foo(1, fail, 2)

was failing to parse, because the parser was interpreting the comma
as the start of an expression that was an argument to fail, rather
than recognizing that the fail here has no arguments

Fixed this by using can_begin_expr to determine whether the next
token after a fail token suggests that this is a nullary fail or a
unary fail.

In addition, when translating calls, check before translating each
argument that the block still isn't terminated. This has the effect
that if an argument list includes fail, the back-end won't keep trying
to generate code for successive arguments and trip the !*terminated
assertion.
This commit is contained in:
Tim Chevalier 2011-07-03 10:39:07 -07:00
parent 6369807ffe
commit 046c25dbc0
3 changed files with 22 additions and 9 deletions

View file

@ -9,6 +9,7 @@ import std::either;
import std::either::left;
import std::either::right;
import std::map::hashmap;
import token::can_begin_expr;
import driver::session;
import util::common;
import util::common::filename;
@ -120,7 +121,6 @@ fn new_parser(session::session sess, ast::crate_cfg cfg,
ext::syntax_expander_table());
}
// These are the words that shouldn't be allowed as value identifiers,
// because, if used at the start of a line, they will cause the line to be
// interpreted as a specific kind of statement, which would be confusing.
@ -841,14 +841,13 @@ fn parse_bottom_expr(&parser p) -> @ast::expr {
lo = ex_ext.span.lo;
ex = ex_ext.node;
} else if (eat_word(p, "fail")) {
alt (p.peek()) {
case (token::SEMI) { ex = ast::expr_fail(none) }
case (token::RBRACE) { ex = ast::expr_fail(none) }
case (_) {
auto e = parse_expr(p);
hi = e.span.hi;
ex = ast::expr_fail(some(e));
}
if (can_begin_expr(p.peek())) {
auto e = parse_expr(p);
hi = e.span.hi;
ex = ast::expr_fail(some(e));
}
else {
ex = ast::expr_fail(none);
}
} else if (eat_word(p, "log")) {
auto e = parse_expr(p);

View file

@ -5682,6 +5682,11 @@ fn trans_args(&@block_ctxt cx, ValueRef llenv, &option::t[ValueRef] llobj,
auto arg_tys = type_of_explicit_args(cx.fcx.lcx.ccx, cx.sp, args);
auto i = 0u;
for (@ast::expr e in es) {
if (bcx.build.is_terminated()) {
// This means an earlier arg was divergent.
// So this arg can't be evaluated.
break;
}
auto r = trans_arg_expr(bcx, args.(i), arg_tys.(i), e);
bcx = r.bcx;
llargs += [r.val];

View file

@ -0,0 +1,9 @@
// xfail-stage0
// error-pattern:meep
fn f(int a, int b, @int c) {
fail "moop";
}
fn main() {
f(1, fail "meep", @42);
}