}
}
- ast::pat_vec(_, Some(tail_pat)) => {
- // The `tail_pat` here creates a slice into the
+ ast::pat_vec(_, Some(slice_pat), _) => {
+ // The `slice_pat` here creates a slice into the
// original vector. This is effectively a borrow of
// the elements of the vector being matched.
- let tail_ty = self.tcx().ty(tail_pat);
- let (tail_mutbl, tail_r) =
- self.vec_slice_info(tail_pat, tail_ty);
+ let slice_ty = self.tcx().ty(slice_pat);
+ let (slice_mutbl, slice_r) =
+ self.vec_slice_info(slice_pat, slice_ty);
let mcx = self.bccx.mc_ctxt();
- let cmt_index = mcx.cat_index(tail_pat, cmt);
- self.guarantee_valid(cmt_index, tail_mutbl, tail_r);
+ let cmt_index = mcx.cat_index(slice_pat, cmt);
+ self.guarantee_valid(cmt_index, slice_mutbl, slice_r);
}
_ => {}
fn vec_slice_info(@mut self,
pat: @ast::pat,
- tail_ty: ty::t) -> (ast::mutability, ty::Region) {
+ slice_ty: ty::t) -> (ast::mutability, ty::Region) {
/*!
*
* In a pattern like [a, b, ..c], normally `c` has slice type,
* to recurse through rptrs.
*/
- match ty::get(tail_ty).sty {
- ty::ty_evec(tail_mt, ty::vstore_slice(tail_r)) => {
- (tail_mt.mutbl, tail_r)
+ match ty::get(slice_ty).sty {
+ ty::ty_evec(slice_mt, ty::vstore_slice(slice_r)) => {
+ (slice_mt.mutbl, slice_r)
}
ty::ty_rptr(_, ref mt) => {
_ => {
self.tcx().sess.span_bug(
pat.span,
- fmt!("Type of tail pattern is not a slice"));
+ fmt!("Type of slice pattern is not a slice"));
}
}
}
ty::ty_unboxed_vec(*) | ty::ty_evec(*) => {
let max_len = do m.foldr(0) |r, max_len| {
match /*bad*/copy r[0].node {
- pat_vec(elems, _) => uint::max(elems.len(), max_len),
+ pat_vec(before, _, after) => {
+ uint::max(before.len() + after.len(), max_len)
+ }
_ => max_len
}
};
pat_box(_) | pat_uniq(_) | pat_tup(_) | pat_region(*) => {
Some(single)
}
- pat_vec(elems, tail) => {
- match tail {
+ pat_vec(before, slice, after) => {
+ match slice {
Some(_) => None,
- None => Some(vec(elems.len()))
+ None => Some(vec(before.len() + after.len()))
}
}
}
}
ty::ty_unboxed_vec(*) | ty::ty_evec(*) => {
- // Find the lengths and tails of all vector patterns.
+ // Find the lengths and slices of all vector patterns.
let vec_pat_lens = do m.filter_mapped |r| {
match r[0].node {
- pat_vec(ref elems, ref tail) => {
- Some((elems.len(), tail.is_some()))
+ pat_vec(ref before, ref slice, ref after) => {
+ Some((before.len() + after.len(), slice.is_some()))
}
_ => None
}
};
// Sort them by length such that for patterns of the same length,
- // those with a destructured tail come first.
+ // those with a destructured slice come first.
let mut sorted_vec_lens = sort::merge_sort(vec_pat_lens,
- |&(len1, tail1), &(len2, tail2)| {
+ |&(len1, slice1), &(len2, slice2)| {
if len1 == len2 {
- tail1 > tail2
+ slice1 > slice2
} else {
len1 <= len2
}
);
vec::dedup(&mut sorted_vec_lens);
- let mut found_tail = false;
+ let mut found_slice = false;
let mut next = 0;
let mut missing = None;
- for sorted_vec_lens.each |&(length, tail)| {
+ for sorted_vec_lens.each |&(length, slice)| {
if length != next {
missing = Some(next);
break;
}
- if tail {
- found_tail = true;
+ if slice {
+ found_slice = true;
break;
}
next += 1;
}
// We found patterns of all lengths within <0, next), yet there was no
- // pattern with a tail - therefore, we report vec(next) as missing.
- if !found_tail {
+ // pattern with a slice - therefore, we report vec(next) as missing.
+ if !found_slice {
missing = Some(next);
}
match missing {
compare_const_vals(c_hi, v_hi) <= 0;
if match_ { Some(vec::from_slice(r.tail())) } else { None }
}
- pat_vec(elems, tail) => {
+ pat_vec(before, slice, after) => {
match ctor_id {
vec(_) => {
- let num_elements = elems.len();
- if num_elements < arity && tail.is_some() {
+ let num_elements = before.len() + after.len();
+ if num_elements < arity && slice.is_some() {
Some(vec::append(
- vec::append(elems, vec::from_elem(
- arity - num_elements, wild()
- )),
- vec::from_slice(r.tail())
+ vec::concat(&[
+ before,
+ vec::from_elem(
+ arity - num_elements, wild()),
+ after
+ ]),
+ r.tail()
))
} else if num_elements == arity {
- Some(vec::append(elems, r.tail()))
+ Some(vec::append(
+ vec::append(before, after),
+ r.tail()
+ ))
} else {
None
}
self.cat_pattern(subcmt, subpat, op);
}
- ast::pat_vec(ref pats, opt_tail_pat) => {
- for pats.each |pat| {
+ ast::pat_vec(ref before, slice, ref after) => {
+ for before.each |pat| {
let elt_cmt = self.cat_index(*pat, cmt);
self.cat_pattern(elt_cmt, *pat, op);
}
-
- for opt_tail_pat.each |tail_pat| {
- let tail_ty = self.tcx.ty(*tail_pat);
- let tail_cmt = self.cat_rvalue(*tail_pat, tail_ty);
- self.cat_pattern(tail_cmt, *tail_pat, op);
+ for slice.each |slice_pat| {
+ let slice_ty = self.tcx.ty(*slice_pat);
+ let slice_cmt = self.cat_rvalue(*slice_pat, slice_ty);
+ self.cat_pattern(slice_cmt, *slice_pat, op);
+ }
+ for after.each |pat| {
+ let elt_cmt = self.cat_index(*pat, cmt);
+ self.cat_pattern(elt_cmt, *pat, op);
}
}
var(/* disr val */int, @adt::Repr),
range(@ast::expr, @ast::expr),
vec_len_eq(uint),
- vec_len_ge(uint)
+ vec_len_ge(uint, /* slice */uint)
}
pub fn opt_eq(tcx: ty::ctxt, a: &Opt, b: &Opt) -> bool {
}
(&var(a, _), &var(b, _)) => a == b,
(&vec_len_eq(a), &vec_len_eq(b)) => a == b,
- (&vec_len_ge(a), &vec_len_ge(b)) => a == b,
+ (&vec_len_ge(a, _), &vec_len_ge(b, _)) => a == b,
_ => false
}
}
vec_len_eq(n) => {
return single_result(rslt(bcx, C_int(ccx, n as int)));
}
- vec_len_ge(n) => {
+ vec_len_ge(n, _) => {
return lower_bound(rslt(bcx, C_int(ccx, n as int)));
}
}
None
}
}
- ast::pat_vec(elems, tail) => {
- match tail {
+ ast::pat_vec(before, slice, after) => {
+ match slice {
Some(_) => {
- if opt_eq(tcx, &vec_len_ge(elems.len()), opt) {
- Some(vec::append_one(elems, tail.get()))
+ let n = before.len() + after.len();
+ let i = before.len();
+ if opt_eq(tcx, &vec_len_ge(n, i), opt) {
+ Some(vec::concat(
+ &[before, ~[slice.get()], after]))
} else {
None
}
}
None => {
- if opt_eq(tcx, &vec_len_eq(elems.len()), opt) {
- Some(copy elems)
+ let n = before.len();
+ if opt_eq(tcx, &vec_len_eq(n), opt) {
+ Some(copy before)
} else {
None
}
ast::pat_range(l1, l2) => {
add_to_set(ccx.tcx, &mut found, range(l1, l2));
}
- ast::pat_vec(elems, tail) => {
- let opt = match tail {
- None => vec_len_eq(elems.len()),
- Some(_) => vec_len_ge(elems.len())
+ ast::pat_vec(before, slice, after) => {
+ let opt = match slice {
+ None => vec_len_eq(before.len()),
+ Some(_) => vec_len_ge(before.len() + after.len(),
+ before.len())
};
add_to_set(ccx.tcx, &mut found, opt);
}
pub fn extract_vec_elems(bcx: block,
pat_id: ast::node_id,
elem_count: uint,
- tail: bool,
- val: ValueRef)
+ slice: Option<uint>,
+ val: ValueRef,
+ count: ValueRef)
-> ExtractedBlock {
let _icx = bcx.insn_ctxt("match::extract_vec_elems");
let vt = tvec::vec_types(bcx, node_id_type(bcx, pat_id));
let (base, len) = tvec::get_base_and_len(bcx, unboxed, vt.vec_ty);
let mut elems = do vec::from_fn(elem_count) |i| {
- GEPi(bcx, base, ~[i])
+ match slice {
+ None => GEPi(bcx, base, ~[i]),
+ Some(n) if i < n => GEPi(bcx, base, ~[i]),
+ Some(n) if i > n => {
+ InBoundsGEP(bcx, base, ~[
+ Sub(bcx, count,
+ C_int(bcx.ccx(), (elem_count - i) as int))])
+ }
+ _ => unsafe { llvm::LLVMGetUndef(vt.llunit_ty) }
+ }
};
- if tail {
- let tail_offset = Mul(bcx, vt.llunit_size,
- C_int(bcx.ccx(), elem_count as int)
+ if slice.is_some() {
+ let n = slice.get();
+ let slice_offset = Mul(bcx, vt.llunit_size,
+ C_int(bcx.ccx(), n as int)
+ );
+ let slice_begin = tvec::pointer_add(bcx, base, slice_offset);
+ let slice_len_offset = Mul(bcx, vt.llunit_size,
+ C_int(bcx.ccx(), (elem_count - 1u) as int)
);
- let tail_begin = tvec::pointer_add(bcx, base, tail_offset);
- let tail_len = Sub(bcx, len, tail_offset);
- let tail_ty = ty::mk_evec(bcx.tcx(),
+ let slice_len = Sub(bcx, len, slice_len_offset);
+ let slice_ty = ty::mk_evec(bcx.tcx(),
ty::mt {ty: vt.unit_ty, mutbl: ast::m_imm},
ty::vstore_slice(ty::re_static)
);
- let scratch = scratch_datum(bcx, tail_ty, false);
- Store(bcx, tail_begin,
+ let scratch = scratch_datum(bcx, slice_ty, false);
+ Store(bcx, slice_begin,
GEPi(bcx, scratch.val, [0u, abi::slice_elt_base])
);
- Store(bcx, tail_len,
+ Store(bcx, slice_len,
GEPi(bcx, scratch.val, [0u, abi::slice_elt_len])
);
- elems.push(scratch.val);
+ elems[n] = scratch.val;
scratch.add_clean(bcx);
}
test_val = Load(bcx, val);
kind = compare;
},
- vec_len_eq(_) | vec_len_ge(_) => {
+ vec_len_eq(*) | vec_len_ge(*) => {
let vt = tvec::vec_types(bcx, node_id_type(bcx, pat_id));
let unboxed = load_if_immediate(bcx, val, vt.vec_ty);
let (_, len) = tvec::get_base_and_len(
unpacked = argvals;
opt_cx = new_bcx;
}
- vec_len_eq(n) | vec_len_ge(n) => {
- let tail = match *opt {
- vec_len_ge(_) => true,
- _ => false
+ vec_len_eq(n) | vec_len_ge(n, _) => {
+ let n = match *opt {
+ vec_len_ge(*) => n + 1u,
+ _ => n
+ };
+ let slice = match *opt {
+ vec_len_ge(_, i) => Some(i),
+ _ => None
};
- let args = extract_vec_elems(opt_cx, pat_id, n, tail, val);
+ let args = extract_vec_elems(opt_cx, pat_id, n, slice,
+ val, test_val);
size = args.vals.len();
unpacked = /*bad*/copy args.vals;
opt_cx = args.bcx;
}
}
}
- ast::pat_vec(elts, tail) => {
+ ast::pat_vec(before, slice, after) => {
let default_region_var =
fcx.infcx().next_region_var_with_lb(
pat.span, pcx.block_region
);
}
};
- for elts.each |elt| {
+ for before.each |elt| {
check_pat(pcx, *elt, elt_type.ty);
}
- fcx.write_ty(pat.id, expected);
-
- match tail {
- Some(tail_pat) => {
+ match slice {
+ Some(slice_pat) => {
let slice_ty = ty::mk_evec(tcx,
ty::mt {ty: elt_type.ty, mutbl: elt_type.mutbl},
ty::vstore_slice(region_var)
);
- check_pat(pcx, tail_pat, slice_ty);
+ check_pat(pcx, slice_pat, slice_ty);
}
None => ()
}
+ for after.each |elt| {
+ check_pat(pcx, *elt, elt_type.ty);
+ }
+ fcx.write_ty(pat.id, expected);
}
}
}
}
ast::pat_lit(*) => {}
ast::pat_range(*) => {}
- ast::pat_vec(ref ps, ref opt_tail_pat) => {
+ ast::pat_vec(ref before, ref slice, ref after) => {
let vec_ty = rcx.resolve_node_type(pat.id);
if !ty::type_contains_err(vec_ty) {
let vstore = ty::ty_vstore(vec_ty);
ty::vstore_box => None
};
- link_ref_bindings_in_pats(rcx, ps, guarantor1);
-
- for opt_tail_pat.each |p| {
- link_ref_bindings_in_pat(rcx, *p, guarantor);
+ link_ref_bindings_in_pats(rcx, before, guarantor1);
+ for slice.each |&p| {
+ link_ref_bindings_in_pat(rcx, p, guarantor);
}
+ link_ref_bindings_in_pats(rcx, after, guarantor1);
}
}
}
pat_region(@pat), // borrowed pointer pattern
pat_lit(@expr),
pat_range(@expr, @expr),
- pat_vec(~[@pat], Option<@pat>)
+ // [a, b, ..i, y, z] is represented as
+ // pat_vec(~[a, b], Some(i), ~[y, z])
+ pat_vec(~[@pat], Option<@pat>, ~[@pat])
}
#[auto_encode]
pat_box(s) | pat_uniq(s) | pat_region(s) => {
walk_pat(s, it)
}
- pat_vec(ref elts, ref tail) => {
- for elts.each |p| {
+ pat_vec(ref before, ref slice, ref after) => {
+ for before.each |p| {
walk_pat(*p, it)
}
- for tail.each |tail| {
- walk_pat(*tail, it)
+ for slice.each |p| {
+ walk_pat(*p, it)
+ }
+ for after.each |p| {
+ walk_pat(*p, it)
}
}
pat_wild | pat_lit(_) | pat_range(_, _) | pat_ident(_, _, _) |
pat_range(e1, e2) => {
pat_range(fld.fold_expr(e1), fld.fold_expr(e2))
},
- pat_vec(ref elts, ref tail) => {
+ pat_vec(ref before, ref slice, ref after) => {
pat_vec(
- elts.map(|x| fld.fold_pat(*x)),
- tail.map(|tail| fld.fold_pat(*tail))
+ before.map(|x| fld.fold_pat(*x)),
+ slice.map(|x| fld.fold_pat(*x)),
+ after.map(|x| fld.fold_pat(*x))
)
}
}
fn parse_pat_vec_elements(
&self,
refutable: bool
- ) -> (~[@pat], Option<@pat>) {
- let mut elements = ~[];
- let mut tail = None;
+ ) -> (~[@pat], Option<@pat>, ~[@pat]) {
+ let mut before = ~[];
+ let mut slice = None;
+ let mut after = ~[];
let mut first = true;
+ let mut before_slice = true;
while *self.token != token::RBRACKET {
if first { first = false; }
else { self.expect(&token::COMMA); }
- let mut is_tail = false;
- if *self.token == token::DOTDOT {
- self.bump();
- is_tail = true;
+ let mut is_slice = false;
+ if before_slice {
+ if *self.token == token::DOTDOT {
+ self.bump();
+ is_slice = true;
+ before_slice = false;
+ }
}
let subpat = self.parse_pat(refutable);
- if is_tail {
+ if is_slice {
match subpat {
@ast::pat { node: pat_wild, _ } => (),
@ast::pat { node: pat_ident(_, _, _), _ } => (),
span, ~"expected an identifier or `_`"
)
}
- tail = Some(subpat);
- break;
+ slice = Some(subpat);
+ } else {
+ if before_slice {
+ before.push(subpat);
+ } else {
+ after.push(subpat);
+ }
}
-
- elements.push(subpat);
}
- return (elements, tail);
+
+ (before, slice, after)
}
fn parse_pat_fields(&self, refutable: bool) -> (~[ast::field_pat], bool) {
}
token::LBRACKET => {
self.bump();
- let (elements, tail) = self.parse_pat_vec_elements(refutable);
+ let (before, slice, after) =
+ self.parse_pat_vec_elements(refutable);
hi = self.span.hi;
self.expect(&token::RBRACKET);
- pat = ast::pat_vec(elements, tail);
+ pat = ast::pat_vec(before, slice, after);
}
copy tok => {
if !is_ident_or_path(&tok)
word(s.s, ~"..");
print_expr(s, end);
}
- ast::pat_vec(elts, tail) => {
+ ast::pat_vec(before, slice, after) => {
word(s.s, ~"[");
- commasep(s, inconsistent, elts, |s, p| print_pat(s, p, refutable));
- for tail.each |tail| {
- if vec::len(elts) != 0u { word_space(s, ~","); }
+ do commasep(s, inconsistent, before) |s, p| {
+ print_pat(s, p, refutable);
+ }
+ for slice.each |&p| {
+ if !before.is_empty() { word_space(s, ~","); }
word(s.s, ~"..");
- print_pat(s, *tail, refutable);
+ print_pat(s, p, refutable);
+ if !after.is_empty() { word_space(s, ~","); }
+ }
+ do commasep(s, inconsistent, after) |s, p| {
+ print_pat(s, p, refutable);
}
word(s.s, ~"]");
}
(v.visit_expr)(e2, e, v);
}
pat_wild => (),
- pat_vec(ref elts, ref tail) => {
- for elts.each |elt| {
+ pat_vec(ref before, ref slice, ref after) => {
+ for before.each |elt| {
+ (v.visit_pat)(*elt, e, v);
+ }
+ for slice.each |elt| {
(v.visit_pat)(*elt, e, v);
}
- for tail.each |tail| {
+ for after.each |tail| {
(v.visit_pat)(*tail, e, v);
}
}
+++ /dev/null
-fn main() {
- match ~[] {
- [_, ..tail, _] => {}, //~ ERROR: expected `]` but found `,`
- _ => ()
- }
-}
fn main() {
let a = ~[];
match a {
- [1, ..tail, ..tail] => {}, //~ ERROR: expected `]` but found `,`
+ [1, ..tail, ..tail] => {}, //~ ERROR: unexpected token: `..`
_ => ()
}
}
fn a() -> &[int] {
let vec = [1, 2, 3, 4];
let tail = match vec { //~ ERROR illegal borrow
- [_a, ..tail] => tail,
- _ => fail!(~"foo")
+ [_, ..tail] => tail,
+ _ => fail!(~"a")
};
tail
}
-fn main() {
- let tail = a();
- for tail.each |n| {
- io::println(fmt!("%d", *n));
- }
+fn b() -> &[int] {
+ let vec = [1, 2, 3, 4];
+ let init = match vec { //~ ERROR illegal borrow
+ [..init, _] => init,
+ _ => fail!(~"b")
+ };
+ init
}
+
+fn c() -> &[int] {
+ let vec = [1, 2, 3, 4];
+ let slice = match vec { //~ ERROR illegal borrow
+ [_, ..slice, _] => slice,
+ _ => fail!(~"c")
+ };
+ slice
+}
+
+fn main() {}
--- /dev/null
+fn foldl<T, U: Copy>(
+ values: &[T],
+ initial: U,
+ function: &fn(partial: U, element: &T) -> U
+) -> U {
+ match values {
+ [head, ..tail] =>
+ foldl(tail, function(initial, &head), function),
+ [] => copy initial
+ }
+}
+
+fn foldr<T, U: Copy>(
+ values: &[T],
+ initial: U,
+ function: &fn(element: &T, partial: U) -> U
+) -> U {
+ match values {
+ [..head, tail] =>
+ foldr(head, function(&tail, initial), function),
+ [] => copy initial
+ }
+}
+
+pub fn main() {
+ let x = [1, 2, 3, 4, 5];
+
+ let product = foldl(x, 1, |a, b| a * *b);
+ fail_unless!(product == 120);
+
+ let sum = foldr(x, 0, |a, b| *a + b);
+ fail_unless!(sum == 15);
+}
-fn foldl<T, U: Copy>(
- values: &[T],
- initial: U,
- function: &fn(partial: U, element: &T) -> U
-) -> U {
- match values {
- [head, ..tail] =>
- foldl(tail, function(initial, &head), function),
- _ => copy initial
- }
-}
-
pub fn main() {
- let x = [1, 2, 3, 4, 5];
+ let x = [1];
match x {
- [a, b, c, d, e, f] => {
- ::core::util::unreachable();
- }
- [a, b, c, d, e] => {
+ [_, _, _, _, _, .._] => ::core::util::unreachable(),
+ [.._, _, _, _, _] => ::core::util::unreachable(),
+ [_, .._, _, _] => ::core::util::unreachable(),
+ [_, _] => ::core::util::unreachable(),
+ [a] => {
fail_unless!(a == 1);
- fail_unless!(b == 2);
- fail_unless!(c == 3);
- fail_unless!(d == 4);
- fail_unless!(e == 5);
- }
- _ => {
- ::core::util::unreachable();
}
+ [] => ::core::util::unreachable()
}
-
- let product = foldl(x, 1, |a, b| a * *b);
- fail_unless!(product == 120);
}