2012-01-09 09:24:53 -06:00
|
|
|
import std::map;
|
2012-03-07 18:48:57 -06:00
|
|
|
import std::map::hashmap;
|
2011-07-05 04:48:19 -05:00
|
|
|
import syntax::ast::*;
|
2011-09-15 06:18:20 -05:00
|
|
|
import syntax::ast_util;
|
2012-03-01 21:37:52 -06:00
|
|
|
import syntax::ast_util::inlined_item_methods;
|
2011-09-12 18:13:28 -05:00
|
|
|
import syntax::{visit, codemap};
|
2012-03-07 05:21:08 -06:00
|
|
|
import driver::session::session;
|
|
|
|
import front::attr;
|
2011-06-19 15:41:21 -05:00
|
|
|
|
2012-02-03 02:53:37 -06:00
|
|
|
enum path_elt { path_mod(str), path_name(str) }
|
|
|
|
type path = [path_elt];
|
|
|
|
|
2012-02-10 08:01:32 -06:00
|
|
|
fn path_to_str_with_sep(p: path, sep: str) -> str {
|
|
|
|
let strs = vec::map(p) {|e|
|
|
|
|
alt e {
|
|
|
|
path_mod(s) { s }
|
|
|
|
path_name(s) { s }
|
|
|
|
}
|
|
|
|
};
|
|
|
|
str::connect(strs, sep)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn path_to_str(p: path) -> str {
|
2012-02-11 19:14:29 -06:00
|
|
|
path_to_str_with_sep(p, "::")
|
2012-02-10 08:01:32 -06:00
|
|
|
}
|
|
|
|
|
2012-01-19 16:24:03 -06:00
|
|
|
enum ast_node {
|
2012-02-03 02:53:37 -06:00
|
|
|
node_item(@item, @path),
|
2012-03-07 05:21:08 -06:00
|
|
|
node_native_item(@native_item, native_abi, @path),
|
2012-03-02 15:14:10 -06:00
|
|
|
node_method(@method, def_id /* impl did */, @path /* path to the impl */),
|
2012-03-07 05:21:08 -06:00
|
|
|
node_variant(variant, @item, @path),
|
2012-01-19 19:56:05 -06:00
|
|
|
node_expr(@expr),
|
2012-03-06 06:57:07 -06:00
|
|
|
node_export(@view_path, @path),
|
2011-09-15 06:18:20 -05:00
|
|
|
// 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),
|
2012-03-07 05:21:08 -06:00
|
|
|
node_ctor(@item),
|
2012-03-15 20:46:18 -05:00
|
|
|
node_block(blk),
|
2011-06-19 15:41:21 -05:00
|
|
|
}
|
|
|
|
|
2012-03-07 18:48:57 -06:00
|
|
|
type map = std::map::hashmap<node_id, ast_node>;
|
2012-03-07 05:21:08 -06:00
|
|
|
type ctx = {map: map, mutable path: path,
|
|
|
|
mutable local_id: uint, sess: session};
|
2012-02-03 02:53:37 -06:00
|
|
|
type vt = visit::vt<ctx>;
|
2011-06-19 15:41:21 -05:00
|
|
|
|
2012-03-06 06:57:07 -06:00
|
|
|
fn extend(cx: ctx, elt: str) -> @path {
|
|
|
|
@(cx.path + [path_name(elt)])
|
|
|
|
}
|
|
|
|
|
2012-02-14 17:21:53 -06:00
|
|
|
fn mk_ast_map_visitor() -> vt {
|
|
|
|
ret visit::mk_vt(@{
|
2012-02-03 02:53:37 -06:00
|
|
|
visit_item: map_item,
|
|
|
|
visit_expr: map_expr,
|
|
|
|
visit_fn: map_fn,
|
|
|
|
visit_local: map_local,
|
2012-03-06 06:57:07 -06:00
|
|
|
visit_arm: map_arm,
|
|
|
|
visit_view_item: map_view_item
|
2012-02-03 02:53:37 -06:00
|
|
|
with *visit::default_visitor()
|
2012-02-14 17:21:53 -06:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2012-03-07 05:21:08 -06:00
|
|
|
fn map_crate(sess: session, c: crate) -> map {
|
2012-03-14 14:07:23 -05:00
|
|
|
let cx = {map: std::map::int_hash(),
|
2012-02-14 17:21:53 -06:00
|
|
|
mutable path: [],
|
2012-03-07 05:21:08 -06:00
|
|
|
mutable local_id: 0u,
|
|
|
|
sess: sess};
|
2012-02-14 17:21:53 -06:00
|
|
|
visit::visit_crate(c, cx, mk_ast_map_visitor());
|
2011-09-15 06:18:20 -05:00
|
|
|
ret 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.
|
2012-03-07 05:21:08 -06:00
|
|
|
fn map_decoded_item(sess: session, map: map, path: path, ii: inlined_item) {
|
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
|
|
|
|
// 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,
|
|
|
|
mutable path: path,
|
2012-03-07 05:21:08 -06:00
|
|
|
mutable local_id: 0u,
|
|
|
|
sess: sess};
|
2012-02-14 17:21:53 -06:00
|
|
|
let v = mk_ast_map_visitor();
|
2012-03-02 15:14:10 -06:00
|
|
|
|
|
|
|
// 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:
|
|
|
|
alt ii {
|
|
|
|
ii_item(i) { /* fallthrough */ }
|
|
|
|
ii_method(impl_did, m) {
|
2012-03-07 05:21:08 -06:00
|
|
|
map_method(impl_did, @path, m, cx);
|
2012-03-02 15:14:10 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// visit the item / method contents and add those to the map:
|
2012-03-01 21:37:52 -06:00
|
|
|
ii.accept(cx, v);
|
2012-03-01 12:36:22 -06:00
|
|
|
}
|
|
|
|
|
2012-02-03 02:53:37 -06:00
|
|
|
fn map_fn(fk: visit::fn_kind, decl: fn_decl, body: blk,
|
|
|
|
sp: codemap::span, id: node_id, cx: ctx, v: vt) {
|
2011-12-20 13:03:21 -06:00
|
|
|
for a in decl.inputs {
|
2011-09-15 06:18:20 -05:00
|
|
|
cx.map.insert(a.id, node_arg(a, cx.local_id));
|
|
|
|
cx.local_id += 1u;
|
|
|
|
}
|
2012-02-03 02:53:37 -06:00
|
|
|
visit::visit_fn(fk, decl, body, sp, id, cx, v);
|
2011-09-15 06:18:20 -05:00
|
|
|
}
|
|
|
|
|
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(b));
|
|
|
|
visit::visit_block(b, cx, v);
|
|
|
|
}
|
|
|
|
|
2012-02-22 09:57:23 -06:00
|
|
|
fn number_pat(cx: ctx, pat: @pat) {
|
|
|
|
pat_util::walk_pat(pat) {|p|
|
|
|
|
alt p.node {
|
|
|
|
pat_ident(_, _) {
|
|
|
|
cx.map.insert(p.id, node_local(cx.local_id));
|
|
|
|
cx.local_id += 1u;
|
|
|
|
}
|
|
|
|
_ {}
|
|
|
|
}
|
2011-10-21 05:41:42 -05:00
|
|
|
};
|
2012-02-22 09:57:23 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
fn map_local(loc: @local, cx: ctx, v: vt) {
|
|
|
|
number_pat(cx, loc.node.pat);
|
2012-02-03 02:53:37 -06:00
|
|
|
visit::visit_local(loc, cx, v);
|
2011-09-15 06:18:20 -05:00
|
|
|
}
|
|
|
|
|
2012-02-03 02:53:37 -06:00
|
|
|
fn map_arm(arm: arm, cx: ctx, v: vt) {
|
2012-02-22 09:57:23 -06:00
|
|
|
number_pat(cx, arm.pats[0]);
|
2012-02-03 02:53:37 -06:00
|
|
|
visit::visit_arm(arm, cx, v);
|
2011-09-14 08:30:59 -05:00
|
|
|
}
|
|
|
|
|
2012-03-02 15:14:10 -06:00
|
|
|
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));
|
2012-03-07 05:54:00 -06:00
|
|
|
cx.map.insert(m.self_id, node_local(cx.local_id));
|
|
|
|
cx.local_id += 1u;
|
2012-03-02 15:14:10 -06:00
|
|
|
}
|
|
|
|
|
2012-02-03 02:53:37 -06:00
|
|
|
fn map_item(i: @item, cx: ctx, v: vt) {
|
2012-03-02 15:14:10 -06:00
|
|
|
let item_path = @cx.path;
|
|
|
|
cx.map.insert(i.id, node_item(i, item_path));
|
2011-07-27 07:19:39 -05:00
|
|
|
alt i.node {
|
2011-12-20 09:33:55 -06:00
|
|
|
item_impl(_, _, _, ms) {
|
2012-03-02 15:14:10 -06:00
|
|
|
let impl_did = ast_util::local_def(i.id);
|
|
|
|
for m in ms {
|
2012-03-07 05:21:08 -06:00
|
|
|
map_method(impl_did, extend(cx, i.ident), m, cx);
|
2012-03-02 15:14:10 -06:00
|
|
|
}
|
2011-12-19 00:36:37 -06:00
|
|
|
}
|
2011-12-22 10:49:54 -06:00
|
|
|
item_res(_, _, _, dtor_id, ctor_id) {
|
2012-03-07 05:21:08 -06:00
|
|
|
cx.map.insert(ctor_id, node_ctor(i));
|
2012-03-02 15:14:10 -06:00
|
|
|
cx.map.insert(dtor_id, node_item(i, item_path));
|
2011-12-16 07:41:12 -06:00
|
|
|
}
|
2012-02-08 03:05:44 -06:00
|
|
|
item_enum(vs, _) {
|
|
|
|
for v in vs {
|
|
|
|
cx.map.insert(v.node.id, node_variant(
|
2012-03-07 05:21:08 -06:00
|
|
|
v, i, extend(cx, i.ident)));
|
2012-02-08 03:05:44 -06:00
|
|
|
}
|
|
|
|
}
|
2012-03-07 05:21:08 -06:00
|
|
|
item_native_mod(nm) {
|
|
|
|
let abi = alt attr::native_abi(i.attrs) {
|
|
|
|
either::left(msg) { cx.sess.span_fatal(i.span, msg); }
|
|
|
|
either::right(abi) { abi }
|
|
|
|
};
|
|
|
|
for nitem in nm.items {
|
|
|
|
cx.map.insert(nitem.id, node_native_item(nitem, abi, @cx.path));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
item_class(_, _, ctor) {
|
|
|
|
cx.map.insert(ctor.node.id, node_ctor(i));
|
|
|
|
}
|
2011-07-27 07:19:39 -05:00
|
|
|
_ { }
|
2011-06-19 15:41:21 -05:00
|
|
|
}
|
2012-02-03 02:53:37 -06:00
|
|
|
alt i.node {
|
2012-03-06 06:57:07 -06:00
|
|
|
item_mod(_) | item_native_mod(_) {
|
|
|
|
cx.path += [path_mod(i.ident)];
|
|
|
|
}
|
2012-02-03 02:53:37 -06:00
|
|
|
_ { cx.path += [path_name(i.ident)]; }
|
|
|
|
}
|
|
|
|
visit::visit_item(i, cx, v);
|
|
|
|
vec::pop(cx.path);
|
2011-06-19 15:41:21 -05:00
|
|
|
}
|
|
|
|
|
2012-03-06 06:57:07 -06:00
|
|
|
fn map_view_item(vi: @view_item, cx: ctx, _v: vt) {
|
|
|
|
alt vi.node {
|
|
|
|
view_item_export(vps) {
|
|
|
|
for vp in vps {
|
|
|
|
let (id, name) = alt vp.node {
|
|
|
|
view_path_simple(nm, _, id) { (id, nm) }
|
|
|
|
view_path_glob(pth, id) | view_path_list(pth, _, id) {
|
2012-03-08 14:08:47 -06:00
|
|
|
// should be a constraint on the type
|
|
|
|
assert (vec::is_not_empty(*pth));
|
2012-03-08 17:24:27 -06:00
|
|
|
(id, vec::last(*pth))
|
2012-03-06 06:57:07 -06:00
|
|
|
}
|
|
|
|
};
|
|
|
|
cx.map.insert(id, node_export(vp, extend(cx, name)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-02-03 02:53:37 -06:00
|
|
|
fn map_expr(ex: @expr, cx: ctx, v: vt) {
|
2011-09-15 06:18:20 -05:00
|
|
|
cx.map.insert(ex.id, node_expr(ex));
|
2012-02-03 02:53:37 -06:00
|
|
|
visit::visit_expr(ex, cx, v);
|
2011-06-19 15:41:21 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// Local Variables:
|
|
|
|
// mode: rust
|
|
|
|
// fill-column: 78;
|
|
|
|
// indent-tabs-mode: nil
|
|
|
|
// c-basic-offset: 4
|
|
|
|
// buffer-file-coding-system: utf-8-unix
|
|
|
|
// End:
|