Implement 'else if'
This commit is contained in:
parent
eb16942c1d
commit
70bf54bcac
@ -447,6 +447,7 @@ TEST_XFAILS_RUSTC := $(filter-out \
|
||||
div-mod.rs \
|
||||
drop-bind-thunk-args.rs \
|
||||
drop-on-ret.rs \
|
||||
else-if.rs \
|
||||
fact.rs \
|
||||
fn-lval.rs \
|
||||
fun-call-variants.rs \
|
||||
|
@ -149,7 +149,7 @@ tag expr_ {
|
||||
expr_unary(unop, @expr, ann);
|
||||
expr_lit(@lit, ann);
|
||||
expr_cast(@expr, @ty, ann);
|
||||
expr_if(@expr, block, option.t[block], ann);
|
||||
expr_if(@expr, block, vec[tup(@expr, block)], option.t[block], ann);
|
||||
expr_while(@expr, block, ann);
|
||||
expr_for(@decl, @expr, block, ann);
|
||||
expr_do_while(block, @expr, ann);
|
||||
|
@ -891,18 +891,40 @@ 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.block] els = none[ast.block];
|
||||
hi = thn.span;
|
||||
alt (p.peek()) {
|
||||
case (token.ELSE) {
|
||||
p.bump();
|
||||
auto eblk = parse_block(p);
|
||||
els = some(eblk);
|
||||
hi = eblk.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;
|
||||
}
|
||||
}
|
||||
case (_) { /* fall through */ }
|
||||
}
|
||||
ret @spanned(lo, hi, ast.expr_if(cond, thn, els, ast.ann_none));
|
||||
|
||||
ret @spanned(lo, hi, ast.expr_if(cond, thn, elifs, els, ast.ann_none));
|
||||
}
|
||||
|
||||
impure fn parse_head_local(parser p) -> @ast.decl {
|
||||
@ -1331,7 +1353,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_while(_,_,_)) { ret false; }
|
||||
case (ast.expr_do_while(_,_,_)) { ret false; }
|
||||
|
@ -28,6 +28,7 @@ import front.ast.def;
|
||||
import front.ast.def_id;
|
||||
import front.ast.ann;
|
||||
|
||||
import std._uint;
|
||||
import std._vec;
|
||||
|
||||
type ast_fold[ENV] =
|
||||
@ -100,6 +101,7 @@ type ast_fold[ENV] =
|
||||
|
||||
(fn(&ENV e, &span sp,
|
||||
@expr cond, &block thn,
|
||||
&vec[tup(@expr, block)] elifs,
|
||||
&option.t[block] els,
|
||||
ann a) -> @expr) fold_expr_if,
|
||||
|
||||
@ -501,9 +503,19 @@ 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, ?els, ?t)) {
|
||||
case (ast.expr_if(?cnd, ?thn, ?elifs, ?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];
|
||||
alt (els) {
|
||||
case (some[block](?b)) {
|
||||
@ -511,7 +523,7 @@ fn fold_expr[ENV](&ENV env, ast_fold[ENV] fld, &@expr e) -> @expr {
|
||||
}
|
||||
case (_) { /* fall through */ }
|
||||
}
|
||||
ret fld.fold_expr_if(env_, e.span, ccnd, tthn, eels, t);
|
||||
ret fld.fold_expr_if(env_, e.span, ccnd, tthn, eelifs, eels, t);
|
||||
}
|
||||
|
||||
case (ast.expr_for(?decl, ?seq, ?body, ?t)) {
|
||||
@ -961,8 +973,9 @@ 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, els, a));
|
||||
ret @respan(sp, ast.expr_if(cond, thn, elifs, els, a));
|
||||
}
|
||||
|
||||
fn identity_fold_expr_for[ENV](&ENV env, &span sp,
|
||||
@ -1237,7 +1250,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_while = bind identity_fold_expr_while[ENV](_,_,_,_,_),
|
||||
fold_expr_do_while
|
||||
|
@ -1957,8 +1957,9 @@ fn join_results(@block_ctxt parent_cx,
|
||||
ret res(join_cx, phi);
|
||||
}
|
||||
|
||||
fn trans_if(@block_ctxt cx, @ast.expr cond,
|
||||
&ast.block thn, &option.t[ast.block] els) -> result {
|
||||
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 {
|
||||
|
||||
auto cond_res = trans_expr(cx, cond);
|
||||
|
||||
@ -1968,11 +1969,25 @@ fn trans_if(@block_ctxt cx, @ast.expr cond,
|
||||
auto else_cx = new_scope_block_ctxt(cx, "else");
|
||||
auto else_res = res(else_cx, C_nil());
|
||||
|
||||
alt (els) {
|
||||
case (some[ast.block](?eblk)) {
|
||||
else_res = trans_block(else_cx, eblk);
|
||||
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 */ }
|
||||
}
|
||||
case (_) { /* fall through */ }
|
||||
}
|
||||
|
||||
cond_res.bcx.build.CondBr(cond_res.val,
|
||||
@ -2901,8 +2916,8 @@ fn trans_expr(@block_ctxt cx, @ast.expr e) -> result {
|
||||
ret trans_binary(cx, op, x, y);
|
||||
}
|
||||
|
||||
case (ast.expr_if(?cond, ?thn, ?els, _)) {
|
||||
ret trans_if(cx, cond, thn, els);
|
||||
case (ast.expr_if(?cond, ?thn, ?elifs, ?els, _)) {
|
||||
ret trans_if(cx, cond, thn, elifs, els);
|
||||
}
|
||||
|
||||
case (ast.expr_for(?decl, ?seq, ?body, _)) {
|
||||
|
@ -653,7 +653,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_while(_, _, ?ann)) { ret ann_to_type(ann); }
|
||||
case (ast.expr_do_while(_, _, ?ann)) { ret ann_to_type(ann); }
|
||||
|
@ -864,10 +864,19 @@ fn demand_expr_full(&@fn_ctxt fcx, @ty.t expected, @ast.expr e,
|
||||
auto t = demand(fcx, e.span, expected, ann_to_type(ann));
|
||||
e_1 = ast.expr_cast(sube, ast_ty, ast.ann_type(t));
|
||||
}
|
||||
case (ast.expr_if(?cond, ?then_0, ?else_0, ?ann)) {
|
||||
case (ast.expr_if(?cond, ?then_0, ?elifs_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]; }
|
||||
@ -876,7 +885,7 @@ fn demand_expr_full(&@fn_ctxt fcx, @ty.t expected, @ast.expr e,
|
||||
else_1 = some[ast.block](b_1);
|
||||
}
|
||||
}
|
||||
e_1 = ast.expr_if(cond, then_1, else_1, ast.ann_type(t));
|
||||
e_1 = ast.expr_if(cond, then_1, elifs_1, else_1, ast.ann_type(t));
|
||||
}
|
||||
case (ast.expr_for(?decl, ?seq, ?bloc, ?ann)) {
|
||||
auto t = demand(fcx, e.span, expected, ann_to_type(ann));
|
||||
@ -1195,13 +1204,28 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr {
|
||||
ann));
|
||||
}
|
||||
|
||||
case (ast.expr_if(?cond, ?thn, ?elsopt, _)) {
|
||||
case (ast.expr_if(?cond, ?thn, ?elifs, ?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) {
|
||||
@ -1220,7 +1244,8 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr {
|
||||
auto thn_1 = demand_block(fcx, elsopt_t, thn_0);
|
||||
|
||||
ret @fold.respan[ast.expr_](expr.span,
|
||||
ast.expr_if(cond_1, thn_1, elsopt_1,
|
||||
ast.expr_if(cond_1, thn_1,
|
||||
elifs_1, elsopt_1,
|
||||
ast.ann_type(elsopt_t)));
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user