diff options
| author | Tim Chevalier <[email protected]> | 2011-04-21 17:39:04 -0700 |
|---|---|---|
| committer | Graydon Hoare <[email protected]> | 2011-04-28 13:26:19 -0700 |
| commit | 0190ebfe0748f28c290eb4759a03ffbd416cbeac (patch) | |
| tree | a419e87e4071017aa52399f74646865f3f2c22ae /src/comp/util/common.rs | |
| parent | Further work on typestate_check (diff) | |
| download | rust-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/common.rs')
| -rw-r--r-- | src/comp/util/common.rs | 32 |
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 |