2011-06-15 13:19:50 -05:00
|
|
|
|
2011-05-12 10:24:54 -05:00
|
|
|
import front::ast::ident;
|
2011-05-17 13:41:41 -05:00
|
|
|
import std::vec;
|
2011-05-12 10:24:54 -05:00
|
|
|
import std::bitv;
|
2011-03-24 14:12:04 -05:00
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
|
2011-03-24 14:12:04 -05:00
|
|
|
/*
|
|
|
|
This says: this expression requires the idents in <pre> to be initialized,
|
|
|
|
and given the precondition, it guarantees that the idents in <post> are
|
|
|
|
initialized.
|
|
|
|
*/
|
2011-06-15 13:19:50 -05:00
|
|
|
type precond = bitv::t;
|
|
|
|
|
|
|
|
/* 1 means "this variable must be initialized"
|
|
|
|
0 means "don't care about this variable" */
|
|
|
|
type postcond = bitv::t;
|
|
|
|
|
|
|
|
/* 1 means "this variable is initialized"
|
|
|
|
0 means "don't know about this variable */
|
|
|
|
type prestate = bitv::t;
|
|
|
|
|
|
|
|
/* 1 means "this variable is definitely initialized"
|
|
|
|
0 means "don't know whether this variable is
|
|
|
|
initialized" */
|
|
|
|
type poststate = bitv::t;
|
|
|
|
|
|
|
|
/* 1 means "this variable is definitely initialized"
|
|
|
|
0 means "don't know whether this variable is
|
|
|
|
initialized" */
|
|
|
|
/* named thus so as not to confuse with prestate and poststate */
|
2011-05-18 17:43:05 -05:00
|
|
|
type pre_and_post = @rec(precond precondition, postcond postcondition);
|
2011-06-15 13:19:50 -05:00
|
|
|
|
|
|
|
|
2011-03-24 14:12:04 -05:00
|
|
|
/* FIXME: once it's implemented: */
|
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
// : ((*.precondition).nbits == (*.postcondition).nbits);
|
2011-04-04 16:31:49 -05:00
|
|
|
type pre_and_post_state = rec(prestate prestate, poststate poststate);
|
|
|
|
|
2011-05-18 17:43:05 -05:00
|
|
|
type ts_ann = @rec(pre_and_post conditions, pre_and_post_state states);
|
2011-03-24 14:12:04 -05:00
|
|
|
|
|
|
|
fn true_precond(uint num_vars) -> precond {
|
2011-06-15 13:19:50 -05:00
|
|
|
be bitv::create(num_vars, false);
|
2011-03-24 14:12:04 -05:00
|
|
|
}
|
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
fn true_postcond(uint num_vars) -> postcond { be true_precond(num_vars); }
|
2011-03-24 14:12:04 -05:00
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
fn empty_prestate(uint num_vars) -> prestate { be true_precond(num_vars); }
|
2011-04-06 19:56:44 -05:00
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
fn empty_poststate(uint num_vars) -> poststate { be true_precond(num_vars); }
|
2011-04-06 19:56:44 -05:00
|
|
|
|
Further work on typestate_check
Lots of work on typestate_check, seems to get a lot of the way
through checking the standard library.
* Added for, for_each, assign_op, bind, cast, put, check, break,
and cont. (I'm not sure break and cont are actually handled correctly.)
* Fixed side-effect bug in seq_preconds so that unioning the
preconditions of a sequence of statements or expressions
is handled correctly.
* Pass poststate correctly through a stmt_decl.
* Handle expr_ret and expr_fail properly (after execution of a ret
or fail, everything is true -- this is needed to handle ifs and alts
where one branch is a ret or fail)
* Fixed bug in set_prestate_ann where a thing that needed to be
mutated wasn't getting passed as an alias
* Fixed bug in how expr_alt was treated (zero is not the identity
for intersect, who knew, right?)
* Update logging to reflect log_err vs. log
* Fixed find_locals so as to return all local decls and exclude
function arguments.
* Make union_postconds work on an empty vector (needed to handle
empty blocks correctly)
* Added _vec.cat_options, which takes a list of option[T] to a list
of T, ignoring any Nones
* Added two test cases.
2011-04-20 14:11:01 -05:00
|
|
|
fn false_postcond(uint num_vars) -> postcond {
|
2011-05-12 10:24:54 -05:00
|
|
|
be bitv::create(num_vars, true);
|
Further work on typestate_check
Lots of work on typestate_check, seems to get a lot of the way
through checking the standard library.
* Added for, for_each, assign_op, bind, cast, put, check, break,
and cont. (I'm not sure break and cont are actually handled correctly.)
* Fixed side-effect bug in seq_preconds so that unioning the
preconditions of a sequence of statements or expressions
is handled correctly.
* Pass poststate correctly through a stmt_decl.
* Handle expr_ret and expr_fail properly (after execution of a ret
or fail, everything is true -- this is needed to handle ifs and alts
where one branch is a ret or fail)
* Fixed bug in set_prestate_ann where a thing that needed to be
mutated wasn't getting passed as an alias
* Fixed bug in how expr_alt was treated (zero is not the identity
for intersect, who knew, right?)
* Update logging to reflect log_err vs. log
* Fixed find_locals so as to return all local decls and exclude
function arguments.
* Make union_postconds work on an empty vector (needed to handle
empty blocks correctly)
* Added _vec.cat_options, which takes a list of option[T] to a list
of T, ignoring any Nones
* Added two test cases.
2011-04-20 14:11:01 -05:00
|
|
|
}
|
|
|
|
|
2011-04-04 16:31:49 -05:00
|
|
|
fn empty_pre_post(uint num_vars) -> pre_and_post {
|
2011-06-15 13:19:50 -05:00
|
|
|
ret @rec(precondition=empty_prestate(num_vars),
|
|
|
|
postcondition=empty_poststate(num_vars));
|
2011-03-24 14:12:04 -05:00
|
|
|
}
|
|
|
|
|
2011-04-04 16:31:49 -05:00
|
|
|
fn empty_states(uint num_vars) -> pre_and_post_state {
|
2011-06-15 13:19:50 -05:00
|
|
|
ret rec(prestate=true_precond(num_vars),
|
|
|
|
poststate=true_postcond(num_vars));
|
2011-04-04 16:31:49 -05:00
|
|
|
}
|
|
|
|
|
2011-04-06 19:56:44 -05:00
|
|
|
fn empty_ann(uint num_vars) -> ts_ann {
|
2011-06-15 13:19:50 -05:00
|
|
|
ret @rec(conditions=empty_pre_post(num_vars),
|
|
|
|
states=empty_states(num_vars));
|
2011-04-06 19:56:44 -05:00
|
|
|
}
|
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
fn get_pre(&pre_and_post p) -> precond { ret p.precondition; }
|
2011-03-24 14:12:04 -05:00
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
fn get_post(&pre_and_post p) -> postcond { ret p.postcondition; }
|
2011-03-24 14:12:04 -05:00
|
|
|
|
|
|
|
fn difference(&precond p1, &precond p2) -> bool {
|
2011-06-15 13:19:50 -05:00
|
|
|
be bitv::difference(p1, p2);
|
2011-03-24 14:12:04 -05:00
|
|
|
}
|
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
fn union(&precond p1, &precond p2) -> bool { be bitv::union(p1, p2); }
|
2011-03-24 14:12:04 -05:00
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
fn intersect(&precond p1, &precond p2) -> bool { be bitv::intersect(p1, p2); }
|
2011-04-12 21:03:52 -05:00
|
|
|
|
2011-03-24 14:12:04 -05:00
|
|
|
fn pps_len(&pre_and_post p) -> uint {
|
2011-06-15 13:19:50 -05:00
|
|
|
// gratuitous check
|
|
|
|
|
|
|
|
assert (p.precondition.nbits == p.postcondition.nbits);
|
|
|
|
ret p.precondition.nbits;
|
2011-03-24 14:12:04 -05:00
|
|
|
}
|
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
fn require(uint i, &pre_and_post p) {
|
|
|
|
// sets the ith bit in p's pre
|
|
|
|
|
|
|
|
bitv::set(p.precondition, i, true);
|
2011-06-09 11:56:35 -05:00
|
|
|
}
|
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
fn require_and_preserve(uint i, &pre_and_post p) {
|
|
|
|
// sets the ith bit in p's pre and post
|
|
|
|
|
|
|
|
bitv::set(p.precondition, i, true);
|
|
|
|
bitv::set(p.postcondition, i, true);
|
2011-04-04 16:31:49 -05:00
|
|
|
}
|
|
|
|
|
2011-04-19 15:35:49 -05:00
|
|
|
fn set_in_postcond(uint i, &pre_and_post p) -> bool {
|
2011-06-15 13:19:50 -05:00
|
|
|
// sets the ith bit in p's post
|
|
|
|
|
|
|
|
auto was_set = bitv::get(p.postcondition, i);
|
|
|
|
bitv::set(p.postcondition, i, true);
|
|
|
|
ret !was_set;
|
2011-04-12 14:16:21 -05:00
|
|
|
}
|
|
|
|
|
2011-04-19 15:35:49 -05:00
|
|
|
fn set_in_poststate(uint i, &pre_and_post_state s) -> bool {
|
2011-06-15 13:19:50 -05:00
|
|
|
// sets the ith bit in p's post
|
|
|
|
|
|
|
|
auto was_set = bitv::get(s.poststate, i);
|
|
|
|
bitv::set(s.poststate, i, true);
|
|
|
|
ret !was_set;
|
2011-04-06 19:56:44 -05:00
|
|
|
}
|
|
|
|
|
2011-05-20 21:50:29 -05:00
|
|
|
fn clear_in_poststate(uint i, &pre_and_post_state s) -> bool {
|
2011-06-15 13:19:50 -05:00
|
|
|
// sets the ith bit in p's post
|
|
|
|
|
|
|
|
auto was_set = bitv::get(s.poststate, i);
|
|
|
|
bitv::set(s.poststate, i, false);
|
|
|
|
ret was_set;
|
2011-05-20 21:50:29 -05:00
|
|
|
}
|
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
|
2011-04-06 19:56:44 -05:00
|
|
|
// Sets all the bits in a's precondition to equal the
|
|
|
|
// corresponding bit in p's precondition.
|
2011-06-15 13:19:50 -05:00
|
|
|
fn set_precondition(ts_ann a, &precond p) {
|
|
|
|
bitv::copy(a.conditions.precondition, p);
|
2011-04-06 19:56:44 -05:00
|
|
|
}
|
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
|
2011-04-06 19:56:44 -05:00
|
|
|
// Sets all the bits in a's postcondition to equal the
|
|
|
|
// corresponding bit in p's postcondition.
|
2011-06-15 13:19:50 -05:00
|
|
|
fn set_postcondition(ts_ann a, &postcond p) {
|
|
|
|
bitv::copy(a.conditions.postcondition, p);
|
2011-04-06 19:56:44 -05:00
|
|
|
}
|
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
|
2011-04-07 20:15:56 -05:00
|
|
|
// Sets all the bits in a's prestate to equal the
|
|
|
|
// corresponding bit in p's prestate.
|
2011-05-18 17:43:05 -05:00
|
|
|
fn set_prestate(ts_ann a, &prestate p) -> bool {
|
2011-06-15 13:19:50 -05:00
|
|
|
ret bitv::copy(a.states.prestate, p);
|
2011-04-07 20:15:56 -05:00
|
|
|
}
|
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
|
2011-04-07 20:15:56 -05:00
|
|
|
// Sets all the bits in a's postcondition to equal the
|
|
|
|
// corresponding bit in p's postcondition.
|
2011-05-18 17:43:05 -05:00
|
|
|
fn set_poststate(ts_ann a, &poststate p) -> bool {
|
2011-06-15 13:19:50 -05:00
|
|
|
ret bitv::copy(a.states.poststate, p);
|
2011-04-12 14:16:21 -05:00
|
|
|
}
|
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
|
2011-04-12 14:16:21 -05:00
|
|
|
// Set all the bits in p that are set in new
|
2011-04-19 15:35:49 -05:00
|
|
|
fn extend_prestate(&prestate p, &poststate new) -> bool {
|
2011-06-15 13:19:50 -05:00
|
|
|
ret bitv::union(p, new);
|
2011-04-07 20:15:56 -05:00
|
|
|
}
|
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
|
2011-04-06 19:56:44 -05:00
|
|
|
// Set all the bits in p that are set in new
|
2011-04-19 15:35:49 -05:00
|
|
|
fn extend_poststate(&poststate p, &poststate new) -> bool {
|
2011-06-15 13:19:50 -05:00
|
|
|
ret bitv::union(p, new);
|
2011-04-06 19:56:44 -05:00
|
|
|
}
|
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
|
Further work on typestate_check
Lots of work on typestate_check, seems to get a lot of the way
through checking the standard library.
* Added for, for_each, assign_op, bind, cast, put, check, break,
and cont. (I'm not sure break and cont are actually handled correctly.)
* Fixed side-effect bug in seq_preconds so that unioning the
preconditions of a sequence of statements or expressions
is handled correctly.
* Pass poststate correctly through a stmt_decl.
* Handle expr_ret and expr_fail properly (after execution of a ret
or fail, everything is true -- this is needed to handle ifs and alts
where one branch is a ret or fail)
* Fixed bug in set_prestate_ann where a thing that needed to be
mutated wasn't getting passed as an alias
* Fixed bug in how expr_alt was treated (zero is not the identity
for intersect, who knew, right?)
* Update logging to reflect log_err vs. log
* Fixed find_locals so as to return all local decls and exclude
function arguments.
* Make union_postconds work on an empty vector (needed to handle
empty blocks correctly)
* Added _vec.cat_options, which takes a list of option[T] to a list
of T, ignoring any Nones
* Added two test cases.
2011-04-20 14:11:01 -05:00
|
|
|
// Clears the given bit in p
|
|
|
|
fn relax_prestate(uint i, &prestate p) -> bool {
|
2011-05-12 10:24:54 -05:00
|
|
|
auto was_set = bitv::get(p, i);
|
|
|
|
bitv::set(p, i, false);
|
Further work on typestate_check
Lots of work on typestate_check, seems to get a lot of the way
through checking the standard library.
* Added for, for_each, assign_op, bind, cast, put, check, break,
and cont. (I'm not sure break and cont are actually handled correctly.)
* Fixed side-effect bug in seq_preconds so that unioning the
preconditions of a sequence of statements or expressions
is handled correctly.
* Pass poststate correctly through a stmt_decl.
* Handle expr_ret and expr_fail properly (after execution of a ret
or fail, everything is true -- this is needed to handle ifs and alts
where one branch is a ret or fail)
* Fixed bug in set_prestate_ann where a thing that needed to be
mutated wasn't getting passed as an alias
* Fixed bug in how expr_alt was treated (zero is not the identity
for intersect, who knew, right?)
* Update logging to reflect log_err vs. log
* Fixed find_locals so as to return all local decls and exclude
function arguments.
* Make union_postconds work on an empty vector (needed to handle
empty blocks correctly)
* Added _vec.cat_options, which takes a list of option[T] to a list
of T, ignoring any Nones
* Added two test cases.
2011-04-20 14:11:01 -05:00
|
|
|
ret was_set;
|
|
|
|
}
|
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
|
2011-05-18 17:43:05 -05:00
|
|
|
// Clears all the bits in p
|
2011-06-15 13:19:50 -05:00
|
|
|
fn clear(&precond p) { bitv::clear(p); }
|
|
|
|
|
2011-05-18 17:43:05 -05:00
|
|
|
|
|
|
|
// Sets all the bits in p
|
2011-06-15 13:19:50 -05:00
|
|
|
fn set(&precond p) { bitv::set_all(p); }
|
2011-05-18 17:43:05 -05:00
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
fn ann_precond(&ts_ann a) -> precond { ret a.conditions.precondition; }
|
2011-04-06 19:56:44 -05:00
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
fn ann_prestate(&ts_ann a) -> prestate { ret a.states.prestate; }
|
2011-04-06 19:56:44 -05:00
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
fn ann_poststate(&ts_ann a) -> poststate { ret a.states.poststate; }
|
2011-05-14 21:02:30 -05:00
|
|
|
|
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
2011-04-18 17:33:10 -05:00
|
|
|
fn pp_clone(&pre_and_post p) -> pre_and_post {
|
2011-06-15 13:19:50 -05:00
|
|
|
ret @rec(precondition=clone(p.precondition),
|
|
|
|
postcondition=clone(p.postcondition));
|
Further work on typestate_check
Lots of work on typestate_check, seems to get a lot of the way
through checking the standard library.
* Added for, for_each, assign_op, bind, cast, put, check, break,
and cont. (I'm not sure break and cont are actually handled correctly.)
* Fixed side-effect bug in seq_preconds so that unioning the
preconditions of a sequence of statements or expressions
is handled correctly.
* Pass poststate correctly through a stmt_decl.
* Handle expr_ret and expr_fail properly (after execution of a ret
or fail, everything is true -- this is needed to handle ifs and alts
where one branch is a ret or fail)
* Fixed bug in set_prestate_ann where a thing that needed to be
mutated wasn't getting passed as an alias
* Fixed bug in how expr_alt was treated (zero is not the identity
for intersect, who knew, right?)
* Update logging to reflect log_err vs. log
* Fixed find_locals so as to return all local decls and exclude
function arguments.
* Make union_postconds work on an empty vector (needed to handle
empty blocks correctly)
* Added _vec.cat_options, which takes a list of option[T] to a list
of T, ignoring any Nones
* Added two test cases.
2011-04-20 14:11:01 -05:00
|
|
|
}
|
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
fn clone(prestate p) -> prestate { ret bitv::clone(p); }
|
|
|
|
|
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
2011-04-18 17:33:10 -05:00
|
|
|
|
2011-04-12 14:16:21 -05:00
|
|
|
// returns true if a implies b
|
|
|
|
// that is, returns true except if for some bits c and d,
|
|
|
|
// c = 1 and d = 0
|
2011-05-12 10:24:54 -05:00
|
|
|
fn implies(bitv::t a, bitv::t b) -> bool {
|
2011-06-15 13:19:50 -05:00
|
|
|
auto tmp = bitv::clone(b);
|
|
|
|
bitv::difference(tmp, a);
|
|
|
|
ret bitv::is_false(tmp);
|
2011-04-04 16:31:49 -05:00
|
|
|
}
|
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
2011-04-18 17:33:10 -05:00
|
|
|
//
|
|
|
|
// 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:
|
|
|
|
//
|