diff options
| author | Graydon Hoare <[email protected]> | 2010-11-03 11:05:15 -0700 |
|---|---|---|
| committer | Graydon Hoare <[email protected]> | 2010-11-03 11:05:15 -0700 |
| commit | e5fdd7b63a7365df015c9d08111a8f635b25e058 (patch) | |
| tree | daa0b7450779173d9eceed343e038424799b645d /src | |
| parent | Teach rustc lexer about changes to stratum, opacity and effect keywords. (diff) | |
| download | rust-e5fdd7b63a7365df015c9d08111a8f635b25e058.tar.xz rust-e5fdd7b63a7365df015c9d08111a8f635b25e058.zip | |
Support while and do-while loops in rustc.
Diffstat (limited to 'src')
| -rw-r--r-- | src/comp/front/ast.rs | 2 | ||||
| -rw-r--r-- | src/comp/front/parser.rs | 43 | ||||
| -rw-r--r-- | src/comp/middle/fold.rs | 35 | ||||
| -rw-r--r-- | src/comp/middle/trans.rs | 36 |
4 files changed, 116 insertions, 0 deletions
diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs index 0d042d0d..32317812 100644 --- a/src/comp/front/ast.rs +++ b/src/comp/front/ast.rs @@ -94,6 +94,8 @@ tag expr_ { expr_lit(@lit, option[@ty]); expr_cast(@expr, @ty); expr_if(@expr, block, option[block], option[@ty]); + expr_while(@expr, block, option[@ty]); + expr_do_while(block, @expr, option[@ty]); expr_block(block, option[@ty]); expr_assign(@expr /* TODO: @expr|is_lval */, @expr, option[@ty]); expr_field(@expr, ident, option[@ty]); diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index fd3bd1c0..7046f4b0 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -613,6 +613,33 @@ impure fn parse_if_expr(parser p) -> @ast.expr { ret @spanned(lo, hi, ast.expr_if(cond, thn, els, none[@ast.ty])); } +impure fn parse_while_expr(parser p) -> @ast.expr { + auto lo = p.get_span(); + auto hi = lo; + + expect(p, token.WHILE); + expect (p, token.LPAREN); + auto cond = parse_expr(p); + expect(p, token.RPAREN); + auto body = parse_block(p); + hi = body.span; + ret @spanned(lo, hi, ast.expr_while(cond, body, none[@ast.ty])); +} + +impure fn parse_do_while_expr(parser p) -> @ast.expr { + auto lo = p.get_span(); + auto hi = lo; + + expect(p, token.DO); + auto body = parse_block(p); + expect(p, token.WHILE); + expect (p, token.LPAREN); + auto cond = parse_expr(p); + expect(p, token.RPAREN); + hi = cond.span; + ret @spanned(lo, hi, ast.expr_do_while(body, cond, none[@ast.ty])); +} + impure fn parse_expr(parser p) -> @ast.expr { alt (p.peek()) { case (token.LBRACE) { @@ -623,6 +650,12 @@ impure fn parse_expr(parser p) -> @ast.expr { case (token.IF) { ret parse_if_expr(p); } + case (token.WHILE) { + ret parse_while_expr(p); + } + case (token.DO) { + ret parse_do_while_expr(p); + } case (_) { ret parse_assign_expr(p); } @@ -741,6 +774,16 @@ impure fn parse_stmt(parser p) -> @ast.stmt { ret @spanned(lo, e.span, ast.stmt_expr(e)); } + case (token.WHILE) { + auto e = parse_expr(p); + ret @spanned(lo, e.span, ast.stmt_expr(e)); + } + + case (token.DO) { + auto e = parse_expr(p); + ret @spanned(lo, e.span, ast.stmt_expr(e)); + } + case (token.LBRACE) { auto e = parse_expr(p); ret @spanned(lo, e.span, ast.stmt_expr(e)); diff --git a/src/comp/middle/fold.rs b/src/comp/middle/fold.rs index eeea6bba..c5685680 100644 --- a/src/comp/middle/fold.rs +++ b/src/comp/middle/fold.rs @@ -82,6 +82,14 @@ type ast_fold[ENV] = option[@ty] ty) -> @expr) fold_expr_if, (fn(&ENV e, &span sp, + @expr cond, &block body, + option[@ty] ty) -> @expr) fold_expr_while, + + (fn(&ENV e, &span sp, + &block body, @expr cond, + option[@ty] ty) -> @expr) fold_expr_do_while, + + (fn(&ENV e, &span sp, &block blk, option[@ty] ty) -> @expr) fold_expr_block, (fn(&ENV e, &span sp, @@ -335,6 +343,18 @@ fn fold_expr[ENV](&ENV env, ast_fold[ENV] fld, &@expr e) -> @expr { ret fld.fold_expr_if(env_, e.span, ccnd, tthn, eels, t); } + case (ast.expr_while(?cnd, ?body, ?t)) { + auto ccnd = fold_expr(env_, fld, cnd); + auto bbody = fold_block(env_, fld, body); + ret fld.fold_expr_while(env_, e.span, ccnd, bbody, t); + } + + case (ast.expr_do_while(?body, ?cnd, ?t)) { + auto bbody = fold_block(env_, fld, body); + auto ccnd = fold_expr(env_, fld, cnd); + ret fld.fold_expr_do_while(env_, e.span, bbody, ccnd, t); + } + case (ast.expr_block(?b, ?t)) { auto bb = fold_block(env_, fld, b); ret fld.fold_expr_block(env_, e.span, bb, t); @@ -598,6 +618,18 @@ fn identity_fold_expr_if[ENV](&ENV env, &span sp, ret @respan(sp, ast.expr_if(cond, thn, els, t)); } +fn identity_fold_expr_while[ENV](&ENV env, &span sp, + @expr cond, &block body, + option[@ty] t) -> @expr { + ret @respan(sp, ast.expr_while(cond, body, t)); +} + +fn identity_fold_expr_do_while[ENV](&ENV env, &span sp, + &block body, @expr cond, + option[@ty] t) -> @expr { + ret @respan(sp, ast.expr_do_while(body, cond, t)); +} + fn identity_fold_expr_block[ENV](&ENV env, &span sp, &block blk, option[@ty] t) -> @expr { ret @respan(sp, ast.expr_block(blk, t)); @@ -765,6 +797,9 @@ 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_if = bind identity_fold_expr_if[ENV](_,_,_,_,_,_), + fold_expr_while = bind identity_fold_expr_while[ENV](_,_,_,_,_), + fold_expr_do_while + = bind identity_fold_expr_do_while[ENV](_,_,_,_,_), fold_expr_block = bind identity_fold_expr_block[ENV](_,_,_,_), fold_expr_assign = bind identity_fold_expr_assign[ENV](_,_,_,_,_), fold_expr_field = bind identity_fold_expr_field[ENV](_,_,_,_,_), diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 9fefcf55..c5374212 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -653,6 +653,38 @@ impure fn trans_if(@block_ctxt cx, &ast.expr cond, ret res(next_cx, phi); } +impure fn trans_while(@block_ctxt cx, &ast.expr cond, + &ast.block body) -> result { + + auto cond_cx = new_empty_block_ctxt(cx.fcx); + auto body_cx = new_empty_block_ctxt(cx.fcx); + auto next_cx = new_extension_block_ctxt(cx); + + cx.build.Br(cond_cx.llbb); + auto cond_res = trans_expr(cond_cx, cond); + cond_cx.build.CondBr(cond_res.val, + body_cx.llbb, + next_cx.llbb); + auto body_res = trans_block(body_cx, body); + body_cx.build.Br(cond_cx.llbb); + ret res(next_cx, C_nil()); +} + +impure fn trans_do_while(@block_ctxt cx, &ast.block body, + &ast.expr cond) -> result { + + auto body_cx = new_empty_block_ctxt(cx.fcx); + auto next_cx = new_extension_block_ctxt(cx); + + cx.build.Br(body_cx.llbb); + auto body_res = trans_block(body_cx, body); + auto cond_res = trans_expr(body_cx, cond); + body_cx.build.CondBr(cond_res.val, + body_cx.llbb, + next_cx.llbb); + ret res(next_cx, body_res.val); +} + // The additional bool returned indicates whether it's a local // (that is represented as an alloca, hence needs a 'load' to be // used as an rval). @@ -723,6 +755,10 @@ impure fn trans_expr(@block_ctxt cx, &ast.expr e) -> result { ret trans_if(cx, *cond, thn, els); } + case (ast.expr_while(?cond, ?body, _)) { + ret trans_while(cx, *cond, body); + } + case (ast.expr_block(?blk, _)) { auto sub_cx = new_empty_block_ctxt(cx.fcx); auto next_cx = new_extension_block_ctxt(cx); |