Skip to content

Commit

Permalink
Add --pretty everybody_loops option.
Browse files Browse the repository at this point in the history
This prints out a transformed version of the input source code where
every function body is replaced with `loop { }`.

All such bodies are (1.) trivial and (2.) guaranteed to pass the
type-checker in a valid compiler; therefore they make very nice input
to start with when narrowing down a bug exposed by a large test input
(such as librustc itself).
  • Loading branch information
pnkfelix committed Dec 22, 2014
1 parent e711e2d commit 41def27
Showing 1 changed file with 74 additions and 1 deletion.
75 changes: 74 additions & 1 deletion src/librustc_driver/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@ use rustc_borrowck::graphviz as borrowck_dot;

use syntax::ast;
use syntax::ast_map::{mod, blocks, NodePrinter};
use syntax::codemap;
use syntax::fold::{mod, Folder};
use syntax::print::{pp, pprust};
use syntax::ptr::P;

use graphviz as dot;

Expand All @@ -42,6 +45,7 @@ use arena::TypedArena;
#[deriving(Copy, PartialEq, Show)]
pub enum PpSourceMode {
PpmNormal,
PpmEveryBodyLoops,
PpmExpanded,
PpmTyped,
PpmIdentified,
Expand All @@ -61,6 +65,7 @@ pub fn parse_pretty(sess: &Session, name: &str) -> (PpMode, Option<UserIdentifie
let opt_second = split.next();
let first = match first {
"normal" => PpmSource(PpmNormal),
"everybody_loops" => PpmSource(PpmEveryBodyLoops),
"expanded" => PpmSource(PpmExpanded),
"typed" => PpmSource(PpmTyped),
"expanded,identified" => PpmSource(PpmExpandedIdentified),
Expand Down Expand Up @@ -105,7 +110,7 @@ impl PpSourceMode {
F: FnOnce(&PrinterSupport, B) -> A,
{
match *self {
PpmNormal | PpmExpanded => {
PpmNormal | PpmEveryBodyLoops | PpmExpanded => {
let annotation = NoAnn { sess: sess, ast_map: ast_map };
f(&annotation, payload)
}
Expand Down Expand Up @@ -384,6 +389,7 @@ impl UserIdentifiedItem {
fn needs_ast_map(ppm: &PpMode, opt_uii: &Option<UserIdentifiedItem>) -> bool {
match *ppm {
PpmSource(PpmNormal) |
PpmSource(PpmEveryBodyLoops) |
PpmSource(PpmIdentified) => opt_uii.is_some(),

PpmSource(PpmExpanded) |
Expand All @@ -397,6 +403,7 @@ fn needs_ast_map(ppm: &PpMode, opt_uii: &Option<UserIdentifiedItem>) -> bool {
fn needs_expansion(ppm: &PpMode) -> bool {
match *ppm {
PpmSource(PpmNormal) |
PpmSource(PpmEveryBodyLoops) |
PpmSource(PpmIdentified) => false,

PpmSource(PpmExpanded) |
Expand All @@ -407,13 +414,79 @@ fn needs_expansion(ppm: &PpMode) -> bool {
}
}

struct ReplaceBodyWithLoop {
within_static_or_const: bool,
}

impl ReplaceBodyWithLoop {
fn new() -> ReplaceBodyWithLoop {
ReplaceBodyWithLoop { within_static_or_const: false }
}
}

impl fold::Folder for ReplaceBodyWithLoop {
fn fold_item_underscore(&mut self, i: ast::Item_) -> ast::Item_ {
match i {
ast::ItemStatic(..) | ast::ItemConst(..) => {
self.within_static_or_const = true;
let ret = fold::noop_fold_item_underscore(i, self);
self.within_static_or_const = false;
return ret;
}
_ => {
fold::noop_fold_item_underscore(i, self)
}
}
}


fn fold_block(&mut self, b: P<ast::Block>) -> P<ast::Block> {
fn expr_to_block(rules: ast::BlockCheckMode,
e: Option<P<ast::Expr>>) -> P<ast::Block> {
P(ast::Block {
expr: e,
view_items: vec![], stmts: vec![], rules: rules,
id: ast::DUMMY_NODE_ID, span: codemap::DUMMY_SP,
})
}

if !self.within_static_or_const {

let empty_block = expr_to_block(ast::DefaultBlock, None);
let loop_expr = P(ast::Expr {
node: ast::ExprLoop(empty_block, None),
id: ast::DUMMY_NODE_ID, span: codemap::DUMMY_SP
});

expr_to_block(b.rules, Some(loop_expr))

} else {
fold::noop_fold_block(b, self)
}
}

// in general the pretty printer processes unexpanded code, so
// we override the default `fold_mac` method which panics.
fn fold_mac(&mut self, _macro: ast::Mac) -> ast::Mac {
fold::noop_fold_mac(_macro, self)
}
}

pub fn pretty_print_input(sess: Session,
cfg: ast::CrateConfig,
input: &Input,
ppm: PpMode,
opt_uii: Option<UserIdentifiedItem>,
ofile: Option<Path>) {
let krate = driver::phase_1_parse_input(&sess, cfg, input);

let krate = if let PpmSource(PpmEveryBodyLoops) = ppm {
let mut fold = ReplaceBodyWithLoop::new();
fold.fold_crate(krate)
} else {
krate
};

let id = link::find_crate_name(Some(&sess), krate.attrs.as_slice(), input);

let is_expanded = needs_expansion(&ppm);
Expand Down

0 comments on commit 41def27

Please sign in to comment.