From 4a72a23171d87fb5a0f9b7ad039944856b93bf0f Mon Sep 17 00:00:00 2001 From: Graydon Hoare <graydon@mozilla.com> Date: Mon, 14 Feb 2011 18:17:31 -0800 Subject: [PATCH] Add basic front-end support for 'for each' loops. --- src/comp/front/ast.rs | 1 + src/comp/front/parser.rs | 17 ++++++++++++++++- src/comp/middle/fold.rs | 19 +++++++++++++++++++ src/comp/middle/resolve.rs | 3 +++ src/comp/middle/trans.rs | 13 +++++++++++++ src/comp/middle/ty.rs | 2 ++ src/comp/middle/typeck.rs | 15 +++++++++++++++ 7 files changed, 69 insertions(+), 1 deletion(-) diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs index cb2df2a5a3e..9e43d3496b4 100644 --- a/src/comp/front/ast.rs +++ b/src/comp/front/ast.rs @@ -151,6 +151,7 @@ tag expr_ { expr_if(@expr, block, vec[tup(@expr, block)], option.t[block], ann); expr_while(@expr, block, ann); expr_for(@decl, @expr, block, ann); + expr_for_each(@decl, @expr, block, ann); expr_do_while(block, @expr, ann); expr_alt(@expr, vec[arm], ann); expr_block(block, ann); diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index a779d0133cd..ddadc789764 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -1049,8 +1049,14 @@ impure fn parse_head_local(parser p) -> @ast.decl { impure fn parse_for_expr(parser p) -> @ast.expr { auto lo = p.get_span(); auto hi = lo; + auto is_each = false; expect(p, token.FOR); + if (p.peek() == token.EACH) { + is_each = true; + p.bump(); + } + expect (p, token.LPAREN); auto decl = parse_head_local(p); @@ -1060,9 +1066,16 @@ impure fn parse_for_expr(parser p) -> @ast.expr { expect(p, token.RPAREN); auto body = parse_block(p); hi = body.span; - ret @spanned(lo, hi, ast.expr_for(decl, seq, body, ast.ann_none)); + if (is_each) { + ret @spanned(lo, hi, ast.expr_for_each(decl, seq, body, + ast.ann_none)); + } else { + ret @spanned(lo, hi, ast.expr_for(decl, seq, body, + ast.ann_none)); + } } + impure fn parse_while_expr(parser p) -> @ast.expr { auto lo = p.get_span(); auto hi = lo; @@ -1422,6 +1435,8 @@ fn stmt_ends_with_semi(@ast.stmt stmt) -> bool { case (ast.expr_cast(_,_,_)) { ret true; } case (ast.expr_if(_,_,_,_,_)) { ret false; } case (ast.expr_for(_,_,_,_)) { ret false; } + case (ast.expr_for_each(_,_,_,_)) + { ret false; } case (ast.expr_while(_,_,_)) { ret false; } case (ast.expr_do_while(_,_,_)) { ret false; } case (ast.expr_alt(_,_,_)) { ret false; } diff --git a/src/comp/middle/fold.rs b/src/comp/middle/fold.rs index 4d3c2e2d149..3cafa9610b6 100644 --- a/src/comp/middle/fold.rs +++ b/src/comp/middle/fold.rs @@ -112,6 +112,10 @@ type ast_fold[ENV] = @decl decl, @expr seq, &block body, ann a) -> @expr) fold_expr_for, + (fn(&ENV e, &span sp, + @decl decl, @expr seq, &block body, + ann a) -> @expr) fold_expr_for_each, + (fn(&ENV e, &span sp, @expr cond, &block body, ann a) -> @expr) fold_expr_while, @@ -574,6 +578,13 @@ fn fold_expr[ENV](&ENV env, ast_fold[ENV] fld, &@expr e) -> @expr { ret fld.fold_expr_for(env_, e.span, ddecl, sseq, bbody, t); } + case (ast.expr_for_each(?decl, ?seq, ?body, ?t)) { + auto ddecl = fold_decl(env_, fld, decl); + auto sseq = fold_expr(env_, fld, seq); + auto bbody = fold_block(env_, fld, body); + ret fld.fold_expr_for_each(env_, e.span, ddecl, sseq, bbody, t); + } + case (ast.expr_while(?cnd, ?body, ?t)) { auto ccnd = fold_expr(env_, fld, cnd); auto bbody = fold_block(env_, fld, body); @@ -1087,6 +1098,12 @@ fn identity_fold_expr_for[ENV](&ENV env, &span sp, ret @respan(sp, ast.expr_for(d, seq, body, a)); } +fn identity_fold_expr_for_each[ENV](&ENV env, &span sp, + @decl d, @expr seq, + &block body, ann a) -> @expr { + ret @respan(sp, ast.expr_for_each(d, seq, body, a)); +} + fn identity_fold_expr_while[ENV](&ENV env, &span sp, @expr cond, &block body, ann a) -> @expr { ret @respan(sp, ast.expr_while(cond, body, a)); @@ -1402,6 +1419,8 @@ fn new_identity_fold[ENV]() -> ast_fold[ENV] { fold_expr_cast = bind identity_fold_expr_cast[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](_,_,_,_,_,_), fold_expr_while = bind identity_fold_expr_while[ENV](_,_,_,_,_), fold_expr_do_while = bind identity_fold_expr_do_while[ENV](_,_,_,_,_), diff --git a/src/comp/middle/resolve.rs b/src/comp/middle/resolve.rs index 96be838c7c8..d4ad907e32a 100644 --- a/src/comp/middle/resolve.rs +++ b/src/comp/middle/resolve.rs @@ -565,6 +565,9 @@ fn update_env_for_expr(&env e, @ast.expr x) -> env { case (ast.expr_for(?d, _, _, _)) { ret rec(scopes = cons[scope](scope_loop(d), @e.scopes) with e); } + case (ast.expr_for_each(?d, _, _, _)) { + ret rec(scopes = cons[scope](scope_loop(d), @e.scopes) with e); + } case (_) { } } ret e; diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index c8f21dff513..c4e5c9c4f33 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -2116,6 +2116,15 @@ fn trans_for(@block_ctxt cx, bind inner(_, local, _, _, body)); } +fn trans_for_each(@block_ctxt cx, + @ast.decl decl, + @ast.expr seq, + &ast.block body) -> result { + cx.fcx.ccx.sess.unimpl("for each loop"); + fail; +} + + fn trans_while(@block_ctxt cx, @ast.expr cond, &ast.block body) -> result { @@ -3035,6 +3044,10 @@ fn trans_expr(@block_ctxt cx, @ast.expr e) -> result { ret trans_for(cx, decl, seq, body); } + case (ast.expr_for_each(?decl, ?seq, ?body, _)) { + ret trans_for_each(cx, decl, seq, body); + } + case (ast.expr_while(?cond, ?body, _)) { ret trans_while(cx, cond, body); } diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index f9b2bd9d000..499ed74d8a9 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -676,6 +676,8 @@ fn expr_ty(@ast.expr expr) -> @t { case (ast.expr_cast(_, _, ?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); } case (ast.expr_while(_, _, ?ann)) { ret ann_to_type(ann); } case (ast.expr_do_while(_, _, ?ann)) { ret ann_to_type(ann); } case (ast.expr_alt(_, _, ?ann)) { ret ann_to_type(ann); } diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index 5109adb2a43..a062f79d4d0 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -995,6 +995,10 @@ 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_for(decl, seq, bloc, ast.ann_type(t)); } + case (ast.expr_for_each(?decl, ?seq, ?bloc, ?ann)) { + auto t = demand(fcx, e.span, expected, ann_to_type(ann)); + e_1 = ast.expr_for_each(decl, seq, bloc, ast.ann_type(t)); + } case (ast.expr_while(?cond, ?bloc, ?ann)) { auto t = demand(fcx, e.span, expected, ann_to_type(ann)); e_1 = ast.expr_while(cond, bloc, ast.ann_type(t)); @@ -1448,6 +1452,17 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr { body_1, ann)); } + case (ast.expr_for_each(?decl, ?seq, ?body, _)) { + auto decl_1 = check_decl_local(fcx, decl); + auto seq_1 = check_expr(fcx, seq); + auto body_1 = check_block(fcx, body); + + auto ann = ast.ann_type(plain_ty(ty.ty_nil)); + ret @fold.respan[ast.expr_](expr.span, + ast.expr_for_each(decl_1, seq_1, + body_1, ann)); + } + case (ast.expr_while(?cond, ?body, _)) { auto cond_0 = check_expr(fcx, cond); auto cond_1 = demand_expr(fcx, plain_ty(ty.ty_bool), cond_0);