rust/src/libsyntax/ast_map.rs

346 lines
11 KiB
Rust
Raw Normal View History

import std::map;
import std::map::hashmap;
import ast::*;
import print::pprust;
import ast_util::path_to_ident;
import diagnostic::span_handler;
2012-06-10 02:49:59 -05:00
enum path_elt { path_mod(ident), path_name(ident) }
type path = ~[path_elt];
2012-06-14 20:46:33 -05:00
/* FIXMEs that say "bad" are as per #2543 */
fn path_to_str_with_sep(p: path, sep: ~str) -> ~str {
2012-06-30 18:19:07 -05:00
let strs = do vec::map(p) |e| {
2012-08-06 14:34:08 -05:00
match e {
2012-08-03 21:59:04 -05:00
path_mod(s) => /* FIXME (#2543) */ copy *s,
path_name(s) => /* FIXME (#2543) */ copy *s
}
};
str::connect(strs, sep)
}
fn path_ident_to_str(p: path, i: ident) -> ~str {
if vec::is_empty(p) {
/* FIXME (#2543) */ copy *i
} else {
fmt!{"%s::%s", path_to_str(p), *i}
}
}
fn path_to_str(p: path) -> ~str {
path_to_str_with_sep(p, ~"::")
}
2012-01-19 16:24:03 -06:00
enum ast_node {
node_item(@item, @path),
node_foreign_item(@foreign_item, foreign_abi, @path),
node_trait_method(@trait_method, def_id /* trait did */,
@path /* path to the trait */),
node_method(@method, def_id /* impl did */, @path /* path to the impl */),
node_variant(variant, @item, @path),
2012-01-19 19:56:05 -06:00
node_expr(@expr),
node_export(@view_path, @path),
// Locals are numbered, because the alias analysis needs to know in which
// order they are introduced.
2012-01-19 19:56:05 -06:00
node_arg(arg, uint),
node_local(uint),
// Constructor for a class
// def_id is parent id
node_ctor(ident, ~[ty_param], @class_ctor, def_id, @path),
// Destructor for a class
node_dtor(~[ty_param], @class_dtor, def_id, @path),
2012-03-15 20:46:18 -05:00
node_block(blk),
}
type map = std::map::hashmap<node_id, ast_node>;
2012-03-26 20:35:18 -05:00
type ctx = {map: map, mut path: path,
mut local_id: uint, diag: span_handler};
type vt = visit::vt<ctx>;
2012-06-10 02:49:59 -05:00
fn extend(cx: ctx, +elt: ident) -> @path {
@(vec::append(cx.path, ~[path_name(elt)]))
}
fn mk_ast_map_visitor() -> vt {
2012-08-01 19:30:05 -05:00
return visit::mk_vt(@{
visit_item: map_item,
visit_expr: map_expr,
visit_fn: map_fn,
visit_local: map_local,
visit_arm: map_arm,
visit_view_item: map_view_item,
visit_block: map_block
with *visit::default_visitor()
});
}
fn map_crate(diag: span_handler, c: crate) -> map {
let cx = {map: std::map::int_hash(),
mut path: ~[],
2012-03-26 20:35:18 -05:00
mut local_id: 0u,
diag: diag};
visit::visit_crate(c, cx, mk_ast_map_visitor());
2012-08-01 19:30:05 -05:00
return cx.map;
}
// Used for items loaded from external crate that are being inlined into this
// crate. The `path` should be the path to the item but should not include
// the item itself.
fn map_decoded_item(diag: span_handler,
map: map, +path: path, ii: inlined_item) {
// 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
// starting from 0. (In particular, I think these ids are only used in
// alias analysis, which we will not be running on the inlined items, and
// even if we did I think it only needs an ordering between local
// variables that are simultaneously in scope).
let cx = {map: map,
mut path: /* FIXME (#2543) */ copy path,
2012-03-26 20:35:18 -05:00
mut local_id: 0u,
diag: diag};
let v = mk_ast_map_visitor();
// methods get added to the AST map when their impl is visited. Since we
// don't decode and instantiate the impl, but just the method, we have to
// add it to the table now:
2012-08-06 14:34:08 -05:00
match ii {
2012-08-03 21:59:04 -05:00
ii_item(*) | ii_ctor(*) | ii_dtor(*) => { /* fallthrough */ }
ii_foreign(i) => {
cx.map.insert(i.id, node_foreign_item(i, foreign_abi_rust_intrinsic,
@path));
}
2012-08-03 21:59:04 -05:00
ii_method(impl_did, m) => {
map_method(impl_did, @path, m, cx);
}
}
// visit the item / method contents and add those to the map:
ii.accept(cx, v);
}
fn map_fn(fk: visit::fn_kind, decl: fn_decl, body: blk,
sp: codemap::span, id: node_id, cx: ctx, v: vt) {
2012-06-30 18:19:07 -05:00
for decl.inputs.each |a| {
cx.map.insert(a.id,
node_arg(/* FIXME (#2543) */
copy a, cx.local_id));
cx.local_id += 1u;
}
2012-08-06 14:34:08 -05:00
match fk {
2012-08-03 21:59:04 -05:00
visit::fk_ctor(nm, attrs, tps, self_id, parent_id) => {
let ct = @{node: {id: id,
attrs: attrs,
self_id: self_id,
dec: /* FIXME (#2543) */ copy decl,
body: /* FIXME (#2543) */ copy body},
span: sp};
cx.map.insert(id, node_ctor(/* FIXME (#2543) */ copy nm,
/* FIXME (#2543) */ copy tps,
ct, parent_id,
@/* FIXME (#2543) */ copy cx.path));
}
2012-08-03 21:59:04 -05:00
visit::fk_dtor(tps, attrs, self_id, parent_id) => {
let dt = @{node: {id: id, attrs: attrs, self_id: self_id,
body: /* FIXME (#2543) */ copy body}, span: sp};
cx.map.insert(id, node_dtor(/* FIXME (#2543) */ copy tps, dt,
2012-06-07 23:53:47 -05:00
parent_id,
@/* FIXME (#2543) */ copy cx.path));
}
2012-08-03 21:59:04 -05:00
_ => ()
}
visit::visit_fn(fk, decl, body, sp, id, cx, v);
}
2012-03-15 20:46:18 -05:00
fn map_block(b: blk, cx: ctx, v: vt) {
cx.map.insert(b.node.id, node_block(/* FIXME (#2543) */ copy b));
2012-03-15 20:46:18 -05:00
visit::visit_block(b, cx, v);
}
fn number_pat(cx: ctx, pat: @pat) {
2012-06-30 18:19:07 -05:00
do ast_util::walk_pat(pat) |p| {
2012-08-06 14:34:08 -05:00
match p.node {
2012-08-03 21:59:04 -05:00
pat_ident(*) => {
cx.map.insert(p.id, node_local(cx.local_id));
cx.local_id += 1u;
}
2012-08-03 21:59:04 -05:00
_ => ()
}
};
}
fn map_local(loc: @local, cx: ctx, v: vt) {
number_pat(cx, loc.node.pat);
visit::visit_local(loc, cx, v);
}
fn map_arm(arm: arm, cx: ctx, v: vt) {
number_pat(cx, arm.pats[0]);
visit::visit_arm(arm, cx, v);
}
fn map_method(impl_did: def_id, impl_path: @path,
m: @method, cx: ctx) {
cx.map.insert(m.id, node_method(m, impl_did, impl_path));
cx.map.insert(m.self_id, node_local(cx.local_id));
cx.local_id += 1u;
}
fn map_item(i: @item, cx: ctx, v: vt) {
let item_path = @/* FIXME (#2543) */ copy cx.path;
cx.map.insert(i.id, node_item(i, item_path));
2012-08-06 14:34:08 -05:00
match i.node {
2012-08-03 21:59:04 -05:00
item_impl(_, opt_ir, _, ms) => {
let impl_did = ast_util::local_def(i.id);
2012-06-30 18:19:07 -05:00
for ms.each |m| {
2012-06-10 02:49:59 -05:00
map_method(impl_did, extend(cx, i.ident), m,
2012-06-07 23:53:47 -05:00
cx);
}
}
item_enum(enum_definition, _) => {
for enum_definition.variants.each |v| {
cx.map.insert(v.node.id, node_variant(
/* FIXME (#2543) */ copy v, i,
2012-06-10 02:49:59 -05:00
extend(cx, i.ident)));
}
}
2012-08-03 21:59:04 -05:00
item_foreign_mod(nm) => {
2012-08-06 14:34:08 -05:00
let abi = match attr::foreign_abi(i.attrs) {
2012-08-03 21:59:04 -05:00
either::left(msg) => cx.diag.span_fatal(i.span, msg),
either::right(abi) => abi
};
2012-06-30 18:19:07 -05:00
for nm.items.each |nitem| {
2012-06-07 23:53:47 -05:00
cx.map.insert(nitem.id,
node_foreign_item(nitem, abi,
/* FIXME (#2543) */
extend(cx, i.ident)));
}
}
item_class(struct_def, _) => {
map_struct_def(struct_def, node_item(i, item_path), i.ident, i.id, cx,
v);
}
2012-08-03 21:59:04 -05:00
item_trait(tps, traits, methods) => {
// Map trait refs to their parent classes. This is
// so we can find the self_ty
for traits.each |p| {
cx.map.insert(p.ref_id, node_item(i, item_path));
// This is so we can look up the right things when
// encoding/decoding
cx.map.insert(p.impl_id, node_item(i, item_path));
}
for methods.each |tm| {
let id = ast_util::trait_method_to_ty_method(tm).id;
let d_id = ast_util::local_def(i.id);
cx.map.insert(id, node_trait_method(@tm, d_id, item_path));
}
}
2012-08-03 21:59:04 -05:00
_ => ()
}
2012-08-06 14:34:08 -05:00
match i.node {
2012-08-03 21:59:04 -05:00
item_mod(_) | item_foreign_mod(_) => {
vec::push(cx.path, path_mod(i.ident));
}
2012-08-03 21:59:04 -05:00
_ => vec::push(cx.path, path_name(i.ident))
}
visit::visit_item(i, cx, v);
vec::pop(cx.path);
}
2012-08-07 19:46:07 -05:00
fn map_struct_def(struct_def: @ast::struct_def, parent_node: ast_node,
ident: ast::ident, id: ast::node_id, cx: ctx, _v: vt) {
let (_, ms) = ast_util::split_class_items(struct_def.members);
// Map trait refs to their parent classes. This is
// so we can find the self_ty
for struct_def.traits.each |p| {
cx.map.insert(p.ref_id, parent_node);
// This is so we can look up the right things when
// encoding/decoding
cx.map.insert(p.impl_id, parent_node);
}
let d_id = ast_util::local_def(id);
let p = extend(cx, ident);
// only need to handle methods
do vec::iter(ms) |m| { map_method(d_id, p, m, cx); }
}
fn map_view_item(vi: @view_item, cx: ctx, _v: vt) {
2012-08-06 14:34:08 -05:00
match vi.node {
2012-08-03 21:59:04 -05:00
view_item_export(vps) => for vps.each |vp| {
2012-08-06 14:34:08 -05:00
let (id, name) = match vp.node {
2012-08-03 21:59:04 -05:00
view_path_simple(nm, _, id) => {
(id, /* FIXME (#2543) */ copy nm)
}
view_path_glob(pth, id) | view_path_list(pth, _, id) => {
(id, path_to_ident(pth))
}
};
cx.map.insert(id, node_export(vp, extend(cx, name)));
},
2012-08-03 21:59:04 -05:00
_ => ()
}
}
fn map_expr(ex: @expr, cx: ctx, v: vt) {
cx.map.insert(ex.id, node_expr(ex));
visit::visit_expr(ex, cx, v);
}
fn node_id_to_str(map: map, id: node_id) -> ~str {
2012-08-06 14:34:08 -05:00
match map.find(id) {
2012-08-03 21:59:04 -05:00
none => {
fmt!{"unknown node (id=%d)", id}
}
2012-08-03 21:59:04 -05:00
some(node_item(item, path)) => {
fmt!{"item %s (id=%?)", path_ident_to_str(*path, item.ident), id}
}
2012-08-03 21:59:04 -05:00
some(node_foreign_item(item, abi, path)) => {
fmt!{"foreign item %s with abi %? (id=%?)",
path_ident_to_str(*path, item.ident), abi, id}
}
2012-08-03 21:59:04 -05:00
some(node_method(m, impl_did, path)) => {
fmt!{"method %s in %s (id=%?)",
*m.ident, path_to_str(*path), id}
}
2012-08-03 21:59:04 -05:00
some(node_trait_method(tm, impl_did, path)) => {
let m = ast_util::trait_method_to_ty_method(*tm);
fmt!{"method %s in %s (id=%?)",
*m.ident, path_to_str(*path), id}
}
2012-08-03 21:59:04 -05:00
some(node_variant(variant, def_id, path)) => {
fmt!{"variant %s in %s (id=%?)",
*variant.node.name, path_to_str(*path), id}
}
2012-08-03 21:59:04 -05:00
some(node_expr(expr)) => {
fmt!{"expr %s (id=%?)",
pprust::expr_to_str(expr), id}
}
2012-06-14 20:46:33 -05:00
// FIXMEs are as per #2410
2012-08-03 21:59:04 -05:00
some(node_export(_, path)) => {
fmt!{"export %s (id=%?)", // add more info here
path_to_str(*path), id}
}
2012-08-03 21:59:04 -05:00
some(node_arg(_, _)) => { // add more info here
fmt!{"arg (id=%?)", id}
}
2012-08-03 21:59:04 -05:00
some(node_local(_)) => { // add more info here
fmt!{"local (id=%?)", id}
}
2012-08-03 21:59:04 -05:00
some(node_ctor(*)) => { // add more info here
fmt!{"node_ctor (id=%?)", id}
}
2012-08-03 21:59:04 -05:00
some(node_dtor(*)) => { // add more info here
fmt!{"node_dtor (id=%?)", id}
}
2012-08-03 21:59:04 -05:00
some(node_block(_)) => {
fmt!{"block"}
}
}
}
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End: