diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs index 9017b1e153769ec77d07d4bc92888fba13717900..daa335fed9379a3a094830a00c0a51fe18da4385 100644 --- a/src/librustc/middle/lint.rs +++ b/src/librustc/middle/lint.rs @@ -34,8 +34,8 @@ use core::vec; use std::map::{Map, HashMap}; use std::map; -use std::smallintmap::{Map, SmallIntMap}; -use std::smallintmap; +use std::oldsmallintmap::{Map, SmallIntMap}; +use std::oldsmallintmap; use syntax::ast_util::{path_to_ident}; use syntax::attr; use syntax::codemap::span; @@ -248,7 +248,7 @@ pub fn get_lint_dict() -> lint_dict { }; pub fn mk_lint_settings() -> lint_settings { - {default_settings: smallintmap::mk(), + {default_settings: oldsmallintmap::mk(), settings_map: HashMap()} } @@ -273,7 +273,8 @@ pub fn get_lint_settings_level(settings: lint_settings, // This is kind of unfortunate. It should be somewhere else, or we should use // a persistent data structure... fn clone_lint_modes(modes: lint_modes) -> lint_modes { - smallintmap::SmallIntMap_(@smallintmap::SmallIntMap_ { v: copy modes.v }) + oldsmallintmap::SmallIntMap_(@oldsmallintmap::SmallIntMap_ + {v: copy modes.v}) } type ctxt_ = {dict: lint_dict, @@ -393,7 +394,7 @@ fn build_settings_item(i: @ast::item, &&cx: ctxt, v: visit::vt) { pub fn build_settings_crate(sess: session::Session, crate: @ast::crate) { let cx = ctxt_({dict: get_lint_dict(), - curr: smallintmap::mk(), + curr: oldsmallintmap::mk(), is_default: true, sess: sess}); diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index dd4c773278f159705b38d71998d4f0bdf4c44cc9..d0f9c9316167520a2fb3d6d046ec36135c993696 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -76,7 +76,7 @@ use core::option; use core::uint; use std::map::HashMap; -use std::smallintmap; +use std::oldsmallintmap; use std::{map, time, list}; use syntax::ast_map::{path, path_elt_to_str, path_mod, path_name}; use syntax::ast_util::{def_id_of_def, local_def, path_to_ident}; diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 928a1cfa96744d3d65be2bf62174f58316835961..b07e3ef7b81744594457542d4ba532476d9fa191 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -42,7 +42,7 @@ use core::uint; use core::vec; use std::map::HashMap; -use std::{map, smallintmap}; +use std::{map, oldsmallintmap}; use syntax::ast::*; use syntax::ast_util::{is_local, local_def}; use syntax::ast_util; @@ -785,7 +785,7 @@ pub fn param_bounds_to_kind(bounds: param_bounds) -> Kind { type constness_cache = HashMap; -pub type node_type_table = @smallintmap::SmallIntMap; +pub type node_type_table = @oldsmallintmap::SmallIntMap; fn mk_rcache() -> creader_cache { type val = {cnum: int, pos: uint, len: uint}; @@ -837,7 +837,7 @@ pub fn mk_ctxt(s: session::Session, def_map: dm, region_map: region_map, region_paramd_items: region_paramd_items, - node_types: @smallintmap::mk(), + node_types: @oldsmallintmap::mk(), node_type_substs: map::HashMap(), items: amap, intrinsic_defs: map::HashMap(), @@ -2799,7 +2799,7 @@ pub fn br_hashmap() -> HashMap { pub fn node_id_to_type(cx: ctxt, id: ast::node_id) -> t { //io::println(fmt!("%?/%?", id, cx.node_types.size())); - match smallintmap::find(*cx.node_types, id as uint) { + match oldsmallintmap::find(*cx.node_types, id as uint) { Some(t) => t, None => cx.sess.bug( fmt!("node_id_to_type: no type for node `%s`", @@ -3175,7 +3175,7 @@ pub fn expr_kind(tcx: ctxt, } ast::expr_cast(*) => { - match smallintmap::find(*tcx.node_types, expr.id as uint) { + match oldsmallintmap::find(*tcx.node_types, expr.id as uint) { Some(t) => { if ty::type_is_immediate(t) { RvalueDatumExpr diff --git a/src/librustc/middle/typeck/infer/mod.rs b/src/librustc/middle/typeck/infer/mod.rs index 2272e99995d171876361b6667f4003823f433cbc..2a39022e8d41c08be7ea01fe8904b2fd705c039f 100644 --- a/src/librustc/middle/typeck/infer/mod.rs +++ b/src/librustc/middle/typeck/infer/mod.rs @@ -281,7 +281,7 @@ fn bar() { use core::vec; use std::list::Nil; use std::map::HashMap; -use std::smallintmap; +use std::oldsmallintmap; use syntax::ast::{ret_style, purity}; use syntax::ast::{m_const, m_imm, m_mutbl}; use syntax::ast::{unsafe_fn, impure_fn, pure_fn, extern_fn}; @@ -353,7 +353,7 @@ pub fn fixup_err_to_str(f: fixup_err) -> ~str { fn new_ValsAndBindings() -> ValsAndBindings { ValsAndBindings { - vals: smallintmap::mk(), + vals: oldsmallintmap::mk(), mut bindings: ~[] } } diff --git a/src/librustc/middle/typeck/infer/unify.rs b/src/librustc/middle/typeck/infer/unify.rs index 30329f299455f4d990b65c5cd80c68b65b1af38c..3b38197c51c449f06f27e5d5ed1e820895a37560 100644 --- a/src/librustc/middle/typeck/infer/unify.rs +++ b/src/librustc/middle/typeck/infer/unify.rs @@ -10,7 +10,7 @@ use core::prelude::*; use core::result; -use std::smallintmap::SmallIntMap; +use std::oldsmallintmap::SmallIntMap; use middle::ty::{Vid, expected_found, IntVarValue}; use middle::ty; diff --git a/src/librustc/middle/typeck/mod.rs b/src/librustc/middle/typeck/mod.rs index ae57cd90bd7ce4e75257663767f9165cb3d681b9..5059de1314907f60483ad40cfd2a1f648281377d 100644 --- a/src/librustc/middle/typeck/mod.rs +++ b/src/librustc/middle/typeck/mod.rs @@ -69,7 +69,7 @@ use std::list; use std::map::HashMap; use std::map; -use std::smallintmap; +use std::oldsmallintmap; use syntax::ast::{provided, required, spanned}; use syntax::ast_map::node_id_to_str; use syntax::ast_util::{local_def, respan, split_trait_methods}; @@ -212,7 +212,7 @@ pub enum crate_ctxt { // Functions that write types into the node type table pub fn write_ty_to_tcx(tcx: ty::ctxt, node_id: ast::node_id, ty: ty::t) { debug!("write_ty_to_tcx(%d, %s)", node_id, ppaux::ty_to_str(tcx, ty)); - smallintmap::insert(*tcx.node_types, node_id as uint, ty); + oldsmallintmap::insert(*tcx.node_types, node_id as uint, ty); } pub fn write_substs_to_tcx(tcx: ty::ctxt, node_id: ast::node_id, diff --git a/src/libstd/oldsmallintmap.rs b/src/libstd/oldsmallintmap.rs new file mode 100644 index 0000000000000000000000000000000000000000..803e75e4cf7a3c034146b2db63267bbb31856b87 --- /dev/null +++ b/src/libstd/oldsmallintmap.rs @@ -0,0 +1,237 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/*! + * A simple map based on a vector for small integer keys. Space requirements + * are O(highest integer key). + */ +#[forbid(deprecated_mode)]; + +use core::container::{Container, Mutable, Map, Set}; +use core::dvec::DVec; +use core::ops; +use core::option::{Some, None}; +use core::option; +use core::prelude::*; + +// FIXME (#2347): Should not be @; there's a bug somewhere in rustc that +// requires this to be. +struct SmallIntMap_ { + v: DVec>, +} + +pub enum SmallIntMap { + SmallIntMap_(@SmallIntMap_) +} + +/// Create a smallintmap +pub fn mk() -> SmallIntMap { + let v = DVec(); + SmallIntMap_(@SmallIntMap_ { v: v } ) +} + +/** + * Add a value to the map. If the map already contains a value for + * the specified key then the original value is replaced. + */ +#[inline(always)] +pub fn insert(self: SmallIntMap, key: uint, val: T) { + //io::println(fmt!("%?", key)); + self.v.grow_set_elt(key, &None, Some(val)); +} + +/** + * Get the value for the specified key. If the key does not exist + * in the map then returns none + */ +pub pure fn find(self: SmallIntMap, key: uint) -> Option { + if key < self.v.len() { return self.v.get_elt(key); } + return None::; +} + +/** + * Get the value for the specified key + * + * # Failure + * + * If the key does not exist in the map + */ +pub pure fn get(self: SmallIntMap, key: uint) -> T { + match find(self, key) { + None => { + error!("smallintmap::get(): key not present"); + die!(); + } + Some(move v) => return v + } +} + +/// Returns true if the map contains a value for the specified key +pub pure fn contains_key(self: SmallIntMap, key: uint) -> bool { + return !find(self, key).is_none(); +} + +impl SmallIntMap: Container { + /// Return the number of elements in the map + pure fn len(&self) -> uint { + let mut sz = 0u; + for self.v.each |item| { + match *item { + Some(_) => sz += 1u, + _ => () + } + } + sz + } + + /// Return true if the map contains no elements + pure fn is_empty(&self) -> bool { self.len() == 0 } +} + +impl SmallIntMap: Mutable { + fn clear(&mut self) { self.v.set(~[]) } +} + +/// Implements the map::map interface for smallintmap +impl SmallIntMap { + #[inline(always)] + fn insert(key: uint, value: V) -> bool { + let exists = contains_key(self, key); + insert(self, key, value); + return !exists; + } + fn remove(key: uint) -> bool { + if key >= self.v.len() { + return false; + } + let old = self.v.get_elt(key); + self.v.set_elt(key, None); + old.is_some() + } + pure fn contains_key(key: uint) -> bool { + contains_key(self, key) + } + pure fn contains_key_ref(key: &uint) -> bool { + contains_key(self, *key) + } + pure fn get(key: uint) -> V { get(self, key) } + pure fn find(key: uint) -> Option { find(self, key) } + + fn update_with_key(key: uint, val: V, ff: fn(uint, V, V) -> V) -> bool { + match self.find(key) { + None => return self.insert(key, val), + Some(copy orig) => return self.insert(key, ff(key, orig, val)), + } + } + + fn update(key: uint, newval: V, ff: fn(V, V) -> V) -> bool { + return self.update_with_key(key, newval, |_k, v, v1| ff(v,v1)); + } + + pure fn each(it: fn(key: uint, value: V) -> bool) { + self.each_ref(|k, v| it(*k, *v)) + } + pure fn each_key(it: fn(key: uint) -> bool) { + self.each_ref(|k, _v| it(*k)) + } + pure fn each_value(it: fn(value: V) -> bool) { + self.each_ref(|_k, v| it(*v)) + } + pure fn each_ref(it: fn(key: &uint, value: &V) -> bool) { + let mut idx = 0u, l = self.v.len(); + while idx < l { + match self.v.get_elt(idx) { + Some(ref elt) => if !it(&idx, elt) { break }, + None => () + } + idx += 1u; + } + } + pure fn each_key_ref(blk: fn(key: &uint) -> bool) { + self.each_ref(|k, _v| blk(k)) + } + pure fn each_value_ref(blk: fn(value: &V) -> bool) { + self.each_ref(|_k, v| blk(v)) + } +} + +impl SmallIntMap: ops::Index { + pure fn index(&self, key: uint) -> V { + unsafe { + get(*self, key) + } + } +} + +#[cfg(test)] +mod tests { + use super::{mk, SmallIntMap}; + + use core::option::None; + + #[test] + fn test_len() { + let mut map = mk(); + assert map.len() == 0; + assert map.is_empty(); + map.insert(5, 20); + assert map.len() == 1; + assert !map.is_empty(); + map.insert(11, 12); + assert map.len() == 2; + assert !map.is_empty(); + map.insert(14, 22); + assert map.len() == 3; + assert !map.is_empty(); + } + + #[test] + fn test_clear() { + let mut map = mk(); + map.insert(5, 20); + map.insert(11, 12); + map.insert(14, 22); + map.clear(); + assert map.is_empty(); + assert map.find(5).is_none(); + assert map.find(11).is_none(); + assert map.find(14).is_none(); + } + + #[test] + fn test_insert_with_key() { + let map: SmallIntMap = mk(); + + // given a new key, initialize it with this new count, given + // given an existing key, add more to its count + fn addMoreToCount(_k: uint, v0: uint, v1: uint) -> uint { + v0 + v1 + } + + fn addMoreToCount_simple(v0: uint, v1: uint) -> uint { + v0 + v1 + } + + // count integers + map.update(3, 1, addMoreToCount_simple); + map.update_with_key(9, 1, addMoreToCount); + map.update(3, 7, addMoreToCount_simple); + map.update_with_key(5, 3, addMoreToCount); + map.update_with_key(3, 2, addMoreToCount); + + // check the total counts + assert map.find(3).get() == 10; + assert map.find(5).get() == 3; + assert map.find(9).get() == 1; + + // sadly, no sevens were counted + assert None == map.find(7); + } +} diff --git a/src/libstd/smallintmap.rs b/src/libstd/smallintmap.rs index c4680056e19df353f56eec8f07b9fb1a0c24f7a1..a21328b3d6340e671707ef38632bd2593b375033 100644 --- a/src/libstd/smallintmap.rs +++ b/src/libstd/smallintmap.rs @@ -14,171 +14,161 @@ */ #[forbid(deprecated_mode)]; -use map; -use map::StdMap; - -use core::dvec::DVec; -use core::ops; +use core::container::{Container, Mutable, Map, Set}; use core::option::{Some, None}; -use core::option; use core::prelude::*; -// FIXME (#2347): Should not be @; there's a bug somewhere in rustc that -// requires this to be. -struct SmallIntMap_ { - v: DVec>, -} - -pub enum SmallIntMap { - SmallIntMap_(@SmallIntMap_) +pub struct SmallIntMap { + priv v: ~[Option], } -/// Create a smallintmap -pub fn mk() -> SmallIntMap { - let v = DVec(); - SmallIntMap_(@SmallIntMap_ { v: v } ) -} +impl SmallIntMap: Container { + /// Return the number of elements in the map + pure fn len(&self) -> uint { + let mut sz = 0; + for self.v.each |item| { + if item.is_some() { + sz += 1; + } + } + sz + } -/** - * Add a value to the map. If the map already contains a value for - * the specified key then the original value is replaced. - */ -#[inline(always)] -pub fn insert(self: SmallIntMap, key: uint, val: T) { - //io::println(fmt!("%?", key)); - self.v.grow_set_elt(key, &None, Some(val)); + /// Return true if the map contains no elements + pure fn is_empty(&self) -> bool { self.len() == 0 } } -/** - * Get the value for the specified key. If the key does not exist - * in the map then returns none - */ -pub pure fn find(self: SmallIntMap, key: uint) -> Option { - if key < self.v.len() { return self.v.get_elt(key); } - return None::; +impl SmallIntMap: Mutable { + /// Clear the map, removing all key-value pairs. + fn clear(&mut self) { self.v.clear() } } -/** - * Get the value for the specified key - * - * # Failure - * - * If the key does not exist in the map - */ -pub pure fn get(self: SmallIntMap, key: uint) -> T { - match find(self, key) { - None => { - error!("smallintmap::get(): key not present"); - die!(); - } - Some(move v) => return v +impl SmallIntMap: Map { + /// Return true if the map contains a value for the specified key + pure fn contains_key(&self, key: &uint) -> bool { + self.find(key).is_some() } -} - -/// Returns true if the map contains a value for the specified key -pub pure fn contains_key(self: SmallIntMap, key: uint) -> bool { - return !find(self, key).is_none(); -} -/// Implements the map::map interface for smallintmap -impl SmallIntMap: map::StdMap { - pure fn size() -> uint { - let mut sz = 0u; - for self.v.each |item| { - match *item { - Some(_) => sz += 1u, - _ => () + /// Visit all key-value pairs + pure fn each(&self, it: fn(key: &uint, value: &V) -> bool) { + for uint::range(0, self.v.len()) |i| { + match self.v[i] { + Some(ref elt) => if !it(&i, elt) { break }, + None => () } } - sz - } - #[inline(always)] - fn insert(key: uint, value: V) -> bool { - let exists = contains_key(self, key); - insert(self, key, value); - return !exists; - } - fn remove(key: uint) -> bool { - if key >= self.v.len() { - return false; - } - let old = self.v.get_elt(key); - self.v.set_elt(key, None); - old.is_some() } - fn clear() { - self.v.set(~[]); - } - pure fn contains_key(key: uint) -> bool { - contains_key(self, key) + + /// Visit all keys + pure fn each_key(&self, blk: fn(key: &uint) -> bool) { + self.each(|k, _| blk(k)) } - pure fn contains_key_ref(key: &uint) -> bool { - contains_key(self, *key) + + /// Visit all values + pure fn each_value(&self, blk: fn(value: &V) -> bool) { + self.each(|_, v| blk(v)) } - pure fn get(key: uint) -> V { get(self, key) } - pure fn find(key: uint) -> Option { find(self, key) } - fn update_with_key(key: uint, val: V, ff: fn(uint, V, V) -> V) -> bool { - match self.find(key) { - None => return self.insert(key, val), - Some(copy orig) => return self.insert(key, ff(key, orig, val)), + /// Return the value corresponding to the key in the map + pure fn find(&self, key: &uint) -> Option<&self/V> { + if *key < self.v.len() { + match self.v[*key] { + Some(ref value) => Some(value), + None => None + } + } else { + None } } - fn update(key: uint, newval: V, ff: fn(V, V) -> V) -> bool { - return self.update_with_key(key, newval, |_k, v, v1| ff(v,v1)); + /// Insert a key-value pair into the map. An existing value for a + /// key is replaced by the new value. Return true if the key did + /// not already exist in the map. + fn insert(&mut self, key: uint, value: V) -> bool { + let exists = self.contains_key(&key); + let len = self.v.len(); + if len <= key { + vec::grow_fn(&mut self.v, key - len + 1, |_| None); + } + self.v[key] = Some(value); + !exists } - pure fn each(it: fn(key: uint, value: V) -> bool) { - self.each_ref(|k, v| it(*k, *v)) - } - pure fn each_key(it: fn(key: uint) -> bool) { - self.each_ref(|k, _v| it(*k)) - } - pure fn each_value(it: fn(value: V) -> bool) { - self.each_ref(|_k, v| it(*v)) - } - pure fn each_ref(it: fn(key: &uint, value: &V) -> bool) { - let mut idx = 0u, l = self.v.len(); - while idx < l { - match self.v.get_elt(idx) { - Some(ref elt) => if !it(&idx, elt) { break }, - None => () - } - idx += 1u; + /// Remove a key-value pair from the map. Return true if the key + /// was present in the map, otherwise false. + fn remove(&mut self, key: &uint) -> bool { + if *key >= self.v.len() { + return false; } + let removed = self.v[*key].is_some(); + self.v[*key] = None; + removed } - pure fn each_key_ref(blk: fn(key: &uint) -> bool) { - self.each_ref(|k, _v| blk(k)) - } - pure fn each_value_ref(blk: fn(value: &V) -> bool) { - self.each_ref(|_k, v| blk(v)) +} + +pub impl SmallIntMap { + /// Create an empty SmallIntMap + static pure fn new() -> SmallIntMap { SmallIntMap{v: ~[]} } + + pure fn get(&self, key: &uint) -> &self/V { + self.find(key).expect("key not present") } } -impl SmallIntMap: ops::Index { - pure fn index(&self, key: uint) -> V { - unsafe { - get(*self, key) +pub impl SmallIntMap { + // FIXME: #4733, remove after the next snapshot + #[cfg(stage2)] + fn update_with_key(&mut self, key: uint, val: V, + ff: fn(uint, V, V) -> V) -> bool { + match self.find(&key) { + None => self.insert(key, val), + Some(orig) => self.insert(key, ff(key, copy *orig, val)), } } -} -/// Cast the given smallintmap to a map::map -pub fn as_map(s: SmallIntMap) -> map::StdMap { - s as map::StdMap:: + // FIXME: #4733, remove after the next snapshot + #[cfg(stage2)] + fn update(&mut self, key: uint, newval: V, ff: fn(V, V) -> V) -> bool { + self.update_with_key(key, newval, |_k, v, v1| ff(v,v1)) + } } #[cfg(test)] mod tests { - use smallintmap::{mk, SmallIntMap}; + use super::SmallIntMap; - use core::option::None; - use core::option; + #[test] + fn test_len() { + let mut map = SmallIntMap::new(); + assert map.len() == 0; + assert map.is_empty(); + assert map.insert(5, 20); + assert map.len() == 1; + assert !map.is_empty(); + assert map.insert(11, 12); + assert map.len() == 2; + assert !map.is_empty(); + assert map.insert(14, 22); + assert map.len() == 3; + assert !map.is_empty(); + } + + #[test] + fn test_clear() { + let mut map = SmallIntMap::new(); + assert map.insert(5, 20); + assert map.insert(11, 12); + assert map.insert(14, 22); + map.clear(); + assert map.is_empty(); + assert map.find(&5).is_none(); + assert map.find(&11).is_none(); + assert map.find(&14).is_none(); + } #[test] fn test_insert_with_key() { - let map: SmallIntMap = mk(); + let mut map = SmallIntMap::new(); // given a new key, initialize it with this new count, given // given an existing key, add more to its count @@ -198,11 +188,11 @@ fn addMoreToCount_simple(v0: uint, v1: uint) -> uint { map.update_with_key(3, 2, addMoreToCount); // check the total counts - assert 10 == option::get(map.find(3)); - assert 3 == option::get(map.find(5)); - assert 1 == option::get(map.find(9)); + assert map.find(&3).get() == &10; + assert map.find(&5).get() == &3; + assert map.find(&9).get() == &1; // sadly, no sevens were counted - assert None == map.find(7); + assert map.find(&7).is_none(); } } diff --git a/src/libstd/std.rc b/src/libstd/std.rc index 51b55b1c46fd2f10ae8a0dbdc171517515d9053d..dc73b430099ab23b60904a63f48dcd903c6b65e7 100644 --- a/src/libstd/std.rc +++ b/src/libstd/std.rc @@ -83,6 +83,7 @@ pub mod map; pub mod priority_queue; pub mod rope; pub mod smallintmap; +pub mod oldsmallintmap; pub mod sort; pub mod treemap; diff --git a/src/test/bench/std-smallintmap.rs b/src/test/bench/std-smallintmap.rs index a72831c2b061e20c233fc369f651b5be63ea4648..0687799cf288c8c085c2382080a36c8fa668a0ad 100644 --- a/src/test/bench/std-smallintmap.rs +++ b/src/test/bench/std-smallintmap.rs @@ -11,19 +11,18 @@ // Microbenchmark for the smallintmap library extern mod std; -use std::smallintmap; use std::smallintmap::SmallIntMap; use io::WriterUtil; -fn append_sequential(min: uint, max: uint, map: SmallIntMap) { +fn append_sequential(min: uint, max: uint, map: &mut SmallIntMap) { for uint::range(min, max) |i| { map.insert(i, i + 22u); } } -fn check_sequential(min: uint, max: uint, map: SmallIntMap) { +fn check_sequential(min: uint, max: uint, map: &SmallIntMap) { for uint::range(min, max) |i| { - assert map.get(i) == i + 22u; + assert *map.get(&i) == i + 22u; } } @@ -43,11 +42,11 @@ fn main() { let mut appendf = 0.0; for uint::range(0u, rep) |_r| { - let map = smallintmap::mk(); + let mut map = SmallIntMap::new(); let start = std::time::precise_time_s(); - append_sequential(0u, max, map); + append_sequential(0u, max, &mut map); let mid = std::time::precise_time_s(); - check_sequential(0u, max, map); + check_sequential(0u, max, &map); let end = std::time::precise_time_s(); checkf += (end - mid) as float;