Allow binding of nested patterns
See src/test/run-pass/nested-patterns.rs for some examples. The syntax is
boundvar@subpattern
Which will match the subpattern as usual, but also bind boundvar to the
whole matched value.
Closes #838
This commit is contained in:
parent
8c966b7b18
commit
9a269a3aa8
17 changed files with 132 additions and 79 deletions
|
|
@ -92,7 +92,7 @@ type field_pat = {ident: ident, pat: @pat};
|
|||
|
||||
tag pat_ {
|
||||
pat_wild;
|
||||
pat_bind(ident);
|
||||
pat_bind(ident, option::t<@pat>);
|
||||
pat_tag(@path, [@pat]);
|
||||
pat_rec([field_pat], bool);
|
||||
pat_tup([@pat]);
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ type pat_id_map = std::map::hashmap<str, node_id>;
|
|||
fn pat_id_map(pat: @pat) -> pat_id_map {
|
||||
let map = std::map::new_str_hash::<node_id>();
|
||||
pat_bindings(pat) {|bound|
|
||||
let name = alt bound.node { pat_bind(n) { n } };
|
||||
let name = alt bound.node { pat_bind(n, _) { n } };
|
||||
map.insert(name, bound.id);
|
||||
};
|
||||
ret map;
|
||||
|
|
@ -67,7 +67,8 @@ fn pat_id_map(pat: @pat) -> pat_id_map {
|
|||
// FIXME: could return a constrained type
|
||||
fn pat_bindings(pat: @pat, it: block(@pat)) {
|
||||
alt pat.node {
|
||||
pat_bind(_) { it(pat); }
|
||||
pat_bind(_, option::none.) { it(pat); }
|
||||
pat_bind(_, option::some(sub)) { it(pat); pat_bindings(sub, it); }
|
||||
pat_tag(_, sub) { for p in sub { pat_bindings(p, it); } }
|
||||
pat_rec(fields, _) { for f in fields { pat_bindings(f.pat, it); } }
|
||||
pat_tup(elts) { for elt in elts { pat_bindings(elt, it); } }
|
||||
|
|
|
|||
|
|
@ -270,7 +270,9 @@ fn noop_fold_arm(a: arm, fld: ast_fold) -> arm {
|
|||
fn noop_fold_pat(p: pat_, fld: ast_fold) -> pat_ {
|
||||
ret alt p {
|
||||
pat_wild. { p }
|
||||
pat_bind(ident) { pat_bind(fld.fold_ident(ident)) }
|
||||
pat_bind(ident, sub) {
|
||||
pat_bind(fld.fold_ident(ident), option::map(fld.fold_pat, sub))
|
||||
}
|
||||
pat_lit(_) { p }
|
||||
pat_tag(pth, pats) {
|
||||
pat_tag(fld.fold_path(pth), vec::map(fld.fold_pat, pats))
|
||||
|
|
|
|||
|
|
@ -1429,10 +1429,9 @@ fn parse_pat(p: parser) -> @ast::pat {
|
|||
if p.get_bad_expr_words().contains_key(fieldname) {
|
||||
p.fatal("found " + fieldname + " in binding position");
|
||||
}
|
||||
subpat =
|
||||
@{id: p.get_id(),
|
||||
node: ast::pat_bind(fieldname),
|
||||
span: ast_util::mk_sp(lo, hi)};
|
||||
subpat = @{id: p.get_id(),
|
||||
node: ast::pat_bind(fieldname, none),
|
||||
span: ast_util::mk_sp(lo, hi)};
|
||||
}
|
||||
fields += [{ident: fieldname, pat: subpat}];
|
||||
}
|
||||
|
|
@ -1479,7 +1478,9 @@ fn parse_pat(p: parser) -> @ast::pat {
|
|||
_ { true }
|
||||
} {
|
||||
hi = p.get_hi_pos();
|
||||
pat = ast::pat_bind(parse_value_ident(p));
|
||||
let name = parse_value_ident(p);
|
||||
let sub = eat(p, token::AT) ? some(parse_pat(p)) : none;
|
||||
pat = ast::pat_bind(name, sub);
|
||||
} else {
|
||||
let tag_path = parse_path_and_ty_param_substs(p);
|
||||
hi = tag_path.span.hi;
|
||||
|
|
|
|||
|
|
@ -1062,7 +1062,13 @@ fn print_pat(s: ps, &&pat: @ast::pat) {
|
|||
s.ann.pre(ann_node);
|
||||
alt pat.node {
|
||||
ast::pat_wild. { word(s.s, "_"); }
|
||||
ast::pat_bind(id) { word(s.s, id); }
|
||||
ast::pat_bind(id, sub) {
|
||||
word(s.s, id);
|
||||
alt sub {
|
||||
some(p) { word(s.s, "@"); print_pat(s, p); }
|
||||
_ {}
|
||||
}
|
||||
}
|
||||
ast::pat_tag(path, args) {
|
||||
print_path(s, path, true);
|
||||
if vec::len(args) > 0u {
|
||||
|
|
|
|||
|
|
@ -159,8 +159,9 @@ fn visit_pat<E>(p: @pat, e: E, v: vt<E>) {
|
|||
for f: field_pat in fields { v.visit_pat(f.pat, e, v); }
|
||||
}
|
||||
pat_tup(elts) { for elt in elts { v.visit_pat(elt, e, v); } }
|
||||
pat_box(inner) { v.visit_pat(inner, e, v); }
|
||||
pat_uniq(inner) { v.visit_pat(inner, e, v); }
|
||||
pat_box(inner) | pat_uniq(inner) | pat_bind(_, some(inner)) {
|
||||
v.visit_pat(inner, e, v);
|
||||
}
|
||||
_ { }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue