control: &CompileController) -> CompileResult {
macro_rules! controller_entry_point {
($point: ident, $tsess: expr, $make_state: expr, $phase_result: expr) => {{
- let state = $make_state;
+ let state = &mut $make_state;
let phase_result: &CompileResult = &$phase_result;
if phase_result.is_ok() || control.$point.run_callback_on_error {
(control.$point.callback)(state);
}
};
+ let mut compile_state = CompileState::state_after_parse(input,
+ sess,
+ outdir,
+ output,
+ krate,
+ &cstore);
controller_entry_point!(after_parse,
sess,
- CompileState::state_after_parse(input, sess, outdir, &krate),
+ compile_state,
Ok(()));
+ let krate = compile_state.krate.unwrap();
let outputs = build_output_filenames(input, outdir, output, &krate.attrs, sess);
let id = link::find_crate_name(Some(sess), &krate.attrs, input);
// Eventually, we will want to track plugins.
let _ignore = tcx.dep_graph.in_ignore();
- let state = CompileState::state_after_analysis(input,
- &tcx.sess,
- outdir,
- opt_crate,
- tcx.map.krate(),
- &analysis,
- mir_map.as_ref(),
- tcx,
- &id);
- (control.after_analysis.callback)(state);
+ let mut state = CompileState::state_after_analysis(input,
+ &tcx.sess,
+ outdir,
+ opt_crate,
+ tcx.map.krate(),
+ &analysis,
+ mir_map.as_ref(),
+ tcx,
+ &id);
+ (control.after_analysis.callback)(&mut state);
if control.after_analysis.stop == Compilation::Stop {
return result.and_then(|_| Err(0usize));
// If true then the compiler will try to run the callback even if the phase
// ends with an error. Note that this is not always possible.
pub run_callback_on_error: bool,
- pub callback: Box<Fn(CompileState) -> () + 'a>,
+ pub callback: Box<Fn(&mut CompileState) + 'a>,
}
impl<'a> PhaseController<'a> {
pub struct CompileState<'a, 'ast: 'a, 'tcx: 'a> {
pub input: &'a Input,
pub session: &'a Session,
- pub cfg: Option<&'a ast::CrateConfig>,
- pub krate: Option<&'a ast::Crate>,
+ pub krate: Option<ast::Crate>,
+ pub cstore: Option<&'a CStore>,
pub crate_name: Option<&'a str>,
pub output_filenames: Option<&'a OutputFilenames>,
pub out_dir: Option<&'a Path>,
+ pub out_file: Option<&'a Path>,
pub expanded_crate: Option<&'a ast::Crate>,
pub hir_crate: Option<&'a hir::Crate>,
pub ast_map: Option<&'a hir_map::Map<'ast>>,
input: input,
session: session,
out_dir: out_dir.as_ref().map(|s| &**s),
- cfg: None,
+ out_file: None,
krate: None,
+ cstore: None,
crate_name: None,
output_filenames: None,
expanded_crate: None,
fn state_after_parse(input: &'a Input,
session: &'a Session,
out_dir: &'a Option<PathBuf>,
- krate: &'a ast::Crate)
+ out_file: &'a Option<PathBuf>,
+ krate: ast::Crate,
+ cstore: &'a CStore)
-> CompileState<'a, 'ast, 'tcx> {
- CompileState { krate: Some(krate), ..CompileState::empty(input, session, out_dir) }
+ CompileState {
+ krate: Some(krate),
+ cstore: Some(cstore),
+ out_file: out_file.as_ref().map(|s| &**s),
+ ..CompileState::empty(input, session, out_dir)
+ }
}
fn state_after_expand(input: &'a Input,
CompileState {
crate_name: Some(crate_name),
ast_map: Some(hir_map),
- krate: Some(krate),
+ expanded_crate: Some(krate),
hir_crate: Some(hir_crate),
..CompileState::empty(input, session, out_dir)
}
analysis: Some(analysis),
mir_map: mir_map,
tcx: Some(tcx),
- krate: krate,
+ expanded_crate: krate,
hir_crate: Some(hir_crate),
crate_name: Some(crate_name),
..CompileState::empty(input, session, out_dir)
#![feature(set_stdio)]
#![feature(staged_api)]
#![feature(question_mark)]
+#![feature(unboxed_closures)]
extern crate arena;
extern crate flate;
do_or_return!(callbacks.late_callback(&matches, &sess, &input, &odir, &ofile), Some(sess));
- // It is somewhat unfortunate that this is hardwired in.
- let pretty = callbacks.parse_pretty(&sess, &matches);
- if let Some((ppm, opt_uii)) = pretty {
- pretty::pretty_print_input(&sess, &cstore, cfg, &input, ppm, opt_uii, ofile);
- return (Ok(()), None);
- }
-
let plugins = sess.opts.debugging_opts.extra_plugins.clone();
- let control = callbacks.build_controller(&sess);
+ let control = callbacks.build_controller(&sess, &matches);
(driver::compile_input(&sess, &cstore, cfg, &input, &odir, &ofile,
Some(plugins), &control),
Some(sess))
}
}
+fn parse_pretty(sess: &Session,
+ matches: &getopts::Matches)
+ -> Option<(PpMode, Option<UserIdentifiedItem>)> {
+ let pretty = if sess.opts.debugging_opts.unstable_options {
+ matches.opt_default("pretty", "normal").map(|a| {
+ // stable pretty-print variants only
+ pretty::parse_pretty(sess, &a, false)
+ })
+ } else {
+ None
+ };
+ if pretty.is_none() && sess.unstable_options() {
+ matches.opt_str("unpretty").map(|a| {
+ // extended with unstable pretty-print variants
+ pretty::parse_pretty(sess, &a, true)
+ })
+ } else {
+ pretty
+ }
+}
+
// Whether to stop or continue compilation.
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum Compilation {
None
}
- // Parse pretty printing information from the arguments. The implementer can
- // choose to ignore this (the default will return None) which will skip pretty
- // printing. If you do want to pretty print, it is recommended to use the
- // implementation of this method from RustcDefaultCalls.
- // FIXME, this is a terrible bit of API. Parsing of pretty printing stuff
- // should be done as part of the framework and the implementor should customise
- // handling of it. However, that is not possible atm because pretty printing
- // essentially goes off and takes another path through the compiler which
- // means the session is either moved or not depending on what parse_pretty
- // returns (we could fix this by cloning, but it's another hack). The proper
- // solution is to handle pretty printing as if it were a compiler extension,
- // extending CompileController to make this work (see for example the treatment
- // of save-analysis in RustcDefaultCalls::build_controller).
- fn parse_pretty(&mut self,
- _sess: &Session,
- _matches: &getopts::Matches)
- -> Option<(PpMode, Option<UserIdentifiedItem>)> {
- None
- }
-
// Create a CompilController struct for controlling the behaviour of
// compilation.
- fn build_controller(&mut self, &Session) -> CompileController<'a>;
+ fn build_controller(&mut self, &Session, &getopts::Matches) -> CompileController<'a>;
}
// CompilerCalls instance for a regular rustc build.
None
}
- fn parse_pretty(&mut self,
- sess: &Session,
- matches: &getopts::Matches)
- -> Option<(PpMode, Option<UserIdentifiedItem>)> {
- let pretty = if sess.opts.debugging_opts.unstable_options {
- matches.opt_default("pretty", "normal").map(|a| {
- // stable pretty-print variants only
- pretty::parse_pretty(sess, &a, false)
- })
- } else {
- None
- };
- if pretty.is_none() && sess.unstable_options() {
- matches.opt_str("unpretty").map(|a| {
- // extended with unstable pretty-print variants
- pretty::parse_pretty(sess, &a, true)
- })
- } else {
- pretty
- }
- }
-
fn late_callback(&mut self,
matches: &getopts::Matches,
sess: &Session,
.and_then(|| RustcDefaultCalls::list_metadata(sess, matches, input))
}
- fn build_controller(&mut self, sess: &Session) -> CompileController<'a> {
+ fn build_controller(&mut self, sess: &Session, matches: &getopts::Matches) -> CompileController<'a> {
let mut control = CompileController::basic();
+ if let Some((ppm, opt_uii)) = parse_pretty(&sess, &matches) {
+ control.after_parse.stop = Compilation::Stop;
+ control.after_parse.callback = box move |state| {
+ pretty::pretty_print_input(state.session,
+ state.cstore.unwrap(),
+ state.input,
+ state.krate.take().unwrap(),
+ ppm,
+ opt_uii.clone(),
+ state.out_file);
+ };
+ }
+
if sess.opts.parse_only || sess.opts.debugging_opts.show_span.is_some() ||
sess.opts.debugging_opts.ast_json_noexpand {
control.after_parse.stop = Compilation::Stop;
control.after_analysis.callback = box |state| {
time(state.session.time_passes(), "save analysis", || {
save::process_crate(state.tcx.unwrap(),
- state.krate.unwrap(),
+ state.expanded_crate.unwrap(),
state.analysis.unwrap(),
state.crate_name.unwrap(),
state.out_dir,