Skip to content

Recursive elseif #273

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
6 commits merged into from
Mar 15, 2011
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/comp/front/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ tag expr_ {
expr_unary(unop, @expr, ann);
expr_lit(@lit, ann);
expr_cast(@expr, @ty, ann);
expr_if(@expr, block, vec[tup(@expr, block)], option.t[block], ann);
expr_if(@expr, block, option.t[@expr], ann);
expr_while(@expr, block, ann);
expr_for(@decl, @expr, block, ann);
expr_for_each(@decl, @expr, block, ann);
Expand Down
29 changes: 11 additions & 18 deletions src/comp/front/eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ impure fn eval_crate_directive_expr(parser p,

alt (x.node) {

case (ast.expr_if(?cond, ?thn, ?elifs, ?elopt, _)) {
case (ast.expr_if(?cond, ?thn, ?elopt, _)) {
auto cv = eval_expr(sess, e, cond);
if (!val_is_bool(cv)) {
sess.span_err(x.span, "bad cond type in 'if'");
Expand All @@ -301,24 +301,11 @@ impure fn eval_crate_directive_expr(parser p,
index);
}

for (tup(@ast.expr, ast.block) elif in elifs) {
auto cv = eval_expr(sess, e, elif._0);
if (!val_is_bool(cv)) {
sess.span_err(x.span, "bad cond type in 'else if'");
}

if (val_as_bool(cv)) {
ret eval_crate_directive_block(p, e, elif._1, prefix,
view_items, items,
index);
}
}

alt (elopt) {
case (some[ast.block](?els)) {
ret eval_crate_directive_block(p, e, els, prefix,
view_items, items,
index);
case (some[@ast.expr](?els)) {
ret eval_crate_directive_expr(p, e, els, prefix,
view_items, items,
index);
}
case (_) {
// Absent-else is ok.
Expand Down Expand Up @@ -353,6 +340,12 @@ impure fn eval_crate_directive_expr(parser p,
sess.span_err(x.span, "no cases matched in 'alt'");
}

case (ast.expr_block(?block, _)) {
ret eval_crate_directive_block(p, e, block, prefix,
view_items, items,
index);
}

case (_) {
sess.span_err(x.span, "unsupported expr type");
}
Expand Down
54 changes: 23 additions & 31 deletions src/comp/front/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1094,40 +1094,32 @@ impure fn parse_if_expr(parser p) -> @ast.expr {
auto cond = parse_expr(p);
expect(p, token.RPAREN);
auto thn = parse_block(p);
let option.t[@ast.expr] els = none[@ast.expr];
hi = thn.span;

let vec[tup(@ast.expr, ast.block)] elifs = vec();
let option.t[ast.block] els = none[ast.block];
let bool parsing_elses = true;
while (parsing_elses) {
alt (p.peek()) {
case (token.ELSE) {
expect(p, token.ELSE);
alt (p.peek()) {
case (token.IF) {
expect(p, token.IF);
expect(p, token.LPAREN);
auto elifcond = parse_expr(p);
expect(p, token.RPAREN);
auto elifthn = parse_block(p);
elifs += tup(elifcond, elifthn);
hi = elifthn.span;
}
case (_) {
auto eblk = parse_block(p);
els = some(eblk);
hi = eblk.span;
parsing_elses = false;
}
}
}
case (_) {
parsing_elses = false;
}
alt (p.peek()) {
case (token.ELSE) {
auto elexpr = parse_else_expr(p);
els = some(elexpr);
hi = elexpr.span;
}
case (_) { /* fall through */ }
}

ret @spanned(lo, hi, ast.expr_if(cond, thn, elifs, els, ast.ann_none));
ret @spanned(lo, hi, ast.expr_if(cond, thn, els, ast.ann_none));
}

impure fn parse_else_expr(parser p) -> @ast.expr {
expect(p, token.ELSE);
alt (p.peek()) {
case (token.IF) {
ret parse_if_expr(p);
}
case (_) {
auto blk = parse_block(p);
ret @spanned(blk.span, blk.span,
ast.expr_block(blk, ast.ann_none));
}
}
}

impure fn parse_head_local(parser p) -> @ast.decl {
Expand Down Expand Up @@ -1530,7 +1522,7 @@ fn stmt_ends_with_semi(@ast.stmt stmt) -> bool {
case (ast.expr_unary(_,_,_)) { ret true; }
case (ast.expr_lit(_,_)) { ret true; }
case (ast.expr_cast(_,_,_)) { ret true; }
case (ast.expr_if(_,_,_,_,_)) { ret false; }
case (ast.expr_if(_,_,_,_)) { ret false; }
case (ast.expr_for(_,_,_,_)) { ret false; }
case (ast.expr_for_each(_,_,_,_))
{ ret false; }
Expand Down
30 changes: 9 additions & 21 deletions src/comp/middle/fold.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,7 @@ type ast_fold[ENV] =

(fn(&ENV e, &span sp,
@expr cond, &block thn,
&vec[tup(@expr, block)] elifs,
&option.t[block] els,
&option.t[@expr] els,
ann a) -> @expr) fold_expr_if,

(fn(&ENV e, &span sp,
Expand Down Expand Up @@ -565,27 +564,17 @@ fn fold_expr[ENV](&ENV env, ast_fold[ENV] fld, &@expr e) -> @expr {
ret fld.fold_expr_cast(env_, e.span, ee, tt, at);
}

case (ast.expr_if(?cnd, ?thn, ?elifs, ?els, ?t)) {
case (ast.expr_if(?cnd, ?thn, ?els, ?t)) {
auto ccnd = fold_expr(env_, fld, cnd);
auto tthn = fold_block(env_, fld, thn);

let vec[tup(@ast.expr, ast.block)] eelifs = vec();
for (tup(@expr, block) elif in elifs) {
auto elifcnd = elif._0;
auto elifthn = elif._1;
auto elifccnd = fold_expr(env_, fld, elifcnd);
auto eliftthn = fold_block(env_, fld, elifthn);
eelifs += tup(elifccnd, eliftthn);
}

auto eels = none[block];
auto eels = none[@expr];
alt (els) {
case (some[block](?b)) {
eels = some(fold_block(env_, fld, b));
case (some[@expr](?e)) {
eels = some(fold_expr(env_, fld, e));
}
case (_) { /* fall through */ }
}
ret fld.fold_expr_if(env_, e.span, ccnd, tthn, eelifs, eels, t);
ret fld.fold_expr_if(env_, e.span, ccnd, tthn, eels, t);
}

case (ast.expr_for(?decl, ?seq, ?body, ?t)) {
Expand Down Expand Up @@ -1137,9 +1126,8 @@ fn identity_fold_expr_cast[ENV](&ENV env, &span sp, @ast.expr e,

fn identity_fold_expr_if[ENV](&ENV env, &span sp,
@expr cond, &block thn,
&vec[tup(@expr, block)] elifs,
&option.t[block] els, ann a) -> @expr {
ret @respan(sp, ast.expr_if(cond, thn, elifs, els, a));
&option.t[@expr] els, ann a) -> @expr {
ret @respan(sp, ast.expr_if(cond, thn, els, a));
}

fn identity_fold_expr_for[ENV](&ENV env, &span sp,
Expand Down Expand Up @@ -1483,7 +1471,7 @@ fn new_identity_fold[ENV]() -> ast_fold[ENV] {
fold_expr_unary = bind identity_fold_expr_unary[ENV](_,_,_,_,_),
fold_expr_lit = bind identity_fold_expr_lit[ENV](_,_,_,_),
fold_expr_cast = bind identity_fold_expr_cast[ENV](_,_,_,_,_),
fold_expr_if = bind identity_fold_expr_if[ENV](_,_,_,_,_,_,_),
fold_expr_if = bind identity_fold_expr_if[ENV](_,_,_,_,_,_),
fold_expr_for = bind identity_fold_expr_for[ENV](_,_,_,_,_,_),
fold_expr_for_each
= bind identity_fold_expr_for_each[ENV](_,_,_,_,_,_),
Expand Down
40 changes: 9 additions & 31 deletions src/comp/middle/trans.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2833,9 +2833,8 @@ fn join_results(@block_ctxt parent_cx,
ret res(join_cx, phi);
}

fn trans_if(@block_ctxt cx, @ast.expr cond, &ast.block thn,
&vec[tup(@ast.expr, ast.block)] elifs,
&option.t[ast.block] els) -> result {
fn trans_if(@block_ctxt cx, @ast.expr cond,
&ast.block thn, &option.t[@ast.expr] els) -> result {

auto cond_res = trans_expr(cx, cond);

Expand All @@ -2845,25 +2844,11 @@ fn trans_if(@block_ctxt cx, @ast.expr cond, &ast.block thn,
auto else_cx = new_scope_block_ctxt(cx, "else");
auto else_res = res(else_cx, C_nil());

auto num_elifs = _vec.len[tup(@ast.expr, ast.block)](elifs);
if (num_elifs > 0u) {
auto next_elif = elifs.(0u);
auto next_elifthn = next_elif._0;
auto next_elifcnd = next_elif._1;
auto rest_elifs = _vec.shift[tup(@ast.expr, ast.block)](elifs);
else_res = trans_if(else_cx, next_elifthn, next_elifcnd,
rest_elifs, els);
}

/* else: FIXME: rustboot has a problem here
with preconditions inside an else block */
if (num_elifs == 0u) {
alt (els) {
case (some[ast.block](?eblk)) {
else_res = trans_block(else_cx, eblk);
}
case (_) { /* fall through */ }
alt (els) {
case (some[@ast.expr](?elexpr)) {
else_res = trans_expr(else_cx, elexpr);
}
case (_) { /* fall through */ }
}

cond_res.bcx.build.CondBr(cond_res.val,
Expand Down Expand Up @@ -4303,8 +4288,8 @@ fn trans_expr(@block_ctxt cx, @ast.expr e) -> result {
ret trans_binary(cx, op, x, y);
}

case (ast.expr_if(?cond, ?thn, ?elifs, ?els, _)) {
ret trans_if(cx, cond, thn, elifs, els);
case (ast.expr_if(?cond, ?thn, ?els, _)) {
ret trans_if(cx, cond, thn, els);
}

case (ast.expr_for(?decl, ?seq, ?body, _)) {
Expand All @@ -4328,14 +4313,7 @@ fn trans_expr(@block_ctxt cx, @ast.expr e) -> result {
}

case (ast.expr_block(?blk, _)) {
auto sub_cx = new_scope_block_ctxt(cx, "block-expr body");
auto next_cx = new_sub_block_ctxt(cx, "next");
auto sub = trans_block(sub_cx, blk);

cx.build.Br(sub_cx.llbb);
sub.bcx.build.Br(next_cx.llbb);

ret res(next_cx, sub.val);
ret trans_block(cx, blk);
}

case (ast.expr_assign(?dst, ?src, ?ann)) {
Expand Down
2 changes: 1 addition & 1 deletion src/comp/middle/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -702,7 +702,7 @@ fn expr_ty(@ast.expr expr) -> @t {
case (ast.expr_unary(_, _, ?ann)) { ret ann_to_type(ann); }
case (ast.expr_lit(_, ?ann)) { ret ann_to_type(ann); }
case (ast.expr_cast(_, _, ?ann)) { ret ann_to_type(ann); }
case (ast.expr_if(_, _, _, _, ?ann)) { ret ann_to_type(ann); }
case (ast.expr_if(_, _, _, ?ann)) { ret ann_to_type(ann); }
case (ast.expr_for(_, _, _, ?ann)) { ret ann_to_type(ann); }
case (ast.expr_for_each(_, _, _, ?ann))
{ ret ann_to_type(ann); }
Expand Down
53 changes: 15 additions & 38 deletions src/comp/middle/typeck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1263,28 +1263,20 @@ fn demand_expr_full(&@fn_ctxt fcx, @ty.t expected, @ast.expr e,
e_1 = ast.expr_cast(sube, ast_ty,
ast.ann_type(t, none[vec[@ty.t]]));
}
case (ast.expr_if(?cond, ?then_0, ?elifs_0, ?else_0, ?ann)) {
case (ast.expr_if(?cond, ?then_0, ?else_0, ?ann)) {
auto t = demand_full(fcx, e.span, expected,
ann_to_type(ann), adk);
auto then_1 = demand_block(fcx, expected, then_0);

let vec[tup(@ast.expr, ast.block)] elifs_1 = vec();
for (tup(@ast.expr, ast.block) elif in elifs_0) {
auto elifcond = elif._0;
auto elifthn_0 = elif._1;
auto elifthn_1 = demand_block(fcx, expected, elifthn_0);
elifs_1 += tup(elifcond, elifthn_1);
}

auto else_1;
alt (else_0) {
case (none[ast.block]) { else_1 = none[ast.block]; }
case (some[ast.block](?b_0)) {
auto b_1 = demand_block(fcx, expected, b_0);
else_1 = some[ast.block](b_1);
case (none[@ast.expr]) { else_1 = none[@ast.expr]; }
case (some[@ast.expr](?e_0)) {
auto e_1 = demand_expr(fcx, expected, e_0);
else_1 = some[@ast.expr](e_1);
}
}
e_1 = ast.expr_if(cond, then_1, elifs_1, else_1,
e_1 = ast.expr_if(cond, then_1, else_1,
ast.ann_type(t, none[vec[@ty.t]]));
}
case (ast.expr_for(?decl, ?seq, ?bloc, ?ann)) {
Expand Down Expand Up @@ -1795,39 +1787,24 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr {
ann));
}

case (ast.expr_if(?cond, ?thn, ?elifs, ?elsopt, _)) {
case (ast.expr_if(?cond, ?thn, ?elsopt, _)) {
auto cond_0 = check_expr(fcx, cond);
auto cond_1 = demand_expr(fcx, plain_ty(ty.ty_bool), cond_0);

auto thn_0 = check_block(fcx, thn);
auto thn_t = block_ty(thn_0);

auto num_elifs = _vec.len[tup(@ast.expr, ast.block)](elifs);
let vec[tup(@ast.expr, ast.block)] elifs_1 = vec();
for each (uint i in _uint.range(0u, num_elifs)) {
auto elif = elifs.(i);
auto elifcond = elif._0;
auto elifcond_0 = check_expr(fcx, cond);
auto elifcond_1 = demand_expr(fcx,
plain_ty(ty.ty_bool),
elifcond_0);
auto elifthn = elif._1;
auto elifthn_0 = check_block(fcx, elifthn);
auto elifthn_1 = demand_block(fcx, thn_t, elifthn_0);
elifs_1 += tup(elifcond_1, elifthn_1);
}

auto elsopt_1;
auto elsopt_t;
alt (elsopt) {
case (some[ast.block](?els)) {
auto els_0 = check_block(fcx, els);
auto els_1 = demand_block(fcx, thn_t, els_0);
elsopt_1 = some[ast.block](els_1);
elsopt_t = block_ty(els_1);
case (some[@ast.expr](?els)) {
auto els_0 = check_expr(fcx, els);
auto els_1 = demand_expr(fcx, thn_t, els_0);
elsopt_1 = some[@ast.expr](els_1);
elsopt_t = expr_ty(els_1);
}
case (none[ast.block]) {
elsopt_1 = none[ast.block];
case (none[@ast.expr]) {
elsopt_1 = none[@ast.expr];
elsopt_t = plain_ty(ty.ty_nil);
}
}
Expand All @@ -1837,7 +1814,7 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr {
auto ann = ast.ann_type(elsopt_t, none[vec[@ty.t]]);
ret @fold.respan[ast.expr_](expr.span,
ast.expr_if(cond_1, thn_1,
elifs_1, elsopt_1, ann));
elsopt_1, ann));
}

case (ast.expr_for(?decl, ?seq, ?body, _)) {
Expand Down
Loading