Navigation Menu

Skip to content

Commit

Permalink
Extract PathCollector
Browse files Browse the repository at this point in the history
  • Loading branch information
nrc committed May 14, 2015
1 parent cea73bf commit c8ddb0f
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 56 deletions.
68 changes: 14 additions & 54 deletions src/librustc_trans/save/dump_csv.rs
Expand Up @@ -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;

Expand Down Expand Up @@ -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>,

Expand All @@ -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)
Expand Down Expand Up @@ -281,12 +277,11 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {

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,
Expand All @@ -300,7 +295,6 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
&path_to_string(p),
&typ[..]);
}
self.collected_paths.clear();
}
}

Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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)
}
}
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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);
}
Expand All @@ -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 { "<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());
Expand All @@ -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);
Expand Down
56 changes: 54 additions & 2 deletions src/librustc_trans/save/mod.rs
Expand Up @@ -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;

Expand Down Expand Up @@ -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,
Expand Down

0 comments on commit c8ddb0f

Please sign in to comment.