Handle nested items correctly in typestate_check

Summary says it all. Actually, only nested objects and functions
are handled, but that's better than before. The fold that I was using
before to traverse a crate wasn't working correctly, because annotations
have to reflect the number of local variables of the nearest enclosing
function (in turn, because annotations are represented as bit vectors).
The fold was traversing the AST in the wrong order, first filling in
the annotations correctly, but then re-traversing them with the bit
vector length for any outer nested functions, and so on.

Remedying this required writing a lot of tedious boilerplate code
because I scrapped the idea of using a fold altogether.

I also made typestate_check handle unary, field, alt, and fail.

Also, some miscellaneous changes:
* added annotations to blocks in typeck
* fix pprust so it can handle spawn
* added more logging functions in util.common
* fixed _vec.or
* added maybe and from_maybe in option
* removed fold_block field from ast_fold, since it was never used
This commit is contained in:
Tim Chevalier 2011-04-18 15:33:10 -07:00 committed by Graydon Hoare
parent 3d9cf15d0b
commit b7dd75c904
9 changed files with 835 additions and 101 deletions

View File

@ -291,8 +291,6 @@ type ast_fold[ENV] =
(fn(&ENV e, ann a) -> ann) fold_ann,
// Additional nodes.
(fn(&ENV e, &span sp,
&ast.block_) -> block) fold_block,
(fn(&ENV e, &fn_decl decl,
ast.proto proto,
@ -1716,7 +1714,6 @@ fn new_identity_fold[ENV]() -> ast_fold[ENV] {
fold_ann = bind identity_fold_ann[ENV](_,_),
fold_block = bind identity_fold_block[ENV](_,_,_),
fold_fn = bind identity_fold_fn[ENV](_,_,_,_),
fold_fn_decl = bind identity_fold_fn_decl[ENV](_,_,_),
fold_mod = bind identity_fold_mod[ENV](_,_),

View File

@ -1469,7 +1469,8 @@ mod Pushdown {
}
case (none[@ast.expr]) {
Demand.simple(fcx, bloc.span, expected, plain_ty(ty.ty_nil));
ret bloc;
ret fold.respan[ast.block_](bloc.span,
rec(a = boring_ann() with bloc.node));
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -475,6 +475,13 @@ fn print_expr(ps s, &@ast.expr expr) {
commasep[option.t[@ast.expr]](s, args, f);
pclose(s);
}
case (ast.expr_spawn(_,_,?e,?es,_)) {
wrd1(s, "spawn");
print_expr(s, e);
popen(s);
commasep_exprs(s, es);
pclose(s);
}
case (ast.expr_binary(?op,?lhs,?rhs,_)) {
auto prec = operator_prec(op);
print_maybe_parens(s, lhs, prec);
@ -1018,3 +1025,13 @@ fn print_comment(ps s, lexer.cmnt_ cmnt) {
}
}
}
//
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
//

View File

@ -137,6 +137,35 @@ fn log_block(&ast.block b) -> () {
log(s.get_str());
}
fn log_ann(&ast.ann a) -> () {
alt (a) {
case (ast.ann_none) {
log("ann_none");
}
case (ast.ann_type(_,_,_)) {
log("ann_type");
}
}
}
fn log_stmt(ast.stmt st) -> () {
let str_writer s = string_writer();
auto out_ = mkstate(s.get_writer(), 80u);
auto out = @rec(s=out_,
comments=none[vec[front.lexer.cmnt]],
mutable cur_cmnt=0u);
alt (st.node) {
case (ast.stmt_decl(?decl,_)) {
print_decl(out, decl);
}
case (ast.stmt_expr(?ex,_)) {
print_expr(out, ex);
}
case (_) { /* do nothing */ }
}
log(s.get_str());
}
//
// Local Variables:
// mode: rust

View File

@ -147,6 +147,11 @@ fn ann_prestate(&ts_ann a) -> prestate {
ret a.states.prestate;
}
fn pp_clone(&pre_and_post p) -> pre_and_post {
ret rec(precondition=bitv.clone(p.precondition),
postcondition=bitv.clone(p.postcondition));
}
// returns true if a implies b
// that is, returns true except if for some bits c and d,
// c = 1 and d = 0
@ -155,3 +160,14 @@ fn implies(bitv.t a, bitv.t b) -> bool {
bitv.difference(tmp, a);
ret bitv.is_false(tmp);
}
//
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
//

View File

@ -266,7 +266,7 @@ fn unzip[T, U](&vec[tup(T, U)] v) -> tup(vec[T], vec[U]) {
fn or(&vec[bool] v) -> bool {
auto f = orb;
be _vec.foldl[bool, bool](f, false, v);
ret _vec.foldl[bool, bool](f, false, v);
}
fn clone[T](&vec[T] v) -> vec[T] {

View File

@ -39,12 +39,16 @@ fn is_none[T](&t[T] opt) -> bool {
}
fn from_maybe[T](&T def, &t[T] opt) -> T {
alt(opt) {
case (none[T]) { ret def; }
case (some[T](?t)) { ret t; }
}
auto f = bind util.id[T](_);
ret maybe[T, T](def, f, opt);
}
fn maybe[T, U](&U def, fn(&T) -> U f, &t[T] opt) -> U {
alt (opt) {
case (none[T]) { ret def; }
case (some[T](?t)) { ret f(t); }
}
}
// Local Variables:
// mode: rust;
// fill-column: 78;

View File

@ -0,0 +1,12 @@
// xfail-stage0
// error-pattern:Unsatisfied precondition
fn main() {
state obj foo(int x) {
drop {
let int baz;
log(baz);
}
}
fail;
}