diff --git a/src/librustc_trans/save/dump_csv.rs b/src/librustc_trans/save/dump_csv.rs index d3493251e2f42..798c35874eeb1 100644 --- a/src/librustc_trans/save/dump_csv.rs +++ b/src/librustc_trans/save/dump_csv.rs @@ -27,7 +27,8 @@ //! the format of the output away from extracting it from the compiler. //! DumpCsvVisitor walks the AST and processes it. -use super::{escape, generated_code, recorder, SaveContext}; + +use super::{escape, generated_code, recorder, SaveContext, PathCollector}; use session::Session; @@ -59,9 +60,6 @@ pub struct DumpCsvVisitor<'l, 'tcx: 'l> { sess: &'l Session, analysis: &'l ty::CrateAnalysis<'tcx>, - collected_paths: Vec<(NodeId, ast::Path, bool, recorder::Row)>, - collecting: bool, - span: SpanUtils<'l>, fmt: FmtStrs<'l>, @@ -79,8 +77,6 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> { err_count: Cell::new(0) }), analysis: analysis, - collected_paths: vec![], - collecting: false, span: SpanUtils { sess: sess, err_count: Cell::new(0) @@ -281,12 +277,11 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> { fn process_formals(&mut self, formals: &Vec, qualname: &str) { for arg in formals { - assert!(self.collected_paths.is_empty() && !self.collecting); - self.collecting = true; - self.visit_pat(&*arg.pat); - self.collecting = false; + self.visit_pat(&arg.pat); + let mut collector = PathCollector::new(); + collector.visit_pat(&arg.pat); let span_utils = self.span.clone(); - for &(id, ref p, _, _) in &self.collected_paths { + for &(id, ref p, _, _) in &collector.collected_paths { let typ = ppaux::ty_to_string( &self.analysis.ty_cx, @@ -300,7 +295,6 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> { &path_to_string(p), &typ[..]); } - self.collected_paths.clear(); } } @@ -1026,7 +1020,6 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> { match p.node { ast::PatStruct(ref path, ref fields, _) => { - self.collected_paths.push((p.id, path.clone(), false, recorder::StructRef)); visit::walk_path(self, path); let def = self.analysis.ty_cx.def_map.borrow().get(&p.id).unwrap().full_def(); @@ -1063,32 +1056,6 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> { } } } - ast::PatEnum(ref path, _) | - ast::PatQPath(_, ref path) => { - self.collected_paths.push((p.id, path.clone(), false, recorder::VarRef)); - visit::walk_pat(self, p); - } - ast::PatIdent(bm, ref path1, ref optional_subpattern) => { - let immut = match bm { - // Even if the ref is mut, you can't change the ref, only - // the data pointed at, so showing the initialising expression - // is still worthwhile. - ast::BindByRef(_) => true, - ast::BindByValue(mt) => { - match mt { - ast::MutMutable => false, - ast::MutImmutable => true, - } - } - }; - // collect path for either visit_local or visit_arm - let path = ast_util::ident_to_path(path1.span,path1.node); - self.collected_paths.push((p.id, path, immut, recorder::VarRef)); - match *optional_subpattern { - None => {} - Some(ref subpattern) => self.visit_pat(&**subpattern) - } - } _ => visit::walk_pat(self, p) } } @@ -1421,23 +1388,20 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> { fn visit_pat(&mut self, p: &ast::Pat) { self.process_pat(p); - if !self.collecting { - self.collected_paths.clear(); - } } fn visit_arm(&mut self, arm: &ast::Arm) { - assert!(self.collected_paths.is_empty() && !self.collecting); - self.collecting = true; + let mut collector = PathCollector::new(); for pattern in &arm.pats { // collect paths from the arm's patterns - self.visit_pat(&**pattern); + collector.visit_pat(&pattern); + self.visit_pat(&pattern); } // This is to get around borrow checking, because we need mut self to call process_path. let mut paths_to_process = vec![]; // process collected paths - for &(id, ref p, ref immut, ref_kind) in &self.collected_paths { + for &(id, ref p, ref immut, ref_kind) in &collector.collected_paths { let def_map = self.analysis.ty_cx.def_map.borrow(); if !def_map.contains_key(&id) { self.sess.span_bug(p.span, @@ -1475,8 +1439,6 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> { for &(id, ref path, ref_kind) in &paths_to_process { self.process_path(id, path.span, path, ref_kind); } - self.collecting = false; - self.collected_paths.clear(); visit::walk_expr_opt(self, &arm.guard); self.visit_expr(&*arm.body); } @@ -1496,14 +1458,13 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> { // The local could declare multiple new vars, we must walk the // pattern and collect them all. - assert!(self.collected_paths.is_empty() && !self.collecting); - self.collecting = true; - self.visit_pat(&*l.pat); - self.collecting = false; + let mut collector = PathCollector::new(); + collector.visit_pat(&l.pat); + self.visit_pat(&l.pat); let value = self.span.snippet(l.span); - for &(id, ref p, ref immut, _) in &self.collected_paths { + for &(id, ref p, ref immut, _) in &collector.collected_paths { let value = if *immut { value.to_string() } else { "".to_string() }; let types = self.analysis.ty_cx.node_types(); let typ = ppaux::ty_to_string(&self.analysis.ty_cx, *types.get(&id).unwrap()); @@ -1518,7 +1479,6 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> { &value[..], &typ[..]); } - self.collected_paths.clear(); // Just walk the initialiser and type (don't want to walk the pattern again). visit::walk_ty_opt(self, &l.ty); diff --git a/src/librustc_trans/save/mod.rs b/src/librustc_trans/save/mod.rs index 98672a546cb11..dc1c36bd00111 100644 --- a/src/librustc_trans/save/mod.rs +++ b/src/librustc_trans/save/mod.rs @@ -15,10 +15,12 @@ use std::env; use std::fs::{self, File}; use std::path::{Path, PathBuf}; -use syntax::{attr, visit}; +use syntax::{attr}; use syntax::ast::{self, NodeId, DefId}; -use syntax::parse::token::keywords; +use syntax::ast_util; use syntax::codemap::*; +use syntax::parse::token::keywords; +use syntax::visit::{self, Visitor}; use self::span_utils::SpanUtils; @@ -94,10 +96,60 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { } pub fn get_data_for_id(&self, id: &NodeId) -> Data { + // TODO unimplemented!(); } } +// An AST visitor for collecting paths from patterns. +struct PathCollector { + // TODO bool -> ast::mutable + // TODO recorder -> var kind new enum + // The Row field identifies the kind of formal variable. + collected_paths: Vec<(NodeId, ast::Path, bool, recorder::Row)>, +} + +impl PathCollector { + fn new() -> PathCollector { + PathCollector { + collected_paths: vec![], + } + } +} + +impl<'v> Visitor<'v> for PathCollector { + fn visit_pat(&mut self, p: &ast::Pat) { + match p.node { + ast::PatStruct(ref path, _, _) => { + self.collected_paths.push((p.id, path.clone(), false, recorder::StructRef)); + } + ast::PatEnum(ref path, _) | + ast::PatQPath(_, ref path) => { + self.collected_paths.push((p.id, path.clone(), false, recorder::VarRef)); + } + ast::PatIdent(bm, ref path1, _) => { + let immut = match bm { + // Even if the ref is mut, you can't change the ref, only + // the data pointed at, so showing the initialising expression + // is still worthwhile. + ast::BindByRef(_) => true, + ast::BindByValue(mt) => { + match mt { + ast::MutMutable => false, + ast::MutImmutable => true, + } + } + }; + // collect path for either visit_local or visit_arm + let path = ast_util::ident_to_path(path1.span,path1.node); + self.collected_paths.push((p.id, path, immut, recorder::VarRef)); + } + _ => {} + } + visit::walk_pat(self, p); + } +} + #[allow(deprecated)] pub fn process_crate(sess: &Session, krate: &ast::Crate,