Skip to content

Commit 38b0c5c

Browse files
catamorphismgraydon
authored andcommitted
---
yaml --- r: 2094 b: refs/heads/master c: 7c6e6fc h: refs/heads/master v: v3
1 parent 85b93de commit 38b0c5c

File tree

4 files changed

+105
-117
lines changed

4 files changed

+105
-117
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
---
2-
refs/heads/master: eb33a5307b42ef1c1ab7697ed1a0583a7f6b80b8
2+
refs/heads/master: 7c6e6fc5d49127e868a8323e0619c9c7597b5b18

trunk/src/comp/middle/typestate_check.rs

Lines changed: 91 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import front.ast.expr_rec;
3030
import front.ast.expr_if;
3131
import front.ast.expr_binary;
3232
import front.ast.expr_assign;
33+
import front.ast.expr_while;
3334
import front.ast.expr_lit;
3435
import front.ast.expr_ret;
3536
import front.ast.path;
@@ -71,6 +72,8 @@ import util.common.new_def_hash;
7172
import util.common.uistr;
7273
import util.common.elt_exprs;
7374
import util.common.field_exprs;
75+
import util.common.log_expr;
76+
import util.common.lift;
7477
import util.typestate_ann;
7578
import util.typestate_ann.ts_ann;
7679
import util.typestate_ann.empty_pre_post;
@@ -717,6 +720,33 @@ fn find_pre_post_item(_fn_info_map fm, fn_info enclosing, &item i) -> () {
717720
}
718721
}
719722

723+
/* Finds the pre and postcondition for each expr in <args>;
724+
sets the precondition in a to be the result of combining
725+
the preconditions for <args>, and the postcondition in a to
726+
be the union of all postconditions for <args> */
727+
fn find_pre_post_exprs(&_fn_info_map fm, &fn_info enclosing,
728+
&vec[@expr] args, ann a) {
729+
fn do_one(_fn_info_map fm, fn_info enclosing,
730+
&@expr e) -> () {
731+
find_pre_post_expr(fm, enclosing, *e);
732+
}
733+
auto f = bind do_one(fm, enclosing, _);
734+
735+
_vec.map[@expr, ()](f, args);
736+
737+
fn get_pp(&@expr e) -> pre_and_post {
738+
ret expr_pp(*e);
739+
}
740+
auto g = get_pp;
741+
auto pps = _vec.map[@expr, pre_and_post](g, args);
742+
auto h = get_post;
743+
744+
set_pre_and_post(a,
745+
rec(precondition=seq_preconds(num_locals(enclosing), pps),
746+
postcondition=union_postconds
747+
(_vec.map[pre_and_post, postcond](h, pps))));
748+
}
749+
720750
/* Fills in annotations as a side effect. Does not rebuild the expr */
721751
fn find_pre_post_expr(&_fn_info_map fm, &fn_info enclosing, &expr e) -> () {
722752
auto num_local_vars = num_locals(enclosing);
@@ -730,24 +760,9 @@ fn find_pre_post_expr(&_fn_info_map fm, &fn_info enclosing, &expr e) -> () {
730760

731761
alt(e.node) {
732762
case(expr_call(?operator, ?operands, ?a)) {
733-
find_pre_post_expr(fm, enclosing, *operator);
734-
735-
auto do_rand = bind do_rand_(fm, enclosing,_);
736-
auto f = do_rand;
737-
_vec.map[@expr, ()](f, operands);
738-
739-
auto g = pp_one;
740-
auto pps = _vec.map[@expr, pre_and_post](g, operands);
741-
_vec.push[pre_and_post](pps, expr_pp(*operator));
742-
auto h = get_post;
743-
auto res_postconds = _vec.map[pre_and_post, postcond](h, pps);
744-
auto res_postcond = union_postconds(res_postconds);
745-
746-
let pre_and_post pp =
747-
rec(precondition=seq_preconds(num_local_vars, pps),
748-
postcondition=res_postcond);
749-
set_pre_and_post(a, pp);
750-
ret;
763+
auto args = _vec.clone[@expr](operands);
764+
_vec.push[@expr](args, operator);
765+
find_pre_post_exprs(fm, enclosing, args, a);
751766
}
752767
case(expr_path(?p, ?maybe_def, ?a)) {
753768
auto df;
@@ -779,98 +794,21 @@ fn find_pre_post_expr(&_fn_info_map fm, &fn_info enclosing, &expr e) -> () {
779794
set_pre_and_post(a, block_pp(b));
780795
}
781796
case (expr_rec(?fields,?maybe_base,?a)) {
782-
/* factor out this code */
783797
auto es = field_exprs(fields);
784-
auto do_rand = bind do_rand_(fm, enclosing,_);
785-
auto f = do_rand;
786-
_vec.map[@expr, ()](f, es);
787-
auto g = pp_one;
788-
auto h = get_post;
789-
/* FIXME avoid repeated code */
790-
alt (maybe_base) {
791-
case (none[@expr]) {
792-
auto pps = _vec.map[@expr, pre_and_post](g, es);
793-
auto res_postconds = _vec.map[pre_and_post, postcond]
794-
(h, pps);
795-
auto res_postcond = union_postconds(res_postconds);
796-
let pre_and_post pp =
797-
rec(precondition=seq_preconds(num_local_vars, pps),
798-
postcondition=res_postcond);
799-
set_pre_and_post(a, pp);
800-
}
801-
case (some[@expr](?base_exp)) {
802-
find_pre_post_expr(fm, enclosing, *base_exp);
803-
804-
es += vec(base_exp);
805-
auto pps = _vec.map[@expr, pre_and_post](g, es);
806-
auto res_postconds = _vec.map[pre_and_post, postcond]
807-
(h, pps);
808-
auto res_postcond = union_postconds(res_postconds);
809-
810-
let pre_and_post pp =
811-
rec(precondition=seq_preconds(num_local_vars, pps),
812-
postcondition=res_postcond);
813-
set_pre_and_post(a, pp);
814-
}
815-
}
816-
ret;
798+
_vec.plus_option[@expr](es, maybe_base);
799+
find_pre_post_exprs(fm, enclosing, es, a);
817800
}
818801
case (expr_assign(?lhs, ?rhs, ?a)) {
819-
// what's below should be compressed into two cases:
820-
// path of a local, and non-path-of-a-local
821802
alt (lhs.node) {
822-
case (expr_field(?e,?id,?a_lhs)) {
823-
// lhs is already initialized, so this doesn't initialize
824-
// anything anew
825-
find_pre_post_expr(fm, enclosing, *e);
826-
set_pre_and_post(a_lhs, expr_pp(*e));
827-
803+
case (expr_path(?p, some[def](def_local(?d_id)), ?a_lhs)) {
828804
find_pre_post_expr(fm, enclosing, *rhs);
829-
let pre_and_post expr_assign_pp =
830-
rec(precondition=seq_preconds
831-
(num_local_vars,
832-
vec(expr_pp(*e), expr_pp(*rhs))),
833-
postcondition=union_postconds
834-
(vec(expr_postcond(*e), expr_postcond(*rhs))));
835-
set_pre_and_post(a, expr_assign_pp);
836-
}
837-
case (expr_path(?p,?maybe_def,?a_lhs)) {
838-
find_pre_post_expr(fm, enclosing, *rhs);
839-
set_pre_and_post(a_lhs, empty_pre_post(num_local_vars));
840-
find_pre_post_expr(fm, enclosing, *rhs);
841-
alt (maybe_def) {
842-
// is this a local variable?
843-
// if so, the only case in which an assign actually
844-
// causes a variable to become initialized
845-
case (some[def](def_local(?d_id))) {
846-
set_pre_and_post(a, expr_pp(*rhs));
847-
gen(enclosing, a, d_id);
848-
}
849-
case (_) {
850-
// already initialized
851-
set_pre_and_post(a, expr_pp(*rhs));
852-
}
853-
}
854-
}
855-
case (expr_index(?e,?sub,_)) {
856-
// lhs is already initialized
857-
// assuming the array subscript gets evaluated before the
858-
// array
859-
find_pre_post_expr(fm, enclosing, *lhs);
860-
find_pre_post_expr(fm, enclosing, *rhs);
861-
set_pre_and_post(a,
862-
rec(precondition=
863-
seq_preconds
864-
(num_local_vars, vec(expr_pp(*lhs),
865-
expr_pp(*rhs))),
866-
postcondition=
867-
union_postconds(vec(expr_postcond(*lhs),
868-
expr_postcond(*rhs)))));
869-
805+
set_pre_and_post(a, expr_pp(*rhs));
806+
gen(enclosing, a, d_id);
870807
}
871808
case (_) {
872-
log("find_pre_post_for_expr: non-lval on lhs of assign");
873-
fail;
809+
// doesn't check that lhs is an lval, but
810+
// that's probably ok
811+
find_pre_post_exprs(fm, enclosing, vec(lhs, rhs), a);
874812
}
875813
}
876814
}
@@ -927,15 +865,22 @@ fn find_pre_post_expr(&_fn_info_map fm, &fn_info enclosing, &expr e) -> () {
927865
case (expr_binary(?bop,?l,?r,?a)) {
928866
/* *unless* bop is lazy (e.g. and, or)?
929867
FIXME */
930-
find_pre_post_expr(fm, enclosing, *l);
931-
find_pre_post_expr(fm, enclosing, *r);
932-
set_pre_and_post(a,
933-
rec(precondition=
934-
seq_preconds(num_local_vars,
935-
vec(expr_pp(*l), expr_pp(*r))),
936-
postcondition=
937-
union_postconds(vec(expr_postcond(*l),
938-
expr_postcond(*r)))));
868+
find_pre_post_exprs(fm, enclosing, vec(l, r), a);
869+
}
870+
case (expr_while(?test, ?body, ?a)) {
871+
find_pre_post_expr(fm, enclosing, *test);
872+
find_pre_post_block(fm, enclosing, body);
873+
set_pre_and_post(a,
874+
rec(precondition=
875+
seq_preconds(num_local_vars,
876+
vec(expr_pp(*test),
877+
block_pp(body))),
878+
postcondition=
879+
intersect_postconds(vec(expr_postcond(*test),
880+
block_postcond(body)))));
881+
}
882+
case (expr_index(?e, ?sub, ?a)) {
883+
find_pre_post_exprs(fm, enclosing, vec(e, sub), a);
939884
}
940885
case(_) {
941886
log("this sort of expr isn't implemented!");
@@ -1253,6 +1198,33 @@ fn find_pre_post_state_expr(&_fn_info_map fm, &fn_info enclosing,
12531198
changed = extend_poststate_ann(a, expr_poststate(*r)) || changed;
12541199
ret changed;
12551200
}
1201+
case (expr_while(?test, ?body, ?a)) {
1202+
changed = extend_prestate_ann(a, pres) || changed;
1203+
/* to handle general predicates, we need to pass in
1204+
pres `intersect` (poststate(a))
1205+
like: auto test_pres = intersect_postconds(pres, expr_postcond(a));
1206+
However, this doesn't work right now because we would be passing
1207+
in an all-zero prestate initially
1208+
FIXME
1209+
maybe need a "don't know" state in addition to 0 or 1?
1210+
*/
1211+
changed = find_pre_post_state_expr(fm, enclosing, pres, test)
1212+
|| changed;
1213+
changed = find_pre_post_state_block(fm,
1214+
enclosing, expr_poststate(*test), body) || changed;
1215+
changed = extend_poststate_ann(a,
1216+
intersect_postconds(vec(expr_poststate(*test),
1217+
block_poststate(body)))) || changed;
1218+
ret changed;
1219+
}
1220+
case (expr_index(?e, ?sub, ?a)) {
1221+
changed = extend_prestate_ann(a, pres) || changed;
1222+
changed = find_pre_post_state_expr(fm, enclosing, pres, e) || changed;
1223+
changed = find_pre_post_state_expr(fm, enclosing,
1224+
expr_poststate(*e), sub) || changed;
1225+
changed = extend_poststate_ann(a, expr_poststate(*sub));
1226+
ret changed;
1227+
}
12561228
case (_) {
12571229
log("find_pre_post_state_expr: implement this case!");
12581230
fail;
@@ -1397,8 +1369,13 @@ impure fn check_states_expr(fn_info enclosing, &expr e) -> () {
13971369
let prestate pres = expr_prestate(e);
13981370

13991371
if (!implies(pres, prec)) {
1400-
log("check_states_expr: unsatisfied precondition");
1401-
fail;
1372+
log("check_states_stmt: unsatisfied precondition for ");
1373+
log_expr(e);
1374+
log("Precondition: ");
1375+
log_bitv(enclosing, prec);
1376+
log("Prestate: ");
1377+
log_bitv(enclosing, pres);
1378+
fail;
14021379
}
14031380
}
14041381

trunk/src/comp/util/common.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,14 +115,14 @@ fn plain_ann() -> ast.ann {
115115
none[vec[@middle.ty.t]], none[@ts_ann]);
116116
}
117117

118-
fn log_expr(@ast.expr e) -> () {
118+
fn log_expr(&ast.expr e) -> () {
119119
let str_writer s = string_writer();
120120
auto out_ = mkstate(s.get_writer(), 80u);
121121
auto out = @rec(s=out_,
122122
comments=none[vec[front.lexer.cmnt]],
123123
mutable cur_cmnt=0u);
124124

125-
print_expr(out, e);
125+
print_expr(out, @e);
126126
log(s.get_str());
127127
}
128128

trunk/src/lib/_vec.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,17 @@ fn or(&vec[bool] v) -> bool {
251251
be _vec.foldl[bool, bool](f, false, v);
252252
}
253253

254+
fn clone[T](&vec[T] v) -> vec[T] {
255+
ret slice[T](v, 0u, len[T](v));
256+
}
257+
258+
fn plus_option[T](&vec[T] v, &option.t[T] o) -> () {
259+
alt (o) {
260+
case (none[T]) {}
261+
case (some[T](?x)) { v += vec(x); }
262+
}
263+
}
264+
254265
// Local Variables:
255266
// mode: rust;
256267
// fill-column: 78;

0 commit comments

Comments
 (0)