@@ -30,6 +30,7 @@ import front.ast.expr_rec;
30
30
import front. ast . expr_if ;
31
31
import front. ast . expr_binary ;
32
32
import front. ast . expr_assign ;
33
+ import front. ast . expr_while ;
33
34
import front. ast . expr_lit ;
34
35
import front. ast . expr_ret ;
35
36
import front. ast . path ;
@@ -71,6 +72,8 @@ import util.common.new_def_hash;
71
72
import util. common . uistr ;
72
73
import util. common . elt_exprs ;
73
74
import util. common . field_exprs ;
75
+ import util. common . log_expr ;
76
+ import util. common . lift ;
74
77
import util. typestate_ann ;
75
78
import util. typestate_ann . ts_ann ;
76
79
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) -> () {
717
720
}
718
721
}
719
722
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
+
720
750
/* Fills in annotations as a side effect. Does not rebuild the expr */
721
751
fn find_pre_post_expr( & _fn_info_map fm, & fn_info enclosing , & expr e) -> ( ) {
722
752
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) -> () {
730
760
731
761
alt ( e. node ) {
732
762
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) ;
751
766
}
752
767
case ( expr_path ( ?p, ?maybe_def, ?a) ) {
753
768
auto df;
@@ -779,98 +794,21 @@ fn find_pre_post_expr(&_fn_info_map fm, &fn_info enclosing, &expr e) -> () {
779
794
set_pre_and_post ( a, block_pp ( b) ) ;
780
795
}
781
796
case ( expr_rec ( ?fields, ?maybe_base, ?a) ) {
782
- /* factor out this code */
783
797
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) ;
817
800
}
818
801
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
821
802
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) ) {
828
804
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) ;
870
807
}
871
808
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) ;
874
812
}
875
813
}
876
814
}
@@ -927,15 +865,22 @@ fn find_pre_post_expr(&_fn_info_map fm, &fn_info enclosing, &expr e) -> () {
927
865
case ( expr_binary( ?bop, ?l, ?r, ?a) ) {
928
866
/* *unless* bop is lazy (e.g. and, or)?
929
867
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) ;
939
884
}
940
885
case ( _) {
941
886
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,
1253
1198
changed = extend_poststate_ann ( a, expr_poststate ( * r) ) || changed;
1254
1199
ret changed;
1255
1200
}
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
+ }
1256
1228
case ( _) {
1257
1229
log ( "find_pre_post_state_expr: implement this case!" ) ;
1258
1230
fail;
@@ -1397,8 +1369,13 @@ impure fn check_states_expr(fn_info enclosing, &expr e) -> () {
1397
1369
let prestate pres = expr_prestate ( e) ;
1398
1370
1399
1371
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;
1402
1379
}
1403
1380
}
1404
1381
0 commit comments