diff --git a/src/libcore/condition.rs b/src/libcore/condition.rs index ed94f2ef2c45c..dc6c80228dd74 100644 --- a/src/libcore/condition.rs +++ b/src/libcore/condition.rs @@ -28,7 +28,7 @@ pub struct Condition<'self, T, U> { } pub impl<'self, T, U> Condition<'self, T, U> { - fn trap(&self, h: &'self fn(T) -> U) -> Trap<'self, T, U> { + fn trap(&'self self, h: &'self fn(T) -> U) -> Trap<'self, T, U> { unsafe { let p : *RustClosure = ::cast::transmute(&h); let prev = task::local_data::local_data_get(self.key); diff --git a/src/libcore/container.rs b/src/libcore/container.rs index a1836d16fd733..88c78aebfc5c7 100644 --- a/src/libcore/container.rs +++ b/src/libcore/container.rs @@ -25,6 +25,7 @@ pub trait Mutable: Container { fn clear(&mut self); } +#[cfg(stage0)] pub trait Map: Mutable { /// Return true if the map contains a value for the specified key fn contains_key(&self, key: &K) -> bool; @@ -57,6 +58,41 @@ pub trait Map: Mutable { fn remove(&mut self, key: &K) -> bool; } +#[cfg(stage1)] +#[cfg(stage2)] +#[cfg(stage3)] +pub trait Map: Mutable { + /// Return true if the map contains a value for the specified key + fn contains_key(&self, key: &K) -> bool; + + // Visits all keys and values + fn each<'a>(&'a self, f: &fn(&K, &'a V) -> bool); + + /// Visit all keys + fn each_key(&self, f: &fn(&K) -> bool); + + /// Visit all values + fn each_value<'a>(&'a self, f: &fn(&'a V) -> bool); + + /// Iterate over the map and mutate the contained values + fn mutate_values(&mut self, f: &fn(&K, &mut V) -> bool); + + /// Return a reference to the value corresponding to the key + fn find<'a>(&'a self, key: &K) -> Option<&'a V>; + + /// Return a mutable reference to the value corresponding to the key + fn find_mut<'a>(&'a mut self, key: &K) -> Option<&'a mut V>; + + /// 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: K, value: V) -> bool; + + /// 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: &K) -> bool; +} + pub trait Set: Mutable { /// Return true if the set contains a value fn contains(&self, value: &T) -> bool; diff --git a/src/libcore/hashmap.rs b/src/libcore/hashmap.rs index d4af0ffe7fe7b..2869c198ca2fc 100644 --- a/src/libcore/hashmap.rs +++ b/src/libcore/hashmap.rs @@ -186,6 +186,7 @@ priv impl HashMap { } } + #[cfg(stage0)] #[inline(always)] fn value_for_bucket(&self, idx: uint) -> &'self V { match self.buckets[idx] { @@ -194,6 +195,18 @@ priv impl HashMap { } } + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + #[inline(always)] + fn value_for_bucket<'a>(&'a self, idx: uint) -> &'a V { + match self.buckets[idx] { + Some(ref bkt) => &bkt.value, + None => fail!(~"HashMap::find: internal logic error"), + } + } + + #[cfg(stage0)] #[inline(always)] fn mut_value_for_bucket(&mut self, idx: uint) -> &'self mut V { match self.buckets[idx] { @@ -202,6 +215,17 @@ priv impl HashMap { } } + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + #[inline(always)] + fn mut_value_for_bucket<'a>(&'a mut self, idx: uint) -> &'a mut V { + match self.buckets[idx] { + Some(ref mut bkt) => &mut bkt.value, + None => unreachable() + } + } + /// Inserts the key value pair into the buckets. /// Assumes that there will be a bucket. /// True if there was no previous entry with that key @@ -307,6 +331,7 @@ impl Map for HashMap { } /// Visit all key-value pairs + #[cfg(stage0)] fn each(&self, blk: &fn(&'self K, &'self V) -> bool) { for uint::range(0, self.buckets.len()) |i| { for self.buckets[i].each |bucket| { @@ -317,19 +342,41 @@ impl Map for HashMap { } } + /// Visit all key-value pairs + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn each<'a>(&'a self, blk: &fn(&'a K, &'a V) -> bool) { + for uint::range(0, self.buckets.len()) |i| { + for self.buckets[i].each |bucket| { + if !blk(&bucket.key, &bucket.value) { + return; + } + } + } + } + /// Visit all keys fn each_key(&self, blk: &fn(k: &K) -> bool) { self.each(|k, _| blk(k)) } /// Visit all values + #[cfg(stage0)] fn each_value(&self, blk: &fn(v: &V) -> bool) { self.each(|_, v| blk(v)) } + /// Visit all values + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn each_value<'a>(&'a self, blk: &fn(v: &'a V) -> bool) { + self.each(|_, v| blk(v)) + } + /// Iterate over the map and mutate the contained values - fn mutate_values(&mut self, blk: &fn(&'self K, - &'self mut V) -> bool) { + fn mutate_values(&mut self, blk: &fn(&K, &mut V) -> bool) { for uint::range(0, self.buckets.len()) |i| { match self.buckets[i] { Some(Bucket{key: ref key, value: ref mut value, _}) => { @@ -341,6 +388,7 @@ impl Map for HashMap { } /// Return a reference to the value corresponding to the key + #[cfg(stage0)] fn find(&self, k: &K) -> Option<&'self V> { match self.bucket_for_key(k) { FoundEntry(idx) => Some(self.value_for_bucket(idx)), @@ -348,7 +396,19 @@ impl Map for HashMap { } } + /// Return a reference to the value corresponding to the key + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn find<'a>(&'a self, k: &K) -> Option<&'a V> { + match self.bucket_for_key(k) { + FoundEntry(idx) => Some(self.value_for_bucket(idx)), + TableFull | FoundHole(_) => None, + } + } + /// Return a mutable reference to the value corresponding to the key + #[cfg(stage0)] fn find_mut(&mut self, k: &K) -> Option<&'self mut V> { let idx = match self.bucket_for_key(k) { FoundEntry(idx) => idx, @@ -359,6 +419,20 @@ impl Map for HashMap { } } + /// Return a mutable reference to the value corresponding to the key + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn find_mut<'a>(&'a mut self, k: &K) -> Option<&'a mut V> { + let idx = match self.bucket_for_key(k) { + FoundEntry(idx) => idx, + TableFull | FoundHole(_) => return None + }; + unsafe { // FIXME(#4903)---requires flow-sensitive borrow checker + Some(::cast::transmute_mut_region(self.mut_value_for_bucket(idx))) + } + } + /// 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. @@ -431,6 +505,7 @@ pub impl HashMap { /// Return the value corresponding to the key in the map, or insert /// and return the value if it doesn't exist. + #[cfg(stage0)] fn find_or_insert(&mut self, k: K, v: V) -> &'self V { if self.size >= self.resize_at { // n.b.: We could also do this after searching, so @@ -459,8 +534,42 @@ pub impl HashMap { } } + /// Return the value corresponding to the key in the map, or insert + /// and return the value if it doesn't exist. + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn find_or_insert<'a>(&'a mut self, k: K, v: V) -> &'a V { + if self.size >= self.resize_at { + // n.b.: We could also do this after searching, so + // that we do not resize if this call to insert is + // simply going to update a key in place. My sense + // though is that it's worse to have to search through + // buckets to find the right spot twice than to just + // resize in this corner case. + self.expand(); + } + + let hash = k.hash_keyed(self.k0, self.k1) as uint; + let idx = match self.bucket_for_key_with_hash(hash, &k) { + TableFull => fail!(~"Internal logic error"), + FoundEntry(idx) => idx, + FoundHole(idx) => { + self.buckets[idx] = Some(Bucket{hash: hash, key: k, + value: v}); + self.size += 1; + idx + }, + }; + + unsafe { // FIXME(#4903)---requires flow-sensitive borrow checker + ::cast::transmute_region(self.value_for_bucket(idx)) + } + } + /// Return the value corresponding to the key in the map, or create, /// insert, and return a new value if it doesn't exist. + #[cfg(stage0)] fn find_or_insert_with(&mut self, k: K, f: &fn(&K) -> V) -> &'self V { if self.size >= self.resize_at { // n.b.: We could also do this after searching, so @@ -490,6 +599,40 @@ pub impl HashMap { } } + /// Return the value corresponding to the key in the map, or create, + /// insert, and return a new value if it doesn't exist. + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn find_or_insert_with<'a>(&'a mut self, k: K, f: &fn(&K) -> V) -> &'a V { + if self.size >= self.resize_at { + // n.b.: We could also do this after searching, so + // that we do not resize if this call to insert is + // simply going to update a key in place. My sense + // though is that it's worse to have to search through + // buckets to find the right spot twice than to just + // resize in this corner case. + self.expand(); + } + + let hash = k.hash_keyed(self.k0, self.k1) as uint; + let idx = match self.bucket_for_key_with_hash(hash, &k) { + TableFull => fail!(~"Internal logic error"), + FoundEntry(idx) => idx, + FoundHole(idx) => { + let v = f(&k); + self.buckets[idx] = Some(Bucket{hash: hash, key: k, + value: v}); + self.size += 1; + idx + }, + }; + + unsafe { // FIXME(#4903)---requires flow-sensitive borrow checker + ::cast::transmute_region(self.value_for_bucket(idx)) + } + } + fn consume(&mut self, f: &fn(K, V)) { let mut buckets = ~[]; self.buckets <-> buckets; @@ -506,6 +649,7 @@ pub impl HashMap { } } + #[cfg(stage0)] fn get(&self, k: &K) -> &'self V { match self.find(k) { Some(v) => v, @@ -513,6 +657,16 @@ pub impl HashMap { } } + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn get<'a>(&'a self, k: &K) -> &'a V { + match self.find(k) { + Some(v) => v, + None => fail!(fmt!("No entry found for key: %?", k)), + } + } + /// Return true if the map contains a value for the specified key, /// using equivalence fn contains_key_equiv>(&self, key: &Q) @@ -525,6 +679,7 @@ pub impl HashMap { /// Return the value corresponding to the key in the map, using /// equivalence + #[cfg(stage0)] fn find_equiv>(&self, k: &Q) -> Option<&'self V> { match self.bucket_for_key_equiv(k) { @@ -532,6 +687,20 @@ pub impl HashMap { TableFull | FoundHole(_) => None, } } + + /// Return the value corresponding to the key in the map, using + /// equivalence + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn find_equiv<'a, Q:Hash + IterBytes + Equiv>( + &'a self, k: &Q) -> Option<&'a V> + { + match self.bucket_for_key_equiv(k) { + FoundEntry(idx) => Some(self.value_for_bucket(idx)), + TableFull | FoundHole(_) => None, + } + } } impl Eq for HashMap { diff --git a/src/libcore/option.rs b/src/libcore/option.rs index de1482e2c3918..9b7276879c123 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -101,11 +101,21 @@ impl> Add, Option> for Option { impl BaseIter for Option { /// Performs an operation on the contained value by reference + #[cfg(stage0)] #[inline(always)] fn each(&self, f: &fn(x: &'self T) -> bool) { match *self { None => (), Some(ref t) => { f(t); } } } + /// Performs an operation on the contained value by reference + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + #[inline(always)] + fn each<'a>(&'a self, f: &fn(x: &'a T) -> bool) { + match *self { None => (), Some(ref t) => { f(t); } } + } + #[inline(always)] fn size_hint(&self) -> Option { if self.is_some() { Some(1) } else { Some(0) } @@ -113,10 +123,19 @@ impl BaseIter for Option { } impl MutableIter for Option { + #[cfg(stage0)] #[inline(always)] fn each_mut(&mut self, f: &fn(&'self mut T) -> bool) { match *self { None => (), Some(ref mut t) => { f(t); } } } + + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + #[inline(always)] + fn each_mut<'a>(&'a mut self, f: &fn(&'a mut T) -> bool) { + match *self { None => (), Some(ref mut t) => { f(t); } } + } } impl ExtendedIter for Option { @@ -182,17 +201,40 @@ pub impl Option { * Update an optional value by optionally running its content by reference * through a function that returns an option. */ + #[cfg(stage0)] #[inline(always)] fn chain_ref(&self, f: &fn(x: &'self T) -> Option) -> Option { match *self { Some(ref x) => f(x), None => None } } + /** + * Update an optional value by optionally running its content by reference + * through a function that returns an option. + */ + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + #[inline(always)] + fn chain_ref<'a, U>(&'a self, f: &fn(x: &'a T) -> Option) -> Option { + match *self { Some(ref x) => f(x), None => None } + } + /// Maps a `some` value from one type to another by reference + #[cfg(stage0)] #[inline(always)] fn map(&self, f: &fn(&'self T) -> U) -> Option { match *self { Some(ref x) => Some(f(x)), None => None } } + /// Maps a `some` value from one type to another by reference + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + #[inline(always)] + fn map<'a, U>(&self, f: &fn(&'a T) -> U) -> Option { + match *self { Some(ref x) => Some(f(x)), None => None } + } + /// As `map`, but consumes the option and gives `f` ownership to avoid /// copying. #[inline(always)] @@ -201,11 +243,21 @@ pub impl Option { } /// Applies a function to the contained value or returns a default + #[cfg(stage0)] #[inline(always)] fn map_default(&self, def: U, f: &fn(&'self T) -> U) -> U { match *self { None => def, Some(ref t) => f(t) } } + /// Applies a function to the contained value or returns a default + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + #[inline(always)] + fn map_default<'a, U>(&'a self, def: U, f: &fn(&'a T) -> U) -> U { + match *self { None => def, Some(ref t) => f(t) } + } + /// As `map_default`, but consumes the option and gives `f` /// ownership to avoid copying. #[inline(always)] @@ -244,6 +296,7 @@ pub impl Option { case explicitly. */ #[inline(always)] + #[cfg(stage0)] fn get_ref(&self) -> &'self T { match *self { Some(ref x) => x, @@ -251,6 +304,31 @@ pub impl Option { } } + /** + Gets an immutable reference to the value inside an option. + + # Failure + + Fails if the value equals `None` + + # Safety note + + In general, because this function may fail, its use is discouraged + (calling `get` on `None` is akin to dereferencing a null pointer). + Instead, prefer to use pattern matching and handle the `None` + case explicitly. + */ + #[inline(always)] + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn get_ref<'a>(&'a self) -> &'a T { + match *self { + Some(ref x) => x, + None => fail!(~"option::get_ref none") + } + } + /** Gets a mutable reference to the value inside an option. @@ -266,6 +344,7 @@ pub impl Option { case explicitly. */ #[inline(always)] + #[cfg(stage0)] fn get_mut_ref(&mut self) -> &'self mut T { match *self { Some(ref mut x) => x, @@ -273,6 +352,31 @@ pub impl Option { } } + /** + Gets a mutable reference to the value inside an option. + + # Failure + + Fails if the value equals `None` + + # Safety note + + In general, because this function may fail, its use is discouraged + (calling `get` on `None` is akin to dereferencing a null pointer). + Instead, prefer to use pattern matching and handle the `None` + case explicitly. + */ + #[inline(always)] + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn get_mut_ref<'a>(&'a mut self) -> &'a mut T { + match *self { + Some(ref mut x) => x, + None => fail!(~"option::get_mut_ref none") + } + } + #[inline(always)] fn unwrap(self) -> T { /*! diff --git a/src/libcore/result.rs b/src/libcore/result.rs index 8fd81a2060342..58e281c29c605 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -226,9 +226,16 @@ pub fn map_err(res: &Result, op: &fn(&E) -> F) } pub impl Result { + #[cfg(stage0)] #[inline(always)] fn get_ref(&self) -> &'self T { get_ref(self) } + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + #[inline(always)] + fn get_ref<'a>(&'a self) -> &'a T { get_ref(self) } + #[inline(always)] fn is_ok(&self) -> bool { is_ok(self) } diff --git a/src/libcore/rt/rtio.rs b/src/libcore/rt/rtio.rs index 55e062de85b06..6a7c3970c0091 100644 --- a/src/libcore/rt/rtio.rs +++ b/src/libcore/rt/rtio.rs @@ -22,7 +22,12 @@ pub trait EventLoop { fn run(&mut self); fn callback(&mut self, ~fn()); /// The asynchronous I/O services. Not all event loops may provide one + #[cfg(stage0)] fn io(&mut self) -> Option<&'self mut IoFactoryObject>; + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn io<'a>(&'a mut self) -> Option<&'a mut IoFactoryObject>; } pub trait IoFactory { diff --git a/src/libcore/rt/sched.rs b/src/libcore/rt/sched.rs index 46ea5713e2af3..25f446fb86d19 100644 --- a/src/libcore/rt/sched.rs +++ b/src/libcore/rt/sched.rs @@ -272,6 +272,7 @@ pub impl Scheduler { // XXX: Hack. This should return &'self mut but I don't know how to // make the borrowcheck happy + #[cfg(stage0)] fn task_from_last_cleanup_job(&mut self) -> &mut Task { assert!(!self.cleanup_jobs.is_empty()); let last_job: &'self mut CleanupJob = &mut self.cleanup_jobs[0]; @@ -285,6 +286,25 @@ pub impl Scheduler { // borrows return unsafe { transmute::<&Task, &mut Task>(last_task) }; } + + // XXX: Hack. This should return &'self mut but I don't know how to + // make the borrowcheck happy + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn task_from_last_cleanup_job<'a>(&'a mut self) -> &mut Task { + assert!(!self.cleanup_jobs.is_empty()); + let last_job: &'a mut CleanupJob = &mut self.cleanup_jobs[0]; + let last_task: &'a Task = match last_job { + &RescheduleTask(~ref task) => task, + &RecycleTask(~ref task) => task, + &GiveTask(~ref task, _) => task, + }; + // XXX: Pattern matching mutable pointers above doesn't work + // because borrowck thinks the three patterns are conflicting + // borrows + return unsafe { transmute::<&Task, &mut Task>(last_task) }; + } } static TASK_MIN_STACK_SIZE: uint = 10000000; // XXX: Too much stack @@ -354,6 +374,7 @@ impl ThreadLocalScheduler { } } + #[cfg(stage0)] fn get_scheduler(&mut self) -> &'self mut Scheduler { unsafe { let key = match self { &ThreadLocalScheduler(key) => key }; @@ -370,6 +391,25 @@ impl ThreadLocalScheduler { } } + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn get_scheduler<'a>(&'a mut self) -> &'a mut Scheduler { + unsafe { + let key = match self { &ThreadLocalScheduler(key) => key }; + let mut value: *mut c_void = tls::get(key); + assert!(value.is_not_null()); + { + let value_ptr = &mut value; + let sched: &mut ~Scheduler = { + transmute::<&mut *mut c_void, &mut ~Scheduler>(value_ptr) + }; + let sched: &mut Scheduler = &mut **sched; + return sched; + } + } + } + fn take_scheduler(&mut self) -> ~Scheduler { unsafe { let key = match self { &ThreadLocalScheduler(key) => key }; diff --git a/src/libcore/rt/uvio.rs b/src/libcore/rt/uvio.rs index 37f29d1a5c0fe..7162ed27a9d77 100644 --- a/src/libcore/rt/uvio.rs +++ b/src/libcore/rt/uvio.rs @@ -67,9 +67,17 @@ impl EventLoop for UvEventLoop { } } + #[cfg(stage0)] fn io(&mut self) -> Option<&'self mut IoFactoryObject> { Some(&mut self.uvio) } + + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn io<'a>(&'a mut self) -> Option<&'a mut IoFactoryObject> { + Some(&mut self.uvio) + } } #[test] @@ -89,9 +97,17 @@ fn test_callback_run_once() { pub struct UvIoFactory(Loop); pub impl UvIoFactory { + #[cfg(stage0)] fn uv_loop(&mut self) -> &'self mut Loop { match self { &UvIoFactory(ref mut ptr) => ptr } } + + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn uv_loop<'a>(&'a mut self) -> &'a mut Loop { + match self { &UvIoFactory(ref mut ptr) => ptr } + } } impl IoFactory for UvIoFactory { diff --git a/src/libcore/task/mod.rs b/src/libcore/task/mod.rs index 502efcf9dc6cb..e4ee430cdda64 100644 --- a/src/libcore/task/mod.rs +++ b/src/libcore/task/mod.rs @@ -39,7 +39,7 @@ use result::Result; use comm::{stream, Chan, GenericChan, GenericPort, Port}; use prelude::*; use result; -use task::rt::{task_id, sched_id, rust_task}; +use task::rt::{task_id, sched_id}; use util; use util::replace; use unstable::finally::Finally; diff --git a/src/libcore/trie.rs b/src/libcore/trie.rs index f6a92a213859e..f4e9ddbdd90a1 100644 --- a/src/libcore/trie.rs +++ b/src/libcore/trie.rs @@ -56,10 +56,20 @@ impl Map for TrieMap { /// Visit all key-value pairs in order #[inline(always)] + #[cfg(stage0)] fn each(&self, f: &fn(&uint, &'self T) -> bool) { self.root.each(f); } + /// Visit all key-value pairs in order + #[inline(always)] + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn each<'a>(&'a self, f: &fn(&uint, &'a T) -> bool) { + self.root.each(f); + } + /// Visit all keys in order #[inline(always)] fn each_key(&self, f: &fn(&uint) -> bool) { @@ -68,10 +78,20 @@ impl Map for TrieMap { /// Visit all values in order #[inline(always)] + #[cfg(stage0)] fn each_value(&self, f: &fn(&T) -> bool) { self.each(|_, v| f(v)) } + /// Visit all values in order + #[inline(always)] + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn each_value<'a>(&'a self, f: &fn(&'a T) -> bool) { + self.each(|_, v| f(v)) + } + /// Iterate over the map and mutate the contained values #[inline(always)] fn mutate_values(&mut self, f: &fn(&uint, &mut T) -> bool) { @@ -79,6 +99,7 @@ impl Map for TrieMap { } /// Return a reference to the value corresponding to the key + #[cfg(stage0)] #[inline(hint)] fn find(&self, key: &uint) -> Option<&'self T> { let mut node: &'self TrieNode = &self.root; @@ -99,12 +120,46 @@ impl Map for TrieMap { } } + /// Return a reference to the value corresponding to the key + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + #[inline(hint)] + fn find<'a>(&'a self, key: &uint) -> Option<&'a T> { + let mut node: &'a TrieNode = &self.root; + let mut idx = 0; + loop { + match node.children[chunk(*key, idx)] { + Internal(ref x) => node = &**x, + External(stored, ref value) => { + if stored == *key { + return Some(value) + } else { + return None + } + } + Nothing => return None + } + idx += 1; + } + } + /// Return a mutable reference to the value corresponding to the key + #[cfg(stage0)] #[inline(always)] fn find_mut(&mut self, key: &uint) -> Option<&'self mut T> { find_mut(&mut self.root.children[chunk(*key, 0)], *key, 1) } + /// Return a mutable reference to the value corresponding to the key + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + #[inline(always)] + fn find_mut<'a>(&'a mut self, key: &uint) -> Option<&'a mut T> { + find_mut(&mut self.root.children[chunk(*key, 0)], *key, 1) + } + /// 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. @@ -138,10 +193,20 @@ pub impl TrieMap { /// Visit all key-value pairs in reverse order #[inline(always)] + #[cfg(stage0)] fn each_reverse(&self, f: &fn(&uint, &'self T) -> bool) { self.root.each_reverse(f); } + /// Visit all key-value pairs in reverse order + #[inline(always)] + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn each_reverse<'a>(&'a self, f: &fn(&uint, &'a T) -> bool) { + self.root.each_reverse(f); + } + /// Visit all keys in reverse order #[inline(always)] fn each_key_reverse(&self, f: &fn(&uint) -> bool) { @@ -233,6 +298,7 @@ impl TrieNode { } impl TrieNode { + #[cfg(stage0)] fn each(&self, f: &fn(&uint, &'self T) -> bool) -> bool { for uint::range(0, self.children.len()) |idx| { match self.children[idx] { @@ -244,6 +310,21 @@ impl TrieNode { true } + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn each<'a>(&'a self, f: &fn(&uint, &'a T) -> bool) -> bool { + for uint::range(0, self.children.len()) |idx| { + match self.children[idx] { + Internal(ref x) => if !x.each(f) { return false }, + External(k, ref v) => if !f(&k, v) { return false }, + Nothing => () + } + } + true + } + + #[cfg(stage0)] fn each_reverse(&self, f: &fn(&uint, &'self T) -> bool) -> bool { for uint::range_rev(self.children.len(), 0) |idx| { match self.children[idx - 1] { @@ -255,7 +336,21 @@ impl TrieNode { true } - fn mutate_values(&mut self, f: &fn(&uint, &mut T) -> bool) -> bool { + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn each_reverse<'a>(&'a self, f: &fn(&uint, &'a T) -> bool) -> bool { + for uint::range_rev(self.children.len(), 0) |idx| { + match self.children[idx - 1] { + Internal(ref x) => if !x.each_reverse(f) { return false }, + External(k, ref v) => if !f(&k, v) { return false }, + Nothing => () + } + } + true + } + + fn mutate_values<'a>(&'a mut self, f: &fn(&uint, &mut T) -> bool) -> bool { for vec::each_mut(self.children) |child| { match *child { Internal(ref mut x) => if !x.mutate_values(f) { diff --git a/src/libcore/tuple.rs b/src/libcore/tuple.rs index 8234129e25474..8e908435f3543 100644 --- a/src/libcore/tuple.rs +++ b/src/libcore/tuple.rs @@ -56,11 +56,13 @@ impl Clone for (T, U) { } } +#[cfg(stage0)] pub trait ImmutableTuple { fn first_ref(&self) -> &'self T; fn second_ref(&self) -> &'self U; } +#[cfg(stage0)] impl ImmutableTuple for (T, U) { #[inline(always)] fn first_ref(&self) -> &'self T { @@ -76,6 +78,32 @@ impl ImmutableTuple for (T, U) { } } +#[cfg(stage1)] +#[cfg(stage2)] +#[cfg(stage3)] +pub trait ImmutableTuple { + fn first_ref<'a>(&'a self) -> &'a T; + fn second_ref<'a>(&'a self) -> &'a U; +} + +#[cfg(stage1)] +#[cfg(stage2)] +#[cfg(stage3)] +impl ImmutableTuple for (T, U) { + #[inline(always)] + fn first_ref<'a>(&'a self) -> &'a T { + match *self { + (ref t, _) => t, + } + } + #[inline(always)] + fn second_ref<'a>(&'a self) -> &'a U { + match *self { + (_, ref u) => u, + } + } +} + pub trait ExtendedTupleOps { fn zip(&self) -> ~[(A, B)]; fn map(&self, f: &fn(a: &A, b: &B) -> C) -> ~[C]; diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs index 5b06591f9ecc8..7940502d27e48 100644 --- a/src/libcore/vec.rs +++ b/src/libcore/vec.rs @@ -1763,6 +1763,7 @@ impl<'self,T:Copy> CopyableVector for &'self const [T] { } } +#[cfg(stage0)] pub trait ImmutableVector { fn slice(&self, start: uint, end: uint) -> &'self [T]; fn head(&self) -> &'self T; @@ -1785,6 +1786,7 @@ pub trait ImmutableVector { } /// Extension methods for vectors +#[cfg(stage0)] impl<'self,T> ImmutableVector for &'self [T] { /// Return a slice that points into another slice. #[inline] @@ -1893,6 +1895,142 @@ impl<'self,T> ImmutableVector for &'self [T] { } } +#[cfg(stage1)] +#[cfg(stage2)] +#[cfg(stage3)] +pub trait ImmutableVector<'self, T> { + fn slice(&self, start: uint, end: uint) -> &'self [T]; + fn head(&self) -> &'self T; + fn head_opt(&self) -> Option<&'self T>; + fn tail(&self) -> &'self [T]; + fn tailn(&self, n: uint) -> &'self [T]; + fn init(&self) -> &'self [T]; + fn initn(&self, n: uint) -> &'self [T]; + fn last(&self) -> &'self T; + fn last_opt(&self) -> Option<&'self T>; + fn each_reverse(&self, blk: &fn(&T) -> bool); + fn eachi_reverse(&self, blk: &fn(uint, &T) -> bool); + fn foldr(&self, z: U, p: &fn(t: &T, u: U) -> U) -> U; + fn map(&self, f: &fn(t: &T) -> U) -> ~[U]; + fn mapi(&self, f: &fn(uint, t: &T) -> U) -> ~[U]; + fn map_r(&self, f: &fn(x: &T) -> U) -> ~[U]; + fn alli(&self, f: &fn(uint, t: &T) -> bool) -> bool; + fn flat_map(&self, f: &fn(t: &T) -> ~[U]) -> ~[U]; + fn filter_mapped(&self, f: &fn(t: &T) -> Option) -> ~[U]; +} + +/// Extension methods for vectors +#[cfg(stage1)] +#[cfg(stage2)] +#[cfg(stage3)] +impl<'self,T> ImmutableVector<'self, T> for &'self [T] { + /// Return a slice that points into another slice. + #[inline] + fn slice(&self, start: uint, end: uint) -> &'self [T] { + slice(*self, start, end) + } + + /// Returns the first element of a vector, failing if the vector is empty. + #[inline] + fn head(&self) -> &'self T { head(*self) } + + /// Returns the first element of a vector + #[inline] + fn head_opt(&self) -> Option<&'self T> { head_opt(*self) } + + /// Returns all but the first element of a vector + #[inline] + fn tail(&self) -> &'self [T] { tail(*self) } + + /// Returns all but the first `n' elements of a vector + #[inline] + fn tailn(&self, n: uint) -> &'self [T] { tailn(*self, n) } + + /// Returns all but the last elemnt of a vector + #[inline] + fn init(&self) -> &'self [T] { init(*self) } + + /// Returns all but the last `n' elemnts of a vector + #[inline] + fn initn(&self, n: uint) -> &'self [T] { initn(*self, n) } + + /// Returns the last element of a `v`, failing if the vector is empty. + #[inline] + fn last(&self) -> &'self T { last(*self) } + + /// Returns the last element of a `v`, failing if the vector is empty. + #[inline] + fn last_opt(&self) -> Option<&'self T> { last_opt(*self) } + + /// Iterates over a vector's elements in reverse. + #[inline] + fn each_reverse(&self, blk: &fn(&T) -> bool) { + each_reverse(*self, blk) + } + + /// Iterates over a vector's elements and indices in reverse. + #[inline] + fn eachi_reverse(&self, blk: &fn(uint, &T) -> bool) { + eachi_reverse(*self, blk) + } + + /// Reduce a vector from right to left + #[inline] + fn foldr(&self, z: U, p: &fn(t: &T, u: U) -> U) -> U { + foldr(*self, z, p) + } + + /// Apply a function to each element of a vector and return the results + #[inline] + fn map(&self, f: &fn(t: &T) -> U) -> ~[U] { map(*self, f) } + + /** + * Apply a function to the index and value of each element in the vector + * and return the results + */ + fn mapi(&self, f: &fn(uint, t: &T) -> U) -> ~[U] { + mapi(*self, f) + } + + #[inline] + fn map_r(&self, f: &fn(x: &T) -> U) -> ~[U] { + let mut r = ~[]; + let mut i = 0; + while i < self.len() { + r.push(f(&self[i])); + i += 1; + } + r + } + + /** + * Returns true if the function returns true for all elements. + * + * If the vector is empty, true is returned. + */ + fn alli(&self, f: &fn(uint, t: &T) -> bool) -> bool { + alli(*self, f) + } + /** + * Apply a function to each element of a vector and return a concatenation + * of each result vector + */ + #[inline] + fn flat_map(&self, f: &fn(t: &T) -> ~[U]) -> ~[U] { + flat_map(*self, f) + } + /** + * Apply a function to each element of a vector and return the results + * + * If function `f` returns `none` then that element is excluded from + * the resulting vector. + */ + #[inline] + fn filter_mapped(&self, f: &fn(t: &T) -> Option) -> ~[U] { + filter_mapped(*self, f) + } +} + pub trait ImmutableEqVector { fn position(&self, f: &fn(t: &T) -> bool) -> Option; fn position_elem(&self, t: &T) -> Option; @@ -2353,6 +2491,7 @@ pub mod bytes { // ___________________________________________________________________________ // ITERATION TRAIT METHODS +#[cfg(stage0)] impl<'self,A> iter::BaseIter for &'self [A] { #[inline(always)] fn each(&self, blk: &fn(v: &'self A) -> bool) { each(*self, blk) } @@ -2360,7 +2499,18 @@ impl<'self,A> iter::BaseIter for &'self [A] { fn size_hint(&self) -> Option { Some(self.len()) } } +#[cfg(stage1)] +#[cfg(stage2)] +#[cfg(stage3)] +impl<'self,A> iter::BaseIter for &'self [A] { + #[inline(always)] + fn each<'a>(&'a self, blk: &fn(v: &'a A) -> bool) { each(*self, blk) } + #[inline(always)] + fn size_hint(&self) -> Option { Some(self.len()) } +} + // FIXME(#4148): This should be redundant +#[cfg(stage0)] impl iter::BaseIter for ~[A] { #[inline(always)] fn each(&self, blk: &fn(v: &'self A) -> bool) { each(*self, blk) } @@ -2369,6 +2519,18 @@ impl iter::BaseIter for ~[A] { } // FIXME(#4148): This should be redundant +#[cfg(stage1)] +#[cfg(stage2)] +#[cfg(stage3)] +impl iter::BaseIter for ~[A] { + #[inline(always)] + fn each<'a>(&'a self, blk: &fn(v: &'a A) -> bool) { each(*self, blk) } + #[inline(always)] + fn size_hint(&self) -> Option { Some(self.len()) } +} + +// FIXME(#4148): This should be redundant +#[cfg(stage0)] impl iter::BaseIter for @[A] { #[inline(always)] fn each(&self, blk: &fn(v: &'self A) -> bool) { each(*self, blk) } @@ -2376,6 +2538,18 @@ impl iter::BaseIter for @[A] { fn size_hint(&self) -> Option { Some(self.len()) } } +// FIXME(#4148): This should be redundant +#[cfg(stage1)] +#[cfg(stage2)] +#[cfg(stage3)] +impl iter::BaseIter for @[A] { + #[inline(always)] + fn each<'a>(&'a self, blk: &fn(v: &'a A) -> bool) { each(*self, blk) } + #[inline(always)] + fn size_hint(&self) -> Option { Some(self.len()) } +} + +#[cfg(stage0)] impl<'self,A> iter::MutableIter for &'self mut [A] { #[inline(always)] fn each_mut(&mut self, blk: &fn(v: &'self mut A) -> bool) { @@ -2383,7 +2557,18 @@ impl<'self,A> iter::MutableIter for &'self mut [A] { } } +#[cfg(stage1)] +#[cfg(stage2)] +#[cfg(stage3)] +impl<'self,A> iter::MutableIter for &'self mut [A] { + #[inline(always)] + fn each_mut<'a>(&'a mut self, blk: &fn(v: &'a mut A) -> bool) { + each_mut(*self, blk) + } +} + // FIXME(#4148): This should be redundant +#[cfg(stage0)] impl iter::MutableIter for ~[A] { #[inline(always)] fn each_mut(&mut self, blk: &fn(v: &'self mut A) -> bool) { @@ -2391,6 +2576,16 @@ impl iter::MutableIter for ~[A] { } } +#[cfg(stage1)] +#[cfg(stage2)] +#[cfg(stage3)] +impl iter::MutableIter for ~[A] { + #[inline(always)] + fn each_mut<'a>(&'a mut self, blk: &fn(v: &'a mut A) -> bool) { + each_mut(*self, blk) + } +} + // FIXME(#4148): This should be redundant impl iter::MutableIter for @mut [A] { #[inline(always)]