Skip to content

Commit a1bb4a4

Browse files
committed
Refactor some typestate-related data structures
1 parent d1857d3 commit a1bb4a4

File tree

6 files changed

+142
-143
lines changed

6 files changed

+142
-143
lines changed

src/comp/middle/tstate/auxiliary.rs

Lines changed: 58 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -76,12 +76,12 @@ fn comma_str(vec[@constr_arg_use] args) -> str {
7676
ret res;
7777
}
7878

79-
fn constraint_to_str(ty::ctxt tcx, constr c) -> str {
80-
alt (c.node) {
81-
case (ninit(?i, _)) {
79+
fn constraint_to_str(&ty::ctxt tcx, &constr c) -> str {
80+
alt (c.node.c) {
81+
case (ninit(?i)) {
8282
ret "init(" + i + " [" + tcx.sess.span_str(c.span) + "])";
8383
}
84-
case (npred(?p, _, ?args)) {
84+
case (npred(?p, ?args)) {
8585
ret path_to_str(p) + "(" + comma_str(args) + ")"
8686
+ "[" + tcx.sess.span_str(c.span) + "]";
8787
}
@@ -101,7 +101,7 @@ fn bitv_to_str(fn_ctxt fcx, bitv::t v) -> str {
101101
ret s;
102102
}
103103

104-
fn log_bitv(fn_ctxt fcx, bitv::t v) {
104+
fn log_bitv(&fn_ctxt fcx, &bitv::t v) {
105105
log(bitv_to_str(fcx, v));
106106
}
107107

@@ -208,43 +208,50 @@ fn print_idents(vec[ident] idents) -> () {
208208
/* data structures */
209209

210210
/**********************************************************************/
211-
/* mapping from def_id to bit number and other data
212-
(ident/path/span are there for error-logging purposes) */
211+
/* Two different data structures represent constraints in different
212+
contexts: constraint and norm_constraint.
213213
214-
/* FIXME very confused about why we have all these different types. */
214+
constraint gets used to record constraints in a table keyed by def_ids.
215+
cinit constraints represent a single constraint, for the initialization
216+
state of a variable; a cpred constraint, with a single operator and a
217+
list of possible argument lists, could represent several constraints at
218+
once.
219+
220+
norm_constraint, in contrast, gets used when handling an instance
221+
of a constraint rather than a definition of a constraint. It can
222+
also be init or pred (ninit or npred), but the npred case just has
223+
a single argument list.
224+
225+
The representation of constraints, where multiple instances of the
226+
same predicate are collapsed into one entry in the table, makes it
227+
easier to look up a specific instance.
228+
229+
Both types are in constrast with the constraint type defined in
230+
front::ast, which is for predicate constraints only, and is what
231+
gets generated by the parser. aux and ast share the same type
232+
to represent predicate *arguments* however. This type
233+
(constr_arg_general) is parameterized (see comments in front::ast).
234+
235+
Both types store an ident and span, for error-logging purposes.
236+
*/
215237

216238
type pred_desc_ = rec(vec[@constr_arg_use] args,
217239
uint bit_num);
218240
type pred_desc = spanned[pred_desc_];
219241
tag constraint {
220-
cinit(uint, span, def_id, ident);
221-
cpred(path, def_id, @mutable vec[pred_desc]);
242+
cinit(uint, span, ident);
243+
cpred(path, @mutable vec[pred_desc]);
222244
}
223-
tag constr_ {
224-
ninit(ident, def_id);
225-
npred(path, def_id, vec[@constr_arg_use]);
245+
tag constr__ {
246+
ninit(ident);
247+
npred(path, vec[@constr_arg_use]);
226248
}
249+
type constr_ = rec(def_id id, constr__ c);
227250
type constr = spanned[constr_];
228251
type norm_constraint = rec(uint bit_num,
229252
constr c);
230-
/* "constraint occurrence" to disambiguate
231-
between constraints. either "this is an
232-
init constraint", or the list of args for
233-
a pred. */
234-
tag constr_occ {
235-
occ_init;
236-
occ_args(vec[@constr_arg_use]);
237-
}
238-
239253
type constr_map = @std::map::hashmap[def_id, constraint];
240254

241-
fn constr_id(&constr c) -> def_id {
242-
ret (alt (c.node) {
243-
case (ninit(_, ?i)) { i }
244-
case (npred(_, ?i, _)) { i }
245-
})
246-
}
247-
248255
type fn_info = rec(constr_map constrs, uint num_constraints, controlflow cf);
249256

250257
/* mapping from node ID to typestate annotation */
@@ -529,16 +536,16 @@ fn ann_to_def(&crate_ctxt ccx, &ann a) -> option::t[def] {
529536
ret ccx.tcx.def_map.find(a.id);
530537
}
531538

532-
fn norm_a_constraint(&constraint c) -> vec[norm_constraint] {
539+
fn norm_a_constraint(&def_id id, &constraint c) -> vec[norm_constraint] {
533540
alt (c) {
534-
case (cinit(?n, ?sp, ?id, ?i)) {
535-
ret [rec(bit_num=n, c=respan(sp, ninit(i, id)))];
541+
case (cinit(?n, ?sp, ?i)) {
542+
ret [rec(bit_num=n, c=respan(sp, rec(id=id, c=ninit(i))))];
536543
}
537-
case (cpred(?p, ?id, ?descs)) {
544+
case (cpred(?p, ?descs)) {
538545
let vec[norm_constraint] res = [];
539546
for (pred_desc pd in *descs) {
540547
vec::push(res, rec(bit_num=pd.node.bit_num,
541-
c=respan(pd.span, npred(p, id, pd.node.args))));
548+
c=respan(pd.span, rec(id=id, c=npred(p, pd.node.args)))));
542549
}
543550
ret res;
544551
}
@@ -551,7 +558,7 @@ fn constraints(&fn_ctxt fcx) -> vec[norm_constraint] {
551558
let vec[norm_constraint] res = [];
552559
for each (@tup(def_id, constraint) p in
553560
fcx.enclosing.constrs.items()) {
554-
res += norm_a_constraint(p._1);
561+
res += norm_a_constraint(p._0, p._1);
555562
}
556563
ret res;
557564
}
@@ -572,13 +579,6 @@ fn match_args(&fn_ctxt fcx, vec[pred_desc] occs,
572579
fcx.ccx.tcx.sess.bug("match_args: no match for occurring args");
573580
}
574581

575-
fn constr_to_constr_occ(&ty::ctxt tcx, &constr_ c) -> constr_occ {
576-
alt (c) {
577-
case (ninit(_, _)) { ret occ_init; }
578-
case (npred(_, _, ?args)) { ret occ_args(args); }
579-
}
580-
}
581-
582582
fn def_id_for_constr(ty::ctxt tcx, uint t) -> def_id {
583583
alt (tcx.def_map.find(t)) {
584584
case (none) {
@@ -627,8 +627,9 @@ fn expr_to_constr(ty::ctxt tcx, &@expr e) -> constr {
627627
alt (operator.node) {
628628
case (expr_path(?p, ?a)) {
629629
ret respan(e.span,
630-
npred(p, def_id_for_constr(tcx, a.id),
631-
exprs_to_constr_args(tcx, args)));
630+
rec(id=def_id_for_constr(tcx, a.id),
631+
c=npred(p,
632+
exprs_to_constr_args(tcx, args))));
632633
}
633634
case (_) {
634635
tcx.sess.span_err(operator.span, "Internal error: " +
@@ -648,20 +649,14 @@ fn pred_desc_to_str(&pred_desc p) -> str {
648649
pretty::ppaux::constr_args_to_str_1(p.node.args) + ">");
649650
}
650651

651-
fn substitute_constr_args_(&ty::ctxt cx,
652+
fn substitute_constr_args(&ty::ctxt cx,
652653
&vec[@expr] actuals, &@ast::constr c)
653-
-> vec[@constr_arg_use] {
654+
-> constr__ {
654655
let vec[@constr_arg_use] res = [];
655656
for (@constr_arg a in c.node.args) {
656657
res += [substitute_arg(cx, actuals, a)];
657658
}
658-
ret res;
659-
660-
}
661-
662-
fn substitute_constr_args(&ty::ctxt cx,
663-
&vec[@expr] actuals, &@ast::constr c) -> constr_occ {
664-
ret occ_args(substitute_constr_args_(cx, actuals, c));
659+
ret npred(c.node.path, res);
665660
}
666661

667662
type subst = vec[tup(arg, @expr)];
@@ -683,6 +678,16 @@ fn substitute_arg(&ty::ctxt cx, &vec[@expr] actuals, @ast::constr_arg a)
683678
}
684679
}
685680

681+
fn path_to_ident(&ty::ctxt cx, &path p) -> ident {
682+
alt (vec::last(p.node.idents)) {
683+
case (none) {
684+
cx.sess.span_err(p.span, "Malformed path");
685+
}
686+
case (some(?i)) {
687+
ret i;
688+
}
689+
}
690+
}
686691
//
687692
// Local Variables:
688693
// mode: rust

src/comp/middle/tstate/bitvectors.rs

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,13 @@ import aux::fn_ctxt;
99
import aux::fn_info;
1010
import aux::log_bitv;
1111
import aux::num_constraints;
12-
import aux::constr_occ;
13-
import aux::occ_init;
14-
import aux::occ_args;
1512
import aux::cinit;
1613
import aux::cpred;
14+
import aux::ninit;
15+
import aux::npred;
1716
import aux::pred_desc;
1817
import aux::match_args;
18+
import aux::constr_;
1919

2020
import tstate::aux::ann_to_ts_ann;
2121
import tstate::ann::pre_and_post;
@@ -35,13 +35,13 @@ import tstate::ann::set_in_postcond;
3535
import tstate::ann::set_in_poststate;
3636
import tstate::ann::clear_in_poststate;
3737

38-
fn bit_num(&fn_ctxt fcx, &def_id v, &constr_occ o) -> uint {
39-
assert (fcx.enclosing.constrs.contains_key(v));
40-
auto res = fcx.enclosing.constrs.get(v);
41-
alt (o) {
42-
case (occ_init) {
38+
fn bit_num(&fn_ctxt fcx, &constr_ c) -> uint {
39+
assert (fcx.enclosing.constrs.contains_key(c.id));
40+
auto res = fcx.enclosing.constrs.get(c.id);
41+
alt (c.c) {
42+
case (ninit(_)) {
4343
alt (res) {
44-
case (cinit(?n,_,_,_)) {
44+
case (cinit(?n,_,_)) {
4545
ret n;
4646
}
4747
case (_) {
@@ -50,9 +50,9 @@ fn bit_num(&fn_ctxt fcx, &def_id v, &constr_occ o) -> uint {
5050
}
5151
}
5252
}
53-
case (occ_args(?args)) {
53+
case (npred(_, ?args)) {
5454
alt (res) {
55-
case (cpred(_, _, ?descs)) {
55+
case (cpred(_, ?descs)) {
5656
ret match_args(fcx, *descs, args);
5757
}
5858
case (_) {
@@ -64,8 +64,8 @@ fn bit_num(&fn_ctxt fcx, &def_id v, &constr_occ o) -> uint {
6464
}
6565
}
6666

67-
fn promises(&fn_ctxt fcx, &poststate p, &def_id v, &constr_occ o) -> bool {
68-
ret bitv::get(p, bit_num(fcx, v, o));
67+
fn promises(&fn_ctxt fcx, &poststate p, &constr_ c) -> bool {
68+
ret bitv::get(p, bit_num(fcx, c));
6969
}
7070

7171
// Given a list of pres and posts for exprs e0 ... en,
@@ -143,27 +143,26 @@ fn intersect_postconds(&vec[postcond] pcs) -> postcond {
143143
ret intersect_postconds_go(bitv::clone(pcs.(0)), pcs);
144144
}
145145

146-
fn gen(&fn_ctxt fcx, &ann a, &def_id id, &constr_occ o) -> bool {
147-
ret set_in_postcond(bit_num(fcx, id, o),
146+
fn gen(&fn_ctxt fcx, &ann a, &constr_ c) -> bool {
147+
ret set_in_postcond(bit_num(fcx, c),
148148
(ann_to_ts_ann(fcx.ccx, a)).conditions);
149149
}
150150

151-
fn declare_var(&fn_ctxt fcx, def_id id, prestate pre)
152-
-> prestate {
151+
fn declare_var(&fn_ctxt fcx, &constr_ c, prestate pre) -> prestate {
153152
auto res = clone(pre);
154-
relax_prestate(bit_num(fcx, id, occ_init), res);
153+
relax_prestate(bit_num(fcx, c), res);
155154
ret res;
156155
}
157156

158-
fn gen_poststate(&fn_ctxt fcx, &ann a, &def_id id, &constr_occ o) -> bool {
157+
fn gen_poststate(&fn_ctxt fcx, &ann a, &constr_ c) -> bool {
159158
log "gen_poststate";
160-
ret set_in_poststate(bit_num(fcx, id, o),
159+
ret set_in_poststate(bit_num(fcx, c),
161160
(ann_to_ts_ann(fcx.ccx, a)).states);
162161
}
163162

164-
fn kill_poststate(&fn_ctxt fcx, &ann a, def_id id, &constr_occ o) -> bool {
163+
fn kill_poststate(&fn_ctxt fcx, &ann a, &constr_ c) -> bool {
165164
log "kill_poststate";
166-
ret clear_in_poststate(bit_num(fcx, id, o),
165+
ret clear_in_poststate(bit_num(fcx, c),
167166
(ann_to_ts_ann(fcx.ccx, a)).states);
168167
}
169168

src/comp/middle/tstate/ck.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,8 +133,9 @@ fn check_states_against_conditions(&fn_ctxt fcx, &_fn f, &ann a) -> () {
133133

134134
auto cf = fcx.enclosing.cf;
135135
/* Finally, check that the return value is initialized */
136+
let aux::constr_ ret_c = rec(id=fcx.id, c=aux::ninit(fcx.name));
136137
if (f.proto == ast::proto_fn
137-
&& ! promises(fcx, *post, fcx.id, aux::occ_init)
138+
&& ! promises(fcx, *post, ret_c)
138139
&& ! type_is_nil(fcx.ccx.tcx,
139140
ret_ty_of_fn(fcx.ccx.tcx, a))
140141
&& cf == return) {
@@ -148,7 +149,7 @@ fn check_states_against_conditions(&fn_ctxt fcx, &_fn f, &ann a) -> () {
148149
// check that this really always fails
149150
// the fcx.id bit means "returns" for a returning fn,
150151
// "diverges" for a non-returning fn
151-
if (! promises(fcx, *post, fcx.id, aux::occ_init)) {
152+
if (! promises(fcx, *post, ret_c)) {
152153
fcx.ccx.tcx.sess.span_err(f.body.span,
153154
"In non-returning function " + fcx.name +
154155
", some control paths may return to the caller");

0 commit comments

Comments
 (0)