aboutsummaryrefslogtreecommitdiff
path: root/src/comp/util
diff options
context:
space:
mode:
authorTim Chevalier <[email protected]>2011-04-21 17:39:04 -0700
committerGraydon Hoare <[email protected]>2011-04-28 13:26:19 -0700
commit0190ebfe0748f28c290eb4759a03ffbd416cbeac (patch)
treea419e87e4071017aa52399f74646865f3f2c22ae /src/comp/util
parentFurther work on typestate_check (diff)
downloadrust-0190ebfe0748f28c290eb4759a03ffbd416cbeac.tar.xz
rust-0190ebfe0748f28c290eb4759a03ffbd416cbeac.zip
Support all expression forms in typestate
Added support for self_method, cont, chan, port, recv, send, be, do_while, spawn, and ext; handled break and cont correctly. (However, there are no non-xfailed test cases for ext or spawn in stage0 currently.) Although the standard library compiles and all test cases pass with typestate enabled, I left typestate checking disabled as rustc terminates abnormally when building the standard library if so, even though it does generate code correctly.
Diffstat (limited to 'src/comp/util')
-rw-r--r--src/comp/util/common.rs32
1 files changed, 32 insertions, 0 deletions
diff --git a/src/comp/util/common.rs b/src/comp/util/common.rs
index d2ed72a0..fd0d688b 100644
--- a/src/comp/util/common.rs
+++ b/src/comp/util/common.rs
@@ -1,3 +1,5 @@
+import std.map;
+import std.map.hashmap;
import std._uint;
import std._int;
import std._vec;
@@ -5,6 +7,9 @@ import std.option.none;
import front.ast;
import util.typestate_ann.ts_ann;
+import middle.fold;
+import middle.fold.respan;
+
import std.io.stdout;
import std.io.str_writer;
import std.io.string_writer;
@@ -16,6 +21,7 @@ import pretty.pp.mkstate;
type filename = str;
type span = rec(uint lo, uint hi);
type spanned[T] = rec(T node, span span);
+type flag = hashmap[str, ()];
tag ty_mach {
ty_i8;
@@ -222,6 +228,32 @@ fn decl_lhs(@ast.decl d) -> ast.def_id {
}
}
+fn has_nonlocal_exits(&ast.block b) -> bool {
+ /* overkill, but just passing around a mutable bool doesn't seem
+ to work in rustboot */
+ auto has_exits = new_str_hash[()]();
+
+ fn set_break(&flag f, &span sp, ast.ann a) -> @ast.expr {
+ f.insert("foo", ());
+ ret @respan(sp, ast.expr_break(a));
+ }
+ fn set_cont(&flag f, &span sp, ast.ann a) -> @ast.expr {
+ f.insert("foo", ());
+ ret @respan(sp, ast.expr_cont(a));
+ }
+ fn check_b(&flag f) -> bool {
+ ret (f.size() == 0u);
+ }
+
+ auto fld0 = fold.new_identity_fold[flag]();
+
+ fld0 = @rec(fold_expr_break = bind set_break(_,_,_),
+ fold_expr_cont = bind set_cont(_,_,_),
+ keep_going = bind check_b(_) with *fld0);
+ fold.fold_block[flag](has_exits, fld0, b);
+
+ ret (has_exits.size() > 0u);
+}
//
// Local Variables:
// mode: rust