]> git.lizzy.rs Git - rust.git/commitdiff
Extract PathCollector
authorNick Cameron <ncameron@mozilla.com>
Tue, 5 May 2015 10:03:20 +0000 (22:03 +1200)
committerNick Cameron <ncameron@mozilla.com>
Thu, 14 May 2015 03:28:17 +0000 (15:28 +1200)
src/librustc_trans/save/dump_csv.rs
src/librustc_trans/save/mod.rs

index d3493251e2f42c3d33deb8c68e120def99fc83c4..798c35874eeb1b76cd9d9b4248fd76d5e72f19d2 100644 (file)
@@ -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 @@ pub fn new(sess: &'l Session,
                 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 @@ fn lookup_def_kind(&self, ref_id: NodeId, span: Span) -> Option<recorder::Row> {
 
     fn process_formals(&mut self, formals: &Vec<ast::Arg>, 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 @@ fn process_formals(&mut self, formals: &Vec<ast::Arg>, qualname: &str) {
                                     &path_to_string(p),
                                     &typ[..]);
             }
-            self.collected_paths.clear();
         }
     }
 
@@ -1026,7 +1020,6 @@ fn process_pat(&mut self, p:&ast::Pat) {
 
         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 @@ fn process_pat(&mut self, p:&ast::Pat) {
                     }
                 }
             }
-            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 @@ fn visit_mac(&mut self, _: &ast::Mac) {
 
     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 @@ fn visit_arm(&mut self, arm: &ast::Arm) {
         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 @@ fn visit_local(&mut self, l: &ast::Local) {
 
         // 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 { "<mutable>".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 @@ fn visit_local(&mut self, l: &ast::Local) {
                                   &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);
index 98672a546cb117eab34426c75026e3cf31616bdf..dc1c36bd0011188f5f10e0e016ccb981526f6a0b 100644 (file)
 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 @@ pub fn get_item_data(&self, item: &ast::Item) -> Data {
     }
 
     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,