Skip to content

Commit 3cb9781

Browse files
committed
---
yaml --- r: 1329 b: refs/heads/master c: 70bf54b h: refs/heads/master i: 1327: 06c6375 v: v3
1 parent 9b3ab92 commit 3cb9781

File tree

8 files changed

+105
-29
lines changed

8 files changed

+105
-29
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
---
2-
refs/heads/master: eb16942c1de42c2f30f7e0eb0ff69371a167f7bd
2+
refs/heads/master: 70bf54bcac587c0bc8a3a593bda75115e4c23aa8

trunk/src/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,7 @@ TEST_XFAILS_RUSTC := $(filter-out \
447447
div-mod.rs \
448448
drop-bind-thunk-args.rs \
449449
drop-on-ret.rs \
450+
else-if.rs \
450451
fact.rs \
451452
fn-lval.rs \
452453
fun-call-variants.rs \

trunk/src/comp/front/ast.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ tag expr_ {
149149
expr_unary(unop, @expr, ann);
150150
expr_lit(@lit, ann);
151151
expr_cast(@expr, @ty, ann);
152-
expr_if(@expr, block, option.t[block], ann);
152+
expr_if(@expr, block, vec[tup(@expr, block)], option.t[block], ann);
153153
expr_while(@expr, block, ann);
154154
expr_for(@decl, @expr, block, ann);
155155
expr_do_while(block, @expr, ann);

trunk/src/comp/front/parser.rs

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -891,18 +891,40 @@ impure fn parse_if_expr(parser p) -> @ast.expr {
891891
auto cond = parse_expr(p);
892892
expect(p, token.RPAREN);
893893
auto thn = parse_block(p);
894-
let option.t[ast.block] els = none[ast.block];
895894
hi = thn.span;
896-
alt (p.peek()) {
897-
case (token.ELSE) {
898-
p.bump();
899-
auto eblk = parse_block(p);
900-
els = some(eblk);
901-
hi = eblk.span;
895+
896+
let vec[tup(@ast.expr, ast.block)] elifs = vec();
897+
let option.t[ast.block] els = none[ast.block];
898+
let bool parsing_elses = true;
899+
while (parsing_elses) {
900+
alt (p.peek()) {
901+
case (token.ELSE) {
902+
expect(p, token.ELSE);
903+
alt (p.peek()) {
904+
case (token.IF) {
905+
expect(p, token.IF);
906+
expect(p, token.LPAREN);
907+
auto elifcond = parse_expr(p);
908+
expect(p, token.RPAREN);
909+
auto elifthn = parse_block(p);
910+
elifs += tup(elifcond, elifthn);
911+
hi = elifthn.span;
912+
}
913+
case (_) {
914+
auto eblk = parse_block(p);
915+
els = some(eblk);
916+
hi = eblk.span;
917+
parsing_elses = false;
918+
}
919+
}
920+
}
921+
case (_) {
922+
parsing_elses = false;
923+
}
902924
}
903-
case (_) { /* fall through */ }
904925
}
905-
ret @spanned(lo, hi, ast.expr_if(cond, thn, els, ast.ann_none));
926+
927+
ret @spanned(lo, hi, ast.expr_if(cond, thn, elifs, els, ast.ann_none));
906928
}
907929

908930
impure fn parse_head_local(parser p) -> @ast.decl {
@@ -1331,7 +1353,7 @@ fn stmt_ends_with_semi(@ast.stmt stmt) -> bool {
13311353
case (ast.expr_unary(_,_,_)) { ret true; }
13321354
case (ast.expr_lit(_,_)) { ret true; }
13331355
case (ast.expr_cast(_,_,_)) { ret true; }
1334-
case (ast.expr_if(_,_,_,_)) { ret false; }
1356+
case (ast.expr_if(_,_,_,_,_)) { ret false; }
13351357
case (ast.expr_for(_,_,_,_)) { ret false; }
13361358
case (ast.expr_while(_,_,_)) { ret false; }
13371359
case (ast.expr_do_while(_,_,_)) { ret false; }

trunk/src/comp/middle/fold.rs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import front.ast.def;
2828
import front.ast.def_id;
2929
import front.ast.ann;
3030

31+
import std._uint;
3132
import std._vec;
3233

3334
type ast_fold[ENV] =
@@ -100,6 +101,7 @@ type ast_fold[ENV] =
100101

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

@@ -501,17 +503,27 @@ fn fold_expr[ENV](&ENV env, ast_fold[ENV] fld, &@expr e) -> @expr {
501503
ret fld.fold_expr_cast(env_, e.span, ee, tt, at);
502504
}
503505

504-
case (ast.expr_if(?cnd, ?thn, ?els, ?t)) {
506+
case (ast.expr_if(?cnd, ?thn, ?elifs, ?els, ?t)) {
505507
auto ccnd = fold_expr(env_, fld, cnd);
506508
auto tthn = fold_block(env_, fld, thn);
509+
510+
let vec[tup(@ast.expr, ast.block)] eelifs = vec();
511+
for (tup(@expr, block) elif in elifs) {
512+
auto elifcnd = elif._0;
513+
auto elifthn = elif._1;
514+
auto elifccnd = fold_expr(env_, fld, elifcnd);
515+
auto eliftthn = fold_block(env_, fld, elifthn);
516+
eelifs += tup(elifccnd, eliftthn);
517+
}
518+
507519
auto eels = none[block];
508520
alt (els) {
509521
case (some[block](?b)) {
510522
eels = some(fold_block(env_, fld, b));
511523
}
512524
case (_) { /* fall through */ }
513525
}
514-
ret fld.fold_expr_if(env_, e.span, ccnd, tthn, eels, t);
526+
ret fld.fold_expr_if(env_, e.span, ccnd, tthn, eelifs, eels, t);
515527
}
516528

517529
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,
961973

962974
fn identity_fold_expr_if[ENV](&ENV env, &span sp,
963975
@expr cond, &block thn,
976+
&vec[tup(@expr, block)] elifs,
964977
&option.t[block] els, ann a) -> @expr {
965-
ret @respan(sp, ast.expr_if(cond, thn, els, a));
978+
ret @respan(sp, ast.expr_if(cond, thn, elifs, els, a));
966979
}
967980

968981
fn identity_fold_expr_for[ENV](&ENV env, &span sp,
@@ -1237,7 +1250,7 @@ fn new_identity_fold[ENV]() -> ast_fold[ENV] {
12371250
fold_expr_unary = bind identity_fold_expr_unary[ENV](_,_,_,_,_),
12381251
fold_expr_lit = bind identity_fold_expr_lit[ENV](_,_,_,_),
12391252
fold_expr_cast = bind identity_fold_expr_cast[ENV](_,_,_,_,_),
1240-
fold_expr_if = bind identity_fold_expr_if[ENV](_,_,_,_,_,_),
1253+
fold_expr_if = bind identity_fold_expr_if[ENV](_,_,_,_,_,_,_),
12411254
fold_expr_for = bind identity_fold_expr_for[ENV](_,_,_,_,_,_),
12421255
fold_expr_while = bind identity_fold_expr_while[ENV](_,_,_,_,_),
12431256
fold_expr_do_while

trunk/src/comp/middle/trans.rs

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1957,8 +1957,9 @@ fn join_results(@block_ctxt parent_cx,
19571957
ret res(join_cx, phi);
19581958
}
19591959

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

19631964
auto cond_res = trans_expr(cx, cond);
19641965

@@ -1968,11 +1969,25 @@ fn trans_if(@block_ctxt cx, @ast.expr cond,
19681969
auto else_cx = new_scope_block_ctxt(cx, "else");
19691970
auto else_res = res(else_cx, C_nil());
19701971

1971-
alt (els) {
1972-
case (some[ast.block](?eblk)) {
1973-
else_res = trans_block(else_cx, eblk);
1972+
auto num_elifs = _vec.len[tup(@ast.expr, ast.block)](elifs);
1973+
if (num_elifs > 0u) {
1974+
auto next_elif = elifs.(0u);
1975+
auto next_elifthn = next_elif._0;
1976+
auto next_elifcnd = next_elif._1;
1977+
auto rest_elifs = _vec.shift[tup(@ast.expr, ast.block)](elifs);
1978+
else_res = trans_if(else_cx, next_elifthn, next_elifcnd,
1979+
rest_elifs, els);
1980+
}
1981+
1982+
/* else: FIXME: rustboot has a problem here
1983+
with preconditions inside an else block */
1984+
if (num_elifs == 0u) {
1985+
alt (els) {
1986+
case (some[ast.block](?eblk)) {
1987+
else_res = trans_block(else_cx, eblk);
1988+
}
1989+
case (_) { /* fall through */ }
19741990
}
1975-
case (_) { /* fall through */ }
19761991
}
19771992

19781993
cond_res.bcx.build.CondBr(cond_res.val,
@@ -2901,8 +2916,8 @@ fn trans_expr(@block_ctxt cx, @ast.expr e) -> result {
29012916
ret trans_binary(cx, op, x, y);
29022917
}
29032918

2904-
case (ast.expr_if(?cond, ?thn, ?els, _)) {
2905-
ret trans_if(cx, cond, thn, els);
2919+
case (ast.expr_if(?cond, ?thn, ?elifs, ?els, _)) {
2920+
ret trans_if(cx, cond, thn, elifs, els);
29062921
}
29072922

29082923
case (ast.expr_for(?decl, ?seq, ?body, _)) {

trunk/src/comp/middle/ty.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -653,7 +653,7 @@ fn expr_ty(@ast.expr expr) -> @t {
653653
case (ast.expr_unary(_, _, ?ann)) { ret ann_to_type(ann); }
654654
case (ast.expr_lit(_, ?ann)) { ret ann_to_type(ann); }
655655
case (ast.expr_cast(_, _, ?ann)) { ret ann_to_type(ann); }
656-
case (ast.expr_if(_, _, _, ?ann)) { ret ann_to_type(ann); }
656+
case (ast.expr_if(_, _, _, _, ?ann)) { ret ann_to_type(ann); }
657657
case (ast.expr_for(_, _, _, ?ann)) { ret ann_to_type(ann); }
658658
case (ast.expr_while(_, _, ?ann)) { ret ann_to_type(ann); }
659659
case (ast.expr_do_while(_, _, ?ann)) { ret ann_to_type(ann); }

trunk/src/comp/middle/typeck.rs

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -864,10 +864,19 @@ fn demand_expr_full(&@fn_ctxt fcx, @ty.t expected, @ast.expr e,
864864
auto t = demand(fcx, e.span, expected, ann_to_type(ann));
865865
e_1 = ast.expr_cast(sube, ast_ty, ast.ann_type(t));
866866
}
867-
case (ast.expr_if(?cond, ?then_0, ?else_0, ?ann)) {
867+
case (ast.expr_if(?cond, ?then_0, ?elifs_0, ?else_0, ?ann)) {
868868
auto t = demand_full(fcx, e.span, expected,
869869
ann_to_type(ann), adk);
870870
auto then_1 = demand_block(fcx, expected, then_0);
871+
872+
let vec[tup(@ast.expr, ast.block)] elifs_1 = vec();
873+
for (tup(@ast.expr, ast.block) elif in elifs_0) {
874+
auto elifcond = elif._0;
875+
auto elifthn_0 = elif._1;
876+
auto elifthn_1 = demand_block(fcx, expected, elifthn_0);
877+
elifs_1 += tup(elifcond, elifthn_1);
878+
}
879+
871880
auto else_1;
872881
alt (else_0) {
873882
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,
876885
else_1 = some[ast.block](b_1);
877886
}
878887
}
879-
e_1 = ast.expr_if(cond, then_1, else_1, ast.ann_type(t));
888+
e_1 = ast.expr_if(cond, then_1, elifs_1, else_1, ast.ann_type(t));
880889
}
881890
case (ast.expr_for(?decl, ?seq, ?bloc, ?ann)) {
882891
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 {
11951204
ann));
11961205
}
11971206

1198-
case (ast.expr_if(?cond, ?thn, ?elsopt, _)) {
1207+
case (ast.expr_if(?cond, ?thn, ?elifs, ?elsopt, _)) {
11991208
auto cond_0 = check_expr(fcx, cond);
12001209
auto cond_1 = demand_expr(fcx, plain_ty(ty.ty_bool), cond_0);
12011210

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

1214+
auto num_elifs = _vec.len[tup(@ast.expr, ast.block)](elifs);
1215+
let vec[tup(@ast.expr, ast.block)] elifs_1 = vec();
1216+
for each (uint i in _uint.range(0u, num_elifs)) {
1217+
auto elif = elifs.(i);
1218+
auto elifcond = elif._0;
1219+
auto elifcond_0 = check_expr(fcx, cond);
1220+
auto elifcond_1 = demand_expr(fcx,
1221+
plain_ty(ty.ty_bool),
1222+
elifcond_0);
1223+
auto elifthn = elif._1;
1224+
auto elifthn_0 = check_block(fcx, elifthn);
1225+
auto elifthn_1 = demand_block(fcx, thn_t, elifthn_0);
1226+
elifs_1 += tup(elifcond_1, elifthn_1);
1227+
}
1228+
12051229
auto elsopt_1;
12061230
auto elsopt_t;
12071231
alt (elsopt) {
@@ -1220,7 +1244,8 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr {
12201244
auto thn_1 = demand_block(fcx, elsopt_t, thn_0);
12211245

12221246
ret @fold.respan[ast.expr_](expr.span,
1223-
ast.expr_if(cond_1, thn_1, elsopt_1,
1247+
ast.expr_if(cond_1, thn_1,
1248+
elifs_1, elsopt_1,
12241249
ast.ann_type(elsopt_t)));
12251250
}
12261251

0 commit comments

Comments
 (0)