Skip to content

Commit

Permalink
save-analysis: start factoring out an API
Browse files Browse the repository at this point in the history
  • Loading branch information
nrc committed May 14, 2015
1 parent c8ddb0f commit 83c6a12
Show file tree
Hide file tree
Showing 3 changed files with 129 additions and 69 deletions.
99 changes: 49 additions & 50 deletions src/librustc_trans/save/dump_csv.rs
Expand Up @@ -89,7 +89,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
sess: sess,
err_count: Cell::new(0)
}),
cur_scope: 0
cur_scope: 0
}
}

Expand All @@ -108,7 +108,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {

// Dump info about all the external crates referenced from this crate.
for c in &self.save_ctxt.get_external_crates() {
self.fmt.external_crate_str(krate.span, &c.name, c.number);
self.fmt.external_crate_str(krate.span, &c.name, c.number);
}
self.fmt.recorder.record("end_external_crates\n");
}
Expand Down Expand Up @@ -496,58 +496,52 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
decl: &ast::FnDecl,
ty_params: &ast::Generics,
body: &ast::Block) {
let qualname = format!("::{}", self.analysis.ty_cx.map.path_to_string(item.id));
let fn_data = self.save_ctxt.get_item_data(item);
if let super::Data::FunctionData(fn_data) = fn_data {
self.fmt.fn_str(item.span,
Some(fn_data.span),
fn_data.id,
&fn_data.qualname,
fn_data.scope);

let sub_span = self.span.sub_span_after_keyword(item.span, keywords::Fn);
self.fmt.fn_str(item.span,
sub_span,
item.id,
&qualname[..],
self.cur_scope);

self.process_formals(&decl.inputs, &qualname[..]);
self.process_formals(&decl.inputs, &fn_data.qualname);
self.process_generic_params(ty_params, item.span, &fn_data.qualname, item.id);
} else {
unreachable!();
}

// walk arg and return types
for arg in &decl.inputs {
self.visit_ty(&*arg.ty);
self.visit_ty(&arg.ty);
}

if let ast::Return(ref ret_ty) = decl.output {
self.visit_ty(&**ret_ty);
self.visit_ty(&ret_ty);
}

// walk the body
self.nest(item.id, |v| v.visit_block(&*body));

self.process_generic_params(ty_params, item.span, &qualname[..], item.id);
self.nest(item.id, |v| v.visit_block(&body));
}

fn process_static(&mut self,
item: &ast::Item,
typ: &ast::Ty,
mt: ast::Mutability,
expr: &ast::Expr)
fn process_static_or_const_item(&mut self,
item: &ast::Item,
typ: &ast::Ty,
expr: &ast::Expr)
{
let qualname = format!("::{}", self.analysis.ty_cx.map.path_to_string(item.id));

// If the variable is immutable, save the initialising expression.
let (value, keyword) = match mt {
ast::MutMutable => (String::from_str("<mutable>"), keywords::Mut),
ast::MutImmutable => (self.span.snippet(expr.span), keywords::Static),
};

let sub_span = self.span.sub_span_after_keyword(item.span, keyword);
self.fmt.static_str(item.span,
sub_span,
item.id,
&get_ident(item.ident),
&qualname[..],
&value[..],
&ty_to_string(&*typ),
self.cur_scope);
let var_data = self.save_ctxt.get_item_data(item);
if let super::Data::VariableData(var_data) = var_data {
self.fmt.static_str(item.span,
Some(var_data.span),
var_data.id,
&var_data.name,
&var_data.qualname,
&var_data.value,
&var_data.type_value,
var_data.scope);
} else {
unreachable!();
}

// walk type and init value
self.visit_ty(&*typ);
self.visit_ty(&typ);
self.visit_expr(expr);
}

Expand All @@ -562,12 +556,13 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {

let sub_span = self.span.sub_span_after_keyword(span,
keywords::Const);

self.fmt.static_str(span,
sub_span,
id,
&get_ident((*ident).clone()),
&qualname[..],
"",
&self.span.snippet(expr.span),
&ty_to_string(&*typ),
self.cur_scope);

Expand Down Expand Up @@ -1174,10 +1169,10 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> {
}
ast::ItemFn(ref decl, _, _, ref ty_params, ref body) =>
self.process_fn(item, &**decl, ty_params, &**body),
ast::ItemStatic(ref typ, mt, ref expr) =>
self.process_static(item, &**typ, mt, &**expr),
ast::ItemStatic(ref typ, _, ref expr) =>
self.process_static_or_const_item(item, typ, expr),
ast::ItemConst(ref typ, ref expr) =>
self.process_const(item.id, &item.ident, item.span, &*typ, &*expr),
self.process_static_or_const_item(item, &typ, &expr),
ast::ItemStruct(ref def, ref ty_params) => self.process_struct(item, &**def, ty_params),
ast::ItemEnum(ref def, ref ty_params) => self.process_enum(item, def, ty_params),
ast::ItemImpl(_, _,
Expand Down Expand Up @@ -1378,7 +1373,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> {
},
_ => {
visit::walk_expr(self, ex)
},
}
}
}

Expand All @@ -1401,7 +1396,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> {
// 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 &collector.collected_paths {
for &(id, ref p, 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 All @@ -1411,7 +1406,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> {
let def = def_map.get(&id).unwrap().full_def();
match def {
def::DefLocal(id) => {
let value = if *immut {
let value = if immut == ast::MutImmutable {
self.span.snippet(p.span).to_string()
} else {
"<mutable>".to_string()
Expand Down Expand Up @@ -1464,8 +1459,12 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> {

let value = self.span.snippet(l.span);

for &(id, ref p, ref immut, _) in &collector.collected_paths {
let value = if *immut { value.to_string() } else { "<mutable>".to_string() };
for &(id, ref p, immut, _) in &collector.collected_paths {
let value = if immut == ast::MutImmutable {
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());
// Get the span only for the name of the variable (I hope the path
Expand Down
96 changes: 77 additions & 19 deletions src/librustc_trans/save/mod.rs
Expand Up @@ -19,8 +19,10 @@ use syntax::{attr};
use syntax::ast::{self, NodeId, DefId};
use syntax::ast_util;
use syntax::codemap::*;
use syntax::parse::token::keywords;
use syntax::parse::token::{self, get_ident, keywords};
use syntax::visit::{self, Visitor};
use syntax::print::pprust::ty_to_string;


use self::span_utils::SpanUtils;

Expand All @@ -40,18 +42,32 @@ pub struct CrateData {
pub number: u32,
}

// Data for any entity in the Rust language. The actual data contained varied
// with the kind of entity being queried. See the nested structs for details.
pub enum Data {
FunctionData(FunctionData),
VariableData(VariableData),
}

pub struct FunctionData {
pub id: NodeId,
pub name: String,
pub qualname: String,
pub declaration: Option<DefId>,
pub span: Span,
pub scope: NodeId,
}

pub struct VariableData {
pub id: NodeId,
pub name: String,
pub qualname: String,
pub span: Span,
pub scope: NodeId,
pub value: String,
pub type_value: String,
}

impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
pub fn new(sess: &'l Session,
analysis: &'l ty::CrateAnalysis<'tcx>,
Expand All @@ -78,35 +94,71 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
pub fn get_item_data(&self, item: &ast::Item) -> Data {
match item.node {
ast::Item_::ItemFn(..) => {
let qualname = format!("::{}", self.analysis.ty_cx.map.path_to_string(item.id));
let name = self.analysis.ty_cx.map.path_to_string(item.id);
let qualname = format!("::{}", name);
let sub_span = self.span_utils.sub_span_after_keyword(item.span, keywords::Fn);

Data::FunctionData(FunctionData {
id: item.id,
name: name,
qualname: qualname,
declaration: None,
span: sub_span.unwrap(),
scope: self.analysis.ty_cx.map.get_parent(item.id),
})
}
ast::ItemStatic(ref typ, mt, ref expr) => {
let qualname = format!("::{}", self.analysis.ty_cx.map.path_to_string(item.id));

// If the variable is immutable, save the initialising expression.
let value = match mt {
ast::MutMutable => String::from_str("<mutable>"),
ast::MutImmutable => self.span_utils.snippet(expr.span),
};

let sub_span = self.span_utils.sub_span_after_keyword(item.span, keywords::Static);

Data::VariableData(VariableData {
id: item.id,
name: get_ident(item.ident).to_string(),
qualname: qualname,
span: sub_span.unwrap(),
scope: self.analysis.ty_cx.map.get_parent(item.id),
value: value,
type_value: ty_to_string(&typ),
})
}
ast::ItemConst(ref typ, ref expr) => {
let qualname = format!("::{}", self.analysis.ty_cx.map.path_to_string(item.id));
let sub_span = self.span_utils.sub_span_after_keyword(item.span, keywords::Const);

Data::VariableData(VariableData {
id: item.id,
name: get_ident(item.ident).to_string(),
qualname: qualname,
span: sub_span.unwrap(),
scope: self.analysis.ty_cx.map.get_parent(item.id),
value: self.span_utils.snippet(expr.span),
type_value: ty_to_string(&typ),
})
}
_ => {
// FIXME
unimplemented!();
}
}
}

pub fn get_data_for_id(&self, id: &NodeId) -> Data {
// TODO
unimplemented!();
pub fn get_data_for_id(&self, _id: &NodeId) -> Data {
// FIXME
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)>,
// The Row field identifies the kind of pattern.
collected_paths: Vec<(NodeId, ast::Path, ast::Mutability, recorder::Row)>,
}

impl PathCollector {
Expand All @@ -119,29 +171,35 @@ impl PathCollector {

impl<'v> Visitor<'v> for PathCollector {
fn visit_pat(&mut self, p: &ast::Pat) {
if generated_code(p.span) {
return;
}

match p.node {
ast::PatStruct(ref path, _, _) => {
self.collected_paths.push((p.id, path.clone(), false, recorder::StructRef));
self.collected_paths.push((p.id,
path.clone(),
ast::MutMutable,
recorder::StructRef));
}
ast::PatEnum(ref path, _) |
ast::PatQPath(_, ref path) => {
self.collected_paths.push((p.id, path.clone(), false, recorder::VarRef));
self.collected_paths.push((p.id, path.clone(), ast::MutMutable, recorder::VarRef));
}
ast::PatIdent(bm, ref path1, _) => {
debug!("PathCollector, visit ident in pat {}: {:?} {:?}",
token::get_ident(path1.node),
p.span,
path1.span);
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,
}
}
ast::BindByRef(_) => ast::MutImmutable,
ast::BindByValue(mt) => mt,
};
// collect path for either visit_local or visit_arm
let path = ast_util::ident_to_path(path1.span,path1.node);
let path = ast_util::ident_to_path(path1.span, path1.node);
self.collected_paths.push((p.id, path, immut, recorder::VarRef));
}
_ => {}
Expand Down
3 changes: 3 additions & 0 deletions src/librustc_trans/save/recorder.rs
Expand Up @@ -62,6 +62,9 @@ macro_rules! svec {
})
}

// FIXME recorder should operate on super::Data, rather than lots of ad hoc
// data.

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum Row {
Variable,
Expand Down

0 comments on commit 83c6a12

Please sign in to comment.