1
+ import std:: vec;
1
2
import std:: ivec;
3
+ import std:: int:: str;
2
4
import std:: str;
3
5
import std:: option;
4
- import std:: option:: none;
5
- import std:: option:: some;
6
- import std:: option:: maybe;
6
+ import std:: option:: * ;
7
7
import std:: int;
8
8
import std:: uint;
9
9
import syntax:: ast:: * ;
@@ -26,19 +26,32 @@ import tstate::ann::empty_states;
26
26
import tstate:: ann:: pps_len;
27
27
import tstate:: ann:: set_prestate;
28
28
import tstate:: ann:: set_poststate;
29
+ import tstate:: ann:: set_in_poststate_;
29
30
import tstate:: ann:: extend_prestate;
30
31
import tstate:: ann:: extend_poststate;
31
32
import tstate:: ann:: set_precondition;
32
33
import tstate:: ann:: set_postcondition;
34
+ import tstate:: ann:: set_in_postcond_;
33
35
import tstate:: ann:: ts_ann;
34
36
import tstate:: ann:: clear_in_postcond;
35
37
import tstate:: ann:: clear_in_poststate;
36
38
import tstate:: ann:: clear_in_poststate_;
37
39
import tritv:: * ;
40
+ import bitvectors:: promises_;
38
41
39
42
import syntax:: print:: pprust:: constr_args_to_str;
43
+ import syntax:: print:: pprust:: constr_arg_to_str;
40
44
import syntax:: print:: pprust:: lit_to_str;
41
45
46
+ // Used to communicate which operands should be invalidated
47
+ // to helper functions
48
+ tag oper_type {
49
+ oper_move;
50
+ oper_swap;
51
+ oper_assign;
52
+ oper_assign_op;
53
+ oper_pure;
54
+ }
42
55
43
56
/* logging funs */
44
57
fn def_id_to_str ( def_id d) -> str {
@@ -195,6 +208,8 @@ type pred_desc_ = rec((@constr_arg_use)[] args, uint bit_num);
195
208
196
209
type pred_desc = spanned[pred_desc_];
197
210
211
+ // FIXME: Should be node_id, since we can only talk
212
+ // about locals.
198
213
type constr_arg_use = constr_arg_general[tup(ident, def_id)];
199
214
200
215
tag constraint {
@@ -564,9 +579,13 @@ fn expr_to_constr_arg(ty::ctxt tcx, &@expr e) -> @constr_arg_use {
564
579
}
565
580
566
581
fn exprs_to_constr_args ( ty:: ctxt tcx, & ( @expr) [ ] args)
567
- -> ( @constr_arg_use ) [ ] {
582
+ -> ( @constr_arg_use ) [ ] {
568
583
auto f = bind expr_to_constr_arg ( tcx, _) ;
569
- ret ivec:: map ( f, args) ;
584
+ let ( @constr_arg_use) [ ] rslt = ~[ ] ;
585
+ for ( @expr e in args) {
586
+ rslt += ~[ f ( e) ] ;
587
+ }
588
+ rslt
570
589
}
571
590
572
591
fn expr_to_constr ( ty:: ctxt tcx, & @expr e) -> constr {
@@ -602,14 +621,9 @@ fn expr_to_constr(ty::ctxt tcx, &@expr e) -> constr {
602
621
}
603
622
604
623
fn pred_desc_to_str ( & pred_desc p) -> str {
605
- // FIXME: Remove this vec->ivec conversion.
606
- let ( @constr_arg_use) [ ] cau_ivec = ~[ ] ;
607
- for ( @constr_arg_use cau in p. node. args) {
608
- cau_ivec += ~[ cau] ;
609
- }
610
-
611
- ret "<" + uint:: str ( p. node . bit_num ) + ", " +
612
- constr_args_to_str ( std:: util:: fst[ ident, def_id] , cau_ivec) + ">" ;
624
+ "<" + uint:: str ( p. node . bit_num ) + ", " +
625
+ constr_args_to_str ( std:: util:: fst[ ident, def_id] ,
626
+ p. node . args ) + ">"
613
627
}
614
628
615
629
fn substitute_constr_args ( & ty:: ctxt cx, & ( @expr) [ ] actuals,
@@ -621,8 +635,6 @@ fn substitute_constr_args(&ty::ctxt cx, &(@expr)[] actuals,
621
635
ret npred( c. node. path, rslt ) ;
622
636
}
623
637
624
- type subst = tup ( arg , @expr) [ ] ;
625
-
626
638
fn substitute_arg( & ty:: ctxt cx, & ( @expr) [ ] actuals, @constr_arg a) ->
627
639
@constr_arg_use {
628
640
auto num_actuals = ivec: : len( actuals) ;
@@ -640,6 +652,144 @@ fn substitute_arg(&ty::ctxt cx, &(@expr)[] actuals, @constr_arg a) ->
640
652
}
641
653
}
642
654
655
+ fn pred_desc_matches( & ( constr_arg_general_[ tup( ident, def_id) ] ) [ ] pattern,
656
+ & pred_desc desc) -> bool {
657
+ auto i = 0 u;
658
+ for ( @constr_arg_use c in desc. node. args) {
659
+ auto n = pattern. ( i) ;
660
+ alt ( c. node) {
661
+ case ( carg_ident( ?p) ) {
662
+ alt ( n) {
663
+ case ( carg_ident( ?q) ) {
664
+ if ( p. _1 != q. _1) {
665
+ ret false;
666
+ }
667
+ }
668
+ case ( _) { ret false ; }
669
+ }
670
+ }
671
+ case ( carg_base) {
672
+ if ( n != carg_base) {
673
+ ret false;
674
+ }
675
+ }
676
+ case ( carg_lit( ?l) ) {
677
+ alt ( n) {
678
+ case ( carg_lit( ?m) ) {
679
+ if ( !lit_eq( l, m) ) {
680
+ ret false;
681
+ }
682
+ }
683
+ case ( _) { ret false ; }
684
+ }
685
+ }
686
+ }
687
+ i += 1 u;
688
+ }
689
+ ret true;
690
+ }
691
+
692
+ fn find_instance_( & ( constr_arg_general_[ tup( ident, def_id) ] ) [ ] pattern,
693
+ & pred_desc[ ] descs) -> option:: t[ uint] {
694
+ for ( pred_desc d in descs) {
695
+ if ( pred_desc_matches( pattern, d) ) {
696
+ ret some( d. node. bit_num) ;
697
+ }
698
+ }
699
+ ret none;
700
+ }
701
+
702
+ type inst = tup( ident, def_id) ;
703
+ type subst = tup( inst, inst) [ ] ;
704
+
705
+ fn find_instances( & fn_ctxt fcx, & subst subst, & constraint c)
706
+ -> vec[ tup( uint, uint) ] {
707
+
708
+ let vec[ tup( uint, uint) ] rslt = [ ] ;
709
+ if ( ivec:: len( subst) == 0 u) {
710
+ ret rslt;
711
+ }
712
+
713
+ alt ( c) {
714
+ case ( cinit( _, _, _) ) { /* this is dealt with separately */ }
715
+ case ( cpred( ?p, ?descs) ) {
716
+ for ( pred_desc d in * descs) {
717
+ if ( args_mention( d. node. args, find_in_subst_bool, subst) ) {
718
+ auto old_bit_num = d. node. bit_num;
719
+ auto new = replace( subst, d) ;
720
+ alt ( find_instance_( new, * descs) ) {
721
+ case ( some( ?d1) ) {
722
+ rslt += [ tup( old_bit_num, d1) ] ;
723
+ }
724
+ case ( _) { }
725
+ }
726
+ }
727
+ }
728
+ }
729
+ }
730
+ rslt
731
+ }
732
+
733
+ fn find_in_subst( def_id id, & subst s) -> option:: t[ inst] {
734
+ for ( tup( inst, inst) p in s) {
735
+ if ( id == p. _0. _1) {
736
+ ret some( p. _1) ;
737
+ }
738
+ }
739
+ ret none;
740
+ }
741
+
742
+ fn find_in_subst_bool( & subst s, def_id id) -> bool {
743
+ is_some( find_in_subst( id, s) )
744
+ }
745
+
746
+ fn insts_to_str( & ( constr_arg_general_[ inst] ) [ ] stuff) -> str {
747
+ auto rslt = "<" ;
748
+ for ( constr_arg_general_[ inst] i in stuff) {
749
+ rslt += " " + alt( i) {
750
+ case ( carg_ident( ?p) ) { p. _0 }
751
+ case ( carg_base) { "*" }
752
+ case ( carg_lit( _) ) { "[lit]" } } + " " ;
753
+ }
754
+ rslt += ">" ;
755
+ rslt
756
+ }
757
+
758
+ fn replace( subst subst, pred_desc d) -> ( constr_arg_general_[ inst] ) [ ] {
759
+ let ( constr_arg_general_[ inst] ) [ ] rslt = ~[ ] ;
760
+ for ( @constr_arg_use c in d. node. args) {
761
+ alt ( c. node) {
762
+ case ( carg_ident( ?p) ) {
763
+ alt ( find_in_subst( p. _1, subst) ) {
764
+ case ( some( ?new) ) {
765
+ rslt += ~[ carg_ident( new) ] ;
766
+ }
767
+ case ( _) {
768
+ rslt += ~[ c. node] ;
769
+ }
770
+ }
771
+ }
772
+ case ( _) {
773
+ // log_err "##";
774
+ rslt += ~[ c. node] ;
775
+ }
776
+ }
777
+ }
778
+
779
+ /*
780
+ for (constr_arg_general_[tup(ident, def_id)] p in rslt) {
781
+ alt (p) {
782
+ case (carg_ident(?p)) {
783
+ log_err p._0;
784
+ }
785
+ case (_) {}
786
+ }
787
+ }
788
+ */
789
+
790
+ ret rslt;
791
+ }
792
+
643
793
fn path_to_ident( & ty:: ctxt cx, & path p) -> ident {
644
794
alt ( ivec:: last( p. node. idents) ) {
645
795
case ( none) { cx. sess. span_fatal( p. span, "Malformed path" ) ; }
@@ -684,6 +834,56 @@ fn local_node_id_to_def_id(&fn_ctxt fcx, &node_id i) -> option::t[def_id] {
684
834
}
685
835
}
686
836
837
+ fn copy_in_postcond( & fn_ctxt fcx, node_id parent_exp, inst dest, inst src,
838
+ oper_type ty) {
839
+ auto post = node_id_to_ts_ann( fcx. ccx, parent_exp) . conditions.
840
+ postcondition;
841
+ copy_in_poststate_two( fcx, post, post, dest, src, ty) ;
842
+ }
843
+
844
+ // FIXME refactor
845
+ fn copy_in_poststate( & fn_ctxt fcx, & poststate post, inst dest, inst src,
846
+ oper_type ty) {
847
+ copy_in_poststate_two( fcx, post, post, dest, src, ty) ;
848
+ }
849
+
850
+ // In target_post, set the bits corresponding to copies of any
851
+ // constraints mentioning src that are set in src_post, with
852
+ // dest substituted for src.
853
+ // (This doesn't create any new constraints. If a new, substituted
854
+ // constraint isn't already in the bit vector, it's ignored.)
855
+ fn copy_in_poststate_two( & fn_ctxt fcx, & poststate src_post,
856
+ & poststate target_post, inst dest, inst src,
857
+ oper_type ty) {
858
+ auto subst;
859
+ alt ( ty) {
860
+ case ( oper_swap) {
861
+ subst = ~[ tup( dest, src) ,
862
+ tup( src, dest) ] ;
863
+ }
864
+ case ( oper_assign_op) {
865
+ ret; // Don't do any propagation
866
+ }
867
+ case ( _) {
868
+ subst = ~[ tup( src, dest) ] ;
869
+ }
870
+ }
871
+
872
+ for each ( @tup( node_id, constraint) p in
873
+ fcx. enclosing. constrs. items( ) ) {
874
+ // replace any occurrences of the src def_id with the
875
+ // dest def_id
876
+ auto instances = find_instances( fcx, subst, p. _1) ;
877
+
878
+ for ( tup( uint, uint) p in instances) {
879
+ if ( promises_( p. _0, src_post) ) {
880
+ set_in_poststate_( p. _1, target_post) ;
881
+ }
882
+ }
883
+ }
884
+ }
885
+
886
+
687
887
/* FIXME should refactor this better */
688
888
fn forget_in_postcond( & fn_ctxt fcx, node_id parent_exp, node_id dead_v) {
689
889
// In the postcondition given by parent_exp, clear the bits
@@ -757,13 +957,20 @@ fn forget_in_poststate_still_init(&fn_ctxt fcx, &poststate p, node_id dead_v)
757
957
ret changed;
758
958
}
759
959
760
- fn constraint_mentions ( & fn_ctxt fcx, & norm_constraint c, & def_id v) -> bool {
960
+ fn any_eq( & ( def_id) [ ] v, def_id d) -> bool {
961
+ for ( def_id i in v) {
962
+ if ( i == d) { ret true; }
963
+ }
964
+ false
965
+ }
966
+
967
+ fn constraint_mentions( & fn_ctxt fcx, & norm_constraint c, def_id v) -> bool {
761
968
ret ( alt ( c. c. node. c) {
762
969
case ( ninit( _) ) {
763
970
v == local_def( c. c. node. id)
764
971
}
765
972
case ( npred( _, ?args) ) {
766
- args_mention ( args, v )
973
+ args_mention( args, any_eq , ~ [ v ] )
767
974
}
768
975
} ) ;
769
976
}
@@ -775,20 +982,42 @@ fn non_init_constraint_mentions(&fn_ctxt fcx, &norm_constraint c,
775
982
false
776
983
}
777
984
case ( npred( _, ?args) ) {
778
- args_mention ( args, v )
985
+ args_mention( args, any_eq , ~ [ v ] )
779
986
}
780
987
} ) ;
781
988
}
782
989
783
-
784
- fn args_mention ( & ( @constr_arg_use) [ ] args, & def_id v) -> bool {
785
- fn mentions( & def_id v, & @constr_arg_use a) -> bool {
990
+ fn args_mention[ T ] ( & ( @constr_arg_use) [ ] args, fn ( & ( T ) [ ] , def_id) -> bool q,
991
+ & ( T ) [ ] s) -> bool {
992
+ /*
993
+ FIXME
994
+ The following version causes an assertion in trans to fail
995
+ (something about type_is_tup_like)
996
+ fn mentions[T](&(T)[] s, &fn(&(T)[], def_id) -> bool q,
997
+ &@constr_arg_use a) -> bool {
786
998
alt (a.node) {
787
- case ( carg_ident( ?p1) ) { p1. _1 == v }
999
+ case (carg_ident(?p1)) {
1000
+ auto res = q(s, p1._1);
1001
+ log_err (res);
1002
+ res
1003
+ }
788
1004
case (_) { false }
789
1005
}
790
1006
}
791
- ret ivec:: any[ @constr_arg_use] ( bind mentions( v, _) , args) ;
1007
+ ret ivec::any(bind mentions(s,q,_), args);
1008
+ */
1009
+
1010
+ for ( @constr_arg_use a in args) {
1011
+ alt ( a. node) {
1012
+ case ( carg_ident( ?p1) ) {
1013
+ if ( q( s, p1. _1) ) {
1014
+ ret true;
1015
+ }
1016
+ }
1017
+ case ( _) { }
1018
+ }
1019
+ }
1020
+ ret false;
792
1021
}
793
1022
794
1023
fn use_var( & fn_ctxt fcx, & node_id v) {
@@ -803,6 +1032,12 @@ fn vec_contains(&@mutable (node_id[]) v, &node_id i) -> bool {
803
1032
ret false;
804
1033
}
805
1034
1035
+ fn op_to_oper_ty( init_op io) -> oper_type {
1036
+ alt ( io) {
1037
+ case ( init_move) { oper_move }
1038
+ case ( _) { oper_assign }
1039
+ }
1040
+ }
806
1041
//
807
1042
// Local Variables:
808
1043
// mode: rust
0 commit comments