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
This commit is contained in:
Marijn Haverbeke 2011-07-22 17:19:06 +02:00
parent b45d973552
commit b9b674abe7
13 changed files with 81 additions and 46 deletions

View File

@ -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 {}
}
}
_ {}
}
_ {}
}
}

View File

@ -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) {

View File

@ -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 */ }
}
}

View File

@ -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;
}
}
}

View File

@ -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);

View File

@ -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) |

View File

@ -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 */ }
}
}

View File

@ -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);

View File

@ -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)) }
}

View File

@ -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 {

View File

@ -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); }

View File

@ -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); }
}

View File

@ -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);