2013-09-09 20:57:50 -05:00
|
|
|
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
|
2012-12-03 18:48:01 -06:00
|
|
|
// file at the top-level directory of this distribution and at
|
|
|
|
// http://rust-lang.org/COPYRIGHT.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
|
|
// option. This file may not be copied, modified, or distributed
|
|
|
|
// except according to those terms.
|
|
|
|
|
2013-03-13 21:25:28 -05:00
|
|
|
use abi::AbiSet;
|
2012-09-04 13:37:29 -05:00
|
|
|
use ast::*;
|
2012-12-23 16:41:37 -06:00
|
|
|
use ast;
|
|
|
|
use ast_util;
|
2013-08-31 11:13:04 -05:00
|
|
|
use codemap::Span;
|
2013-12-31 08:17:59 -06:00
|
|
|
use diagnostic::SpanHandler;
|
2014-01-09 07:05:33 -06:00
|
|
|
use fold::Folder;
|
2014-01-06 06:00:46 -06:00
|
|
|
use fold;
|
2014-01-09 07:05:33 -06:00
|
|
|
use parse::token::{get_ident_interner, IdentInterner};
|
2013-07-19 20:42:11 -05:00
|
|
|
use parse::token::special_idents;
|
2012-12-23 16:41:37 -06:00
|
|
|
use print::pprust;
|
2014-01-06 06:00:46 -06:00
|
|
|
use util::small_vector::SmallVector;
|
2012-12-23 16:41:37 -06:00
|
|
|
|
2014-01-17 06:23:09 -06:00
|
|
|
use std::logging;
|
2013-12-27 18:09:29 -06:00
|
|
|
use std::cell::RefCell;
|
2014-01-17 06:23:09 -06:00
|
|
|
use extra::smallintmap::SmallIntMap;
|
2011-06-19 15:41:21 -05:00
|
|
|
|
2013-07-02 14:47:32 -05:00
|
|
|
#[deriving(Clone, Eq)]
|
2014-01-09 07:05:33 -06:00
|
|
|
pub enum PathElem {
|
|
|
|
PathMod(Ident),
|
|
|
|
PathName(Ident),
|
2013-08-30 02:47:10 -05:00
|
|
|
|
|
|
|
// A pretty name can come from an `impl` block. We attempt to select a
|
|
|
|
// reasonable name for debuggers to see, but to guarantee uniqueness with
|
|
|
|
// other paths the hash should also be taken into account during symbol
|
|
|
|
// generation.
|
2014-01-09 07:05:33 -06:00
|
|
|
PathPrettyName(Ident, u64),
|
2012-08-27 18:26:35 -05:00
|
|
|
}
|
|
|
|
|
2014-01-09 07:05:33 -06:00
|
|
|
impl PathElem {
|
2013-09-11 04:08:44 -05:00
|
|
|
pub fn ident(&self) -> Ident {
|
|
|
|
match *self {
|
2014-01-09 07:05:33 -06:00
|
|
|
PathMod(ident) |
|
|
|
|
PathName(ident) |
|
|
|
|
PathPrettyName(ident, _) => ident
|
2013-09-11 04:08:44 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-09 07:05:33 -06:00
|
|
|
pub type Path = ~[PathElem];
|
2012-02-03 02:53:37 -06:00
|
|
|
|
2014-01-09 07:05:33 -06:00
|
|
|
pub fn path_to_str_with_sep(p: &[PathElem], sep: &str, itr: @IdentInterner)
|
|
|
|
-> ~str {
|
2013-11-20 18:23:04 -06:00
|
|
|
let strs = p.map(|e| {
|
2012-09-21 20:43:30 -05:00
|
|
|
match *e {
|
2014-01-09 07:05:33 -06:00
|
|
|
PathMod(s) | PathName(s) | PathPrettyName(s, _) => {
|
2013-08-30 02:47:10 -05:00
|
|
|
itr.get(s.name)
|
|
|
|
}
|
2012-02-10 08:01:32 -06:00
|
|
|
}
|
2013-11-20 18:23:04 -06:00
|
|
|
});
|
2013-06-10 08:25:25 -05:00
|
|
|
strs.connect(sep)
|
2012-02-10 08:01:32 -06:00
|
|
|
}
|
|
|
|
|
2014-01-09 07:05:33 -06:00
|
|
|
pub fn path_ident_to_str(p: &Path, i: Ident, itr: @IdentInterner) -> ~str {
|
2013-06-08 20:38:47 -05:00
|
|
|
if p.is_empty() {
|
2013-06-12 12:02:55 -05:00
|
|
|
itr.get(i.name).to_owned()
|
2012-03-28 14:54:06 -05:00
|
|
|
} else {
|
2013-09-27 23:01:58 -05:00
|
|
|
format!("{}::{}", path_to_str(*p, itr), itr.get(i.name))
|
2012-03-28 14:54:06 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-09 07:05:33 -06:00
|
|
|
pub fn path_to_str(p: &[PathElem], itr: @IdentInterner) -> ~str {
|
2013-06-05 06:57:24 -05:00
|
|
|
path_to_str_with_sep(p, "::", itr)
|
2012-02-10 08:01:32 -06:00
|
|
|
}
|
|
|
|
|
2014-01-09 07:05:33 -06:00
|
|
|
pub fn path_elem_to_str(pe: PathElem, itr: @IdentInterner) -> ~str {
|
2013-01-10 01:17:57 -06:00
|
|
|
match pe {
|
2014-01-09 07:05:33 -06:00
|
|
|
PathMod(s) | PathName(s) | PathPrettyName(s, _) => {
|
2013-08-30 02:47:10 -05:00
|
|
|
itr.get(s.name).to_owned()
|
|
|
|
}
|
2013-01-10 01:17:57 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-31 23:30:21 -06:00
|
|
|
/// write a "pretty" version of `ty` to `out`. This is designed so
|
|
|
|
/// that symbols of `impl`'d methods give some hint of where they came
|
|
|
|
/// from, even if it's hard to read (previously they would all just be
|
|
|
|
/// listed as `__extensions__::method_name::hash`, with no indication
|
|
|
|
/// of the type).
|
|
|
|
// XXX: these dollar signs and the names in general are actually a
|
|
|
|
// relic of $ being one of the very few valid symbol names on
|
|
|
|
// unix. These kinds of details shouldn't be exposed way up here
|
|
|
|
// in the ast.
|
2014-01-09 07:05:33 -06:00
|
|
|
fn pretty_ty(ty: &Ty, itr: @IdentInterner, out: &mut ~str) {
|
2013-12-31 23:30:21 -06:00
|
|
|
let (prefix, subty) = match ty.node {
|
2014-01-09 07:05:33 -06:00
|
|
|
TyUniq(ty) => ("$UP$", &*ty),
|
|
|
|
TyBox(ty) => ("$SP$", &*ty),
|
|
|
|
TyPtr(MutTy { ty, mutbl }) => (if mutbl == MutMutable {"$RPmut$"} else {"$RP$"},
|
|
|
|
&*ty),
|
|
|
|
TyRptr(_, MutTy { ty, mutbl }) => (if mutbl == MutMutable {"$BPmut$"} else {"$BP$"},
|
|
|
|
&*ty),
|
2013-12-31 23:30:21 -06:00
|
|
|
|
2014-01-09 07:05:33 -06:00
|
|
|
TyVec(ty) => ("$VEC$", &*ty),
|
|
|
|
TyFixedLengthVec(ty, _) => ("$FIXEDVEC$", &*ty),
|
2013-12-31 23:30:21 -06:00
|
|
|
|
|
|
|
// these can't be represented as <prefix><contained ty>, so
|
|
|
|
// need custom handling.
|
2014-01-09 07:05:33 -06:00
|
|
|
TyNil => { out.push_str("$NIL$"); return }
|
|
|
|
TyPath(ref path, _, _) => {
|
|
|
|
out.push_str(itr.get(path.segments.last().identifier.name));
|
|
|
|
return
|
|
|
|
}
|
|
|
|
TyTup(ref tys) => {
|
2013-12-31 23:30:21 -06:00
|
|
|
out.push_str(format!("$TUP_{}$", tys.len()));
|
|
|
|
for subty in tys.iter() {
|
|
|
|
pretty_ty(*subty, itr, out);
|
|
|
|
out.push_char('$');
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// meh, better than nothing.
|
2014-01-09 07:05:33 -06:00
|
|
|
TyBot => { out.push_str("$BOT$"); return }
|
|
|
|
TyClosure(..) => { out.push_str("$CLOSURE$"); return }
|
|
|
|
TyBareFn(..) => { out.push_str("$FN$"); return }
|
|
|
|
TyTypeof(..) => { out.push_str("$TYPEOF$"); return }
|
|
|
|
TyInfer(..) => { out.push_str("$INFER$"); return }
|
2013-12-31 23:30:21 -06:00
|
|
|
|
2013-09-07 01:56:17 -05:00
|
|
|
};
|
2013-12-31 23:30:21 -06:00
|
|
|
|
|
|
|
out.push_str(prefix);
|
|
|
|
pretty_ty(subty, itr, out);
|
|
|
|
}
|
|
|
|
|
2014-01-09 07:05:33 -06:00
|
|
|
pub fn impl_pretty_name(trait_ref: &Option<TraitRef>, ty: &Ty) -> PathElem {
|
2013-12-31 23:30:21 -06:00
|
|
|
let itr = get_ident_interner();
|
|
|
|
|
2013-09-07 01:56:17 -05:00
|
|
|
let hash = (trait_ref, ty).hash();
|
2013-12-31 23:30:21 -06:00
|
|
|
let mut pretty;
|
2013-09-07 01:56:17 -05:00
|
|
|
match *trait_ref {
|
2013-12-31 23:30:21 -06:00
|
|
|
None => pretty = ~"",
|
2013-09-07 01:56:17 -05:00
|
|
|
Some(ref trait_ref) => {
|
2013-12-31 23:30:21 -06:00
|
|
|
pretty = itr.get(trait_ref.path.segments.last().identifier.name).to_owned();
|
|
|
|
pretty.push_char('$');
|
2013-09-07 01:56:17 -05:00
|
|
|
}
|
2013-12-31 23:30:21 -06:00
|
|
|
};
|
|
|
|
pretty_ty(ty, itr, &mut pretty);
|
|
|
|
|
2014-01-09 07:05:33 -06:00
|
|
|
PathPrettyName(Ident::new(itr.gensym(pretty)), hash)
|
2013-09-07 01:56:17 -05:00
|
|
|
}
|
|
|
|
|
2013-07-02 14:47:32 -05:00
|
|
|
#[deriving(Clone)]
|
2014-01-09 07:05:33 -06:00
|
|
|
pub enum Node {
|
|
|
|
NodeItem(@Item, @Path),
|
|
|
|
NodeForeignItem(@ForeignItem, AbiSet, Visibility, @Path),
|
|
|
|
NodeTraitMethod(@TraitMethod, DefId /* trait did */,
|
|
|
|
@Path /* path to the trait */),
|
|
|
|
NodeMethod(@Method, DefId /* impl did */, @Path /* path to the impl */),
|
|
|
|
|
|
|
|
/// NodeVariant represents a variant of an enum, e.g., for
|
|
|
|
/// `enum A { B, C, D }`, there would be a NodeItem for `A`, and a
|
|
|
|
/// NodeVariant item for each of `B`, `C`, and `D`.
|
|
|
|
NodeVariant(P<Variant>, @Item, @Path),
|
|
|
|
NodeExpr(@Expr),
|
|
|
|
NodeStmt(@Stmt),
|
|
|
|
NodeArg(@Pat),
|
2014-01-06 06:00:46 -06:00
|
|
|
// HACK(eddyb) should always be a pattern, but `self` is not, and thus it
|
|
|
|
// is identified only by an ident and no span is available. In all other
|
|
|
|
// cases, node_span will return the proper span (required by borrowck).
|
2014-01-09 07:05:33 -06:00
|
|
|
NodeLocal(Ident, Option<@Pat>),
|
|
|
|
NodeBlock(P<Block>),
|
2013-11-24 17:38:41 -06:00
|
|
|
|
2014-01-09 07:05:33 -06:00
|
|
|
/// NodeStructCtor represents a tuple struct.
|
|
|
|
NodeStructCtor(@StructDef, @Item, @Path),
|
|
|
|
NodeCalleeScope(@Expr)
|
2011-06-19 15:41:21 -05:00
|
|
|
}
|
|
|
|
|
2014-01-09 07:05:33 -06:00
|
|
|
impl Node {
|
2013-11-19 14:21:21 -06:00
|
|
|
pub fn with_attrs<T>(&self, f: |Option<&[Attribute]>| -> T) -> T {
|
2013-08-31 02:13:57 -05:00
|
|
|
let attrs = match *self {
|
2014-01-09 07:05:33 -06:00
|
|
|
NodeItem(i, _) => Some(i.attrs.as_slice()),
|
|
|
|
NodeForeignItem(fi, _, _, _) => Some(fi.attrs.as_slice()),
|
|
|
|
NodeTraitMethod(tm, _, _) => match *tm {
|
|
|
|
Required(ref type_m) => Some(type_m.attrs.as_slice()),
|
|
|
|
Provided(m) => Some(m.attrs.as_slice())
|
2013-08-31 02:13:57 -05:00
|
|
|
},
|
2014-01-09 07:05:33 -06:00
|
|
|
NodeMethod(m, _, _) => Some(m.attrs.as_slice()),
|
|
|
|
NodeVariant(ref v, _, _) => Some(v.node.attrs.as_slice()),
|
2013-08-31 02:13:57 -05:00
|
|
|
// unit/tuple structs take the attributes straight from
|
|
|
|
// the struct definition.
|
2014-01-09 07:05:33 -06:00
|
|
|
NodeStructCtor(_, strct, _) => Some(strct.attrs.as_slice()),
|
2013-08-31 02:13:57 -05:00
|
|
|
_ => None
|
|
|
|
};
|
|
|
|
f(attrs)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-17 06:23:09 -06:00
|
|
|
pub struct Map {
|
|
|
|
/// NodeIds are sequential integers from 0, so we can be
|
|
|
|
/// super-compact by storing them in a vector. Not everything with
|
|
|
|
/// a NodeId is in the map, but empirically the occupancy is about
|
|
|
|
/// 75-80%, so there's not too much overhead (certainly less than
|
|
|
|
/// a hashmap, since they (at the time of writing) have a maximum
|
|
|
|
/// of 75% occupancy). (The additional overhead of the Option<>
|
|
|
|
/// inside the SmallIntMap could be removed by adding an extra
|
|
|
|
/// empty variant to Node and storing a vector here, but that was
|
|
|
|
/// found to not make much difference.)
|
|
|
|
///
|
|
|
|
/// Also, indexing is pretty quick when you've got a vector and
|
|
|
|
/// plain old integers.
|
|
|
|
priv map: @RefCell<SmallIntMap<Node>>
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Map {
|
|
|
|
/// Retrieve the Node corresponding to `id`, failing if it cannot
|
|
|
|
/// be found.
|
|
|
|
pub fn get(&self, id: ast::NodeId) -> Node {
|
|
|
|
let map = self.map.borrow();
|
|
|
|
*map.get().get(&(id as uint))
|
|
|
|
}
|
|
|
|
/// Retrieve the Node corresponding to `id`, returning None if
|
|
|
|
/// cannot be found.
|
|
|
|
pub fn find(&self, id: ast::NodeId) -> Option<Node> {
|
|
|
|
let map = self.map.borrow();
|
|
|
|
map.get().find(&(id as uint)).map(|&n| n)
|
|
|
|
}
|
|
|
|
}
|
2013-02-04 16:02:01 -06:00
|
|
|
|
2014-01-06 06:00:46 -06:00
|
|
|
pub trait FoldOps {
|
|
|
|
fn new_id(&self, id: ast::NodeId) -> ast::NodeId {
|
|
|
|
id
|
|
|
|
}
|
|
|
|
fn new_span(&self, span: Span) -> Span {
|
|
|
|
span
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct Ctx<F> {
|
2014-01-09 07:05:33 -06:00
|
|
|
map: Map,
|
|
|
|
path: Path,
|
2013-12-27 15:48:00 -06:00
|
|
|
diag: @SpanHandler,
|
2014-01-06 06:00:46 -06:00
|
|
|
fold_ops: F
|
2013-01-17 10:55:28 -06:00
|
|
|
}
|
2011-06-19 15:41:21 -05:00
|
|
|
|
2014-01-06 06:00:46 -06:00
|
|
|
impl<F> Ctx<F> {
|
2014-01-09 07:05:33 -06:00
|
|
|
fn insert(&self, id: ast::NodeId, node: Node) {
|
2014-01-17 06:23:09 -06:00
|
|
|
let mut map = self.map.map.borrow_mut();
|
|
|
|
map.get().insert(id as uint, node);
|
2013-07-19 20:42:11 -05:00
|
|
|
}
|
|
|
|
|
2014-01-09 07:05:33 -06:00
|
|
|
fn map_self(&self, m: @Method) {
|
|
|
|
self.insert(m.self_id, NodeLocal(special_idents::self_, None));
|
2013-07-19 20:42:11 -05:00
|
|
|
}
|
2014-01-06 06:00:46 -06:00
|
|
|
}
|
2013-07-19 20:42:11 -05:00
|
|
|
|
2014-01-09 07:05:33 -06:00
|
|
|
impl<F: FoldOps> Folder for Ctx<F> {
|
2014-01-06 06:00:46 -06:00
|
|
|
fn new_id(&mut self, id: ast::NodeId) -> ast::NodeId {
|
|
|
|
self.fold_ops.new_id(id)
|
2013-07-19 20:42:11 -05:00
|
|
|
}
|
|
|
|
|
2014-01-06 06:00:46 -06:00
|
|
|
fn new_span(&mut self, span: Span) -> Span {
|
|
|
|
self.fold_ops.new_span(span)
|
2013-07-19 20:42:11 -05:00
|
|
|
}
|
2012-03-06 06:57:07 -06:00
|
|
|
|
2014-01-09 07:05:33 -06:00
|
|
|
fn fold_item(&mut self, i: @Item) -> SmallVector<@Item> {
|
2013-07-19 20:42:11 -05:00
|
|
|
// clone is FIXME #2543
|
2014-01-06 06:00:46 -06:00
|
|
|
let item_path = @self.path.clone();
|
|
|
|
self.path.push(match i.node {
|
2014-01-09 07:05:33 -06:00
|
|
|
ItemImpl(_, ref maybe_trait, ty, _) => {
|
2013-09-03 00:34:37 -05:00
|
|
|
// Right now the ident on impls is __extensions__ which isn't
|
|
|
|
// very pretty when debugging, so attempt to select a better
|
|
|
|
// name to use.
|
2014-01-06 06:00:46 -06:00
|
|
|
impl_pretty_name(maybe_trait, ty)
|
|
|
|
}
|
2014-01-09 07:05:33 -06:00
|
|
|
ItemMod(_) | ItemForeignMod(_) => PathMod(i.ident),
|
|
|
|
_ => PathName(i.ident)
|
2014-01-06 06:00:46 -06:00
|
|
|
});
|
2013-09-03 00:34:37 -05:00
|
|
|
|
2014-01-06 06:00:46 -06:00
|
|
|
let i = fold::noop_fold_item(i, self).expect_one("expected one item");
|
2014-01-09 07:05:33 -06:00
|
|
|
self.insert(i.id, NodeItem(i, item_path));
|
2014-01-06 06:00:46 -06:00
|
|
|
|
|
|
|
match i.node {
|
2014-01-09 07:05:33 -06:00
|
|
|
ItemImpl(_, _, _, ref ms) => {
|
2014-01-06 06:00:46 -06:00
|
|
|
// clone is FIXME #2543
|
|
|
|
let p = @self.path.clone();
|
2013-07-19 20:42:11 -05:00
|
|
|
let impl_did = ast_util::local_def(i.id);
|
2014-01-06 06:00:46 -06:00
|
|
|
for &m in ms.iter() {
|
2014-01-09 07:05:33 -06:00
|
|
|
self.insert(m.id, NodeMethod(m, impl_did, p));
|
2014-01-06 06:00:46 -06:00
|
|
|
self.map_self(m);
|
2013-07-19 20:42:11 -05:00
|
|
|
}
|
2013-08-30 02:47:10 -05:00
|
|
|
|
2013-07-19 20:42:11 -05:00
|
|
|
}
|
2014-01-09 07:05:33 -06:00
|
|
|
ItemEnum(ref enum_definition, _) => {
|
2014-01-06 06:00:46 -06:00
|
|
|
// clone is FIXME #2543
|
|
|
|
let p = @self.path.clone();
|
2013-11-30 16:00:39 -06:00
|
|
|
for &v in enum_definition.variants.iter() {
|
2014-01-09 07:05:33 -06:00
|
|
|
self.insert(v.node.id, NodeVariant(v, i, p));
|
2013-07-19 20:42:11 -05:00
|
|
|
}
|
|
|
|
}
|
2014-01-09 07:05:33 -06:00
|
|
|
ItemForeignMod(ref nm) => {
|
2013-08-03 11:45:23 -05:00
|
|
|
for nitem in nm.items.iter() {
|
2013-07-19 20:42:11 -05:00
|
|
|
// Compute the visibility for this native item.
|
2014-01-09 07:05:33 -06:00
|
|
|
let visibility = nitem.vis.inherit_from(i.vis);
|
2013-07-19 20:42:11 -05:00
|
|
|
|
2014-01-06 06:00:46 -06:00
|
|
|
self.insert(nitem.id,
|
|
|
|
// Anonymous extern mods go in the parent scope.
|
2014-01-09 07:05:33 -06:00
|
|
|
NodeForeignItem(*nitem, nm.abis, visibility, item_path));
|
2013-07-19 20:42:11 -05:00
|
|
|
}
|
|
|
|
}
|
2014-01-09 07:05:33 -06:00
|
|
|
ItemStruct(struct_def, _) => {
|
2014-01-06 06:00:46 -06:00
|
|
|
// If this is a tuple-like struct, register the constructor.
|
|
|
|
match struct_def.ctor_id {
|
|
|
|
None => {}
|
|
|
|
Some(ctor_id) => {
|
|
|
|
// clone is FIXME #2543
|
|
|
|
let p = @self.path.clone();
|
2014-01-09 07:05:33 -06:00
|
|
|
self.insert(ctor_id, NodeStructCtor(struct_def, i, p));
|
2014-01-06 06:00:46 -06:00
|
|
|
}
|
|
|
|
}
|
2013-07-19 20:42:11 -05:00
|
|
|
}
|
2014-01-09 07:05:33 -06:00
|
|
|
ItemTrait(_, ref traits, ref methods) => {
|
2014-01-06 06:00:46 -06:00
|
|
|
for t in traits.iter() {
|
2014-01-09 07:05:33 -06:00
|
|
|
self.insert(t.ref_id, NodeItem(i, item_path));
|
2013-07-19 20:42:11 -05:00
|
|
|
}
|
2014-01-06 06:00:46 -06:00
|
|
|
|
|
|
|
// clone is FIXME #2543
|
|
|
|
let p = @self.path.clone();
|
2013-08-03 11:45:23 -05:00
|
|
|
for tm in methods.iter() {
|
2013-07-19 20:42:11 -05:00
|
|
|
let d_id = ast_util::local_def(i.id);
|
2013-08-20 12:15:36 -05:00
|
|
|
match *tm {
|
2014-01-09 07:05:33 -06:00
|
|
|
Required(ref m) => {
|
|
|
|
self.insert(m.id, NodeTraitMethod(@(*tm).clone(), d_id, p));
|
2013-08-20 12:15:36 -05:00
|
|
|
}
|
2014-01-09 07:05:33 -06:00
|
|
|
Provided(m) => {
|
|
|
|
self.insert(m.id, NodeTraitMethod(@Provided(m), d_id, p));
|
2014-01-06 06:00:46 -06:00
|
|
|
self.map_self(m);
|
2013-08-20 12:15:36 -05:00
|
|
|
}
|
|
|
|
}
|
2013-07-19 20:42:11 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
|
2014-01-06 06:00:46 -06:00
|
|
|
self.path.pop();
|
|
|
|
|
|
|
|
SmallVector::one(i)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn fold_pat(&mut self, pat: @Pat) -> @Pat {
|
|
|
|
let pat = fold::noop_fold_pat(pat, self);
|
|
|
|
match pat.node {
|
|
|
|
PatIdent(_, ref path, _) => {
|
|
|
|
// Note: this is at least *potentially* a pattern...
|
2014-01-09 07:05:33 -06:00
|
|
|
self.insert(pat.id, NodeLocal(ast_util::path_to_ident(path), Some(pat)));
|
2013-12-27 18:14:50 -06:00
|
|
|
}
|
2014-01-06 06:00:46 -06:00
|
|
|
_ => {}
|
2013-07-19 20:42:11 -05:00
|
|
|
}
|
2013-12-27 18:14:50 -06:00
|
|
|
|
2014-01-06 06:00:46 -06:00
|
|
|
pat
|
2013-07-19 20:42:11 -05:00
|
|
|
}
|
|
|
|
|
2014-01-06 06:00:46 -06:00
|
|
|
fn fold_expr(&mut self, expr: @Expr) -> @Expr {
|
|
|
|
let expr = fold::noop_fold_expr(expr, self);
|
|
|
|
|
2014-01-09 07:05:33 -06:00
|
|
|
self.insert(expr.id, NodeExpr(expr));
|
2013-07-19 20:42:11 -05:00
|
|
|
|
2014-01-06 06:00:46 -06:00
|
|
|
// Expressions which are or might be calls:
|
|
|
|
{
|
|
|
|
let r = expr.get_callee_id();
|
|
|
|
for callee_id in r.iter() {
|
2014-01-09 07:05:33 -06:00
|
|
|
self.insert(*callee_id, NodeCalleeScope(expr));
|
2014-01-06 06:00:46 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
expr
|
2013-07-19 20:42:11 -05:00
|
|
|
}
|
|
|
|
|
2014-01-06 06:00:46 -06:00
|
|
|
fn fold_stmt(&mut self, stmt: &Stmt) -> SmallVector<@Stmt> {
|
|
|
|
let stmt = fold::noop_fold_stmt(stmt, self).expect_one("expected one statement");
|
2014-01-09 07:05:33 -06:00
|
|
|
self.insert(ast_util::stmt_id(stmt), NodeStmt(stmt));
|
2014-01-06 06:00:46 -06:00
|
|
|
SmallVector::one(stmt)
|
2013-07-19 20:42:11 -05:00
|
|
|
}
|
|
|
|
|
2014-01-09 07:05:33 -06:00
|
|
|
fn fold_method(&mut self, m: @Method) -> @Method {
|
|
|
|
self.path.push(PathName(m.ident));
|
2014-01-06 06:00:46 -06:00
|
|
|
let m = fold::noop_fold_method(m, self);
|
|
|
|
self.path.pop();
|
|
|
|
m
|
2013-07-19 20:42:11 -05:00
|
|
|
}
|
|
|
|
|
2014-01-09 07:05:33 -06:00
|
|
|
fn fold_fn_decl(&mut self, decl: &FnDecl) -> P<FnDecl> {
|
2014-01-06 06:00:46 -06:00
|
|
|
let decl = fold::noop_fold_fn_decl(decl, self);
|
|
|
|
for a in decl.inputs.iter() {
|
2014-01-09 07:05:33 -06:00
|
|
|
self.insert(a.id, NodeArg(a.pat));
|
2014-01-06 06:00:46 -06:00
|
|
|
}
|
|
|
|
decl
|
2013-07-19 20:42:11 -05:00
|
|
|
}
|
|
|
|
|
2014-01-06 06:00:46 -06:00
|
|
|
fn fold_block(&mut self, block: P<Block>) -> P<Block> {
|
|
|
|
let block = fold::noop_fold_block(block, self);
|
2014-01-09 07:05:33 -06:00
|
|
|
self.insert(block.id, NodeBlock(block));
|
2014-01-06 06:00:46 -06:00
|
|
|
block
|
2013-07-19 20:42:11 -05:00
|
|
|
}
|
2012-02-14 17:21:53 -06:00
|
|
|
}
|
|
|
|
|
2014-01-06 06:00:46 -06:00
|
|
|
pub fn map_crate<F: 'static + FoldOps>(diag: @SpanHandler, c: Crate,
|
2014-01-09 07:05:33 -06:00
|
|
|
fold_ops: F) -> (Crate, Map) {
|
2013-12-27 18:16:46 -06:00
|
|
|
let mut cx = Ctx {
|
2014-01-17 06:23:09 -06:00
|
|
|
map: Map { map: @RefCell::new(SmallIntMap::new()) },
|
2014-01-06 06:00:46 -06:00
|
|
|
path: ~[],
|
2013-01-17 10:55:28 -06:00
|
|
|
diag: diag,
|
2014-01-06 06:00:46 -06:00
|
|
|
fold_ops: fold_ops
|
2013-01-17 10:55:28 -06:00
|
|
|
};
|
2014-01-17 06:23:09 -06:00
|
|
|
let crate = cx.fold_crate(c);
|
|
|
|
|
|
|
|
if log_enabled!(logging::DEBUG) {
|
|
|
|
let map = cx.map.map.borrow();
|
|
|
|
// this only makes sense for ordered stores; note the
|
|
|
|
// enumerate to count the number of entries.
|
|
|
|
let (entries_less_1, (largest_id, _)) =
|
|
|
|
map.get().iter().enumerate().last().expect("AST map was empty after folding?");
|
|
|
|
|
|
|
|
let entries = entries_less_1 + 1;
|
|
|
|
let vector_length = largest_id + 1;
|
|
|
|
debug!("The AST map has {} entries with a maximum of {}: occupancy {:.1}%",
|
|
|
|
entries, vector_length, (entries as f64 / vector_length as f64) * 100.);
|
|
|
|
}
|
|
|
|
|
|
|
|
(crate, cx.map)
|
2011-06-19 15:41:21 -05:00
|
|
|
}
|
|
|
|
|
2012-02-14 17:21:53 -06:00
|
|
|
// Used for items loaded from external crate that are being inlined into this
|
2012-03-02 15:14:10 -06:00
|
|
|
// crate. The `path` should be the path to the item but should not include
|
|
|
|
// the item itself.
|
2014-01-06 06:00:46 -06:00
|
|
|
pub fn map_decoded_item<F: 'static + FoldOps>(diag: @SpanHandler,
|
2014-01-09 07:05:33 -06:00
|
|
|
map: Map,
|
|
|
|
path: Path,
|
2014-01-06 06:00:46 -06:00
|
|
|
fold_ops: F,
|
2014-01-09 07:05:33 -06:00
|
|
|
fold_ii: |&mut Ctx<F>| -> InlinedItem)
|
|
|
|
-> InlinedItem {
|
2012-02-14 17:21:53 -06:00
|
|
|
// I believe it is ok for the local IDs of inlined items from other crates
|
|
|
|
// to overlap with the local ids from this crate, so just generate the ids
|
2013-07-19 20:42:11 -05:00
|
|
|
// starting from 0.
|
2013-12-27 18:16:46 -06:00
|
|
|
let mut cx = Ctx {
|
2013-03-23 20:45:27 -05:00
|
|
|
map: map,
|
2014-01-06 06:00:46 -06:00
|
|
|
path: path.clone(),
|
2013-01-17 10:55:28 -06:00
|
|
|
diag: diag,
|
2014-01-06 06:00:46 -06:00
|
|
|
fold_ops: fold_ops
|
2013-01-17 10:55:28 -06:00
|
|
|
};
|
2012-03-02 15:14:10 -06:00
|
|
|
|
2014-01-06 06:00:46 -06:00
|
|
|
let ii = fold_ii(&mut cx);
|
|
|
|
|
2013-09-26 23:53:40 -05:00
|
|
|
// Methods get added to the AST map when their impl is visited. Since we
|
2012-03-02 15:14:10 -06:00
|
|
|
// don't decode and instantiate the impl, but just the method, we have to
|
2013-09-26 23:53:40 -05:00
|
|
|
// add it to the table now. Likewise with foreign items.
|
2014-01-06 06:00:46 -06:00
|
|
|
match ii {
|
2014-01-09 07:05:33 -06:00
|
|
|
IIItem(..) => {} // fallthrough
|
|
|
|
IIForeign(i) => {
|
|
|
|
cx.insert(i.id, NodeForeignItem(i,
|
|
|
|
AbiSet::Intrinsic(),
|
|
|
|
i.vis, // Wrong but OK
|
|
|
|
@path));
|
2012-02-22 09:57:23 -06:00
|
|
|
}
|
2014-01-09 07:05:33 -06:00
|
|
|
IIMethod(impl_did, is_provided, m) => {
|
2014-01-06 06:00:46 -06:00
|
|
|
let entry = if is_provided {
|
2014-01-09 07:05:33 -06:00
|
|
|
NodeTraitMethod(@Provided(m), impl_did, @path)
|
2014-01-06 06:00:46 -06:00
|
|
|
} else {
|
2014-01-09 07:05:33 -06:00
|
|
|
NodeMethod(m, impl_did, @path)
|
2014-01-06 06:00:46 -06:00
|
|
|
};
|
|
|
|
cx.insert(m.id, entry);
|
|
|
|
cx.map_self(m);
|
2012-08-02 17:52:25 -05:00
|
|
|
}
|
2011-06-19 15:41:21 -05:00
|
|
|
}
|
2013-03-15 14:24:24 -05:00
|
|
|
|
2014-01-06 06:00:46 -06:00
|
|
|
ii
|
2012-08-17 16:09:20 -05:00
|
|
|
}
|
|
|
|
|
2014-01-09 07:05:33 -06:00
|
|
|
pub fn node_id_to_str(map: Map, id: NodeId, itr: @IdentInterner) -> ~str {
|
2014-01-17 06:23:09 -06:00
|
|
|
match map.find(id) {
|
2012-08-20 14:23:37 -05:00
|
|
|
None => {
|
2013-09-27 23:01:58 -05:00
|
|
|
format!("unknown node (id={})", id)
|
2012-03-28 14:54:06 -05:00
|
|
|
}
|
2014-01-17 06:23:09 -06:00
|
|
|
Some(NodeItem(item, path)) => {
|
2013-05-11 23:25:31 -05:00
|
|
|
let path_str = path_ident_to_str(path, item.ident, itr);
|
2012-08-09 11:59:50 -05:00
|
|
|
let item_str = match item.node {
|
2014-01-09 07:05:33 -06:00
|
|
|
ItemStatic(..) => ~"static",
|
|
|
|
ItemFn(..) => ~"fn",
|
|
|
|
ItemMod(..) => ~"mod",
|
|
|
|
ItemForeignMod(..) => ~"foreign mod",
|
|
|
|
ItemTy(..) => ~"ty",
|
|
|
|
ItemEnum(..) => ~"enum",
|
|
|
|
ItemStruct(..) => ~"struct",
|
|
|
|
ItemTrait(..) => ~"trait",
|
|
|
|
ItemImpl(..) => ~"impl",
|
|
|
|
ItemMac(..) => ~"macro"
|
2012-08-09 11:59:50 -05:00
|
|
|
};
|
2013-09-27 23:01:58 -05:00
|
|
|
format!("{} {} (id={})", item_str, path_str, id)
|
2012-03-28 14:54:06 -05:00
|
|
|
}
|
2014-01-17 06:23:09 -06:00
|
|
|
Some(NodeForeignItem(item, abi, _, path)) => {
|
2013-09-27 23:01:58 -05:00
|
|
|
format!("foreign item {} with abi {:?} (id={})",
|
2013-05-11 23:25:31 -05:00
|
|
|
path_ident_to_str(path, item.ident, itr), abi, id)
|
2012-03-28 14:54:06 -05:00
|
|
|
}
|
2014-01-17 06:23:09 -06:00
|
|
|
Some(NodeMethod(m, _, path)) => {
|
2013-09-27 23:01:58 -05:00
|
|
|
format!("method {} in {} (id={})",
|
2013-06-12 12:02:55 -05:00
|
|
|
itr.get(m.ident.name), path_to_str(*path, itr), id)
|
2012-03-28 14:54:06 -05:00
|
|
|
}
|
2014-01-17 06:23:09 -06:00
|
|
|
Some(NodeTraitMethod(ref tm, _, path)) => {
|
2013-02-18 00:20:36 -06:00
|
|
|
let m = ast_util::trait_method_to_ty_method(&**tm);
|
2013-09-27 23:01:58 -05:00
|
|
|
format!("method {} in {} (id={})",
|
2013-06-12 12:02:55 -05:00
|
|
|
itr.get(m.ident.name), path_to_str(*path, itr), id)
|
2012-08-02 17:52:25 -05:00
|
|
|
}
|
2014-01-17 06:23:09 -06:00
|
|
|
Some(NodeVariant(ref variant, _, path)) => {
|
2013-09-27 23:01:58 -05:00
|
|
|
format!("variant {} in {} (id={})",
|
2013-06-12 12:02:55 -05:00
|
|
|
itr.get(variant.node.name.name), path_to_str(*path, itr), id)
|
2012-03-28 14:54:06 -05:00
|
|
|
}
|
2014-01-17 06:23:09 -06:00
|
|
|
Some(NodeExpr(expr)) => {
|
2013-09-27 23:01:58 -05:00
|
|
|
format!("expr {} (id={})", pprust::expr_to_str(expr, itr), id)
|
2012-03-28 14:54:06 -05:00
|
|
|
}
|
2014-01-17 06:23:09 -06:00
|
|
|
Some(NodeCalleeScope(expr)) => {
|
2013-09-27 23:01:58 -05:00
|
|
|
format!("callee_scope {} (id={})", pprust::expr_to_str(expr, itr), id)
|
2013-03-15 14:24:24 -05:00
|
|
|
}
|
2014-01-17 06:23:09 -06:00
|
|
|
Some(NodeStmt(stmt)) => {
|
2013-09-27 23:01:58 -05:00
|
|
|
format!("stmt {} (id={})",
|
2013-04-17 11:15:08 -05:00
|
|
|
pprust::stmt_to_str(stmt, itr), id)
|
2012-08-17 16:09:20 -05:00
|
|
|
}
|
2014-01-17 06:23:09 -06:00
|
|
|
Some(NodeArg(pat)) => {
|
2013-09-27 23:01:58 -05:00
|
|
|
format!("arg {} (id={})", pprust::pat_to_str(pat, itr), id)
|
2012-03-28 14:54:06 -05:00
|
|
|
}
|
2014-01-17 06:23:09 -06:00
|
|
|
Some(NodeLocal(ident, _)) => {
|
2013-09-27 23:01:58 -05:00
|
|
|
format!("local (id={}, name={})", id, itr.get(ident.name))
|
2012-03-28 14:54:06 -05:00
|
|
|
}
|
2014-01-17 06:23:09 -06:00
|
|
|
Some(NodeBlock(block)) => {
|
2013-09-27 23:01:58 -05:00
|
|
|
format!("block {} (id={})", pprust::block_to_str(block, itr), id)
|
2012-03-28 14:54:06 -05:00
|
|
|
}
|
2014-01-17 06:23:09 -06:00
|
|
|
Some(NodeStructCtor(_, _, path)) => {
|
2013-09-27 23:01:58 -05:00
|
|
|
format!("struct_ctor {} (id={})", path_to_str(*path, itr), id)
|
2012-10-24 16:36:00 -05:00
|
|
|
}
|
2012-03-28 14:54:06 -05:00
|
|
|
}
|
|
|
|
}
|
2012-11-30 13:24:16 -06:00
|
|
|
|
2014-01-09 07:05:33 -06:00
|
|
|
pub fn node_item_query<Result>(items: Map, id: NodeId, query: |@Item| -> Result, error_msg: ~str)
|
2013-11-19 14:21:21 -06:00
|
|
|
-> Result {
|
2014-01-17 06:23:09 -06:00
|
|
|
match items.find(id) {
|
|
|
|
Some(NodeItem(it, _)) => query(it),
|
2013-10-21 15:08:31 -05:00
|
|
|
_ => fail!("{}", error_msg)
|
2012-11-30 13:24:16 -06:00
|
|
|
}
|
|
|
|
}
|
2013-10-29 05:03:32 -05:00
|
|
|
|
2014-01-09 07:05:33 -06:00
|
|
|
pub fn node_span(items: Map, id: ast::NodeId) -> Span {
|
2014-01-17 06:23:09 -06:00
|
|
|
match items.find(id) {
|
|
|
|
Some(NodeItem(item, _)) => item.span,
|
|
|
|
Some(NodeForeignItem(foreign_item, _, _, _)) => foreign_item.span,
|
|
|
|
Some(NodeTraitMethod(trait_method, _, _)) => {
|
2014-01-03 17:08:48 -06:00
|
|
|
match *trait_method {
|
|
|
|
Required(ref type_method) => type_method.span,
|
|
|
|
Provided(ref method) => method.span,
|
|
|
|
}
|
|
|
|
}
|
2014-01-17 06:23:09 -06:00
|
|
|
Some(NodeMethod(method, _, _)) => method.span,
|
|
|
|
Some(NodeVariant(variant, _, _)) => variant.span,
|
|
|
|
Some(NodeExpr(expr)) => expr.span,
|
|
|
|
Some(NodeStmt(stmt)) => stmt.span,
|
|
|
|
Some(NodeArg(pat)) => pat.span,
|
|
|
|
Some(NodeLocal(_, pat)) => match pat {
|
2014-01-06 06:00:46 -06:00
|
|
|
Some(pat) => pat.span,
|
2014-01-09 07:05:33 -06:00
|
|
|
None => fail!("node_span: cannot get span from NodeLocal (likely `self`)")
|
2014-01-06 06:00:46 -06:00
|
|
|
},
|
2014-01-17 06:23:09 -06:00
|
|
|
Some(NodeBlock(block)) => block.span,
|
|
|
|
Some(NodeStructCtor(_, item, _)) => item.span,
|
|
|
|
Some(NodeCalleeScope(expr)) => expr.span,
|
2013-12-19 00:41:59 -06:00
|
|
|
None => fail!("node_span: could not find id {}", id),
|
2013-10-29 05:03:32 -05:00
|
|
|
}
|
|
|
|
}
|