Implement &-patterns

Closes #2855
This commit is contained in:
Tim Chevalier 2012-09-07 17:07:32 -07:00
parent e9f5a099df
commit 53ce42dc4f
13 changed files with 88 additions and 18 deletions

View File

@ -360,6 +360,7 @@ enum pat_ {
pat_tup(~[@pat]),
pat_box(@pat),
pat_uniq(@pat),
pat_region(@pat), // borrowed pointer pattern
pat_lit(@expr),
pat_range(@expr, @expr),
}

View File

@ -595,7 +595,7 @@ fn walk_pat(pat: @pat, it: fn(@pat)) {
pat_enum(_, Some(s)) | pat_tup(s) => for s.each |p| {
walk_pat(p, it)
},
pat_box(s) | pat_uniq(s) => walk_pat(s, it),
pat_box(s) | pat_uniq(s) | pat_region(s) => walk_pat(s, it),
pat_wild | pat_lit(_) | pat_range(_, _) | pat_ident(_, _, _)
| pat_enum(_, _) => ()
}

View File

@ -384,6 +384,7 @@ fn noop_fold_pat(p: pat_, fld: ast_fold) -> pat_ {
pat_tup(elts) => pat_tup(vec::map(elts, |x| fld.fold_pat(x))),
pat_box(inner) => pat_box(fld.fold_pat(inner)),
pat_uniq(inner) => pat_uniq(fld.fold_pat(inner)),
pat_region(inner) => pat_region(fld.fold_pat(inner)),
pat_range(e1, e2) => {
pat_range(fld.fold_expr(e1), fld.fold_expr(e2))
}

View File

@ -42,8 +42,8 @@ use ast::{_mod, add, alt_check, alt_exhaustive, arg, arm, attribute,
mac_invoc_tt, mac_var, matcher, match_nonterminal, match_seq,
match_tok, method, mode, module_ns, mt, mul, mutability,
named_field, neg, noreturn, not, pat, pat_box, pat_enum,
pat_ident, pat_lit, pat_range, pat_rec, pat_struct, pat_tup,
pat_uniq, pat_wild, path, private, proto, proto_bare,
pat_ident, pat_lit, pat_range, pat_rec, pat_region, pat_struct,
pat_tup, pat_uniq, pat_wild, path, private, proto, proto_bare,
proto_block, proto_box, proto_uniq, provided, public, pure_fn,
purity, re_anon, re_named, region, rem, required, ret_style,
return_val, self_ty, shl, shr, stmt, stmt_decl, stmt_expr,
@ -1844,6 +1844,25 @@ struct parser {
};
}
token::BINOP(token::AND) => {
let lo = self.span.lo;
self.bump();
let sub = self.parse_pat(refutable);
hi = sub.span.hi;
// HACK: parse &"..." as a literal of a borrowed str
pat = match sub.node {
pat_lit(e@@{
node: expr_lit(@{node: lit_str(_), span: _}), _
}) => {
let vst = @{id: self.get_id(), callee_id: self.get_id(),
node: expr_vstore(e,
vstore_slice(self.region_from_name(None))),
span: mk_sp(lo, hi)};
pat_lit(vst)
}
_ => pat_region(sub)
};
}
token::LBRACE => {
self.bump();
let (fields, etc) = self.parse_pat_fields(refutable);

View File

@ -1537,6 +1537,10 @@ fn print_pat(s: ps, &&pat: @ast::pat) {
}
ast::pat_box(inner) => { word(s.s, ~"@"); print_pat(s, inner); }
ast::pat_uniq(inner) => { word(s.s, ~"~"); print_pat(s, inner); }
ast::pat_region(inner) => {
word(s.s, ~"&");
print_pat(s, inner);
}
ast::pat_lit(e) => print_expr(s, e),
ast::pat_range(begin, end) => {
print_expr(s, begin);

View File

@ -237,7 +237,8 @@ fn visit_pat<E>(p: @pat, e: E, v: vt<E>) {
pat_tup(elts) => for elts.each |elt| {
v.visit_pat(elt, e, v)
},
pat_box(inner) | pat_uniq(inner) => v.visit_pat(inner, e, v),
pat_box(inner) | pat_uniq(inner) | pat_region(inner) =>
v.visit_pat(inner, e, v),
pat_ident(_, path, inner) => {
visit_path(path, e, v);
do option::iter(inner) |subpat| { v.visit_pat(subpat, e, v)};

View File

@ -235,7 +235,7 @@ fn pat_ctor_id(tcx: ty::ctxt, p: @pat) -> Option<ctor> {
pat_range(lo, hi) => {
Some(range(eval_const_expr(tcx, lo), eval_const_expr(tcx, hi)))
}
pat_box(_) | pat_uniq(_) | pat_rec(_, _) | pat_tup(_) |
pat_box(_) | pat_uniq(_) | pat_rec(_, _) | pat_tup(_) | pat_region(*) |
pat_struct(*) => {
Some(single)
}
@ -258,8 +258,8 @@ fn is_wild(tcx: ty::ctxt, p: @pat) -> bool {
fn missing_ctor(tcx: ty::ctxt, m: matrix, left_ty: ty::t) -> Option<ctor> {
match ty::get(left_ty).struct {
ty::ty_box(_) | ty::ty_uniq(_) | ty::ty_tup(_) | ty::ty_rec(_) |
ty::ty_class(*) => {
ty::ty_box(_) | ty::ty_uniq(_) | ty::ty_rptr(*) | ty::ty_tup(_) |
ty::ty_rec(_) | ty::ty_class(*) => {
for m.each |r| {
if !is_wild(tcx, r[0]) { return None; }
}
@ -305,7 +305,7 @@ fn ctor_arity(tcx: ty::ctxt, ctor: ctor, ty: ty::t) -> uint {
match ty::get(ty).struct {
ty::ty_tup(fs) => fs.len(),
ty::ty_rec(fs) => fs.len(),
ty::ty_box(_) | ty::ty_uniq(_) => 1u,
ty::ty_box(_) | ty::ty_uniq(_) | ty::ty_rptr(*) => 1u,
ty::ty_enum(eid, _) => {
let id = match ctor { variant(id) => id,
_ => fail ~"impossible case" };
@ -386,7 +386,8 @@ fn specialize(tcx: ty::ctxt, r: ~[@pat], ctor_id: ctor, arity: uint,
Some(vec::append(args, vec::tail(r)))
}
pat_tup(args) => Some(vec::append(args, vec::tail(r))),
pat_box(a) | pat_uniq(a) => Some(vec::append(~[a], vec::tail(r))),
pat_box(a) | pat_uniq(a) | pat_region(a) =>
Some(vec::append(~[a], vec::tail(r))),
pat_lit(expr) => {
let e_v = eval_const_expr(tcx, expr);
let match_ = match ctor_id {
@ -440,7 +441,8 @@ fn is_refutable(tcx: ty::ctxt, pat: @pat) -> bool {
}
match pat.node {
pat_box(sub) | pat_uniq(sub) | pat_ident(_, _, Some(sub)) => {
pat_box(sub) | pat_uniq(sub) | pat_region(sub) |
pat_ident(_, _, Some(sub)) => {
is_refutable(tcx, sub)
}
pat_wild | pat_ident(_, _, None) => { false }

View File

@ -898,8 +898,9 @@ impl &mem_categorization_ctxt {
}
}
ast::pat_box(subpat) | ast::pat_uniq(subpat) => {
// @p1, ~p1
ast::pat_box(subpat) | ast::pat_uniq(subpat) |
ast::pat_region(subpat) => {
// @p1, ~p1, &p1
match self.cat_deref(subpat, cmt, 0u, true) {
Some(subcmt) => {
self.cat_pattern(subcmt, subpat, op);

View File

@ -914,12 +914,8 @@ fn bind_irrefutable_pat(bcx: block, pat: @ast::pat, val: ValueRef,
bcx = bind_irrefutable_pat(bcx, elem, fldptr, make_copy);
}
}
ast::pat_box(inner) => {
let llbox = Load(bcx, val);
let unboxed = GEPi(bcx, llbox, [0u, abi::box_field_body]);
bcx = bind_irrefutable_pat(bcx, inner, unboxed, true);
}
ast::pat_uniq(inner) => {
ast::pat_box(inner) | ast::pat_uniq(inner) |
ast::pat_region(inner) => {
let llbox = Load(bcx, val);
let unboxed = GEPi(bcx, llbox, [0u, abi::box_field_body]);
bcx = bind_irrefutable_pat(bcx, inner, unboxed, true);

View File

@ -447,6 +447,22 @@ fn check_pat(pcx: pat_ctxt, pat: @ast::pat, expected: ty::t) {
}
}
}
ast::pat_region(inner) => {
match structure_of(fcx, pat.span, expected) {
ty::ty_rptr(_, e_inner) => {
check_pat(pcx, inner, e_inner.ty);
fcx.write_ty(pat.id, expected);
}
_ => {
tcx.sess.span_fatal(
pat.span,
~"mismatched types: expected `" +
fcx.infcx().ty_to_str(expected) +
~"` found borrowed pointer");
}
}
}
}
}

View File

@ -0,0 +1,10 @@
fn foo<T>(s: &str) {
match s {
&"kitty" => fail ~"cat",
_ => ()
}
}
fn main() {
}

View File

@ -0,0 +1,10 @@
fn foo<T>(s: &r/uint) {
match s {
&3 => fail ~"oh",
_ => ()
}
}
fn main() {
}

View File

@ -0,0 +1,9 @@
fn foo<T>(x: &T) {
match x {
&a => fail #fmt("%?", a)
}
}
fn main() {
}