diff --git a/src/etc/vim/ftplugin/rust.vim b/src/etc/vim/ftplugin/rust.vim index f329dd6ce02ac..063b1152cb2c6 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 -" 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 55fceb96af3fb..ae3ca403aedd8 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 dfcdb11e7682a..3f654ea903063 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 4f5f1bd85c73f..a17fea24b2c23 100644 --- a/src/libstd/iterator.rs +++ b/src/libstd/iterator.rs @@ -47,6 +47,49 @@ pub trait Iterator { fn size_hint(&self) -> (uint, Option) { (0, None) } } +/// A range iterator able to yield elements from both ends +pub trait DoubleEndedIterator: Iterator { + /// Yield an element from the end of the range, returning `None` if the range is empty. + fn next_back(&mut self) -> Option; +} + +/// Iterator adaptors provided for every `DoubleEndedIterator` implementation. +/// +/// In the future these will be default methods instead of a utility trait. +pub trait DoubleEndedIteratorUtil { + /// Flip the direction of the iterator + fn invert(self) -> InvertIterator; +} + +/// Iterator adaptors provided for every `DoubleEndedIterator` implementation. +/// +/// In the future these will be default methods instead of a utility trait. +impl> DoubleEndedIteratorUtil for T { + /// Flip the direction of the iterator + #[inline] + fn invert(self) -> InvertIterator { + 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 { + priv iter: T +} + +impl> Iterator for InvertIterator { + #[inline] + fn next(&mut self) -> Option { self.iter.next_back() } + #[inline] + fn size_hint(&self) -> (uint, Option) { self.iter.size_hint() } +} + +impl> DoubleEndedIterator for InvertIterator { + #[inline] + fn next_back(&mut self) -> Option { 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 825dc4cc187d8..38212d0f29f11 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; @@ -760,12 +760,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 @@ -1141,7 +1136,6 @@ impl OwnedVector 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 @@ -1175,7 +1169,6 @@ impl OwnedVector 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 @@ -1233,21 +1226,12 @@ impl OwnedVector 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(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. @@ -1717,13 +1701,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() } /** @@ -2083,17 +2063,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)) } } @@ -2101,11 +2081,7 @@ macro_rules! iterator { #[inline] fn size_hint(&self) -> (uint, Option) { - 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)) } @@ -2113,6 +2089,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> { @@ -2120,16 +2115,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. @@ -2138,16 +2126,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 {