about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/etc/vim/ftplugin/rust.vim15
-rw-r--r--src/etc/vim/indent/rust.vim20
-rw-r--r--src/etc/vim/syntax/rust.vim6
-rw-r--r--src/libstd/iterator.rs52
-rw-r--r--src/libstd/vec.rs89
5 files changed, 119 insertions, 63 deletions
diff --git a/src/etc/vim/ftplugin/rust.vim b/src/etc/vim/ftplugin/rust.vim
index f329dd6ce02..063b1152cb2 100644
--- a/src/etc/vim/ftplugin/rust.vim
+++ b/src/etc/vim/ftplugin/rust.vim
@@ -1,14 +1,25 @@
 " Vim syntax file
 " Language:     Rust
 " Maintainer:   Chris Morgan <me@chrismorgan.info>
-" Last Change:  2013 Jul 6
+" Last Change:  2013 Jul 10
 
 if exists("b:did_ftplugin")
 	finish
 endif
 let b:did_ftplugin = 1
 
-setlocal comments=s1:/*,mb:*,ex:*/,:///,://!,://
+" The rust source code at present seems to typically omit a leader on /*!
+" comments, so we'll use that as our default, but make it easy to switch.
+" This does not affect indentation at all (I tested it with and without
+" leader), merely whether a leader is inserted by default or not.
+if exists("g:rust_bang_comment_leader") && g:rust_bang_comment_leader == 1
+	" Why is the `,s0:/*,mb:\ ,ex:*/` there, you ask? I don't understand why,
+	" but without it, */ gets indented one space even if there were no
+	" leaders. I'm fairly sure that's a Vim bug.
+	setlocal comments=s1:/*,mb:*,ex:*/,s0:/*,mb:\ ,ex:*/,:///,://!,://
+else
+	setlocal comments=s0:/*!,m:\ ,ex:*/,s1:/*,mb:*,ex:*/,:///,://!,://
+endif
 setlocal commentstring=//%s
 setlocal formatoptions-=t formatoptions+=croqnlj
 
diff --git a/src/etc/vim/indent/rust.vim b/src/etc/vim/indent/rust.vim
index 55fceb96af3..ae3ca403aed 100644
--- a/src/etc/vim/indent/rust.vim
+++ b/src/etc/vim/indent/rust.vim
@@ -10,7 +10,7 @@ endif
 let b:did_indent = 1
 
 setlocal cindent
-setlocal cinoptions=L0,(0,Ws,JN
+setlocal cinoptions=L0,(0,Ws,JN,j1
 setlocal cinkeys=0{,0},!^F,o,O,0[,0]
 " Don't think cinwords will actually do anything at all... never mind
 setlocal cinwords=do,for,if,else,while,loop,impl,mod,unsafe,trait,struct,enum,fn,extern
@@ -66,12 +66,23 @@ function GetRustIndent(lnum)
 	" Starting assumption: cindent (called at the end) will do it right
 	" normally. We just want to fix up a few cases.
 
+	let line = getline(a:lnum)
+
 	if has('syntax_items')
-		if synIDattr(synID(a:lnum, 1, 1), "name") == "rustString"
+		let synname = synIDattr(synID(a:lnum, 1, 1), "name")
+		if synname == "rustString"
 			" If the start of the line is in a string, don't change the indent
 			return -1
-		elseif synIDattr(synID(a:lnum, 1, 1), "name") =~ "\\(Comment\\|Todo\\)"
-					\ && getline(a:lnum) !~ "^\\s*/\\*"
+		elseif synname =~ "\\(Comment\\|Todo\\)"
+					\ && line !~ "^\\s*/\\*"  " not /* opening line
+			if synname =~ "CommentML" " multi-line
+				if line !~ "^\\s*\\*" && getline(a:lnum - 1) =~ "^\\s*/\\*"
+					" This is (hopefully) the line after a /*, and it has no
+					" leader, so the correct indentation is that of the
+					" previous line.
+					return GetRustIndent(a:lnum - 1)
+				endif
+			endif
 			" If it's in a comment, let cindent take care of it now. This is
 			" for cases like "/*" where the next line should start " * ", not
 			" "* " as the code below would otherwise cause for module scope
@@ -114,7 +125,6 @@ function GetRustIndent(lnum)
 	" start with these two main cases (square brackets and not returning to
 	" column zero)
 
-	let line = getline(a:lnum)
 	call cursor(a:lnum, 1)
 	if searchpair('{\|(', '', '}\|)', 'nbW') == 0
 		if searchpair('\[', '', '\]', 'nbW') == 0
diff --git a/src/etc/vim/syntax/rust.vim b/src/etc/vim/syntax/rust.vim
index dfcdb11e768..3f654ea9030 100644
--- a/src/etc/vim/syntax/rust.vim
+++ b/src/etc/vim/syntax/rust.vim
@@ -117,9 +117,9 @@ syn match     rustFloat       display "\<[0-9][0-9_]*\.[0-9_]\+\%([eE][+-]\=[0-9
 syn match     rustLifetime    display "\'\%([^[:cntrl:][:space:][:punct:][:digit:]]\|_\)\%([^[:cntrl:][:punct:][:space:]]\|_\)*"
 syn match   rustCharacter   "'\([^'\\]\|\\\(['nrt\\\"]\|x\x\{2}\|u\x\{4}\|U\x\{8}\)\)'"
 
-syn region    rustComment     start="/\*" end="\*/" contains=rustTodo
+syn region    rustCommentML   start="/\*" end="\*/" contains=rustTodo
 syn region    rustComment     start="//" skip="\\$" end="$" contains=rustTodo keepend
-syn region    rustCommentDoc  start="/\*\%(!\|\*/\@!\)" end="\*/" contains=rustTodo
+syn region    rustCommentMLDoc start="/\*\%(!\|\*/\@!\)" end="\*/" contains=rustTodo
 syn region    rustCommentDoc  start="//[/!]" skip="\\$" end="$" contains=rustTodo keepend
 
 syn keyword rustTodo contained TODO FIXME XXX NB NOTE
@@ -151,7 +151,9 @@ hi def link rustModPath       Include
 hi def link rustModPathSep    Delimiter
 hi def link rustFuncName      Function
 hi def link rustFuncCall      Function
+hi def link rustCommentMLDoc  rustCommentDoc
 hi def link rustCommentDoc    SpecialComment
+hi def link rustCommentML     rustComment
 hi def link rustComment       Comment
 hi def link rustAssert        PreCondit
 hi def link rustFail          PreCondit
diff --git a/src/libstd/iterator.rs b/src/libstd/iterator.rs
index 4f5f1bd85c7..a17fea24b2c 100644
--- a/src/libstd/iterator.rs
+++ b/src/libstd/iterator.rs
@@ -47,6 +47,49 @@ pub trait Iterator<A> {
     fn size_hint(&self) -> (uint, Option<uint>) { (0, None) }
 }
 
+/// A range iterator able to yield elements from both ends
+pub trait DoubleEndedIterator<A>: Iterator<A> {
+    /// Yield an element from the end of the range, returning `None` if the range is empty.
+    fn next_back(&mut self) -> Option<A>;
+}
+
+/// Iterator adaptors provided for every `DoubleEndedIterator` implementation.
+///
+/// In the future these will be default methods instead of a utility trait.
+pub trait DoubleEndedIteratorUtil<A> {
+    /// Flip the direction of the iterator
+    fn invert(self) -> InvertIterator<A, Self>;
+}
+
+/// Iterator adaptors provided for every `DoubleEndedIterator` implementation.
+///
+/// In the future these will be default methods instead of a utility trait.
+impl<A, T: DoubleEndedIterator<A>> DoubleEndedIteratorUtil<A> for T {
+    /// Flip the direction of the iterator
+    #[inline]
+    fn invert(self) -> InvertIterator<A, T> {
+        InvertIterator{iter: self}
+    }
+}
+
+/// An double-ended iterator with the direction inverted
+// FIXME #6967: Dummy A parameter to get around type inference bug
+pub struct InvertIterator<A, T> {
+    priv iter: T
+}
+
+impl<A, T: DoubleEndedIterator<A>> Iterator<A> for InvertIterator<A, T> {
+    #[inline]
+    fn next(&mut self) -> Option<A> { self.iter.next_back() }
+    #[inline]
+    fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
+}
+
+impl<A, T: Iterator<A>> DoubleEndedIterator<A> for InvertIterator<A, T> {
+    #[inline]
+    fn next_back(&mut self) -> Option<A> { self.iter.next() }
+}
+
 /// Iterator adaptors provided for every `Iterator` implementation. The adaptor objects are also
 /// implementations of the `Iterator` trait.
 ///
@@ -1474,4 +1517,13 @@ mod tests {
         let xs = [-3, 0, 1, 5, -10];
         assert_eq!(*xs.iter().min_by(|x| x.abs()).unwrap(), 0);
     }
+
+    #[test]
+    fn test_invert() {
+        let xs = [2, 4, 6, 8, 10, 12, 14, 16];
+        let mut it = xs.iter();
+        it.next();
+        it.next();
+        assert_eq!(it.invert().transform(|&x| x).collect::<~[int]>(), ~[16, 14, 12, 10, 8, 6]);
+    }
 }
diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs
index 8bcec7e5bbe..89c4b39c429 100644
--- a/src/libstd/vec.rs
+++ b/src/libstd/vec.rs
@@ -18,7 +18,7 @@ use container::{Container, Mutable};
 use cmp;
 use cmp::{Eq, TotalEq, TotalOrd, Ordering, Less, Equal, Greater};
 use clone::Clone;
-use iterator::{FromIterator, Iterator, IteratorUtil};
+use iterator::*;
 use kinds::Copy;
 use libc::c_void;
 use num::Zero;
@@ -762,12 +762,7 @@ impl<'self,T> ImmutableVector<'self, T> for &'self [T] {
     }
     #[inline]
     fn rev_iter(self) -> VecRevIterator<'self, T> {
-        unsafe {
-            let p = vec::raw::to_ptr(self);
-            VecRevIterator{ptr: p.offset(self.len() - 1),
-                           end: p.offset(-1),
-                           lifetime: cast::transmute(p)}
-        }
+        self.iter().invert()
     }
 
     /// Returns an iterator over the subslices of the vector which are
@@ -1143,7 +1138,6 @@ impl<T> OwnedVector<T> for ~[T] {
      *
      * * n - The number of elements to reserve space for
      */
-    #[inline]
     #[cfg(stage0)]
     fn reserve(&mut self, n: uint) {
         // Only make the (slow) call into the runtime if we have to
@@ -1177,7 +1171,6 @@ impl<T> OwnedVector<T> for ~[T] {
      *
      * * n - The number of elements to reserve space for
      */
-    #[inline]
     #[cfg(not(stage0))]
     fn reserve(&mut self, n: uint) {
         // Only make the (slow) call into the runtime if we have to
@@ -1235,21 +1228,12 @@ impl<T> OwnedVector<T> for ~[T] {
             let repr: **raw::VecRepr = transmute(&mut *self);
             let fill = (**repr).unboxed.fill;
             if (**repr).unboxed.alloc <= fill {
-                // need more space
-                reserve_no_inline(self);
+                let new_len = self.len() + 1;
+                self.reserve_at_least(new_len);
             }
 
             self.push_fast(t);
         }
-
-        // this peculiar function is because reserve_at_least is very
-        // large (because of reserve), and will be inlined, which
-        // makes push too large.
-        #[inline(never)]
-        fn reserve_no_inline<T>(v: &mut ~[T]) {
-            let new_len = v.len() + 1;
-            v.reserve_at_least(new_len);
-        }
     }
 
     // This doesn't bother to make sure we have space.
@@ -1737,13 +1721,9 @@ impl<'self,T> MutableVector<'self, T> for &'self mut [T] {
         }
     }
 
+    #[inline]
     fn mut_rev_iter(self) -> VecMutRevIterator<'self, T> {
-        unsafe {
-            let p = vec::raw::to_mut_ptr(self);
-            VecMutRevIterator{ptr: p.offset(self.len() - 1),
-                              end: p.offset(-1),
-                              lifetime: cast::transmute(p)}
-        }
+        self.mut_iter().invert()
     }
 
     /**
@@ -2103,17 +2083,17 @@ macro_rules! iterator {
             priv lifetime: $elem // FIXME: #5922
         }
     };*/
-    (impl $name:ident -> $elem:ty, $step:expr) => {
-        // could be implemented with &[T] with .slice(), but this avoids bounds checks
+    (impl $name:ident -> $elem:ty) => {
         impl<'self, T> Iterator<$elem> for $name<'self, T> {
             #[inline]
             fn next(&mut self) -> Option<$elem> {
+                // could be implemented with slices, but this avoids bounds checks
                 unsafe {
                     if self.ptr == self.end {
                         None
                     } else {
                         let old = self.ptr;
-                        self.ptr = self.ptr.offset($step);
+                        self.ptr = self.ptr.offset(1);
                         Some(cast::transmute(old))
                     }
                 }
@@ -2121,11 +2101,7 @@ macro_rules! iterator {
 
             #[inline]
             fn size_hint(&self) -> (uint, Option<uint>) {
-                let diff = if $step > 0 {
-                    (self.end as uint) - (self.ptr as uint)
-                } else {
-                    (self.ptr as uint) - (self.end as uint)
-                };
+                let diff = (self.end as uint) - (self.ptr as uint);
                 let exact = diff / size_of::<$elem>();
                 (exact, Some(exact))
             }
@@ -2133,6 +2109,25 @@ macro_rules! iterator {
     }
 }
 
+macro_rules! double_ended_iterator {
+    (impl $name:ident -> $elem:ty) => {
+        impl<'self, T> DoubleEndedIterator<$elem> for $name<'self, T> {
+            #[inline]
+            fn next_back(&mut self) -> Option<$elem> {
+                // could be implemented with slices, but this avoids bounds checks
+                unsafe {
+                    if self.end == self.ptr {
+                        None
+                    } else {
+                        self.end = self.end.offset(-1);
+                        Some(cast::transmute(self.end))
+                    }
+                }
+            }
+        }
+    }
+}
+
 //iterator!{struct VecIterator -> *T, &'self T}
 /// An iterator for iterating over a vector.
 pub struct VecIterator<'self, T> {
@@ -2140,16 +2135,9 @@ pub struct VecIterator<'self, T> {
     priv end: *T,
     priv lifetime: &'self T // FIXME: #5922
 }
-iterator!{impl VecIterator -> &'self T, 1}
-
-//iterator!{struct VecRevIterator -> *T, &'self T}
-/// An iterator for iterating over a vector in reverse.
-pub struct VecRevIterator<'self, T> {
-    priv ptr: *T,
-    priv end: *T,
-    priv lifetime: &'self T // FIXME: #5922
-}
-iterator!{impl VecRevIterator -> &'self T, -1}
+iterator!{impl VecIterator -> &'self T}
+double_ended_iterator!{impl VecIterator -> &'self T}
+pub type VecRevIterator<'self, T> = InvertIterator<&'self T, VecIterator<'self, T>>;
 
 //iterator!{struct VecMutIterator -> *mut T, &'self mut T}
 /// An iterator for mutating the elements of a vector.
@@ -2158,16 +2146,9 @@ pub struct VecMutIterator<'self, T> {
     priv end: *mut T,
     priv lifetime: &'self mut T // FIXME: #5922
 }
-iterator!{impl VecMutIterator -> &'self mut T, 1}
-
-//iterator!{struct VecMutRevIterator -> *mut T, &'self mut T}
-/// An iterator for mutating the elements of a vector in reverse.
-pub struct VecMutRevIterator<'self, T> {
-    priv ptr: *mut T,
-    priv end: *mut T,
-    priv lifetime: &'self mut T // FIXME: #5922
-}
-iterator!{impl VecMutRevIterator -> &'self mut T, -1}
+iterator!{impl VecMutIterator -> &'self mut T}
+double_ended_iterator!{impl VecMutIterator -> &'self mut T}
+pub type VecMutRevIterator<'self, T> = InvertIterator<&'self mut T, VecMutIterator<'self, T>>;
 
 /// An iterator that moves out of a vector.
 pub struct VecConsumeIterator<T> {