From: Sangeun Kim Date: Fri, 26 Jul 2013 04:53:29 +0000 (+0900) Subject: Move EnumSet into libextra X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=a76943be47cfa3931c09a79cd741c383d8b76a5b;p=rust.git Move EnumSet into libextra --- diff --git a/src/libextra/enum_set.rs b/src/libextra/enum_set.rs new file mode 100644 index 00000000000..25501faa02e --- /dev/null +++ b/src/libextra/enum_set.rs @@ -0,0 +1,288 @@ +// 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. + +use std::iterator::Iterator; + +#[deriving(Clone, Eq, IterBytes, ToStr)] +/// A specialized Set implementation to use enum types. +pub struct EnumSet { + // We must maintain the invariant that no bits are set + // for which no variant exists + priv bits: uint +} + +/// An iterface for casting C-like enum to uint and back. +pub trait CLike { + /// Converts C-like enum to uint. + pub fn to_uint(&self) -> uint; + /// Converts uint to C-like enum. + pub fn from_uint(uint) -> Self; +} + +fn bit(e: E) -> uint { + 1 << e.to_uint() +} + +impl EnumSet { + /// Returns an empty EnumSet. + pub fn empty() -> EnumSet { + EnumSet {bits: 0} + } + + /// Returns true if an EnumSet is empty. + pub fn is_empty(&self) -> bool { + self.bits == 0 + } + + /// Returns true if an EnumSet contains any enum of a given EnumSet + pub fn intersects(&self, e: EnumSet) -> bool { + (self.bits & e.bits) != 0 + } + + /// Returns an intersection of both EnumSets. + pub fn intersection(&self, e: EnumSet) -> EnumSet { + EnumSet {bits: self.bits & e.bits} + } + + /// Returns true if a given EnumSet is included in an EnumSet. + pub fn contains(&self, e: EnumSet) -> bool { + (self.bits & e.bits) == e.bits + } + + /// Returns a union of both EnumSets. + pub fn union(&self, e: EnumSet) -> EnumSet { + EnumSet {bits: self.bits | e.bits} + } + + /// Add an enum to an EnumSet + pub fn add(&mut self, e: E) { + self.bits |= bit(e); + } + + /// Returns true if an EnumSet contains a given enum + pub fn contains_elem(&self, e: E) -> bool { + (self.bits & bit(e)) != 0 + } + + /// Returns an iterator over an EnumSet + pub fn iter(&self) -> EnumSetIterator { + EnumSetIterator::new(self.bits) + } +} + +impl Sub, EnumSet> for EnumSet { + fn sub(&self, e: &EnumSet) -> EnumSet { + EnumSet {bits: self.bits & !e.bits} + } +} + +impl BitOr, EnumSet> for EnumSet { + fn bitor(&self, e: &EnumSet) -> EnumSet { + EnumSet {bits: self.bits | e.bits} + } +} + +impl BitAnd, EnumSet> for EnumSet { + fn bitand(&self, e: &EnumSet) -> EnumSet { + EnumSet {bits: self.bits & e.bits} + } +} + +/// An iterator over an EnumSet +pub struct EnumSetIterator { + priv index: uint, + priv bits: uint, +} + +impl EnumSetIterator { + fn new(bits: uint) -> EnumSetIterator { + EnumSetIterator { index: 0, bits: bits } + } +} + +impl Iterator for EnumSetIterator { + fn next(&mut self) -> Option { + if (self.bits == 0) { + return None; + } + + while (self.bits & 1) == 0 { + self.index += 1; + self.bits >>= 1; + } + let elem = CLike::from_uint(self.index); + self.index += 1; + self.bits >>= 1; + Some(elem) + } + + fn size_hint(&self) -> (uint, Option) { + let exact = self.bits.population_count(); + (exact, Some(exact)) + } +} + +#[cfg(test)] +mod test { + + use std::cast; + + use enum_set::*; + + #[deriving(Eq)] + enum Foo { + A, B, C + } + + impl CLike for Foo { + pub fn to_uint(&self) -> uint { + *self as uint + } + + pub fn from_uint(v: uint) -> Foo { + unsafe { cast::transmute(v) } + } + } + + #[test] + fn test_empty() { + let e: EnumSet = EnumSet::empty(); + assert!(e.is_empty()); + } + + /////////////////////////////////////////////////////////////////////////// + // intersect + + #[test] + fn test_two_empties_do_not_intersect() { + let e1: EnumSet = EnumSet::empty(); + let e2: EnumSet = EnumSet::empty(); + assert!(!e1.intersects(e2)); + } + + #[test] + fn test_empty_does_not_intersect_with_full() { + let e1: EnumSet = EnumSet::empty(); + + let mut e2: EnumSet = EnumSet::empty(); + e2.add(A); + e2.add(B); + e2.add(C); + + assert!(!e1.intersects(e2)); + } + + #[test] + fn test_disjoint_intersects() { + let mut e1: EnumSet = EnumSet::empty(); + e1.add(A); + + let mut e2: EnumSet = EnumSet::empty(); + e2.add(B); + + assert!(!e1.intersects(e2)); + } + + #[test] + fn test_overlapping_intersects() { + let mut e1: EnumSet = EnumSet::empty(); + e1.add(A); + + let mut e2: EnumSet = EnumSet::empty(); + e2.add(A); + e2.add(B); + + assert!(e1.intersects(e2)); + } + + /////////////////////////////////////////////////////////////////////////// + // contains and contains_elem + + #[test] + fn test_contains() { + let mut e1: EnumSet = EnumSet::empty(); + e1.add(A); + + let mut e2: EnumSet = EnumSet::empty(); + e2.add(A); + e2.add(B); + + assert!(!e1.contains(e2)); + assert!(e2.contains(e1)); + } + + #[test] + fn test_contains_elem() { + let mut e1: EnumSet = EnumSet::empty(); + e1.add(A); + assert!(e1.contains_elem(A)); + assert!(!e1.contains_elem(B)); + assert!(!e1.contains_elem(C)); + + e1.add(A); + e1.add(B); + assert!(e1.contains_elem(A)); + assert!(e1.contains_elem(B)); + assert!(!e1.contains_elem(C)); + } + + /////////////////////////////////////////////////////////////////////////// + // iter + + #[test] + fn test_iterator() { + let mut e1: EnumSet = EnumSet::empty(); + + let elems: ~[Foo] = e1.iter().collect(); + assert_eq!(~[], elems) + + e1.add(A); + let elems: ~[Foo] = e1.iter().collect(); + assert_eq!(~[A], elems) + + e1.add(C); + let elems: ~[Foo] = e1.iter().collect(); + assert_eq!(~[A,C], elems) + + e1.add(C); + let elems: ~[Foo] = e1.iter().collect(); + assert_eq!(~[A,C], elems) + + e1.add(B); + let elems: ~[Foo] = e1.iter().collect(); + assert_eq!(~[A,B,C], elems) + } + + /////////////////////////////////////////////////////////////////////////// + // operators + + #[test] + fn test_operators() { + let mut e1: EnumSet = EnumSet::empty(); + e1.add(A); + e1.add(C); + + let mut e2: EnumSet = EnumSet::empty(); + e2.add(B); + e2.add(C); + + let e_union = e1 | e2; + let elems: ~[Foo] = e_union.iter().collect(); + assert_eq!(~[A,B,C], elems) + + let e_intersection = e1 & e2; + let elems: ~[Foo] = e_intersection.iter().collect(); + assert_eq!(~[C], elems) + + let e_subtract = e1 - e2; + let elems: ~[Foo] = e_subtract.iter().collect(); + assert_eq!(~[A], elems) + } +} diff --git a/src/libextra/extra.rs b/src/libextra/extra.rs index e6134bb340c..58929778a59 100644 --- a/src/libextra/extra.rs +++ b/src/libextra/extra.rs @@ -91,6 +91,7 @@ pub mod base64; pub mod rl; pub mod workcache; +pub mod enum_set; #[path="num/bigint.rs"] pub mod bigint; #[path="num/rational.rs"] diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs index ec50f564385..ffd79433b76 100644 --- a/src/librustc/metadata/tyencode.rs +++ b/src/librustc/metadata/tyencode.rs @@ -413,15 +413,14 @@ fn enc_fn_sig(w: @io::Writer, cx: @ctxt, fsig: &ty::FnSig) { } fn enc_bounds(w: @io::Writer, cx: @ctxt, bs: &ty::ParamBounds) { - do bs.builtin_bounds.each |bound| { + for bound in bs.builtin_bounds.iter() { match bound { ty::BoundSend => w.write_char('S'), ty::BoundFreeze => w.write_char('K'), ty::BoundStatic => w.write_char('O'), ty::BoundSized => w.write_char('Z'), } - true - }; + } for &tp in bs.trait_bounds.iter() { w.write_char('I'); diff --git a/src/librustc/middle/kind.rs b/src/librustc/middle/kind.rs index 3bdf0c0f6dc..84eb371d7b3 100644 --- a/src/librustc/middle/kind.rs +++ b/src/librustc/middle/kind.rs @@ -338,12 +338,11 @@ pub fn check_builtin_bounds(cx: Context, ty: ty::t, bounds: ty::BuiltinBounds, { let kind = ty::type_contents(cx.tcx, ty); let mut missing = ty::EmptyBuiltinBounds(); - do bounds.each |bound| { + for bound in bounds.iter() { if !kind.meets_bound(cx.tcx, bound) { missing.add(bound); } - true - }; + } if !missing.is_empty() { any_missing(missing); } diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 48a003ddaf1..a53bdff85f9 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -25,7 +25,6 @@ use util::ppaux::{trait_store_to_str, ty_to_str, vstore_to_str}; use util::ppaux::{Repr, UserString}; use util::common::{indenter}; -use util::enum_set::{EnumSet, CLike}; use std::cast; use std::cmp; @@ -48,6 +47,7 @@ use syntax::opt_vec; use syntax::abi::AbiSet; use syntax; +use extra::enum_set::{EnumSet, CLike}; pub static INITIAL_DISCRIMINANT_VALUE: uint = 0; @@ -2287,7 +2287,7 @@ fn trait_contents(store: TraitStore, mutbl: ast::mutability, // This is like with typarams below, but less "pessimistic" and also // dependent on the trait store. let mut bt = TC_NONE; - do (AllBuiltinBounds() - bounds).each |bound| { + for bound in (AllBuiltinBounds() - bounds).iter() { bt = bt + match bound { BoundStatic if bounds.contains_elem(BoundSend) => TC_NONE, // Send bound implies static bound. @@ -2296,8 +2296,7 @@ fn trait_contents(store: TraitStore, mutbl: ast::mutability, BoundFreeze => TC_MUTABLE, BoundSized => TC_NONE, // don't care if interior is sized }; - true - }; + } st + mt + bt } @@ -2308,7 +2307,7 @@ fn type_param_def_to_contents(cx: ctxt, let _i = indenter(); let mut tc = TC_ALL; - do type_param_def.bounds.builtin_bounds.each |bound| { + for bound in type_param_def.bounds.builtin_bounds.iter() { debug!("tc = %s, bound = %?", tc.to_str(), bound); tc = tc - match bound { BoundStatic => TypeContents::nonstatic(cx), @@ -2317,8 +2316,7 @@ fn type_param_def_to_contents(cx: ctxt, // The dynamic-size bit can be removed at pointer-level, etc. BoundSized => TypeContents::dynamically_sized(cx), }; - true - }; + } debug!("result = %s", tc.to_str()); return tc; diff --git a/src/librustc/rustc.rs b/src/librustc/rustc.rs index c48b30e8141..46414a7a5e2 100644 --- a/src/librustc/rustc.rs +++ b/src/librustc/rustc.rs @@ -96,7 +96,6 @@ pub mod back { pub mod util { pub mod common; pub mod ppaux; - pub mod enum_set; } pub mod lib { diff --git a/src/librustc/util/enum_set.rs b/src/librustc/util/enum_set.rs deleted file mode 100644 index ced29f18f7f..00000000000 --- a/src/librustc/util/enum_set.rs +++ /dev/null @@ -1,318 +0,0 @@ -// 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. - -use std::iterator::Iterator; - -#[deriving(Clone, Eq, IterBytes, ToStr)] -pub struct EnumSet { - // We must maintain the invariant that no bits are set - // for which no variant exists - priv bits: uint -} - -pub trait CLike { - pub fn to_uint(&self) -> uint; - pub fn from_uint(uint) -> Self; -} - -fn bit(e: E) -> uint { - 1 << e.to_uint() -} - -impl EnumSet { - pub fn empty() -> EnumSet { - EnumSet {bits: 0} - } - - pub fn is_empty(&self) -> bool { - self.bits == 0 - } - - pub fn intersects(&self, e: EnumSet) -> bool { - (self.bits & e.bits) != 0 - } - - pub fn intersection(&self, e: EnumSet) -> EnumSet { - EnumSet {bits: self.bits & e.bits} - } - - pub fn contains(&self, e: EnumSet) -> bool { - (self.bits & e.bits) == e.bits - } - - pub fn union(&self, e: EnumSet) -> EnumSet { - EnumSet {bits: self.bits | e.bits} - } - - pub fn add(&mut self, e: E) { - self.bits |= bit(e); - } - - pub fn contains_elem(&self, e: E) -> bool { - (self.bits & bit(e)) != 0 - } - - pub fn each(&self, f: &fn(E) -> bool) -> bool { - let mut bits = self.bits; - let mut index = 0; - while bits != 0 { - if (bits & 1) != 0 { - let e = CLike::from_uint(index); - if !f(e) { - return false; - } - } - index += 1; - bits >>= 1; - } - return true; - } - - pub fn iter(&self) -> EnumSetIterator { - EnumSetIterator::new(self.bits) - } -} - -impl Sub, EnumSet> for EnumSet { - fn sub(&self, e: &EnumSet) -> EnumSet { - EnumSet {bits: self.bits & !e.bits} - } -} - -impl BitOr, EnumSet> for EnumSet { - fn bitor(&self, e: &EnumSet) -> EnumSet { - EnumSet {bits: self.bits | e.bits} - } -} - -impl BitAnd, EnumSet> for EnumSet { - fn bitand(&self, e: &EnumSet) -> EnumSet { - EnumSet {bits: self.bits & e.bits} - } -} - -pub struct EnumSetIterator { - priv index: uint, - priv bits: uint, -} - -impl EnumSetIterator { - fn new(bits: uint) -> EnumSetIterator { - EnumSetIterator { index: 0, bits: bits } - } -} - -impl Iterator for EnumSetIterator { - fn next(&mut self) -> Option { - if (self.bits == 0) { - return None; - } - - while (self.bits & 1) == 0 { - self.index += 1; - self.bits >>= 1; - } - let elem = CLike::from_uint(self.index); - self.index += 1; - self.bits >>= 1; - Some(elem) - } - - fn size_hint(&self) -> (uint, Option) { - let exact = self.bits.population_count(); - (exact, Some(exact)) - } -} - -#[cfg(test)] -mod test { - - use std::cast; - - use util::enum_set::*; - - #[deriving(Eq)] - enum Foo { - A, B, C - } - - impl CLike for Foo { - pub fn to_uint(&self) -> uint { - *self as uint - } - - pub fn from_uint(v: uint) -> Foo { - unsafe { cast::transmute(v) } - } - } - - #[test] - fn test_empty() { - let e: EnumSet = EnumSet::empty(); - assert!(e.is_empty()); - } - - /////////////////////////////////////////////////////////////////////////// - // intersect - - #[test] - fn test_two_empties_do_not_intersect() { - let e1: EnumSet = EnumSet::empty(); - let e2: EnumSet = EnumSet::empty(); - assert!(!e1.intersects(e2)); - } - - #[test] - fn test_empty_does_not_intersect_with_full() { - let e1: EnumSet = EnumSet::empty(); - - let mut e2: EnumSet = EnumSet::empty(); - e2.add(A); - e2.add(B); - e2.add(C); - - assert!(!e1.intersects(e2)); - } - - #[test] - fn test_disjoint_intersects() { - let mut e1: EnumSet = EnumSet::empty(); - e1.add(A); - - let mut e2: EnumSet = EnumSet::empty(); - e2.add(B); - - assert!(!e1.intersects(e2)); - } - - #[test] - fn test_overlapping_intersects() { - let mut e1: EnumSet = EnumSet::empty(); - e1.add(A); - - let mut e2: EnumSet = EnumSet::empty(); - e2.add(A); - e2.add(B); - - assert!(e1.intersects(e2)); - } - - /////////////////////////////////////////////////////////////////////////// - // contains and contains_elem - - #[test] - fn test_contains() { - let mut e1: EnumSet = EnumSet::empty(); - e1.add(A); - - let mut e2: EnumSet = EnumSet::empty(); - e2.add(A); - e2.add(B); - - assert!(!e1.contains(e2)); - assert!(e2.contains(e1)); - } - - #[test] - fn test_contains_elem() { - let mut e1: EnumSet = EnumSet::empty(); - e1.add(A); - assert!(e1.contains_elem(A)); - assert!(!e1.contains_elem(B)); - assert!(!e1.contains_elem(C)); - - e1.add(A); - e1.add(B); - assert!(e1.contains_elem(A)); - assert!(e1.contains_elem(B)); - assert!(!e1.contains_elem(C)); - } - - /////////////////////////////////////////////////////////////////////////// - // iter / each - - #[test] - fn test_iterator() { - let mut e1: EnumSet = EnumSet::empty(); - - let elems: ~[Foo] = e1.iter().collect(); - assert_eq!(~[], elems) - - e1.add(A); - let elems: ~[Foo] = e1.iter().collect(); - assert_eq!(~[A], elems) - - e1.add(C); - let elems: ~[Foo] = e1.iter().collect(); - assert_eq!(~[A,C], elems) - - e1.add(C); - let elems: ~[Foo] = e1.iter().collect(); - assert_eq!(~[A,C], elems) - - e1.add(B); - let elems: ~[Foo] = e1.iter().collect(); - assert_eq!(~[A,B,C], elems) - } - - #[test] - fn test_each() { - let mut e1: EnumSet = EnumSet::empty(); - - assert_eq!(~[], collect(e1)) - - e1.add(A); - assert_eq!(~[A], collect(e1)) - - e1.add(C); - assert_eq!(~[A,C], collect(e1)) - - e1.add(C); - assert_eq!(~[A,C], collect(e1)) - - e1.add(B); - assert_eq!(~[A,B,C], collect(e1)) - } - - fn collect(e: EnumSet) -> ~[Foo] { - let mut elems = ~[]; - e.each(|elem| { - elems.push(elem); - true - }); - elems - } - - /////////////////////////////////////////////////////////////////////////// - // operators - - #[test] - fn test_operators() { - let mut e1: EnumSet = EnumSet::empty(); - e1.add(A); - e1.add(C); - - let mut e2: EnumSet = EnumSet::empty(); - e2.add(B); - e2.add(C); - - let e_union = e1 | e2; - let elems: ~[Foo] = e_union.iter().collect(); - assert_eq!(~[A,B,C], elems) - - let e_intersection = e1 & e2; - let elems: ~[Foo] = e_intersection.iter().collect(); - assert_eq!(~[C], elems) - - let e_subtract = e1 - e2; - let elems: ~[Foo] = e_subtract.iter().collect(); - assert_eq!(~[A], elems) - } -} diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 8f0dd514570..8329ad2cdf1 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -589,15 +589,14 @@ fn repr(&self, tcx: ctxt) -> ~str { impl Repr for ty::ParamBounds { fn repr(&self, tcx: ctxt) -> ~str { let mut res = ~[]; - do self.builtin_bounds.each |b| { + for b in self.builtin_bounds.iter() { res.push(match b { ty::BoundStatic => ~"'static", ty::BoundSend => ~"Send", ty::BoundFreeze => ~"Freeze", ty::BoundSized => ~"Sized", }); - true - }; + } for t in self.trait_bounds.iter() { res.push(t.repr(tcx)); } @@ -833,10 +832,9 @@ impl UserString for ty::BuiltinBounds { fn user_string(&self, tcx: ctxt) -> ~str { if self.is_empty() { ~"" } else { let mut result = ~[]; - do self.each |bb| { + for bb in self.iter() { result.push(bb.user_string(tcx)); - true - }; + } result.connect("+") } }