From b9b674abe70dd6f666ac3318e26d28c8f61b8e40 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Fri, 22 Jul 2011 17:19:06 +0200 Subject: [PATCH] Start adding support for multiple variable declarations per stmt This adds parser support and most of the machinery for auto x = 10, y = 20; However, the above still goes wrong somewhere in typestate, causing the state checker to believe only the last variable in the list is initialized after the statement. Tim, if you have a moment, could you go over the changes to the tstate code in this patch and see where I'm going wrong? Multi-var-decls without the typestate extension Add a loop --- src/comp/middle/alias.rs | 16 +++++++------ src/comp/middle/resolve.rs | 17 ++++++++----- src/comp/middle/trans.rs | 12 +++++++--- src/comp/middle/trans_dps.rs | 8 +++++-- src/comp/middle/tstate/pre_post_conditions.rs | 4 +++- src/comp/middle/tstate/states.rs | 11 +++++---- src/comp/middle/typeck.rs | 4 +++- src/comp/syntax/ast.rs | 2 +- src/comp/syntax/fold.rs | 5 ++-- src/comp/syntax/parse/parser.rs | 16 +++++++++---- src/comp/syntax/print/pprust.rs | 24 +++++++++++-------- src/comp/syntax/visit.rs | 4 ++-- src/comp/syntax/walk.rs | 4 +++- 13 files changed, 81 insertions(+), 46 deletions(-) diff --git a/src/comp/middle/alias.rs b/src/comp/middle/alias.rs index fac5db76e58..4e86427194b 100644 --- a/src/comp/middle/alias.rs +++ b/src/comp/middle/alias.rs @@ -133,17 +133,19 @@ fn visit_expr(&@ctx cx, &@ast::expr ex, &scope sc, &vt[scope] v) { fn visit_decl(&@ctx cx, &@ast::decl d, &scope sc, &vt[scope] v) { visit::visit_decl(d, sc, v); alt (d.node) { - ast::decl_local(?loc) { + ast::decl_local(?locs) { + for (@ast::local loc in locs) { alt (loc.node.init) { - some(?init) { - if (init.op == ast::init_move) { - check_move_rhs(cx, init.expr, sc, v); - } + some(?init) { + if (init.op == ast::init_move) { + check_move_rhs(cx, init.expr, sc, v); } - none {} + } + none {} } } - _ {} + } + _ {} } } diff --git a/src/comp/middle/resolve.rs b/src/comp/middle/resolve.rs index f00a53b4bfb..a747003f50f 100644 --- a/src/comp/middle/resolve.rs +++ b/src/comp/middle/resolve.rs @@ -787,10 +787,13 @@ fn lookup_in_block(&ident name, &ast::block_ b, namespace ns) -> alt (st.node) { case (ast::stmt_decl(?d, _)) { alt (d.node) { - case (ast::decl_local(?loc)) { - if (ns == ns_value && str::eq(name, loc.node.ident)) { - ret some(ast::def_local(local_def(loc.node.id))); - } + ast::decl_local(?locs) { + for (@ast::local loc in locs) { + if ns == ns_value && str::eq(name, loc.node.ident) { + ret some(ast::def_local + (local_def(loc.node.id))); + } + } } case (ast::decl_item(?it)) { alt (it.node) { @@ -1325,8 +1328,10 @@ fn check_block(@env e, &ast::block b, &() x, &vt[()] v) { alt (st.node) { case (ast::stmt_decl(?d, _)) { alt (d.node) { - ast::decl_local(?loc) { - add_name(values, d.span, loc.node.ident); + ast::decl_local(?locs) { + for (@ast::local loc in locs) { + add_name(values, d.span, loc.node.ident); + } } ast::decl_item(?it) { alt (it.node) { diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 47b5365d755..aa50e5ff0c2 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -6157,8 +6157,10 @@ fn trans_stmt(&@block_ctxt cx, &ast::stmt s) -> result { case (ast::stmt_expr(?e, _)) { bcx = trans_expr(cx, e).bcx; } case (ast::stmt_decl(?d, _)) { alt (d.node) { - case (ast::decl_local(?local)) { - bcx = init_local(bcx, local).bcx; + case (ast::decl_local(?locals)) { + for (@ast::local local in locals) { + bcx = init_local(bcx, local).bcx; + } } case (ast::decl_item(?i)) { trans_item(cx.fcx.lcx, *i); } } @@ -6263,7 +6265,11 @@ iter block_locals(&ast::block b) -> @ast::local { alt (s.node) { case (ast::stmt_decl(?d, _)) { alt (d.node) { - case (ast::decl_local(?local)) { put local; } + case (ast::decl_local(?locals)) { + for (@ast::local local in locals) { + put local; + } + } case (_) {/* fall through */ } } } diff --git a/src/comp/middle/trans_dps.rs b/src/comp/middle/trans_dps.rs index f3d74ec4d3a..193155d259c 100644 --- a/src/comp/middle/trans_dps.rs +++ b/src/comp/middle/trans_dps.rs @@ -597,12 +597,16 @@ fn trans_stmt(&@block_ctxt cx, &@ast::stmt stmt) -> @block_ctxt { } ast::stmt_decl(?d, _) { alt (d.node) { - ast::decl_local(?local) { ret trans_init_local(bcx, local); } + ast::decl_local(?locals) { + for (@ast::local local in locals) { + bcx = trans_init_local(bcx, local); + } + } ast::decl_item(?item) { trans::trans_item(bcx_lcx(bcx), *item); - ret bcx; } } + ret bcx; } } } diff --git a/src/comp/middle/tstate/pre_post_conditions.rs b/src/comp/middle/tstate/pre_post_conditions.rs index 6065b5fa2b2..01930f366d4 100644 --- a/src/comp/middle/tstate/pre_post_conditions.rs +++ b/src/comp/middle/tstate/pre_post_conditions.rs @@ -585,7 +585,8 @@ fn find_pre_post_stmt(&fn_ctxt fcx, &stmt s) { alt (s.node) { case (stmt_decl(?adecl, ?id)) { alt (adecl.node) { - case (decl_local(?alocal)) { + case (decl_local(?alocals)) { + for (@local alocal in alocals) { alt (alocal.node.init) { case (some(?an_init)) { /* LHS always becomes initialized, @@ -628,6 +629,7 @@ fn find_pre_post_stmt(&fn_ctxt fcx, &stmt s) { .conditions); } } + } } case (decl_item(?anitem)) { clear_pp(node_id_to_ts_ann(fcx.ccx, id).conditions); diff --git a/src/comp/middle/tstate/states.rs b/src/comp/middle/tstate/states.rs index c91687be0f8..149d0c5efb5 100644 --- a/src/comp/middle/tstate/states.rs +++ b/src/comp/middle/tstate/states.rs @@ -596,7 +596,9 @@ fn find_pre_post_state_stmt(&fn_ctxt fcx, &prestate pres, @stmt s) -> bool { alt (s.node) { case (stmt_decl(?adecl, ?id)) { alt (adecl.node) { - case (decl_local(?alocal)) { + case (decl_local(?alocals)) { + auto changed = false; + for (@local alocal in alocals) { alt (alocal.node.init) { case (some(?an_init)) { auto changed = set_prestate(stmt_ann, pres) | @@ -646,9 +648,7 @@ fn find_pre_post_state_stmt(&fn_ctxt fcx, &prestate pres, @stmt s) -> bool { /* important to do this in one step to ensure termination (don't want to set changed to true for intermediate changes) */ - ret changed | set_poststate(stmt_ann, post); - - + changed |= set_poststate(stmt_ann, post); } case (none) { // let int = x; => x is uninit in poststate @@ -656,9 +656,10 @@ fn find_pre_post_state_stmt(&fn_ctxt fcx, &prestate pres, @stmt s) -> bool { clear_in_poststate_ident(fcx, alocal.node.id, alocal.node.ident, id); set_prestate(stmt_ann, pres); - ret false; } } + } + ret changed; } case (decl_item(?an_item)) { ret set_prestate(stmt_ann, pres) | diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index 4a0bcf5e61e..584ac7d44fd 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -2584,7 +2584,9 @@ fn check_stmt(&@fn_ctxt fcx, &@ast::stmt stmt) { case (ast::stmt_decl(?decl, ?id)) { node_id = id; alt (decl.node) { - case (ast::decl_local(?l)) { check_decl_local(fcx, l); } + case (ast::decl_local(?ls)) { + for (@ast::local l in ls) { check_decl_local(fcx, l); } + } case (ast::decl_item(_)) {/* ignore for now */ } } } diff --git a/src/comp/syntax/ast.rs b/src/comp/syntax/ast.rs index 04c24aad99a..5992a857d14 100644 --- a/src/comp/syntax/ast.rs +++ b/src/comp/syntax/ast.rs @@ -252,7 +252,7 @@ type local = spanned[local_]; type decl = spanned[decl_]; -tag decl_ { decl_local(@local); decl_item(@item); } +tag decl_ { decl_local((@local)[]); decl_item(@item); } type arm = rec((@pat)[] pats, block block); diff --git a/src/comp/syntax/fold.rs b/src/comp/syntax/fold.rs index 812542bb114..6dd83963bf8 100644 --- a/src/comp/syntax/fold.rs +++ b/src/comp/syntax/fold.rs @@ -298,9 +298,8 @@ fn noop_fold_pat(&pat_ p, ast_fold fld) -> pat_ { fn noop_fold_decl(&decl_ d, ast_fold fld) -> decl_ { ret alt (d) { - // local really doesn't need its own fold... - case (decl_local(?l)) { - decl_local(fld.fold_local(l)) + case (decl_local(?ls)) { + decl_local(ivec::map(fld.fold_local, ls)) } case (decl_item(?it)) { decl_item(fld.fold_item(it)) } } diff --git a/src/comp/syntax/parse/parser.rs b/src/comp/syntax/parse/parser.rs index a0863319b8d..8ea55673207 100644 --- a/src/comp/syntax/parse/parser.rs +++ b/src/comp/syntax/parse/parser.rs @@ -1543,14 +1543,22 @@ fn parse_auto_local(&parser p) -> @ast::local { fn parse_let(&parser p) -> @ast::decl { auto lo = p.get_last_lo_pos(); - auto local = parse_typed_local(p); - ret @spanned(lo, p.get_hi_pos(), ast::decl_local(local)); + auto locals = ~[parse_typed_local(p)]; + while p.peek() == token::COMMA { + p.bump(); + locals += ~[parse_typed_local(p)]; + } + ret @spanned(lo, p.get_hi_pos(), ast::decl_local(locals)); } fn parse_auto(&parser p) -> @ast::decl { auto lo = p.get_last_lo_pos(); - auto local = parse_auto_local(p); - ret @spanned(lo, p.get_hi_pos(), ast::decl_local(local)); + auto locals = ~[parse_auto_local(p)]; + while p.peek() == token::COMMA { + p.bump(); + locals += ~[parse_auto_local(p)]; + } + ret @spanned(lo, p.get_hi_pos(), ast::decl_local(locals)); } fn parse_stmt(&parser p) -> @ast::stmt { diff --git a/src/comp/syntax/print/pprust.rs b/src/comp/syntax/print/pprust.rs index 32ef2e2f471..4dc65d112bc 100644 --- a/src/comp/syntax/print/pprust.rs +++ b/src/comp/syntax/print/pprust.rs @@ -1045,10 +1045,10 @@ fn print_expr(&ps s, &@ast::expr expr) { fn print_decl(&ps s, &@ast::decl decl) { maybe_print_comment(s, decl.span.lo); alt (decl.node) { - case (ast::decl_local(?loc)) { + case (ast::decl_local(?locs)) { space_if_not_hardbreak(s); ibox(s, indent_unit); - alt (loc.node.ty) { + alt (locs.(0).node.ty) { case (some(?ty)) { word_nbsp(s, "let"); print_type(s, *ty); @@ -1058,19 +1058,23 @@ fn print_decl(&ps s, &@ast::decl decl) { word_nbsp(s, "auto"); } } - word(s.s, loc.node.ident); - alt (loc.node.init) { - case (some(?init)) { + fn print_local(&ps s, &@ast::local loc) { + word(s.s, loc.node.ident); + alt loc.node.init { + some(?init) { space(s.s); - alt (init.op) { - case (ast::init_assign) { word_space(s, "="); } - case (ast::init_move) { word_space(s, "<-"); } - case (ast::init_recv) { word_space(s, "|>"); } + alt init.op { + ast::init_assign { word_space(s, "="); } + ast::init_move { word_space(s, "<-"); } + ast::init_recv { word_space(s, "|>"); } } print_expr(s, init.expr); + } + _ { } } - case (_) { } } + fn local_span(&@ast::local loc) -> codemap::span { ret loc.span; } + commasep_cmnt(s, consistent, locs, print_local, local_span); end(s); } case (ast::decl_item(?item)) { print_item(s, item); } diff --git a/src/comp/syntax/visit.rs b/src/comp/syntax/visit.rs index 6893250ac00..820ebf22aae 100644 --- a/src/comp/syntax/visit.rs +++ b/src/comp/syntax/visit.rs @@ -249,8 +249,8 @@ fn visit_stmt[E](&@stmt s, &E e, &vt[E] v) { fn visit_decl[E](&@decl d, &E e, &vt[E] v) { alt (d.node) { - case (decl_local(?loc)) { - v.visit_local(loc, e, v); + case (decl_local(?locs)) { + for (@ast::local loc in locs) { v.visit_local(loc, e, v); } } case (decl_item(?it)) { v.visit_item(it, e, v); } } diff --git a/src/comp/syntax/walk.rs b/src/comp/syntax/walk.rs index 6f993f960a9..88cb173cc7a 100644 --- a/src/comp/syntax/walk.rs +++ b/src/comp/syntax/walk.rs @@ -256,7 +256,9 @@ fn walk_decl(&ast_visitor v, @ast::decl d) { if (!v.keep_going()) { ret; } v.visit_decl_pre(d); alt (d.node) { - case (ast::decl_local(?loc)) { walk_local(v, loc); } + case (ast::decl_local(?locs)) { + for (@ast::local loc in locs) { walk_local(v, loc); } + } case (ast::decl_item(?it)) { walk_item(v, it); } } v.visit_decl_post(d);