Add tuple patterns
This commit is contained in:
parent
1ee24d31e1
commit
3f127e397f
9 changed files with 130 additions and 35 deletions
|
|
@ -84,6 +84,12 @@ fn pattern_supersedes(tcx: &ty::ctxt, a: &@pat, b: &@pat) -> bool {
|
|||
_ { ret false; }
|
||||
}
|
||||
}
|
||||
pat_tup(suba) {
|
||||
alt b.node {
|
||||
pat_tup(subb) { ret patterns_supersede(tcx, suba, subb); }
|
||||
_ { ret false; }
|
||||
}
|
||||
}
|
||||
pat_box(suba) {
|
||||
alt b.node {
|
||||
pat_box(subb) { ret pattern_supersedes(tcx, suba, subb); }
|
||||
|
|
@ -112,6 +118,12 @@ fn is_refutable(tcx: &ty::ctxt, pat: &@pat) -> bool {
|
|||
}
|
||||
ret false;
|
||||
}
|
||||
pat_tup(elts) {
|
||||
for elt in elts {
|
||||
if is_refutable(tcx, elt) { ret true; }
|
||||
}
|
||||
ret false;
|
||||
}
|
||||
pat_tag(_, args) {
|
||||
let vdef = variant_def_ids(tcx.def_map.get(pat.id));
|
||||
if std::ivec::len(ty::tag_variants(tcx, vdef.tg)) != 1u {
|
||||
|
|
|
|||
|
|
@ -644,7 +644,7 @@ fn lookup_in_scope(e: &env, sc: scopes, sp: &span, name: &ident,
|
|||
}
|
||||
scope_loop(local) {
|
||||
if ns == ns_value {
|
||||
alt lookup_in_pat(name, *local.node.pat) {
|
||||
alt lookup_in_pat(name, local.node.pat) {
|
||||
some(did) { ret some(ast::def_local(did)); }
|
||||
_ {}
|
||||
}
|
||||
|
|
@ -654,7 +654,7 @@ fn lookup_in_scope(e: &env, sc: scopes, sp: &span, name: &ident,
|
|||
scope_arm(a) {
|
||||
if ns == ns_value {
|
||||
ret option::map(ast::def_binding,
|
||||
lookup_in_pat(name, *a.pats.(0)));
|
||||
lookup_in_pat(name, a.pats.(0)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -711,30 +711,15 @@ fn lookup_in_ty_params(name: &ident, ty_params: &[ast::ty_param]) ->
|
|||
ret none[def];
|
||||
}
|
||||
|
||||
fn lookup_in_pat(name: &ident, pat: &ast::pat) -> option::t[def_id] {
|
||||
alt pat.node {
|
||||
ast::pat_bind(p_name) {
|
||||
fn lookup_in_pat(name: &ident, pat: &@ast::pat) -> option::t[def_id] {
|
||||
let found = none;
|
||||
for each bound in ast::pat_bindings(pat) {
|
||||
let p_name = alt bound.node { ast::pat_bind(n) { n } };
|
||||
if str::eq(p_name, name) {
|
||||
ret some(local_def(pat.id));
|
||||
found = some(local_def(bound.id));
|
||||
}
|
||||
}
|
||||
ast::pat_wild. { }
|
||||
ast::pat_lit(_) { }
|
||||
ast::pat_tag(_, pats) {
|
||||
for p: @ast::pat in pats {
|
||||
let found = lookup_in_pat(name, *p);
|
||||
if !is_none(found) { ret found; }
|
||||
}
|
||||
}
|
||||
ast::pat_rec(fields, _) {
|
||||
for f: ast::field_pat in fields {
|
||||
let found = lookup_in_pat(name, *f.pat);
|
||||
if !is_none(found) { ret found; }
|
||||
}
|
||||
}
|
||||
ast::pat_box(inner) { ret lookup_in_pat(name, *inner); }
|
||||
}
|
||||
ret none;
|
||||
ret found;
|
||||
}
|
||||
|
||||
fn lookup_in_fn(name: &ident, decl: &ast::fn_decl,
|
||||
|
|
@ -779,7 +764,7 @@ fn lookup_in_block(name: &ident, b: &ast::blk_, ns: namespace) ->
|
|||
ast::decl_local(locs) {
|
||||
for loc: @ast::local in locs {
|
||||
if ns == ns_value {
|
||||
alt lookup_in_pat(name, *loc.node.pat) {
|
||||
alt lookup_in_pat(name, loc.node.pat) {
|
||||
some(did) { ret some(ast::def_local(did)); }
|
||||
_ {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ fn matches_always(p: &@ast::pat) -> bool {
|
|||
ast::pat_wild. { true }
|
||||
ast::pat_bind(_) { true }
|
||||
ast::pat_rec(_, _) { true }
|
||||
ast::pat_tup(_) { true }
|
||||
_ { false }
|
||||
};
|
||||
}
|
||||
|
|
@ -145,6 +146,18 @@ fn enter_rec(m: &match, col: uint, fields: &[ast::ident], val: ValueRef) ->
|
|||
ret enter_match(m, col, val, bind e(dummy, fields, _));
|
||||
}
|
||||
|
||||
fn enter_tup(m: &match, col: uint, val: ValueRef, n_elts: uint) -> match {
|
||||
let dummy = @{id: 0, node: ast::pat_wild, span: {lo: 0u, hi: 0u}};
|
||||
fn e(dummy: &@ast::pat, n_elts: uint, p: &@ast::pat)
|
||||
-> option::t[[@ast::pat]] {
|
||||
alt p.node {
|
||||
ast::pat_tup(elts) { ret some(elts); }
|
||||
_ { ret some(ivec::init_elt(dummy, n_elts)); }
|
||||
}
|
||||
}
|
||||
ret enter_match(m, col, val, bind e(dummy, n_elts, _));
|
||||
}
|
||||
|
||||
fn enter_box(m: &match, col: uint, val: ValueRef) -> match {
|
||||
let dummy = @{id: 0, node: ast::pat_wild, span: {lo: 0u, hi: 0u}};
|
||||
fn e(dummy: &@ast::pat, p: &@ast::pat) -> option::t[[@ast::pat]] {
|
||||
|
|
@ -227,6 +240,13 @@ fn any_box_pat(m: &match, col: uint) -> bool {
|
|||
ret false;
|
||||
}
|
||||
|
||||
fn any_tup_pat(m: &match, col: uint) -> bool {
|
||||
for br: match_branch in m {
|
||||
alt br.pats.(col).node { ast::pat_tup(_) { ret true; } _ { } }
|
||||
}
|
||||
ret false;
|
||||
}
|
||||
|
||||
type exit_node = {bound: bind_map, from: BasicBlockRef, to: BasicBlockRef};
|
||||
type mk_fail = fn() -> BasicBlockRef;
|
||||
|
||||
|
|
@ -300,6 +320,23 @@ fn compile_submatch(bcx: @block_ctxt, m: &match, vals: [ValueRef],
|
|||
ret;
|
||||
}
|
||||
|
||||
if any_tup_pat(m, col) {
|
||||
let tup_ty = ty::node_id_to_monotype(ccx.tcx, pat_id);
|
||||
let n_tup_elts = alt ty::struct(ccx.tcx, tup_ty) {
|
||||
ty::ty_tup(elts) { ivec::len(elts) }
|
||||
};
|
||||
let tup_vals = ~[], i = 0u;
|
||||
while i < n_tup_elts {
|
||||
let r = trans::GEP_tup_like(bcx, tup_ty, val, ~[0, i as int]);
|
||||
tup_vals += ~[r.val];
|
||||
bcx = r.bcx;
|
||||
i += 1u;
|
||||
}
|
||||
compile_submatch(bcx, enter_tup(m, col, val, n_tup_elts),
|
||||
tup_vals + vals_left, f, exits);
|
||||
ret;
|
||||
}
|
||||
|
||||
// Unbox in case of a box field
|
||||
if any_box_pat(m, col) {
|
||||
let box = bcx.build.Load(val);
|
||||
|
|
@ -518,6 +555,15 @@ fn bind_irrefutable_pat(bcx: @block_ctxt, pat: &@ast::pat, val: ValueRef,
|
|||
bcx = bind_irrefutable_pat(r.bcx, f.pat, r.val, table, copy);
|
||||
}
|
||||
}
|
||||
ast::pat_tup(elems) {
|
||||
let tup_ty = ty::node_id_to_monotype(ccx.tcx, pat.id);
|
||||
let i = 0u;
|
||||
for elem in elems {
|
||||
let r = trans::GEP_tup_like(bcx, tup_ty, val, ~[0, i as int]);
|
||||
bcx = bind_irrefutable_pat(r.bcx, elem, r.val, table, copy);
|
||||
i += 1u;
|
||||
}
|
||||
}
|
||||
ast::pat_box(inner) {
|
||||
let box = bcx.build.Load(val);
|
||||
let unboxed = bcx.build.InBoundsGEP
|
||||
|
|
|
|||
|
|
@ -1454,6 +1454,31 @@ fn check_pat(fcx: &@fn_ctxt, map: &ast::pat_id_map, pat: &@ast::pat,
|
|||
}
|
||||
write::ty_only_fixup(fcx, pat.id, expected);
|
||||
}
|
||||
ast::pat_tup(elts) {
|
||||
let ex_elts;
|
||||
alt structure_of(fcx, pat.span, expected) {
|
||||
ty::ty_tup(elts) { ex_elts = elts; }
|
||||
_ {
|
||||
fcx.ccx.tcx.sess.span_fatal(pat.span,
|
||||
#fmt("mismatched types: expected %s, \
|
||||
found tuple", ty_to_str(fcx.ccx.tcx,
|
||||
expected)));
|
||||
}
|
||||
}
|
||||
let e_count = ivec::len(elts);
|
||||
if e_count != ivec::len(ex_elts) {
|
||||
fcx.ccx.tcx.sess.span_fatal
|
||||
(pat.span, #fmt("mismatched types: expected a tuple \
|
||||
with %u fields, found one with %u \
|
||||
fields", ivec::len(ex_elts), e_count));
|
||||
}
|
||||
let i = 0u;
|
||||
for elt in elts {
|
||||
check_pat(fcx, map, elt, ex_elts.(i));
|
||||
i += 1u;
|
||||
}
|
||||
write::ty_only_fixup(fcx, pat.id, expected);
|
||||
}
|
||||
ast::pat_box(inner) {
|
||||
alt structure_of(fcx, pat.span, expected) {
|
||||
ty::ty_box(e_inner) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue