@@ -4,12 +4,15 @@ import std::option;
4
4
import std:: option:: none;
5
5
import std:: option:: some;
6
6
7
+ // FIXME: needs to be tstate::ann because ann is also a type name...
8
+ // that's probably a bug.
7
9
import tstate:: ann:: pre_and_post;
8
10
import tstate:: ann:: get_post;
9
11
import tstate:: ann:: postcond;
10
12
import tstate:: ann:: true_precond;
11
13
import tstate:: ann:: false_postcond;
12
14
import tstate:: ann:: empty_poststate;
15
+ import tstate:: ann:: require;
13
16
import tstate:: ann:: require_and_preserve;
14
17
import tstate:: ann:: union;
15
18
import tstate:: ann:: intersect;
@@ -22,6 +25,7 @@ import aux::fn_ctxt;
22
25
import aux:: occ_init;
23
26
import aux:: num_constraints;
24
27
import aux:: constraint;
28
+ import aux:: constr_occ;
25
29
import aux:: expr_pp;
26
30
import aux:: stmt_pp;
27
31
import aux:: block_pp;
@@ -41,6 +45,11 @@ import aux::ann_to_def_strict;
41
45
import aux:: ann_to_ts_ann;
42
46
import aux:: set_postcond_false;
43
47
import aux:: controlflow_expr;
48
+ import aux:: expr_to_constr;
49
+ import aux:: constraint_info;
50
+ import aux:: constr_to_constr_occ;
51
+ import aux:: constraints_expr;
52
+ import aux:: substitute_constr_args;
44
53
45
54
import bitvectors:: seq_preconds;
46
55
import bitvectors:: union_postconds;
@@ -52,6 +61,7 @@ import bitvectors::gen;
52
61
import front:: ast:: * ;
53
62
54
63
import middle:: ty:: expr_ann;
64
+ import middle:: ty:: lookup_fn_decl;
55
65
56
66
import util:: common:: new_def_hash;
57
67
import util:: common:: decl_lhs;
@@ -210,6 +220,38 @@ fn find_pre_post_expr(&fn_ctxt fcx, @expr e) -> () {
210
220
auto args = vec:: clone[ @expr] ( operands) ;
211
221
vec:: push[ @expr] ( args, operator) ;
212
222
find_pre_post_exprs ( fcx, args, a) ;
223
+
224
+ /* see if the call has any constraints on its in type */
225
+ let option:: t[ tup( fn_decl, def_id) ] decl_and_id =
226
+ lookup_fn_decl ( fcx. ccx . tcx , expr_ann ( operator) ) ;
227
+ alt ( decl_and_id) {
228
+ case ( some ( ?p) ) {
229
+ log ( "known function: " ) ;
230
+ log_expr ( * operator) ;
231
+ let def_id f_id = p. _1 ;
232
+ let fn_decl f_decl = p. _0 ;
233
+ auto pp = expr_pp ( fcx. ccx , e) ;
234
+ for ( @constr c in constraints_expr( fcx. ccx, operator) ) {
235
+ auto i = bit_num( fcx, f_id,
236
+ substitute_constr_args( fcx. ccx. tcx, operands,
237
+ f_decl. inputs, c) ) ;
238
+ require( i, pp) ;
239
+ }
240
+ }
241
+ // FIXME: Soundness? If a function is constrained...
242
+ // shouldn't be able to pass it as an argument
243
+ // But typechecking guarantees that. However, we could
244
+ // have an unknown function w/ a constrained type =>
245
+ // no decl... but need to know the argument names.
246
+ // Fix that and then make a test w/ a higher-order
247
+ // constrained function.
248
+ case ( _) {
249
+ log( "unknown function: " ) ;
250
+ log_expr( * operator) ;
251
+ /* unknown function -- do nothing */ }
252
+ }
253
+ // FIXME: constraints on result type
254
+
213
255
/* if this is a failing call, its postcondition sets everything */
214
256
alt ( controlflow_expr( fcx. ccx, operator) ) {
215
257
case ( noreturn) {
@@ -471,9 +513,14 @@ fn find_pre_post_expr(&fn_ctxt fcx, @expr e) -> () {
471
513
copy_pre_post( fcx. ccx, a, p) ;
472
514
}
473
515
case ( expr_check( ?p, ?a) ) {
474
- /* will need to change when we support arbitrary predicates... */
516
+ /* FIXME: Can we bypass this by having a
517
+ node-id-to-constr_occ table? */
475
518
find_pre_post_expr( fcx, p) ;
476
519
copy_pre_post( fcx. ccx, a, p) ;
520
+ /* predicate p holds after this expression executes */
521
+ let constraint_info c = expr_to_constr( fcx. ccx. tcx, p) ;
522
+ let constr_occ o = constr_to_constr_occ( fcx. ccx. tcx, c. c. node) ;
523
+ gen ( fcx, a, c. id, o) ;
477
524
}
478
525
case( expr_bind( ?operator, ?maybe_args, ?a) ) {
479
526
auto args = vec:: cat_options[ @expr] ( maybe_args) ;
0 commit comments