Skip to content

Commit a9a1392

Browse files
committed
Instantiate function preconditions inside the function body
so that if we have a function like: f(...) : p(x) { ... } p(x) is true inside the body of f. Closes #694.
1 parent 2261ddc commit a9a1392

File tree

5 files changed

+61
-6
lines changed

5 files changed

+61
-6
lines changed

src/comp/middle/tstate/auxiliary.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1053,6 +1053,29 @@ fn op_to_oper_ty(init_op io) -> oper_type {
10531053
fn do_nothing[T](&_fn f, &ty_param[] tp, &span sp, &fn_ident i,
10541054
node_id iid, &T cx, &visit::vt[T] v) {
10551055
}
1056+
1057+
1058+
fn args_to_constr_args(&span sp, &arg[] args) -> (@constr_arg_use)[] {
1059+
let (@constr_arg_use)[] actuals = ~[];
1060+
for (arg a in args) {
1061+
actuals += ~[@respan(sp, carg_ident(tup(a.ident, a.id)))];
1062+
}
1063+
ret actuals;
1064+
}
1065+
1066+
fn ast_constr_to_ts_constr(&ty::ctxt tcx, &arg[] args, &@constr c)
1067+
-> tsconstr {
1068+
auto tconstr = ty::ast_constr_to_constr(tcx, c);
1069+
ret npred(tconstr.node.path, tconstr.node.id,
1070+
args_to_constr_args(tconstr.span, args));
1071+
}
1072+
1073+
fn ast_constr_to_sp_constr(&ty::ctxt tcx, &arg[] args, &@constr c)
1074+
-> sp_constr {
1075+
auto tconstr = ast_constr_to_ts_constr(tcx, args, c);
1076+
ret respan(c.span, tconstr);
1077+
}
1078+
10561079
//
10571080
// Local Variables:
10581081
// mode: rust

src/comp/middle/tstate/bitvectors.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,10 @@ fn set_in_poststate_ident(&fn_ctxt fcx, &node_id id, &ident ident,
233233
ret set_in_poststate_(bit_num(fcx, ninit(id, ident)), t);
234234
}
235235

236+
fn set_in_prestate_constr(&fn_ctxt fcx, &tsconstr c, &prestate t) -> bool {
237+
ret set_in_poststate_(bit_num(fcx, c), t);
238+
}
239+
236240
fn clear_in_poststate_ident(&fn_ctxt fcx, &node_id id, &ident ident,
237241
&node_id parent) -> bool {
238242
ret kill_poststate(fcx, parent, ninit(id, ident));

src/comp/middle/tstate/collect_locals.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
1+
import std::uint;
2+
import std::int;
23
import std::ivec;
34
import syntax::ast::*;
45
import util::ppaux::fn_ident_to_string;
@@ -96,6 +97,7 @@ fn add_constraint(&ty::ctxt tcx, sp_constr c, uint next, constr_map tbl) ->
9697
to a bit number in the precondition/postcondition vectors */
9798
fn mk_fn_info(&crate_ctxt ccx, &_fn f, &ty_param[] tp,
9899
&span f_sp, &fn_ident f_name, node_id id) {
100+
auto name = fn_ident_to_string(id, f_name);
99101
auto res_map = @new_def_hash[constraint]();
100102
let uint next = 0u;
101103

@@ -106,15 +108,23 @@ fn mk_fn_info(&crate_ctxt ccx, &_fn f, &ty_param[] tp,
106108
for (sp_constr c in { *cx.cs }) {
107109
next = add_constraint(cx.tcx, c, next, res_map);
108110
}
111+
/* if this function has any constraints, instantiate them to the
112+
argument names and add them */
113+
auto sc;
114+
for (@constr c in f.decl.constraints) {
115+
sc = ast_constr_to_sp_constr(cx.tcx, f.decl.inputs, c);
116+
next = add_constraint(cx.tcx, sc, next, res_map);
117+
}
118+
109119
/* add a pseudo-entry for the function's return value
110120
we can safely use the function's name itself for this purpose */
111121

112-
auto name = fn_ident_to_string(id, f_name);
113122
add_constraint(cx.tcx, respan(f_sp, ninit(id, name)), next, res_map);
114123
let @mutable node_id[] v = @mutable ~[];
115124
auto rslt =
116125
rec(constrs=res_map,
117-
num_constraints=ivec::len(*cx.cs) + 1u,
126+
num_constraints=ivec::len(*cx.cs) + ivec::len(f.decl.constraints)
127+
+ 1u,
118128
cf=f.decl.cf,
119129
used_vars=v);
120130
ccx.fm.insert(id, rslt);

src/comp/middle/tstate/states.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import syntax::print::pprust::path_to_str;
12
import std::ivec;
23
import std::option;
34
import std::option::get;
@@ -25,6 +26,8 @@ import tritv::tritv_clone;
2526
import tritv::tritv_set;
2627
import tritv::ttrue;
2728

29+
import bitvectors::*;
30+
/*
2831
import bitvectors::set_in_poststate_ident;
2932
import bitvectors::clear_in_poststate_expr;
3033
import bitvectors::clear_in_prestate_ident;
@@ -33,6 +36,7 @@ import bitvectors::gen_poststate;
3336
import bitvectors::kill_poststate;
3437
import bitvectors::clear_in_poststate_ident;
3538
import bitvectors::intersect_states;
39+
*/
3640
import syntax::ast::*;
3741
import middle::ty::expr_ty;
3842
import middle::ty::type_is_nil;
@@ -731,9 +735,15 @@ fn find_pre_post_state_fn(&fn_ctxt fcx, &_fn f) -> bool {
731735
auto num_local_vars = num_constraints(fcx.enclosing);
732736
// make sure the return bit starts out False
733737
clear_in_prestate_ident(fcx, fcx.id, fcx.name, f.body.node.id);
734-
auto changed =
735-
find_pre_post_state_block(fcx, block_prestate(fcx.ccx, f.body),
736-
f.body);
738+
// Instantiate any constraints on the arguments so we can use them
739+
auto block_pre = block_prestate(fcx.ccx, f.body);
740+
auto tsc;
741+
for (@constr c in f.decl.constraints) {
742+
tsc = ast_constr_to_ts_constr(fcx.ccx.tcx, f.decl.inputs, c);
743+
set_in_prestate_constr(fcx, tsc, block_pre);
744+
}
745+
746+
auto changed = find_pre_post_state_block(fcx, block_pre, f.body);
737747
// Treat the tail expression as a return statement
738748

739749
alt (f.body.node.expr) {
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
pred p(int i) -> bool { true }
2+
3+
fn f(int i) : p(i) -> int { i }
4+
5+
fn g(int i) : p(i) -> int { f(i) }
6+
7+
fn main() {
8+
}

0 commit comments

Comments
 (0)