From 70bf54bcac587c0bc8a3a593bda75115e4c23aa8 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Tue, 1 Feb 2011 16:23:48 -0800 Subject: Implement 'else if' --- src/comp/middle/fold.rs | 21 +++++++++++++++++---- src/comp/middle/trans.rs | 31 +++++++++++++++++++++++-------- src/comp/middle/ty.rs | 2 +- src/comp/middle/typeck.rs | 33 +++++++++++++++++++++++++++++---- 4 files changed, 70 insertions(+), 17 deletions(-) (limited to 'src/comp/middle') diff --git a/src/comp/middle/fold.rs b/src/comp/middle/fold.rs index 67c26014..7e6839a8 100644 --- a/src/comp/middle/fold.rs +++ b/src/comp/middle/fold.rs @@ -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 diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 446b4f10..c08147fe 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -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, _)) { diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index b840be91..2f14aae6 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -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); } diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index ea9002ae..7112e982 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -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))); } -- cgit v1.2.3