rust/src/comp/middle/ast_map.rs

122 lines
3.6 KiB
Rust
Raw Normal View History

import std::smallintmap;
import std::option;
import syntax::ast::*;
import syntax::visit;
import visit::vt;
tag ast_node {
node_item(@item);
node_obj_ctor(@item);
node_native_item(@native_item);
node_expr(@expr);
}
type map = std::map::hashmap[node_id, ast_node];
fn map_crate(&crate c) -> map {
// 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.
auto map = new_smallintmap_int_adapter[ast_node]();
auto v_map = @rec(visit_item=bind map_item(map, _, _, _),
visit_native_item=bind map_native_item(map, _, _, _),
visit_expr=bind map_expr(map, _, _, _)
with *visit::default_visitor[()]());
visit::visit_crate(c, (), visit::vtor(v_map));
ret map;
}
fn map_item(&map map, &@item i, &() e, &vt[()] v) {
map.insert(i.id, node_item(i));
alt (i.node) {
case (item_obj(_, _, ?ctor_id)) {
map.insert(ctor_id, node_obj_ctor(i));
}
case (_) {}
}
visit::visit_item(i, e, v);
}
fn map_native_item(&map map, &@native_item i, &() e, &vt[()] v) {
map.insert(i.id, node_native_item(i));
visit::visit_native_item(i, e, v);
}
fn map_expr(&map map, &@expr ex, &() e, &vt[()] v) {
map.insert(ex.id, node_expr(ex));
visit::visit_expr(ex, e, v);
}
fn new_smallintmap_int_adapter[V]() -> std::map::hashmap[int, V] {
auto key_idx = fn(&int key) -> uint { key as uint };
auto idx_key = fn(&uint idx) -> int { idx as int };
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.
fn new_smallintmap_adapter[K, V](fn(&K) -> uint key_idx,
fn(&uint) -> K idx_key)
-> std::map::hashmap[K, V] {
obj adapter[K, V](smallintmap::smallintmap[V] map,
fn(&K) -> uint key_idx,
fn(&uint) -> K idx_key) {
fn size() -> uint { fail }
fn insert(&K key, &V value) -> bool {
auto exists = smallintmap::contains_key(map, key_idx(key));
smallintmap::insert(map, key_idx(key), value);
ret !exists;
}
fn contains_key(&K key) -> bool {
ret smallintmap::contains_key(map, key_idx(key));
}
fn get(&K key) -> V {
ret smallintmap::get(map, key_idx(key));
}
fn find(&K key) -> option::t[V] {
ret smallintmap::find(map, key_idx(key));
}
fn remove(&K key) -> option::t[V] { fail }
fn rehash() { fail }
iter items() -> @tup(K, V) {
auto idx = 0u;
for (option::t[V] item in map.v) {
alt (item) {
case (option::some(?elt)) {
auto value = elt;
auto key = idx_key(idx);
put @tup(key, value);
}
case (option::none) { }
}
idx += 1u;
}
}
}
auto map = smallintmap::mk[V]();
ret adapter(map, key_idx, idx_key);
}
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End: