core: convert vec::{tail,tailn} to return references

This commit is contained in:
Erick Tryzelaar 2013-03-03 07:22:40 -08:00
parent 359bb3e10b
commit 5ae06ae9de
4 changed files with 84 additions and 48 deletions

View File

@ -223,17 +223,10 @@ pub pure fn head_opt<T>(v: &r/[T]) -> Option<&r/T> {
}
/// Returns a vector containing all but the first element of a slice
pub pure fn tail<T:Copy>(v: &[const T]) -> ~[T] {
slice(v, 1u, len(v)).to_vec()
}
pub pure fn tail<T>(v: &r/[T]) -> &r/[T] { slice(v, 1, v.len()) }
/**
* Returns a vector containing all but the first `n` \
* elements of a slice
*/
pub pure fn tailn<T:Copy>(v: &[const T], n: uint) -> ~[T] {
slice(v, n, len(v)).to_vec()
}
/// Returns a vector containing all but the first `n` elements of a slice
pub pure fn tailn<T>(v: &r/[T], n: uint) -> &r/[T] { slice(v, n, v.len()) }
/// Returns a vector containing all but the last element of a slice
pub pure fn init<T:Copy>(v: &[const T]) -> ~[T] {
@ -1704,7 +1697,6 @@ pub trait CopyableVector<T> {
pure fn init(&self) -> ~[T];
pure fn last(&self) -> T;
pure fn slice(&self, start: uint, end: uint) -> ~[T];
pure fn tail(&self) -> ~[T];
}
/// Extension methods for vectors
@ -1722,16 +1714,14 @@ impl<T:Copy> CopyableVector<T> for &[const T] {
pure fn slice(&self, start: uint, end: uint) -> ~[T] {
slice(*self, start, end).to_vec()
}
/// Returns all but the first element of a vector
#[inline]
pure fn tail(&self) -> ~[T] { tail(*self) }
}
pub trait ImmutableVector<T> {
pure fn view(&self, start: uint, end: uint) -> &self/[T];
pure fn head(&self) -> &self/T;
pure fn head_opt(&self) -> Option<&self/T>;
pure fn tail(&self) -> &self/[T];
pure fn tailn(&self, n: uint) -> &self/[T];
pure fn foldr<U: Copy>(&self, z: U, p: fn(t: &T, u: U) -> U) -> U;
pure fn map<U>(&self, f: fn(t: &T) -> U) -> ~[U];
pure fn mapi<U>(&self, f: fn(uint, t: &T) -> U) -> ~[U];
@ -1757,6 +1747,14 @@ impl<T> ImmutableVector<T> for &[T] {
#[inline]
pure fn head_opt(&self) -> Option<&self/T> { head_opt(*self) }
/// Returns all but the first element of a vector
#[inline]
pure fn tail(&self) -> &self/[T] { tail(*self) }
/// Returns all but the first `n' elements of a vector
#[inline]
pure fn tailn(&self, n: uint) -> &self/[T] { tailn(*self, n) }
/// Reduce a vector from right to left
#[inline]
pure fn foldr<U:Copy>(&self, z: U, p: fn(t: &T, u: U) -> U) -> U {
@ -2611,10 +2609,33 @@ mod tests {
#[test]
fn test_tail() {
let mut a = ~[11];
assert (tail(a) == ~[]);
assert a.tail() == &[];
a = ~[11, 12];
assert (tail(a) == ~[12]);
assert a.tail() == &[12];
}
#[test]
#[should_fail]
#[ignore(cfg(windows))]
fn test_tail_empty() {
let a: ~[int] = ~[];
a.tail();
}
#[test]
fn test_tailn() {
let mut a = ~[11, 12, 13];
assert a.tailn(0) == &[11, 12, 13];
a = ~[11, 12, 13];
assert a.tailn(2) == &[13];
}
#[test]
#[should_fail]
#[ignore(cfg(windows))]
fn test_tailn_empty() {
let a: ~[int] = ~[];
a.tailn(2);
}
#[test]

View File

@ -265,7 +265,7 @@ pub fn is_useful(cx: @MatchCheckCtxt, +m: matrix, +v: &[@pat]) -> useful {
Some(ref ctor) => {
match is_useful(cx,
vec::filter_map(m, |r| default(cx, r)),
vec::tail(v)) {
v.tail()) {
useful_ => useful(left_ty, (/*bad*/copy *ctor)),
ref u => (/*bad*/copy *u)
}
@ -281,7 +281,7 @@ pub fn is_useful(cx: @MatchCheckCtxt, +m: matrix, +v: &[@pat]) -> useful {
pub fn is_useful_specialized(cx: @MatchCheckCtxt,
m: matrix,
+v: &[@pat],
v: &[@pat],
+ctor: ctor,
arity: uint,
lty: ty::t)
@ -475,7 +475,7 @@ pub fn wild() -> @pat {
}
pub fn specialize(cx: @MatchCheckCtxt,
+r: &[@pat],
r: &[@pat],
ctor_id: ctor,
arity: uint,
left_ty: ty::t)
@ -485,13 +485,17 @@ pub fn specialize(cx: @MatchCheckCtxt,
match r0 {
pat{id: pat_id, node: n, span: pat_span} =>
match n {
pat_wild => Some(vec::append(vec::from_elem(arity, wild()),
vec::tail(r))),
pat_wild => {
Some(vec::append(vec::from_elem(arity, wild()), r.tail()))
}
pat_ident(_, _, _) => {
match cx.tcx.def_map.find(&pat_id) {
Some(def_variant(_, id)) => {
if variant(id) == ctor_id { Some(vec::tail(r)) }
else { None }
if variant(id) == ctor_id {
Some(vec::from_slice(r.tail()))
} else {
None
}
}
Some(def_const(did)) => {
let const_expr =
@ -506,10 +510,20 @@ pub fn specialize(cx: @MatchCheckCtxt,
single => true,
_ => fail!(~"type error")
};
if match_ { Some(vec::tail(r)) } else { None }
if match_ {
Some(vec::from_slice(r.tail()))
} else {
None
}
}
_ => {
Some(
vec::append(
vec::from_elem(arity, wild()),
r.tail()
)
)
}
_ => Some(vec::append(vec::from_elem(arity, wild()),
vec::tail(r)))
}
}
pat_enum(_, args) => {
@ -519,7 +533,7 @@ pub fn specialize(cx: @MatchCheckCtxt,
Some(args) => args,
None => vec::from_elem(arity, wild())
};
Some(vec::append(args, vec::tail(r)))
Some(vec::append(args, vec::from_slice(r.tail())))
}
def_variant(_, _) => None,
def_struct(*) => {
@ -529,7 +543,7 @@ pub fn specialize(cx: @MatchCheckCtxt,
Some(args) => new_args = args,
None => new_args = vec::from_elem(arity, wild())
}
Some(vec::append(new_args, vec::tail(r)))
Some(vec::append(new_args, vec::from_slice(r.tail())))
}
_ => None
}
@ -545,7 +559,7 @@ pub fn specialize(cx: @MatchCheckCtxt,
_ => wild()
}
});
Some(vec::append(args, vec::tail(r)))
Some(vec::append(args, vec::from_slice(r.tail())))
}
pat_struct(_, ref flds, _) => {
// Is this a struct or an enum variant?
@ -560,7 +574,7 @@ pub fn specialize(cx: @MatchCheckCtxt,
_ => wild()
}
});
Some(vec::append(args, vec::tail(r)))
Some(vec::append(args, vec::from_slice(r.tail())))
} else {
None
}
@ -587,13 +601,14 @@ pub fn specialize(cx: @MatchCheckCtxt,
_ => wild()
}
});
Some(vec::append(args, vec::tail(r)))
Some(vec::append(args, vec::from_slice(r.tail())))
}
}
}
pat_tup(args) => Some(vec::append(args, vec::tail(r))),
pat_box(a) | pat_uniq(a) | pat_region(a) =>
Some(vec::append(~[a], vec::tail(r))),
pat_tup(args) => Some(vec::append(args, r.tail())),
pat_box(a) | pat_uniq(a) | pat_region(a) => {
Some(vec::append(~[a], r.tail()))
}
pat_lit(expr) => {
let e_v = eval_const_expr(cx.tcx, expr);
let match_ = match ctor_id {
@ -605,21 +620,21 @@ pub fn specialize(cx: @MatchCheckCtxt,
single => true,
_ => fail!(~"type error")
};
if match_ { Some(vec::tail(r)) } else { None }
if match_ { Some(vec::from_slice(r.tail())) } else { None }
}
pat_range(lo, hi) => {
let (c_lo, c_hi) = match ctor_id {
val(ref v) => ((/*bad*/copy *v), (/*bad*/copy *v)),
range(ref lo, ref hi) =>
((/*bad*/copy *lo), (/*bad*/copy *hi)),
single => return Some(vec::tail(r)),
single => return Some(vec::from_slice(r.tail())),
_ => fail!(~"type error")
};
let v_lo = eval_const_expr(cx.tcx, lo),
v_hi = eval_const_expr(cx.tcx, hi);
let match_ = compare_const_vals(c_lo, v_lo) >= 0 &&
compare_const_vals(c_hi, v_hi) <= 0;
if match_ { Some(vec::tail(r)) } else { None }
if match_ { Some(vec::from_slice(r.tail())) } else { None }
}
pat_vec(elems, tail) => {
match ctor_id {
@ -630,10 +645,10 @@ pub fn specialize(cx: @MatchCheckCtxt,
vec::append(elems, vec::from_elem(
arity - num_elements, wild()
)),
vec::tail(r)
vec::from_slice(r.tail())
))
} else if num_elements == arity {
Some(vec::append(elems, vec::tail(r)))
Some(vec::append(elems, r.tail()))
} else {
None
}
@ -645,8 +660,8 @@ pub fn specialize(cx: @MatchCheckCtxt,
}
}
pub fn default(cx: @MatchCheckCtxt, r: ~[@pat]) -> Option<~[@pat]> {
if is_wild(cx, r[0]) { Some(vec::tail(r)) }
pub fn default(cx: @MatchCheckCtxt, r: &[@pat]) -> Option<~[@pat]> {
if is_wild(cx, r[0]) { Some(vec::from_slice(r.tail())) }
else { None }
}

View File

@ -71,8 +71,8 @@ pub impl FnType {
let llretptr = GEPi(bcx, llargbundle, [0u, n]);
let llretloc = Load(bcx, llretptr);
llargvals = ~[llretloc];
atys = vec::tail(atys);
attrs = vec::tail(attrs);
atys = vec::from_slice(atys.tail());
attrs = vec::from_slice(attrs.tail());
}
while i < n {
@ -131,8 +131,8 @@ pub impl FnType {
let mut attrs = /*bad*/copy self.attrs;
let mut j = 0u;
let llretptr = if self.sret {
atys = vec::tail(atys);
attrs = vec::tail(attrs);
atys = vec::from_slice(atys.tail());
attrs = vec::from_slice(attrs.tail());
j = 1u;
get_param(llwrapfn, 0u)
} else if self.ret_ty.cast {

View File

@ -79,7 +79,7 @@ fn unindent(s: &str) -> ~str {
if !lines.is_empty() {
let unindented = ~[lines.head().trim()]
+ do vec::tail(lines).map |line| {
+ do lines.tail().map |line| {
if str::is_whitespace(*line) {
copy *line
} else {