Implement std::map as an iface/impl instead of an obj
This commit is contained in:
parent
c68345e57e
commit
15744210e7
9 changed files with 129 additions and 184 deletions
|
@ -20,10 +20,9 @@ export list_file_metadata;
|
||||||
// Traverses an AST, reading all the information about use'd crates and native
|
// Traverses an AST, reading all the information about use'd crates and native
|
||||||
// libraries necessary for later resolving, typechecking, linking, etc.
|
// libraries necessary for later resolving, typechecking, linking, etc.
|
||||||
fn read_crates(sess: session::session, crate: ast::crate) {
|
fn read_crates(sess: session::session, crate: ast::crate) {
|
||||||
let e =
|
let e = @{sess: sess,
|
||||||
@{sess: sess,
|
crate_cache: std::map::new_str_hash::<int>(),
|
||||||
crate_cache: @std::map::new_str_hash::<int>(),
|
mutable next_crate_num: 1};
|
||||||
mutable next_crate_num: 1};
|
|
||||||
let v =
|
let v =
|
||||||
visit::mk_simple_visitor(@{visit_view_item:
|
visit::mk_simple_visitor(@{visit_view_item:
|
||||||
bind visit_view_item(e, _),
|
bind visit_view_item(e, _),
|
||||||
|
@ -32,10 +31,9 @@ fn read_crates(sess: session::session, crate: ast::crate) {
|
||||||
visit::visit_crate(crate, (), v);
|
visit::visit_crate(crate, (), v);
|
||||||
}
|
}
|
||||||
|
|
||||||
type env =
|
type env = @{sess: session::session,
|
||||||
@{sess: session::session,
|
crate_cache: hashmap<str, int>,
|
||||||
crate_cache: @hashmap<str, int>,
|
mutable next_crate_num: ast::crate_num};
|
||||||
mutable next_crate_num: ast::crate_num};
|
|
||||||
|
|
||||||
fn visit_view_item(e: env, i: @ast::view_item) {
|
fn visit_view_item(e: env, i: @ast::view_item) {
|
||||||
alt i.node {
|
alt i.node {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import option;
|
import option;
|
||||||
import std::smallintmap;
|
import std::map;
|
||||||
import syntax::ast::*;
|
import syntax::ast::*;
|
||||||
import syntax::ast_util;
|
import syntax::ast_util;
|
||||||
import syntax::{visit, codemap};
|
import syntax::{visit, codemap};
|
||||||
|
@ -18,14 +18,11 @@ tag ast_node {
|
||||||
node_res_ctor(@item);
|
node_res_ctor(@item);
|
||||||
}
|
}
|
||||||
|
|
||||||
type map = std::map::hashmap<node_id, ast_node>;
|
type map = std::map::map<node_id, ast_node>;
|
||||||
type ctx = @{map: map, mutable local_id: uint};
|
type ctx = @{map: map, mutable local_id: uint};
|
||||||
|
|
||||||
fn map_crate(c: crate) -> map {
|
fn map_crate(c: crate) -> map {
|
||||||
// FIXME: This is using an adapter to convert the smallintmap
|
let cx = @{map: std::map::new_int_hash(),
|
||||||
// interface to the hashmap interface. It would be better to just
|
|
||||||
// convert everything to use the smallintmap.
|
|
||||||
let cx = @{map: new_smallintmap_int_adapter::<ast_node>(),
|
|
||||||
mutable local_id: 0u};
|
mutable local_id: 0u};
|
||||||
|
|
||||||
let v_map = visit::mk_simple_visitor
|
let v_map = visit::mk_simple_visitor
|
||||||
|
@ -98,77 +95,6 @@ fn map_expr(cx: ctx, ex: @expr) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_smallintmap_int_adapter<V: copy>() -> std::map::hashmap<int, V> {
|
|
||||||
let key_idx = fn (&&key: int) -> uint { key as uint };
|
|
||||||
let idx_key = fn (idx: uint) -> 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: copy, V: copy>(key_idx: fn(K) -> uint,
|
|
||||||
idx_key: fn(uint) -> K)
|
|
||||||
-> std::map::hashmap<K, V> {
|
|
||||||
|
|
||||||
obj adapter<K: copy, V: copy>(map: smallintmap::smallintmap<V>,
|
|
||||||
key_idx: fn(K) -> uint,
|
|
||||||
idx_key: fn(uint) -> K) {
|
|
||||||
|
|
||||||
fn size() -> uint { fail }
|
|
||||||
|
|
||||||
fn insert(key: K, value: V) -> bool {
|
|
||||||
let exists = smallintmap::contains_key(map, key_idx(key));
|
|
||||||
smallintmap::insert(map, key_idx(key), value);
|
|
||||||
ret !exists;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn contains_key(key: K) -> bool {
|
|
||||||
ret smallintmap::contains_key(map, key_idx(key));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get(key: K) -> V { ret smallintmap::get(map, key_idx(key)); }
|
|
||||||
|
|
||||||
fn find(key: K) -> option::t<V> {
|
|
||||||
ret smallintmap::find(map, key_idx(key));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn remove(_key: K) -> option::t<V> { fail }
|
|
||||||
|
|
||||||
fn rehash() { fail }
|
|
||||||
|
|
||||||
fn items(it: block(K, V)) {
|
|
||||||
let idx = 0u;
|
|
||||||
for item in map.v {
|
|
||||||
alt item {
|
|
||||||
option::some(elt) {
|
|
||||||
it(idx_key(idx), elt);
|
|
||||||
}
|
|
||||||
option::none. { }
|
|
||||||
}
|
|
||||||
idx += 1u;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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); } _ {} }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let map = smallintmap::mk::<V>();
|
|
||||||
ret adapter(map, key_idx, idx_key);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn node_span(node: ast_node) -> codemap::span {
|
fn node_span(node: ast_node) -> codemap::span {
|
||||||
alt node {
|
alt node {
|
||||||
node_item(item) { item.span }
|
node_item(item) { item.span }
|
||||||
|
|
|
@ -218,7 +218,7 @@ type sp_constr = spanned<tsconstr>;
|
||||||
|
|
||||||
type norm_constraint = {bit_num: uint, c: sp_constr};
|
type norm_constraint = {bit_num: uint, c: sp_constr};
|
||||||
|
|
||||||
type constr_map = @std::map::hashmap<def_id, constraint>;
|
type constr_map = std::map::hashmap<def_id, constraint>;
|
||||||
|
|
||||||
/* Contains stuff that has to be computed up front */
|
/* Contains stuff that has to be computed up front */
|
||||||
/* For easy access, the fn_info stores two special constraints for each
|
/* For easy access, the fn_info stores two special constraints for each
|
||||||
|
@ -278,7 +278,7 @@ type node_ann_table = @mutable [mutable ts_ann];
|
||||||
|
|
||||||
|
|
||||||
/* mapping from function name to fn_info map */
|
/* mapping from function name to fn_info map */
|
||||||
type fn_info_map = @std::map::hashmap<node_id, fn_info>;
|
type fn_info_map = std::map::hashmap<node_id, fn_info>;
|
||||||
|
|
||||||
type fn_ctxt =
|
type fn_ctxt =
|
||||||
{enclosing: fn_info, id: node_id, name: ident, ccx: crate_ctxt};
|
{enclosing: fn_info, id: node_id, name: ident, ccx: crate_ctxt};
|
||||||
|
@ -483,7 +483,7 @@ fn num_constraints(m: fn_info) -> uint { ret m.num_constraints; }
|
||||||
|
|
||||||
fn new_crate_ctxt(cx: ty::ctxt) -> crate_ctxt {
|
fn new_crate_ctxt(cx: ty::ctxt) -> crate_ctxt {
|
||||||
let na: [mutable ts_ann] = [mutable];
|
let na: [mutable ts_ann] = [mutable];
|
||||||
ret {tcx: cx, node_anns: @mutable na, fm: @new_int_hash::<fn_info>()};
|
ret {tcx: cx, node_anns: @mutable na, fm: new_int_hash::<fn_info>()};
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Use e's type to determine whether it returns.
|
/* Use e's type to determine whether it returns.
|
||||||
|
|
|
@ -102,7 +102,7 @@ fn mk_fn_info(ccx: crate_ctxt,
|
||||||
f_sp: span,
|
f_sp: span,
|
||||||
id: node_id) {
|
id: node_id) {
|
||||||
let name = visit::name_of_fn(fk);
|
let name = visit::name_of_fn(fk);
|
||||||
let res_map = @new_def_hash::<constraint>();
|
let res_map = new_def_hash::<constraint>();
|
||||||
let next: uint = 0u;
|
let next: uint = 0u;
|
||||||
|
|
||||||
let cx: ctxt = find_locals(ccx.tcx, fk, f_decl, f_body, f_sp, id);
|
let cx: ctxt = find_locals(ccx.tcx, fk, f_decl, f_body, f_sp, id);
|
||||||
|
|
|
@ -44,7 +44,7 @@ fn find_pre_post_item(ccx: crate_ctxt, i: item) {
|
||||||
{
|
{
|
||||||
// just bogus
|
// just bogus
|
||||||
enclosing:
|
enclosing:
|
||||||
{constrs: @new_def_hash::<constraint>(),
|
{constrs: new_def_hash::<constraint>(),
|
||||||
num_constraints: 0u,
|
num_constraints: 0u,
|
||||||
cf: return_val,
|
cf: return_val,
|
||||||
i_return: ninit(0, ""),
|
i_return: ninit(0, ""),
|
||||||
|
|
|
@ -33,7 +33,7 @@ tag json {
|
||||||
/* Variant: list */
|
/* Variant: list */
|
||||||
list(@[json]);
|
list(@[json]);
|
||||||
/* Variant: dict */
|
/* Variant: dict */
|
||||||
dict(map::hashmap<str,json>);
|
dict(map::map<str,json>);
|
||||||
/* Variant: null */
|
/* Variant: null */
|
||||||
null;
|
null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Module: map
|
Module: map
|
||||||
|
|
||||||
A hashmap
|
A map type
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Section: Types */
|
/* Section: Types */
|
||||||
|
@ -25,14 +25,17 @@ type eqfn<K> = fn(K, K) -> bool;
|
||||||
/*
|
/*
|
||||||
Type: hashset
|
Type: hashset
|
||||||
|
|
||||||
A convenience type to treat a hashmap as a set
|
A convenience type to treat a map as a set
|
||||||
*/
|
*/
|
||||||
type hashset<K> = hashmap<K, ()>;
|
type set<K> = map<K, ()>;
|
||||||
|
|
||||||
|
// Temporary alias to make migration easier
|
||||||
|
type hashmap<K, V> = map<K, V>;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Obj: hashmap
|
IFace: map
|
||||||
*/
|
*/
|
||||||
type hashmap<K, V> = obj {
|
iface map<K: copy, V: copy> {
|
||||||
/*
|
/*
|
||||||
Method: size
|
Method: size
|
||||||
|
|
||||||
|
@ -72,20 +75,14 @@ type hashmap<K, V> = obj {
|
||||||
Get the value for the specified key. If the key does not exist
|
Get the value for the specified key. If the key does not exist
|
||||||
in the map then returns none.
|
in the map then returns none.
|
||||||
*/
|
*/
|
||||||
fn find(K) -> core::option::t<V>;
|
fn find(K) -> option::t<V>;
|
||||||
/*
|
/*
|
||||||
Method: remove
|
Method: remove
|
||||||
|
|
||||||
Remove and return a value from the map. If the key does not exist
|
Remove and return a value from the map. If the key does not exist
|
||||||
in the map then returns none.
|
in the map then returns none.
|
||||||
*/
|
*/
|
||||||
fn remove(K) -> core::option::t<V>;
|
fn remove(K) -> option::t<V>;
|
||||||
/*
|
|
||||||
Method: rehash
|
|
||||||
|
|
||||||
Force map growth and rehashing
|
|
||||||
*/
|
|
||||||
fn rehash();
|
|
||||||
/*
|
/*
|
||||||
Method: items
|
Method: items
|
||||||
|
|
||||||
|
@ -98,46 +95,44 @@ type hashmap<K, V> = obj {
|
||||||
Iterate over all the keys in the map
|
Iterate over all the keys in the map
|
||||||
*/
|
*/
|
||||||
fn keys(block(K));
|
fn keys(block(K));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Iterate over all the values in the map
|
Iterate over all the values in the map
|
||||||
*/
|
*/
|
||||||
fn values(block(V));
|
fn values(block(V));
|
||||||
};
|
}
|
||||||
|
|
||||||
/* Section: Operations */
|
|
||||||
|
|
||||||
|
// FIXME: package this up and export it as a datatype usable for
|
||||||
|
// external code that doesn't want to pay the cost of a box and vtable
|
||||||
|
// lookups.
|
||||||
mod chained {
|
mod chained {
|
||||||
type entry<K: copy, V: copy> = {
|
type entry<K, V> = {
|
||||||
hash: uint,
|
hash: uint,
|
||||||
key: K,
|
key: K,
|
||||||
mutable value: V,
|
mutable value: V,
|
||||||
mutable next: chain<K, V>
|
mutable next: chain<K, V>
|
||||||
};
|
};
|
||||||
|
|
||||||
tag chain<K: copy, V: copy> {
|
tag chain<K, V> {
|
||||||
present(@entry<K, V>);
|
present(@entry<K, V>);
|
||||||
absent;
|
absent;
|
||||||
}
|
}
|
||||||
|
|
||||||
type t<K: copy, V: copy> = {
|
type t<K, V> = {
|
||||||
mutable size: uint,
|
mutable size: uint,
|
||||||
mutable chains: [mutable chain<K,V>],
|
mutable chains: [mutable chain<K,V>],
|
||||||
hasher: hashfn<K>,
|
hasher: hashfn<K>,
|
||||||
eqer: eqfn<K>
|
eqer: eqfn<K>
|
||||||
};
|
};
|
||||||
|
|
||||||
tag search_result<K: copy, V: copy> {
|
tag search_result<K, V> {
|
||||||
not_found;
|
not_found;
|
||||||
found_first(uint, @entry<K,V>);
|
found_first(uint, @entry<K,V>);
|
||||||
found_after(@entry<K,V>, @entry<K,V>);
|
found_after(@entry<K,V>, @entry<K,V>);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn search_rem<K: copy, V: copy>(tbl: t<K,V>,
|
fn search_rem<K: copy, V: copy>(
|
||||||
k: K,
|
tbl: t<K,V>, k: K, h: uint, idx: uint,
|
||||||
h: uint,
|
e_root: @entry<K,V>) -> search_result<K,V> {
|
||||||
idx: uint,
|
|
||||||
e_root: @entry<K,V>) -> search_result<K,V> {
|
|
||||||
let e0 = e_root;
|
let e0 = e_root;
|
||||||
let comp = 1u; // for logging
|
let comp = 1u; // for logging
|
||||||
while true {
|
while true {
|
||||||
|
@ -295,62 +290,40 @@ mod chained {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
obj o<K: copy, V: copy>(tbl: @t<K,V>,
|
impl <K: copy, V: copy> of map<K, V> for t<K, V> {
|
||||||
lf: util::rational) {
|
fn size() -> uint { self.size }
|
||||||
fn size() -> uint {
|
|
||||||
ret tbl.size;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn insert(k: K, v: V) -> bool {
|
fn insert(k: K, v: V) -> bool {
|
||||||
let nchains = vec::len(tbl.chains);
|
let nchains = vec::len(self.chains);
|
||||||
let load = {num:tbl.size + 1u as int, den:nchains as int};
|
let load = {num: self.size + 1u as int, den: nchains as int};
|
||||||
if !util::rational_leq(load, lf) {
|
// Structural consts would be nice. This is a const 3/4
|
||||||
rehash(*tbl);
|
// load factor that we compare against.
|
||||||
}
|
if !util::rational_leq(load, {num:3, den:4}) { rehash(self); }
|
||||||
ret insert(*tbl, k, v);
|
ret insert(self, k, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn contains_key(k: K) -> bool {
|
fn contains_key(k: K) -> bool { option::is_some(get(self, k)) }
|
||||||
ret core::option::is_some(get(*tbl, k));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get(k: K) -> V {
|
fn get(k: K) -> V { option::get(get(self, k)) }
|
||||||
ret core::option::get(get(*tbl, k));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn find(k: K) -> core::option::t<V> {
|
fn find(k: K) -> option::t<V> { get(self, k) }
|
||||||
ret get(*tbl, k);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn remove(k: K) -> core::option::t<V> {
|
fn remove(k: K) -> option::t<V> { remove(self, k) }
|
||||||
ret remove(*tbl, k);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn rehash() {
|
fn items(blk: block(K, V)) { items(self, blk); }
|
||||||
rehash(*tbl);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn items(blk: block(K, V)) {
|
fn keys(blk: block(K)) { items(self) { |k, _v| blk(k) } }
|
||||||
items(*tbl, blk);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn keys(blk: block(K)) {
|
fn values(blk: block(V)) { items(self) { |_k, v| blk(v) } }
|
||||||
items(*tbl) { |k, _v| blk(k) }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn values(blk: block(V)) {
|
|
||||||
items(*tbl) { |_k, v| blk(v) }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mk<K: copy, V: copy>(hasher: hashfn<K>, eqer: eqfn<K>)
|
fn mk<K: copy, V: copy>(hasher: hashfn<K>, eqer: eqfn<K>) -> map<K,V> {
|
||||||
-> hashmap<K,V> {
|
|
||||||
let initial_capacity: uint = 32u; // 2^5
|
let initial_capacity: uint = 32u; // 2^5
|
||||||
let t = @{mutable size: 0u,
|
let slf: t<K, V> = {mutable size: 0u,
|
||||||
mutable chains: chains(initial_capacity),
|
mutable chains: chains(initial_capacity),
|
||||||
hasher: hasher,
|
hasher: hasher,
|
||||||
eqer: eqer};
|
eqer: eqer};
|
||||||
ret o(t, {num:3, den:4});
|
slf as map::<K, V>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -365,8 +338,8 @@ hasher - The hash function for key type K
|
||||||
eqer - The equality function for key type K
|
eqer - The equality function for key type K
|
||||||
*/
|
*/
|
||||||
fn mk_hashmap<K: copy, V: copy>(hasher: hashfn<K>, eqer: eqfn<K>)
|
fn mk_hashmap<K: copy, V: copy>(hasher: hashfn<K>, eqer: eqfn<K>)
|
||||||
-> hashmap<K, V> {
|
-> map<K, V> {
|
||||||
ret chained::mk(hasher, eqer);
|
chained::mk(hasher, eqer)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -374,7 +347,7 @@ Function: new_str_hash
|
||||||
|
|
||||||
Construct a hashmap for string keys
|
Construct a hashmap for string keys
|
||||||
*/
|
*/
|
||||||
fn new_str_hash<V: copy>() -> hashmap<str, V> {
|
fn new_str_hash<V: copy>() -> map<str, V> {
|
||||||
ret mk_hashmap(str::hash, str::eq);
|
ret mk_hashmap(str::hash, str::eq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -383,7 +356,7 @@ Function: new_bytes_hash
|
||||||
|
|
||||||
Construct a hashmap for byte string keys
|
Construct a hashmap for byte string keys
|
||||||
*/
|
*/
|
||||||
fn new_bytes_hash<V: copy>() -> hashmap<[u8], V> {
|
fn new_bytes_hash<V: copy>() -> map<[u8], V> {
|
||||||
ret mk_hashmap(vec::u8::hash, vec::u8::eq);
|
ret mk_hashmap(vec::u8::hash, vec::u8::eq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -392,7 +365,7 @@ Function: new_int_hash
|
||||||
|
|
||||||
Construct a hashmap for int keys
|
Construct a hashmap for int keys
|
||||||
*/
|
*/
|
||||||
fn new_int_hash<V: copy>() -> hashmap<int, V> {
|
fn new_int_hash<V: copy>() -> map<int, V> {
|
||||||
fn hash_int(&&x: int) -> uint { int::hash(x) }
|
fn hash_int(&&x: int) -> uint { int::hash(x) }
|
||||||
fn eq_int(&&a: int, &&b: int) -> bool { ret a == b; }
|
fn eq_int(&&a: int, &&b: int) -> bool { ret a == b; }
|
||||||
ret mk_hashmap(hash_int, eq_int);
|
ret mk_hashmap(hash_int, eq_int);
|
||||||
|
@ -403,7 +376,7 @@ Function: new_uint_hash
|
||||||
|
|
||||||
Construct a hashmap for uint keys
|
Construct a hashmap for uint keys
|
||||||
*/
|
*/
|
||||||
fn new_uint_hash<V: copy>() -> hashmap<uint, V> {
|
fn new_uint_hash<V: copy>() -> map<uint, V> {
|
||||||
fn hash_uint(&&x: uint) -> uint { uint::hash(x) }
|
fn hash_uint(&&x: uint) -> uint { uint::hash(x) }
|
||||||
fn eq_uint(&&a: uint, &&b: uint) -> bool { ret a == b; }
|
fn eq_uint(&&a: uint, &&b: uint) -> bool { ret a == b; }
|
||||||
ret mk_hashmap(hash_uint, eq_uint);
|
ret mk_hashmap(hash_uint, eq_uint);
|
||||||
|
@ -414,12 +387,4 @@ Function: set_add
|
||||||
|
|
||||||
Convenience function for adding keys to a hashmap with nil type keys
|
Convenience function for adding keys to a hashmap with nil type keys
|
||||||
*/
|
*/
|
||||||
fn set_add<K>(set: hashset<K>, key: K) -> bool { ret set.insert(key, ()); }
|
fn set_add<K>(set: set<K>, key: K) -> bool { ret set.insert(key, ()); }
|
||||||
|
|
||||||
// Local Variables:
|
|
||||||
// mode: rust;
|
|
||||||
// fill-column: 78;
|
|
||||||
// indent-tabs-mode: nil
|
|
||||||
// c-basic-offset: 4
|
|
||||||
// buffer-file-coding-system: utf-8-unix
|
|
||||||
// End:
|
|
||||||
|
|
|
@ -80,3 +80,67 @@ fn max_key<T>(m: smallintmap<T>) -> uint {
|
||||||
ret vec::len::<option::t<T>>(m.v);
|
ret vec::len::<option::t<T>>(m.v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Impl: map
|
||||||
|
|
||||||
|
Implements the map::map interface for smallintmap
|
||||||
|
*/
|
||||||
|
impl <V: copy> of map::map<uint, V> for smallintmap<V> {
|
||||||
|
fn size() -> uint {
|
||||||
|
let sz = 0u;
|
||||||
|
for item in self.v {
|
||||||
|
alt item { some(_) { sz += 1u; } _ {} }
|
||||||
|
}
|
||||||
|
sz
|
||||||
|
}
|
||||||
|
fn insert(&&key: uint, value: V) -> bool {
|
||||||
|
let exists = contains_key(self, key);
|
||||||
|
insert(self, key, value);
|
||||||
|
ret !exists;
|
||||||
|
}
|
||||||
|
fn remove(&&key: uint) -> option::t<V> {
|
||||||
|
if key >= vec::len(self.v) { ret none; }
|
||||||
|
let old = self.v[key];
|
||||||
|
self.v[key] = none;
|
||||||
|
old
|
||||||
|
}
|
||||||
|
fn contains_key(&&key: uint) -> bool {
|
||||||
|
contains_key(self, key)
|
||||||
|
}
|
||||||
|
fn get(&&key: uint) -> V { get(self, key) }
|
||||||
|
fn find(&&key: uint) -> option::t<V> { find(self, key) }
|
||||||
|
fn rehash() { fail }
|
||||||
|
fn items(it: block(&&uint, V)) {
|
||||||
|
let idx = 0u;
|
||||||
|
for item in self.v {
|
||||||
|
alt item {
|
||||||
|
some(elt) {
|
||||||
|
it(idx, elt);
|
||||||
|
}
|
||||||
|
none. { }
|
||||||
|
}
|
||||||
|
idx += 1u;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn keys(it: block(&&uint)) {
|
||||||
|
let idx = 0u;
|
||||||
|
for item in self.v {
|
||||||
|
if item != none { it(idx); }
|
||||||
|
idx += 1u;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn values(it: block(V)) {
|
||||||
|
for item in self.v {
|
||||||
|
alt item { some(elt) { it(elt); } _ {} }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Funtion: as_map
|
||||||
|
|
||||||
|
Cast the given smallintmap to a map::map
|
||||||
|
*/
|
||||||
|
fn as_map<V>(s: smallintmap<V>) -> map::map<uint, V> {
|
||||||
|
s as map::map::<uint, V>
|
||||||
|
}
|
||||||
|
|
|
@ -78,7 +78,7 @@ fn test_simple() {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Force map growth and rehashing.
|
* Force map growth
|
||||||
*/
|
*/
|
||||||
#[test]
|
#[test]
|
||||||
fn test_growth() {
|
fn test_growth() {
|
||||||
|
@ -107,7 +107,6 @@ fn test_growth() {
|
||||||
assert (hm_uu.insert(num_to_insert, 17u));
|
assert (hm_uu.insert(num_to_insert, 17u));
|
||||||
assert (hm_uu.get(num_to_insert) == 17u);
|
assert (hm_uu.get(num_to_insert) == 17u);
|
||||||
#debug("-----");
|
#debug("-----");
|
||||||
hm_uu.rehash();
|
|
||||||
i = 0u;
|
i = 0u;
|
||||||
while i < num_to_insert {
|
while i < num_to_insert {
|
||||||
#debug("get(%u) = %u", i, hm_uu.get(i));
|
#debug("get(%u) = %u", i, hm_uu.get(i));
|
||||||
|
@ -142,7 +141,6 @@ fn test_growth() {
|
||||||
assert (str::eq(hm_ss.get(uint::to_str(num_to_insert, 2u)),
|
assert (str::eq(hm_ss.get(uint::to_str(num_to_insert, 2u)),
|
||||||
uint::to_str(17u, 2u)));
|
uint::to_str(17u, 2u)));
|
||||||
#debug("-----");
|
#debug("-----");
|
||||||
hm_ss.rehash();
|
|
||||||
i = 0u;
|
i = 0u;
|
||||||
while i < num_to_insert {
|
while i < num_to_insert {
|
||||||
#debug("get(\"%s\") = \"%s\"",
|
#debug("get(\"%s\") = \"%s\"",
|
||||||
|
@ -200,9 +198,6 @@ fn test_removal() {
|
||||||
i += 2u;
|
i += 2u;
|
||||||
}
|
}
|
||||||
#debug("-----");
|
#debug("-----");
|
||||||
#debug("rehashing");
|
|
||||||
hm.rehash();
|
|
||||||
#debug("-----");
|
|
||||||
i = 1u;
|
i = 1u;
|
||||||
while i < num_to_insert {
|
while i < num_to_insert {
|
||||||
#debug("get(%u) = %u", i, hm.get(i));
|
#debug("get(%u) = %u", i, hm.get(i));
|
||||||
|
@ -225,9 +220,6 @@ fn test_removal() {
|
||||||
i += 1u;
|
i += 1u;
|
||||||
}
|
}
|
||||||
#debug("-----");
|
#debug("-----");
|
||||||
#debug("rehashing");
|
|
||||||
hm.rehash();
|
|
||||||
#debug("-----");
|
|
||||||
assert (hm.size() == num_to_insert);
|
assert (hm.size() == num_to_insert);
|
||||||
i = 0u;
|
i = 0u;
|
||||||
while i < num_to_insert {
|
while i < num_to_insert {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue