2011-12-13 18:25:51 -06:00
|
|
|
import option;
|
|
|
|
import std::smallintmap;
|
2011-07-05 04:48:19 -05:00
|
|
|
import syntax::ast::*;
|
2011-09-15 06:18:20 -05:00
|
|
|
import syntax::ast_util;
|
2011-09-12 18:13:28 -05:00
|
|
|
import syntax::{visit, codemap};
|
2011-06-19 15:41:21 -05:00
|
|
|
|
|
|
|
tag ast_node {
|
|
|
|
node_item(@item);
|
|
|
|
node_obj_ctor(@item);
|
2011-12-18 22:32:38 -06:00
|
|
|
node_obj_method(@method);
|
2011-06-19 15:41:21 -05:00
|
|
|
node_native_item(@native_item);
|
2011-12-16 07:41:12 -06:00
|
|
|
node_method(@method);
|
2011-06-19 15:41:21 -05:00
|
|
|
node_expr(@expr);
|
2011-09-15 06:18:20 -05:00
|
|
|
// Locals are numbered, because the alias analysis needs to know in which
|
|
|
|
// order they are introduced.
|
|
|
|
node_arg(arg, uint);
|
|
|
|
node_local(uint);
|
2011-12-18 22:32:38 -06:00
|
|
|
node_res_ctor(@item);
|
2011-06-19 15:41:21 -05:00
|
|
|
}
|
|
|
|
|
2011-08-12 09:15:18 -05:00
|
|
|
type map = std::map::hashmap<node_id, ast_node>;
|
2011-09-15 06:18:20 -05:00
|
|
|
type ctx = @{map: map, mutable local_id: uint};
|
2011-06-19 15:41:21 -05:00
|
|
|
|
2011-09-12 04:27:30 -05:00
|
|
|
fn map_crate(c: crate) -> map {
|
2011-06-28 21:31:27 -05:00
|
|
|
// FIXME: This is using an adapter to convert the smallintmap
|
|
|
|
// interface to the hashmap interface. It would be better to just
|
|
|
|
// convert everything to use the smallintmap.
|
2011-09-15 06:18:20 -05:00
|
|
|
let cx = @{map: new_smallintmap_int_adapter::<ast_node>(),
|
|
|
|
mutable local_id: 0u};
|
2011-06-19 15:41:21 -05:00
|
|
|
|
2011-09-14 08:30:59 -05:00
|
|
|
let v_map = visit::mk_simple_visitor
|
2011-09-15 06:18:20 -05:00
|
|
|
(@{visit_item: bind map_item(cx, _),
|
|
|
|
visit_native_item: bind map_native_item(cx, _),
|
|
|
|
visit_expr: bind map_expr(cx, _),
|
2011-12-20 13:03:21 -06:00
|
|
|
visit_fn_body: bind map_fn_body(cx, _, _, _, _, _),
|
2011-09-15 06:18:20 -05:00
|
|
|
visit_local: bind map_local(cx, _),
|
|
|
|
visit_arm: bind map_arm(cx, _)
|
|
|
|
with *visit::default_simple_visitor()});
|
2011-09-14 08:30:59 -05:00
|
|
|
visit::visit_crate(c, (), v_map);
|
2011-09-15 06:18:20 -05:00
|
|
|
ret cx.map;
|
2011-06-19 15:41:21 -05:00
|
|
|
}
|
|
|
|
|
2011-12-20 13:03:21 -06:00
|
|
|
fn map_fn_body(cx: ctx, decl: fn_decl, _body: blk,
|
|
|
|
_sp: codemap::span, _n: fn_ident, _id: node_id) {
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn map_local(cx: ctx, loc: @local) {
|
2011-10-21 05:41:42 -05:00
|
|
|
ast_util::pat_bindings(loc.node.pat) {|p|
|
2011-09-15 06:18:20 -05:00
|
|
|
cx.map.insert(p.id, node_local(cx.local_id));
|
|
|
|
cx.local_id += 1u;
|
2011-10-21 05:41:42 -05:00
|
|
|
};
|
2011-09-15 06:18:20 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
fn map_arm(cx: ctx, arm: arm) {
|
2011-10-21 05:41:42 -05:00
|
|
|
ast_util::pat_bindings(arm.pats[0]) {|p|
|
2011-09-15 06:18:20 -05:00
|
|
|
cx.map.insert(p.id, node_local(cx.local_id));
|
|
|
|
cx.local_id += 1u;
|
2011-10-21 05:41:42 -05:00
|
|
|
};
|
2011-09-14 08:30:59 -05:00
|
|
|
}
|
|
|
|
|
2011-09-15 06:18:20 -05:00
|
|
|
fn map_item(cx: ctx, i: @item) {
|
|
|
|
cx.map.insert(i.id, node_item(i));
|
2011-07-27 07:19:39 -05:00
|
|
|
alt i.node {
|
2011-12-18 22:32:38 -06:00
|
|
|
item_obj(ob, _, ctor_id) {
|
|
|
|
cx.map.insert(ctor_id, node_obj_ctor(i));
|
|
|
|
for m in ob.methods {
|
2011-12-22 10:49:54 -06:00
|
|
|
cx.map.insert(m.id, node_obj_method(m));
|
2011-12-18 22:32:38 -06:00
|
|
|
}
|
|
|
|
}
|
2011-12-16 07:41:12 -06:00
|
|
|
item_impl(_, _, ms) {
|
2011-12-22 10:49:54 -06:00
|
|
|
for m in ms { cx.map.insert(m.id, node_method(m)); }
|
2011-12-19 00:36:37 -06:00
|
|
|
}
|
2011-12-22 10:49:54 -06:00
|
|
|
item_res(_, _, _, dtor_id, ctor_id) {
|
2011-12-18 22:32:38 -06:00
|
|
|
cx.map.insert(ctor_id, node_res_ctor(i));
|
|
|
|
cx.map.insert(dtor_id, node_item(i));
|
2011-12-16 07:41:12 -06:00
|
|
|
}
|
2011-07-27 07:19:39 -05:00
|
|
|
_ { }
|
2011-06-19 15:41:21 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-09-15 06:18:20 -05:00
|
|
|
fn map_native_item(cx: ctx, i: @native_item) {
|
|
|
|
cx.map.insert(i.id, node_native_item(i));
|
2011-06-19 15:41:21 -05:00
|
|
|
}
|
|
|
|
|
2011-09-15 06:18:20 -05:00
|
|
|
fn map_expr(cx: ctx, ex: @expr) {
|
|
|
|
cx.map.insert(ex.id, node_expr(ex));
|
2011-06-19 15:41:21 -05:00
|
|
|
}
|
|
|
|
|
2011-11-18 05:39:20 -06:00
|
|
|
fn new_smallintmap_int_adapter<copy V>() -> std::map::hashmap<int, V> {
|
2011-10-06 05:26:12 -05:00
|
|
|
let key_idx = fn (&&key: int) -> uint { key as uint };
|
2011-09-12 04:27:30 -05:00
|
|
|
let idx_key = fn (idx: uint) -> int { idx as int };
|
2011-06-28 21:31:27 -05:00
|
|
|
ret new_smallintmap_adapter(key_idx, idx_key);
|
|
|
|
}
|
|
|
|
|
|
|
|
// This creates an object with the hashmap interface backed
|
|
|
|
// by the smallintmap type, because I don't want to go through
|
|
|
|
// the entire codebase adapting all the callsites to the different
|
|
|
|
// interface.
|
|
|
|
// FIXME: hashmap and smallintmap should support the same interface.
|
2011-11-18 05:39:20 -06:00
|
|
|
fn new_smallintmap_adapter<copy K, copy V>(key_idx: fn(K) -> uint,
|
|
|
|
idx_key: fn(uint) -> K)
|
2011-10-21 05:21:27 -05:00
|
|
|
-> std::map::hashmap<K, V> {
|
2011-06-28 21:31:27 -05:00
|
|
|
|
2011-11-18 05:39:20 -06:00
|
|
|
obj adapter<copy K, copy V>(map: smallintmap::smallintmap<V>,
|
2011-10-28 10:00:14 -05:00
|
|
|
key_idx: fn(K) -> uint,
|
|
|
|
idx_key: fn(uint) -> K) {
|
2011-06-28 21:31:27 -05:00
|
|
|
|
|
|
|
fn size() -> uint { fail }
|
|
|
|
|
2011-09-12 04:27:30 -05:00
|
|
|
fn insert(key: K, value: V) -> bool {
|
2011-07-27 07:19:39 -05:00
|
|
|
let exists = smallintmap::contains_key(map, key_idx(key));
|
2011-06-28 21:31:27 -05:00
|
|
|
smallintmap::insert(map, key_idx(key), value);
|
|
|
|
ret !exists;
|
|
|
|
}
|
|
|
|
|
2011-09-12 04:27:30 -05:00
|
|
|
fn contains_key(key: K) -> bool {
|
2011-06-28 21:31:27 -05:00
|
|
|
ret smallintmap::contains_key(map, key_idx(key));
|
|
|
|
}
|
|
|
|
|
2011-09-12 04:27:30 -05:00
|
|
|
fn get(key: K) -> V { ret smallintmap::get(map, key_idx(key)); }
|
2011-06-28 21:31:27 -05:00
|
|
|
|
2011-09-12 04:27:30 -05:00
|
|
|
fn find(key: K) -> option::t<V> {
|
2011-06-28 21:31:27 -05:00
|
|
|
ret smallintmap::find(map, key_idx(key));
|
|
|
|
}
|
|
|
|
|
2011-09-12 04:27:30 -05:00
|
|
|
fn remove(_key: K) -> option::t<V> { fail }
|
2011-06-28 21:31:27 -05:00
|
|
|
|
|
|
|
fn rehash() { fail }
|
|
|
|
|
2011-10-21 05:21:27 -05:00
|
|
|
fn items(it: block(K, V)) {
|
2011-07-27 07:19:39 -05:00
|
|
|
let idx = 0u;
|
2011-10-21 05:21:27 -05:00
|
|
|
for item in map.v {
|
2011-07-27 07:19:39 -05:00
|
|
|
alt item {
|
|
|
|
option::some(elt) {
|
2011-10-21 05:21:27 -05:00
|
|
|
it(idx_key(idx), elt);
|
2011-07-27 07:19:39 -05:00
|
|
|
}
|
|
|
|
option::none. { }
|
2011-06-28 21:31:27 -05:00
|
|
|
}
|
|
|
|
idx += 1u;
|
|
|
|
}
|
|
|
|
}
|
2011-10-21 05:21:27 -05:00
|
|
|
fn keys(it: block(K)) {
|
|
|
|
let idx = 0u;
|
|
|
|
for item in map.v {
|
|
|
|
if item != option::none { it(idx_key(idx)); }
|
|
|
|
idx += 1u;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fn values(it: block(V)) {
|
|
|
|
for item in map.v {
|
|
|
|
alt item { option::some(elt) { it(elt); } _ {} }
|
|
|
|
}
|
2011-07-21 20:14:39 -05:00
|
|
|
}
|
2011-06-28 21:31:27 -05:00
|
|
|
}
|
|
|
|
|
2011-08-13 02:09:25 -05:00
|
|
|
let map = smallintmap::mk::<V>();
|
2011-06-28 21:31:27 -05:00
|
|
|
ret adapter(map, key_idx, idx_key);
|
|
|
|
}
|
|
|
|
|
2011-09-12 04:27:30 -05:00
|
|
|
fn node_span(node: ast_node) -> codemap::span {
|
2011-08-10 23:43:36 -05:00
|
|
|
alt node {
|
|
|
|
node_item(item) { item.span }
|
|
|
|
node_obj_ctor(item) { item.span }
|
|
|
|
node_native_item(nitem) { nitem.span }
|
|
|
|
node_expr(expr) { expr.span }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod test {
|
2011-08-21 23:44:41 -05:00
|
|
|
import syntax::ast_util;
|
|
|
|
|
2011-11-14 21:37:35 -06:00
|
|
|
#[test]
|
2011-08-10 23:43:36 -05:00
|
|
|
fn test_node_span_item() {
|
2011-08-21 23:44:41 -05:00
|
|
|
let expected: codemap::span = ast_util::mk_sp(20u, 30u);
|
2011-08-19 17:16:48 -05:00
|
|
|
let node =
|
2011-09-02 17:34:58 -05:00
|
|
|
node_item(@{ident: "test",
|
2011-08-19 17:16:48 -05:00
|
|
|
attrs: [],
|
|
|
|
id: 0,
|
|
|
|
node: item_mod({view_items: [], items: []}),
|
|
|
|
span: expected});
|
|
|
|
assert (node_span(node) == expected);
|
2011-08-10 23:43:36 -05:00
|
|
|
}
|
|
|
|
|
2011-11-14 21:37:35 -06:00
|
|
|
#[test]
|
2011-08-10 23:43:36 -05:00
|
|
|
fn test_node_span_obj_ctor() {
|
2011-08-21 23:44:41 -05:00
|
|
|
let expected: codemap::span = ast_util::mk_sp(20u, 30u);
|
2011-08-19 17:16:48 -05:00
|
|
|
let node =
|
2011-09-02 17:34:58 -05:00
|
|
|
node_obj_ctor(@{ident: "test",
|
2011-08-19 17:16:48 -05:00
|
|
|
attrs: [],
|
|
|
|
id: 0,
|
|
|
|
node: item_mod({view_items: [], items: []}),
|
|
|
|
span: expected});
|
|
|
|
assert (node_span(node) == expected);
|
2011-08-10 23:43:36 -05:00
|
|
|
}
|
|
|
|
|
2011-11-14 21:37:35 -06:00
|
|
|
#[test]
|
2011-08-10 23:43:36 -05:00
|
|
|
fn test_node_span_native_item() {
|
2011-08-21 23:44:41 -05:00
|
|
|
let expected: codemap::span = ast_util::mk_sp(20u, 30u);
|
2011-08-19 17:16:48 -05:00
|
|
|
let node =
|
2011-09-02 17:34:58 -05:00
|
|
|
node_native_item(@{ident: "test",
|
2011-08-19 17:16:48 -05:00
|
|
|
attrs: [],
|
|
|
|
node: native_item_ty,
|
|
|
|
id: 0,
|
|
|
|
span: expected});
|
|
|
|
assert (node_span(node) == expected);
|
2011-08-10 23:43:36 -05:00
|
|
|
}
|
|
|
|
|
2011-11-14 21:37:35 -06:00
|
|
|
#[test]
|
2011-08-10 23:43:36 -05:00
|
|
|
fn test_node_span_expr() {
|
2011-08-21 23:44:41 -05:00
|
|
|
let expected: codemap::span = ast_util::mk_sp(20u, 30u);
|
2011-08-19 17:16:48 -05:00
|
|
|
let node = node_expr(@{id: 0, node: expr_break, span: expected});
|
|
|
|
assert (node_span(node) == expected);
|
2011-08-10 23:43:36 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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:
|