about summary refs log tree commit diff
path: root/src/libcore
diff options
context:
space:
mode:
Diffstat (limited to 'src/libcore')
-rw-r--r--src/libcore/arc.rs65
-rw-r--r--src/libcore/cmp.rs8
-rw-r--r--src/libcore/core.rc1
-rw-r--r--src/libcore/core.rs5
-rw-r--r--src/libcore/dlist.rs99
-rw-r--r--src/libcore/f32.rs18
-rw-r--r--src/libcore/f64.rs18
-rw-r--r--src/libcore/float.rs48
-rw-r--r--src/libcore/int-template.rs22
-rw-r--r--src/libcore/io.rs6
-rw-r--r--src/libcore/num.rs18
-rw-r--r--src/libcore/ops.rs66
-rw-r--r--src/libcore/pipes.rs108
-rw-r--r--src/libcore/uint-template.rs22
14 files changed, 271 insertions, 233 deletions
diff --git a/src/libcore/arc.rs b/src/libcore/arc.rs
index 28f07264410..9c46df9731b 100644
--- a/src/libcore/arc.rs
+++ b/src/libcore/arc.rs
@@ -3,10 +3,9 @@
  * share immutable data between tasks.
  */
 
-import comm::{port, chan, methods};
 import sys::methods;
 
-export arc, get, clone, shared_arc, get_arc;
+export arc, get, clone;
 
 export exclusive, methods;
 
@@ -122,49 +121,6 @@ impl methods<T: send> for exclusive<T> {
     }
 }
 
-// Convenience code for sharing arcs between tasks
-
-type get_chan<T: const send> = chan<chan<arc<T>>>;
-
-// (terminate, get)
-type shared_arc<T: const send> = (shared_arc_res, get_chan<T>);
-
-class shared_arc_res {
-   let c: comm::chan<()>;
-   new(c: comm::chan<()>) { self.c = c; }
-   drop { self.c.send(()); }
-}
-
-fn shared_arc<T: send const>(-data: T) -> shared_arc<T> {
-    let a = arc::arc(data);
-    let p = port();
-    let c = chan(p);
-    do task::spawn() |move a| {
-        let mut live = true;
-        let terminate = port();
-        let get = port();
-
-        c.send((chan(terminate), chan(get)));
-
-        while live {
-            alt comm::select2(terminate, get) {
-              either::left(()) { live = false; }
-              either::right(cc) {
-                comm::send(cc, arc::clone(&a));
-              }
-            }
-        }
-    };
-    let (terminate, get) = p.recv();
-    (shared_arc_res(terminate), get)
-}
-
-fn get_arc<T: send const>(c: get_chan<T>) -> arc::arc<T> {
-    let p = port();
-    c.send(chan(p));
-    p.recv()
-}
-
 #[cfg(test)]
 mod tests {
     import comm::*;
@@ -197,25 +153,6 @@ mod tests {
     }
 
     #[test]
-    fn auto_share_arc() {
-        let v = ~[1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
-        let (_res, arc_c) = shared_arc(v);
-
-        let p = port();
-        let c = chan(p);
-
-        do task::spawn() {
-            let arc_v = get_arc(arc_c);
-            let v = *get(&arc_v);
-            assert v[2] == 3;
-
-            c.send(());
-        };
-
-        assert p.recv() == ();
-    }
-
-    #[test]
     #[ignore] // this can probably infinite loop too.
     fn exclusive_arc() {
         let mut futures = ~[];
diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs
index 1bdf3b9909a..d10b9603af0 100644
--- a/src/libcore/cmp.rs
+++ b/src/libcore/cmp.rs
@@ -1,10 +1,10 @@
 /// Interfaces used for comparison.
 
-iface ord {
-    fn lt(&&other: self) -> bool;
+trait ord {
+    pure fn lt(&&other: self) -> bool;
 }
 
-iface eq {
-    fn eq(&&other: self) -> bool;
+trait eq {
+    pure fn eq(&&other: self) -> bool;
 }
 
diff --git a/src/libcore/core.rc b/src/libcore/core.rc
index d298ff15a9e..11e305e22e8 100644
--- a/src/libcore/core.rc
+++ b/src/libcore/core.rc
@@ -161,6 +161,7 @@ mod tuple;
 
 // Ubiquitous-utility-type modules
 
+mod ops;
 mod cmp;
 mod num;
 mod hash;
diff --git a/src/libcore/core.rs b/src/libcore/core.rs
index 4738574fdb4..fdf53524188 100644
--- a/src/libcore/core.rs
+++ b/src/libcore/core.rs
@@ -30,6 +30,8 @@ import float::num;
 import f32::num;
 import f64::num;
 import num::num;
+import ops::{const, copy, send, owned};
+import ops::{add, sub, mul, div, modulo, neg, bitops, index};
 
 export path, option, some, none, unreachable;
 export extensions;
@@ -42,6 +44,9 @@ export immutable_copyable_vector, iter_trait_extensions, vec_concat;
 export base_iter, copyable_iter, extended_iter;
 export tuple_ops, extended_tuple_ops;
 export ptr;
+// The following exports are the core operators and kinds
+export const, copy, send, owned;
+export add, sub, mul, div, modulo, neg, bitops, index;
 
 // Export the log levels as global constants. Higher levels mean
 // more-verbosity. Error is the bottom level, default logging level is
diff --git a/src/libcore/dlist.rs b/src/libcore/dlist.rs
index 087194f721d..cd36d14816c 100644
--- a/src/libcore/dlist.rs
+++ b/src/libcore/dlist.rs
@@ -18,12 +18,28 @@ enum dlist_node<T> = @{
     mut next: dlist_link<T>
 };
 
-// Needs to be an @-box so nodes can back-reference it.
-enum dlist<T> = @{
-    mut size: uint,
-    mut hd: dlist_link<T>,
-    mut tl: dlist_link<T>
-};
+class dlist_root<T> {
+    let mut size: uint;
+    let mut hd:   dlist_link<T>;
+    let mut tl:   dlist_link<T>;
+    new() {
+        self.size = 0; self.hd = none; self.tl = none;
+    }
+    drop {
+        /* FIXME (#????) This doesn't work during task failure - the box
+         * annihilator might have killed some of our nodes already. This will
+         * be safe to uncomment when the box annihilator is safer. As is,
+         * this makes test_dlist_cyclic_link below crash the runtime.
+        // Empty the list. Not doing this explicitly would leave cyclic links
+        // around, not to be freed until cycle collection at task exit.
+        while self.hd.is_some() {
+            self.unlink(self.hd.get());
+        }
+        */
+    }
+}
+
+type dlist<T> = @dlist_root<T>;
 
 impl private_methods<T> for dlist_node<T> {
     pure fn assert_links() {
@@ -91,7 +107,7 @@ pure fn new_dlist_node<T>(+data: T) -> dlist_node<T> {
 
 /// Creates a new, empty dlist.
 pure fn new_dlist<T>() -> dlist<T> {
-    dlist(@{mut size: 0, mut hd: none, mut tl: none})
+    @unchecked { dlist_root() }
 }
 
 /// Creates a new dlist with a single element
@@ -118,7 +134,7 @@ fn concat<T>(lists: dlist<dlist<T>>) -> dlist<T> {
     result
 }
 
-impl private_methods<T> for dlist<T> {
+impl private_methods<T> for dlist_root<T> {
     pure fn new_link(-data: T) -> dlist_link<T> {
         some(dlist_node(@{data: data, mut linked: true,
                           mut prev: none, mut next: none}))
@@ -288,20 +304,6 @@ impl extensions<T> for dlist<T> {
         tl.map(|nobe| self.unlink(nobe));
         tl
     }
-    /// Remove data from the head of the list. O(1).
-    fn pop() -> option<T> {
-        do option::map_consume(self.pop_n()) |nobe| {
-            let dlist_node(@{ data: x, _ }) <- nobe;
-            x
-        }
-    }
-    /// Remove data from the tail of the list. O(1).
-    fn pop_tail() -> option<T> {
-        do option::map_consume(self.pop_tail_n()) |nobe| {
-            let dlist_node(@{ data: x, _ }) <- nobe;
-            x
-        }
-    }
     /// Get the node at the list's head. O(1).
     pure fn peek_n() -> option<dlist_node<T>> { self.hd }
     /// Get the node at the list's tail. O(1).
@@ -334,7 +336,7 @@ impl extensions<T> for dlist<T> {
      * to the other list's head. O(1).
      */
     fn append(them: dlist<T>) {
-        if box::ptr_eq(*self, *them) {
+        if box::ptr_eq(self, them) {
             fail ~"Cannot append a dlist to itself!"
         }
         if them.len() > 0 {
@@ -351,7 +353,7 @@ impl extensions<T> for dlist<T> {
      * list's tail to this list's head. O(1).
      */
     fn prepend(them: dlist<T>) {
-        if box::ptr_eq(*self, *them) {
+        if box::ptr_eq(self, them) {
             fail ~"Cannot prepend a dlist to itself!"
         }
         if them.len() > 0 {
@@ -366,15 +368,25 @@ impl extensions<T> for dlist<T> {
 
     /// Reverse the list's elements in place. O(n).
     fn reverse() {
-        let temp = new_dlist::<T>();
+        do option::while_some(self.hd) |nobe| {
+            let next_nobe = nobe.next;
+            self.remove(nobe);
+            self.make_mine(nobe);
+            self.add_head(some(nobe));
+            next_nobe
+        }
+    }
+
+    /**
+     * Remove everything from the list. This is important because the cyclic
+     * links won't otherwise be automatically refcounted-collected. O(n).
+     */
+    fn clear() {
+        // Cute as it would be to simply detach the list and proclaim "O(1)!",
+        // the GC would still be a hidden O(n). Better to be honest about it.
         while !self.is_empty() {
-            let nobe = self.pop_n().get();
-            nobe.linked = true; // meh, kind of disorganised.
-            temp.add_head(some(nobe));
+            let _ = self.pop_n();
         }
-        self.hd   = temp.hd;
-        self.tl   = temp.tl;
-        self.size = temp.size;
     }
 
     /// Iterate over nodes.
@@ -431,6 +443,10 @@ impl extensions<T> for dlist<T> {
 }
 
 impl extensions<T: copy> for dlist<T> {
+    /// Remove data from the head of the list. O(1).
+    fn pop()       -> option<T> { self.pop_n().map       (|nobe| nobe.data) }
+    /// Remove data from the tail of the list. O(1).
+    fn pop_tail()  -> option<T> { self.pop_tail_n().map  (|nobe| nobe.data) }
     /// Get data at the list's head. O(1).
     pure fn peek() -> option<T> { self.peek_n().map      (|nobe| nobe.data) }
     /// Get data at the list's tail. O(1).
@@ -596,6 +612,13 @@ mod tests {
         a.assert_consistent(); assert a.is_empty();
     }
     #[test]
+    fn test_dlist_clear() {
+        let a = from_vec(~[5,4,3,2,1]);
+        a.clear();
+        assert a.len() == 0;
+        a.assert_consistent();
+    }
+    #[test]
     fn test_dlist_is_empty() {
         let empty = new_dlist::<int>();
         let full1 = from_vec(~[1,2,3]);
@@ -847,7 +870,7 @@ mod tests {
         l.assert_consistent(); assert l.is_empty();
     }
     #[test] #[should_fail] #[ignore(cfg(windows))]
-    fn test_asymmetric_link() {
+    fn test_dlist_asymmetric_link() {
         let l = new_dlist::<int>();
         let _one = l.push_n(1);
         let two = l.push_n(2);
@@ -855,7 +878,7 @@ mod tests {
         l.assert_consistent();
     }
     #[test] #[should_fail] #[ignore(cfg(windows))]
-    fn test_cyclic_list() {
+    fn test_dlist_cyclic_list() {
         let l = new_dlist::<int>();
         let one = l.push_n(1);
         let _two = l.push_n(2);
@@ -865,32 +888,32 @@ mod tests {
         l.assert_consistent();
     }
     #[test] #[should_fail] #[ignore(cfg(windows))]
-    fn test_headless() {
+    fn test_dlist_headless() {
         new_dlist::<int>().head();
     }
     #[test] #[should_fail] #[ignore(cfg(windows))]
-    fn test_insert_already_present_before() {
+    fn test_dlist_insert_already_present_before() {
         let l = new_dlist::<int>();
         let one = l.push_n(1);
         let two = l.push_n(2);
         l.insert_n_before(two, one);
     }
     #[test] #[should_fail] #[ignore(cfg(windows))]
-    fn test_insert_already_present_after() {
+    fn test_dlist_insert_already_present_after() {
         let l = new_dlist::<int>();
         let one = l.push_n(1);
         let two = l.push_n(2);
         l.insert_n_after(one, two);
     }
     #[test] #[should_fail] #[ignore(cfg(windows))]
-    fn test_insert_before_orphan() {
+    fn test_dlist_insert_before_orphan() {
         let l = new_dlist::<int>();
         let one = new_dlist_node(1);
         let two = new_dlist_node(2);
         l.insert_n_before(one, two);
     }
     #[test] #[should_fail] #[ignore(cfg(windows))]
-    fn test_insert_after_orphan() {
+    fn test_dlist_insert_after_orphan() {
         let l = new_dlist::<int>();
         let one = new_dlist_node(1);
         let two = new_dlist_node(2);
diff --git a/src/libcore/f32.rs b/src/libcore/f32.rs
index c72aa6e3aef..3e7bc0097f7 100644
--- a/src/libcore/f32.rs
+++ b/src/libcore/f32.rs
@@ -168,15 +168,15 @@ pure fn log2(n: f32) -> f32 {
 }
 
 impl num of num::num for f32 {
-    fn add(&&other: f32)    -> f32 { ret self + other; }
-    fn sub(&&other: f32)    -> f32 { ret self - other; }
-    fn mul(&&other: f32)    -> f32 { ret self * other; }
-    fn div(&&other: f32)    -> f32 { ret self / other; }
-    fn modulo(&&other: f32) -> f32 { ret self % other; }
-    fn neg()                -> f32 { ret -self;        }
-
-    fn to_int()         -> int { ret self as int; }
-    fn from_int(n: int) -> f32 { ret n as f32;    }
+    pure fn add(&&other: f32)    -> f32 { ret self + other; }
+    pure fn sub(&&other: f32)    -> f32 { ret self - other; }
+    pure fn mul(&&other: f32)    -> f32 { ret self * other; }
+    pure fn div(&&other: f32)    -> f32 { ret self / other; }
+    pure fn modulo(&&other: f32) -> f32 { ret self % other; }
+    pure fn neg()                -> f32 { ret -self;        }
+
+    pure fn to_int()         -> int { ret self as int; }
+    pure fn from_int(n: int) -> f32 { ret n as f32;    }
 }
 
 //
diff --git a/src/libcore/f64.rs b/src/libcore/f64.rs
index 40488d9f8f4..9e84c432bad 100644
--- a/src/libcore/f64.rs
+++ b/src/libcore/f64.rs
@@ -195,15 +195,15 @@ pure fn log2(n: f64) -> f64 {
 }
 
 impl num of num::num for f64 {
-    fn add(&&other: f64)    -> f64 { ret self + other; }
-    fn sub(&&other: f64)    -> f64 { ret self - other; }
-    fn mul(&&other: f64)    -> f64 { ret self * other; }
-    fn div(&&other: f64)    -> f64 { ret self / other; }
-    fn modulo(&&other: f64) -> f64 { ret self % other; }
-    fn neg()                -> f64 { ret -self;        }
-
-    fn to_int()         -> int { ret self as int; }
-    fn from_int(n: int) -> f64 { ret n as f64;    }
+    pure fn add(&&other: f64)    -> f64 { ret self + other; }
+    pure fn sub(&&other: f64)    -> f64 { ret self - other; }
+    pure fn mul(&&other: f64)    -> f64 { ret self * other; }
+    pure fn div(&&other: f64)    -> f64 { ret self / other; }
+    pure fn modulo(&&other: f64) -> f64 { ret self % other; }
+    pure fn neg()                -> f64 { ret -self;        }
+
+    pure fn to_int()         -> int { ret self as int; }
+    pure fn from_int(n: int) -> f64 { ret n as f64;    }
 }
 
 //
diff --git a/src/libcore/float.rs b/src/libcore/float.rs
index 0139c60873b..8b8cc4664dc 100644
--- a/src/libcore/float.rs
+++ b/src/libcore/float.rs
@@ -403,32 +403,32 @@ fn pow_with_uint(base: uint, pow: uint) -> float {
     ret total;
 }
 
-fn is_positive(x: float) -> bool { f64::is_positive(x as f64) }
-fn is_negative(x: float) -> bool { f64::is_negative(x as f64) }
-fn is_nonpositive(x: float) -> bool { f64::is_nonpositive(x as f64) }
-fn is_nonnegative(x: float) -> bool { f64::is_nonnegative(x as f64) }
-fn is_zero(x: float) -> bool { f64::is_zero(x as f64) }
-fn is_infinite(x: float) -> bool { f64::is_infinite(x as f64) }
-fn is_finite(x: float) -> bool { f64::is_finite(x as f64) }
-fn is_NaN(x: float) -> bool { f64::is_NaN(x as f64) }
-
-fn abs(x: float) -> float { f64::abs(x as f64) as float }
-fn sqrt(x: float) -> float { f64::sqrt(x as f64) as float }
-fn atan(x: float) -> float { f64::atan(x as f64) as float }
-fn sin(x: float) -> float { f64::sin(x as f64) as float }
-fn cos(x: float) -> float { f64::cos(x as f64) as float }
-fn tan(x: float) -> float { f64::tan(x as f64) as float }
+pure fn is_positive(x: float) -> bool { f64::is_positive(x as f64) }
+pure fn is_negative(x: float) -> bool { f64::is_negative(x as f64) }
+pure fn is_nonpositive(x: float) -> bool { f64::is_nonpositive(x as f64) }
+pure fn is_nonnegative(x: float) -> bool { f64::is_nonnegative(x as f64) }
+pure fn is_zero(x: float) -> bool { f64::is_zero(x as f64) }
+pure fn is_infinite(x: float) -> bool { f64::is_infinite(x as f64) }
+pure fn is_finite(x: float) -> bool { f64::is_finite(x as f64) }
+pure fn is_NaN(x: float) -> bool { f64::is_NaN(x as f64) }
+
+pure fn abs(x: float) -> float { f64::abs(x as f64) as float }
+pure fn sqrt(x: float) -> float { f64::sqrt(x as f64) as float }
+pure fn atan(x: float) -> float { f64::atan(x as f64) as float }
+pure fn sin(x: float) -> float { f64::sin(x as f64) as float }
+pure fn cos(x: float) -> float { f64::cos(x as f64) as float }
+pure fn tan(x: float) -> float { f64::tan(x as f64) as float }
 
 impl num of num::num for float {
-    fn add(&&other: float)    -> float { ret self + other; }
-    fn sub(&&other: float)    -> float { ret self - other; }
-    fn mul(&&other: float)    -> float { ret self * other; }
-    fn div(&&other: float)    -> float { ret self / other; }
-    fn modulo(&&other: float) -> float { ret self % other; }
-    fn neg()                  -> float { ret -self;        }
-
-    fn to_int()         -> int   { ret self as int; }
-    fn from_int(n: int) -> float { ret n as float;  }
+    pure fn add(&&other: float)    -> float { ret self + other; }
+    pure fn sub(&&other: float)    -> float { ret self - other; }
+    pure fn mul(&&other: float)    -> float { ret self * other; }
+    pure fn div(&&other: float)    -> float { ret self / other; }
+    pure fn modulo(&&other: float) -> float { ret self % other; }
+    pure fn neg()                  -> float { ret -self;        }
+
+    pure fn to_int()         -> int   { ret self as int; }
+    pure fn from_int(n: int) -> float { ret n as float;  }
 }
 
 #[test]
diff --git a/src/libcore/int-template.rs b/src/libcore/int-template.rs
index 02ce125e35c..2b950e4a797 100644
--- a/src/libcore/int-template.rs
+++ b/src/libcore/int-template.rs
@@ -112,27 +112,27 @@ fn to_str_bytes<U>(n: T, radix: uint, f: fn(v: &[u8]) -> U) -> U {
 fn str(i: T) -> ~str { ret to_str(i, 10u); }
 
 impl ord of ord for T {
-    fn lt(&&other: T) -> bool {
+    pure fn lt(&&other: T) -> bool {
         ret self < other;
     }
 }
 
 impl eq of eq for T {
-    fn eq(&&other: T) -> bool {
+    pure fn eq(&&other: T) -> bool {
         ret self == other;
     }
 }
 
 impl num of num::num for T {
-    fn add(&&other: T)    -> T { ret self + other; }
-    fn sub(&&other: T)    -> T { ret self - other; }
-    fn mul(&&other: T)    -> T { ret self * other; }
-    fn div(&&other: T)    -> T { ret self / other; }
-    fn modulo(&&other: T) -> T { ret self % other; }
-    fn neg()              -> T { ret -self;        }
-
-    fn to_int()         -> int { ret self as int; }
-    fn from_int(n: int) -> T   { ret n as T;      }
+    pure fn add(&&other: T)    -> T { ret self + other; }
+    pure fn sub(&&other: T)    -> T { ret self - other; }
+    pure fn mul(&&other: T)    -> T { ret self * other; }
+    pure fn div(&&other: T)    -> T { ret self / other; }
+    pure fn modulo(&&other: T) -> T { ret self % other; }
+    pure fn neg()              -> T { ret -self;        }
+
+    pure fn to_int()         -> int { ret self as int; }
+    pure fn from_int(n: int) -> T   { ret n as T;      }
 }
 
 impl times of iter::times for T {
diff --git a/src/libcore/io.rs b/src/libcore/io.rs
index 25d1b5e6680..3704f2b70da 100644
--- a/src/libcore/io.rs
+++ b/src/libcore/io.rs
@@ -687,7 +687,11 @@ fn seek_in_buf(offset: int, pos: uint, len: uint, whence: seek_style) ->
 
 fn read_whole_file_str(file: ~str) -> result<~str, ~str> {
     result::chain(read_whole_file(file), |bytes| {
-        result::ok(str::from_bytes(bytes))
+        if str::is_utf8(bytes) {
+            result::ok(str::from_bytes(bytes))
+       } else {
+           result::err(file + ~" is not UTF-8")
+       }
     })
 }
 
diff --git a/src/libcore/num.rs b/src/libcore/num.rs
index 130b259c1df..03868527655 100644
--- a/src/libcore/num.rs
+++ b/src/libcore/num.rs
@@ -1,17 +1,17 @@
 /// An interface for numbers.
 
-iface num {
+trait num {
     // FIXME: Cross-crate overloading doesn't work yet. (#2615)
     // FIXME: Interface inheritance. (#2616)
-    fn add(&&other: self) -> self;
-    fn sub(&&other: self) -> self;
-    fn mul(&&other: self) -> self;
-    fn div(&&other: self) -> self;
-    fn modulo(&&other: self) -> self;
-    fn neg() -> self;
+    pure fn add(&&other: self) -> self;
+    pure fn sub(&&other: self) -> self;
+    pure fn mul(&&other: self) -> self;
+    pure fn div(&&other: self) -> self;
+    pure fn modulo(&&other: self) -> self;
+    pure fn neg() -> self;
 
-    fn to_int() -> int;
-    fn from_int(n: int) -> self;    // FIXME (#2376) Static functions.
+    pure fn to_int() -> int;
+    pure fn from_int(n: int) -> self;    // FIXME (#2376) Static functions.
     // n.b. #2376 is for classes, not ifaces, but it could be generalized...
 }
 
diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs
new file mode 100644
index 00000000000..61efe704974
--- /dev/null
+++ b/src/libcore/ops.rs
@@ -0,0 +1,66 @@
+// Core operators and kinds.
+
+#[lang="const"]
+trait const {
+    // Empty.
+}
+
+#[lang="copy"]
+trait copy {
+    // Empty.
+}
+
+#[lang="send"]
+trait send {
+    // Empty.
+}
+
+#[lang="owned"]
+trait owned {
+    // Empty.
+}
+
+#[lang="add"]
+trait add<RHS,Result> {
+    pure fn add(rhs: RHS) -> Result;
+}
+
+#[lang="sub"]
+trait sub<RHS,Result> {
+    pure fn sub(rhs: RHS) -> Result;
+}
+
+#[lang="mul"]
+trait mul<RHS,Result> {
+    pure fn mul(rhs: RHS) -> Result;
+}
+
+#[lang="div"]
+trait div<RHS,Result> {
+    pure fn div(rhs: RHS) -> Result;
+}
+
+#[lang="modulo"]
+trait modulo<RHS,Result> {
+    pure fn modulo(rhs: RHS) -> Result;
+}
+
+#[lang="neg"]
+trait neg<RHS,Result> {
+    pure fn neg(rhs: RHS) -> Result;
+}
+
+#[lang="bitops"]
+trait bitops<RHS,BitCount,Result> {
+    pure fn and(rhs: RHS) -> Result;
+    pure fn or(rhs: RHS) -> Result;
+    pure fn xor(rhs: RHS) -> Result;
+    pure fn shl(n: BitCount) -> Result;
+    pure fn shr(n: BitCount) -> Result;
+}
+
+#[lang="index"]
+trait index<Index,Result> {
+    pure fn index(index: Index) -> Result;
+}
+
diff --git a/src/libcore/pipes.rs b/src/libcore/pipes.rs
index 27cd8ef7caf..4ffa040250f 100644
--- a/src/libcore/pipes.rs
+++ b/src/libcore/pipes.rs
@@ -30,59 +30,6 @@ macro_rules! move {
 // places. Once there is unary move, it can be removed.
 fn move<T>(-x: T) -> T { x }
 
-/**
-
-Some thoughts about fixed buffers.
-
-The idea is if a protocol is bounded, we will synthesize a record that
-has a field for each state. Each of these states contains a packet for
-the messages that are legal to be sent in that state. Then, instead of
-allocating, the send code just finds a pointer to the right field and
-uses that instead.
-
-Unforunately, this makes things kind of tricky. We need to be able to
-find the buffer, which means we need to pass it around. This could
-either be associated with the (send|recv)_packet classes, or with the
-packet itself. We will also need some form of reference counting so we
-can track who has the responsibility of freeing the buffer.
-
-We want to preserve the ability to do things like optimistic buffer
-re-use, and skipping over to a new buffer when necessary. What I mean
-is, suppose we had the typical stream protocol. It'd make sense to
-amortize allocation costs by allocating a buffer with say 16
-messages. When the sender gets to the end of the buffer, it could
-check if the receiver is done with the packet in slot 0. If so, it can
-just reuse that one, checking if the receiver is done with the next
-one in each case. If it is ever not done, it just allocates a new
-buffer and skips over to that.
-
-Also, since protocols are in libcore, we have to do this in a way that
-maintains backwards compatibility.
-
-buffer header and buffer. Cast as c_void when necessary.
-
-===
-
-Okay, here are some new ideas.
-
-It'd be nice to keep the bounded/unbounded case as uniform as
-possible. It leads to less code duplication, and less things that can
-go sublty wrong. For the bounded case, we could either have a struct
-with a bunch of unique pointers to pre-allocated packets, or we could
-lay them out inline. Inline layout is better, if for no other reason
-than that we don't have to allocate each packet
-individually. Currently we pass unique packets around as unsafe
-pointers, but they are actually unique pointers. We should instead use
-real unsafe pointers. This makes freeing data and running destructors
-trickier though. Thus, we should allocate all packets in parter of a
-higher level buffer structure. Packets can maintain a pointer to their
-buffer, and this is the part that gets freed.
-
-It might be helpful to have some idea of a semi-unique pointer (like
-being partially pregnant, also like an ARC).
-
-*/
-
 enum state {
     empty,
     full,
@@ -805,6 +752,12 @@ class port_set<T: send> : recv<T> {
         vec::push(self.ports, port)
     }
 
+    fn chan() -> chan<T> {
+        let (ch, po) = stream();
+        self.add(po);
+        ch
+    }
+
     fn try_recv() -> option<T> {
         let mut result = none;
         while result == none && self.ports.len() > 0 {
@@ -869,3 +822,52 @@ impl chan<T: send> of channel<T> for shared_chan<T> {
 fn shared_chan<T:send>(+c: chan<T>) -> shared_chan<T> {
     arc::exclusive(c)
 }
+
+trait select2<T: send, U: send> {
+    fn try_select() -> either<option<T>, option<U>>;
+    fn select() -> either<T, U>;
+}
+
+impl<T: send, U: send, Left: selectable recv<T>, Right: selectable recv<U>>
+    of select2<T, U> for (Left, Right) {
+
+    fn select() -> either<T, U> {
+        alt self {
+          (lp, rp) {
+            alt select2i(lp, rp) {
+              left(())  { left (lp.recv()) }
+              right(()) { right(rp.recv()) }
+            }
+          }
+        }
+    }
+
+    fn try_select() -> either<option<T>, option<U>> {
+        alt self {
+          (lp, rp) {
+            alt select2i(lp, rp) {
+              left(())  { left (lp.try_recv()) }
+              right(()) { right(rp.try_recv()) }
+            }
+          }
+        }
+    }
+}
+
+#[cfg(test)]
+mod test {
+    #[test]
+    fn test_select2() {
+        let (c1, p1) = pipes::stream();
+        let (c2, p2) = pipes::stream();
+
+        c1.send("abc");
+
+        alt (p1, p2).select() {
+          right(_) { fail }
+          _ { }
+        }
+
+        c2.send(123);
+    }
+}
diff --git a/src/libcore/uint-template.rs b/src/libcore/uint-template.rs
index 75e17cd6a9b..9561ed4e65f 100644
--- a/src/libcore/uint-template.rs
+++ b/src/libcore/uint-template.rs
@@ -53,27 +53,27 @@ pure fn compl(i: T) -> T {
 }
 
 impl ord of ord for T {
-    fn lt(&&other: T) -> bool {
+    pure fn lt(&&other: T) -> bool {
         ret self < other;
     }
 }
 
 impl eq of eq for T {
-    fn eq(&&other: T) -> bool {
+    pure fn eq(&&other: T) -> bool {
         ret self == other;
     }
 }
 
 impl num of num::num for T {
-    fn add(&&other: T)    -> T { ret self + other; }
-    fn sub(&&other: T)    -> T { ret self - other; }
-    fn mul(&&other: T)    -> T { ret self * other; }
-    fn div(&&other: T)    -> T { ret self / other; }
-    fn modulo(&&other: T) -> T { ret self % other; }
-    fn neg()              -> T { ret -self;        }
-
-    fn to_int()         -> int { ret self as int; }
-    fn from_int(n: int) -> T   { ret n as T;      }
+    pure fn add(&&other: T)    -> T { ret self + other; }
+    pure fn sub(&&other: T)    -> T { ret self - other; }
+    pure fn mul(&&other: T)    -> T { ret self * other; }
+    pure fn div(&&other: T)    -> T { ret self / other; }
+    pure fn modulo(&&other: T) -> T { ret self % other; }
+    pure fn neg()              -> T { ret -self;        }
+
+    pure fn to_int()         -> int { ret self as int; }
+    pure fn from_int(n: int) -> T   { ret n as T;      }
 }
 
 /**