+fn file_contains(&str filename, &str needle) -> bool {
+ auto r = io::file_reader(filename);
+ auto contents = str::unsafe_from_bytes(r.read_whole_stream());
+ ret str::find(contents, needle) != -1;
+}
+
+fn find_rust_files(&mutable str[] files, str path) {
+ if (str::ends_with(path, ".rs")) {
+ if (file_contains(path, "xfail-stage1")) {
+ //log_err "Skipping " + path + " because it is marked as xfail-stage1";
+ } else if (
+ !str::ends_with(path, "constrained-type.rs") && // https://github.com/graydon/rust/issues/653
+ str::find(path, "utf8") != -1 && // https://github.com/graydon/rust/issues/654
+ true) {
+ //log_err "Skipping " + path + " because of a known bug";
+ } else {
+ files += ~[path];
+ }
+ } else if (fs::file_is_dir(path) && str::find(path, "compile-fail") == -1) {
+ for (str p in fs::list_dir(path)) {
+ find_rust_files(files, p);
+ }
+ }
+}
+
+fn steal_exprs(&ast::crate crate) -> ast::expr[] {
+ let @mutable ast::expr[] exprs = @mutable ~[];
+ // "Stash" cannot be type-parameterized because of https://github.com/graydon/rust/issues/375
+ fn stash_expr(@mutable ast::expr[] es, &@ast::expr e) { *es += ~[*e]; }
+ auto v = rec(visit_expr_pre = bind stash_expr(exprs, _) with walk::default_visitor());
+ walk::walk_crate(v, crate);
+ *exprs
+}
+
+// https://github.com/graydon/rust/issues/652
+fn safe_to_replace(ast::expr_ e) -> bool {
+ alt (e) {
+ case (ast::expr_if(_, _, _)) { false }
+ case (ast::expr_block(_)) { false }
+ case (_) { true }
+ }
+}
+
+// Replace the |i|th expr (in fold order) of |crate| with |newexpr|.
+fn replace_expr_in_crate(&ast::crate crate, uint i, ast::expr_ newexpr) -> ast::crate {
+ let @mutable uint j = @mutable 0u;
+ fn fold_expr_rep(@mutable uint j_, uint i_, &ast::expr_ newexpr_, &ast::expr_ original, fold::ast_fold fld) -> ast::expr_ {
+ *j_ += 1u;
+ if (i_ + 1u == *j_ && safe_to_replace(original)) {
+ newexpr_
+ } else {
+ fold::noop_fold_expr(original, fld)
+ }
+ }
+ auto afp = rec(fold_expr = bind fold_expr_rep(j, i, newexpr, _, _) with *fold::default_ast_fold());
+ auto af = fold::make_fold(afp);
+ let @ast::crate crate2 = @af.fold_crate(crate);
+ fold::dummy_out(af); // work around a leak (https://github.com/graydon/rust/issues/651)
+ *crate2
+}
+
+iter under(uint n) -> uint { let uint i = 0u; while (i < n) { put i; i += 1u; } }
+
+fn devnull() -> io::writer { std::io::string_writer().get_writer() }
+
+fn pp_variants(&ast::crate crate, &session::session sess, &str filename) {
+ auto exprs = steal_exprs(crate);
+ auto exprsL = ivec::len(exprs);
+ if (exprsL < 100u) {
+ for each (uint i in under(uint::min(exprsL, 20u))) {
+ log_err "Replacing... " + pprust::expr_to_str(@exprs.(i));
+ for each (uint j in under(uint::min(exprsL, 5u))) {
+ log_err "With... " + pprust::expr_to_str(@exprs.(j));
+ auto crate2 = @replace_expr_in_crate(crate, i, exprs.(j).node);
+ pprust::print_crate(sess.get_codemap(), crate2, filename, devnull(), pprust::no_ann());
+ }