2011-05-14 19:02:30 -07:00
|
|
|
import std::bitv;
|
2011-05-17 20:41:41 +02:00
|
|
|
import std::vec;
|
|
|
|
import std::vec::len;
|
|
|
|
import std::vec::slice;
|
2011-05-14 19:02:30 -07:00
|
|
|
|
|
|
|
import front::ast;
|
|
|
|
import front::ast::def_id;
|
|
|
|
import front::ast::expr;
|
|
|
|
import front::ast::ann;
|
|
|
|
|
|
|
|
import aux::fn_ctxt;
|
|
|
|
import aux::fn_info;
|
|
|
|
import aux::log_bitv;
|
|
|
|
import aux::num_locals;
|
|
|
|
import aux::ann_to_ts_ann_strict;
|
|
|
|
|
|
|
|
import tstate::ann::pre_and_post;
|
|
|
|
import tstate::ann::precond;
|
|
|
|
import tstate::ann::postcond;
|
|
|
|
import tstate::ann::prestate;
|
|
|
|
import tstate::ann::poststate;
|
|
|
|
import tstate::ann::relax_prestate;
|
|
|
|
import tstate::ann::pps_len;
|
|
|
|
import tstate::ann::true_precond;
|
|
|
|
import tstate::ann::empty_prestate;
|
|
|
|
import tstate::ann::difference;
|
|
|
|
import tstate::ann::union;
|
|
|
|
import tstate::ann::intersect;
|
|
|
|
import tstate::ann::clone;
|
|
|
|
import tstate::ann::set_in_postcond;
|
|
|
|
import tstate::ann::set_in_poststate;
|
|
|
|
|
|
|
|
fn bit_num(def_id v, fn_info m) -> uint {
|
|
|
|
assert (m.vars.contains_key(v));
|
|
|
|
ret m.vars.get(v)._0;
|
|
|
|
}
|
|
|
|
|
|
|
|
fn promises(&poststate p, def_id v, fn_info m) -> bool {
|
|
|
|
ret bitv::get(p, bit_num(v, m));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Given a list of pres and posts for exprs e0 ... en,
|
|
|
|
// return the precondition for evaluating each expr in order.
|
|
|
|
// So, if e0's post is {x} and e1's pre is {x, y, z}, the entire
|
|
|
|
// precondition shouldn't include x.
|
|
|
|
fn seq_preconds(fn_info enclosing, vec[pre_and_post] pps) -> precond {
|
|
|
|
let uint sz = len[pre_and_post](pps);
|
|
|
|
let uint num_vars = num_locals(enclosing);
|
|
|
|
|
|
|
|
if (sz >= 1u) {
|
|
|
|
auto first = pps.(0);
|
|
|
|
assert (pps_len(first) == num_vars);
|
|
|
|
let precond rest = seq_preconds(enclosing,
|
|
|
|
slice[pre_and_post](pps, 1u, sz));
|
|
|
|
difference(rest, first.postcondition);
|
|
|
|
auto res = clone(first.precondition);
|
|
|
|
union(res, rest);
|
|
|
|
|
|
|
|
log("seq_preconds:");
|
|
|
|
log("first.postcondition =");
|
|
|
|
log_bitv(enclosing, first.postcondition);
|
|
|
|
log("rest =");
|
|
|
|
log_bitv(enclosing, rest);
|
|
|
|
log("returning");
|
|
|
|
log_bitv(enclosing, res);
|
|
|
|
|
|
|
|
ret res;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
ret true_precond(num_vars);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* works on either postconds or preconds
|
|
|
|
should probably rethink the whole type synonym situation */
|
|
|
|
fn union_postconds_go(&postcond first, &vec[postcond] rest) -> postcond {
|
2011-05-17 20:41:41 +02:00
|
|
|
auto sz = vec::len[postcond](rest);
|
2011-05-14 19:02:30 -07:00
|
|
|
|
|
|
|
if (sz > 0u) {
|
|
|
|
auto other = rest.(0);
|
|
|
|
union(first, other);
|
|
|
|
union_postconds_go(first, slice[postcond](rest, 1u, len[postcond](rest)));
|
|
|
|
}
|
|
|
|
|
|
|
|
ret first;
|
|
|
|
}
|
|
|
|
|
|
|
|
fn union_postconds(uint nv, &vec[postcond] pcs) -> postcond {
|
|
|
|
if (len[postcond](pcs) > 0u) {
|
|
|
|
ret union_postconds_go(bitv::clone(pcs.(0)), pcs);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
ret empty_prestate(nv);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Gee, maybe we could use foldl or something */
|
|
|
|
fn intersect_postconds_go(&postcond first, &vec[postcond] rest) -> postcond {
|
2011-05-17 20:41:41 +02:00
|
|
|
auto sz = vec::len[postcond](rest);
|
2011-05-14 19:02:30 -07:00
|
|
|
|
|
|
|
if (sz > 0u) {
|
|
|
|
auto other = rest.(0);
|
|
|
|
intersect(first, other);
|
|
|
|
intersect_postconds_go(first, slice[postcond](rest, 1u,
|
|
|
|
len[postcond](rest)));
|
|
|
|
}
|
|
|
|
|
|
|
|
ret first;
|
|
|
|
}
|
|
|
|
|
|
|
|
fn intersect_postconds(&vec[postcond] pcs) -> postcond {
|
|
|
|
assert (len[postcond](pcs) > 0u);
|
|
|
|
|
|
|
|
ret intersect_postconds_go(bitv::clone(pcs.(0)), pcs);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn gen(&fn_ctxt fcx, &ann a, def_id id) -> bool {
|
|
|
|
assert (fcx.enclosing.vars.contains_key(id));
|
|
|
|
let uint i = (fcx.enclosing.vars.get(id))._0;
|
|
|
|
ret set_in_postcond(i, (ann_to_ts_ann_strict(a)).conditions);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn declare_var(&fn_info enclosing, def_id id, prestate pre)
|
|
|
|
-> prestate {
|
|
|
|
assert (enclosing.vars.contains_key(id));
|
|
|
|
let uint i = (enclosing.vars.get(id))._0;
|
|
|
|
auto res = clone(pre);
|
|
|
|
relax_prestate(i, res);
|
|
|
|
ret res;
|
|
|
|
}
|
|
|
|
|
|
|
|
fn gen_poststate(&fn_ctxt fcx, &ann a, def_id id) -> bool {
|
|
|
|
assert (fcx.enclosing.vars.contains_key(id));
|
|
|
|
let uint i = (fcx.enclosing.vars.get(id))._0;
|
|
|
|
ret set_in_poststate(i, (ann_to_ts_ann_strict(a)).states);
|
|
|
|
}
|
|
|
|
|