mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-25 22:22:44 +00:00
parent
12cb128a0a
commit
7595fe5153
@ -297,6 +297,9 @@ fn arm_defnums(&ast::arm arm) -> vec[node_id] {
|
||||
case (ast::pat_tag(_, ?children)) {
|
||||
for (@ast::pat child in children) { walk_pat(found, child); }
|
||||
}
|
||||
case (ast::pat_rec(?fields, _)) {
|
||||
for (ast::field_pat f in fields) { walk_pat(found, f.pat); }
|
||||
}
|
||||
case (_) { }
|
||||
}
|
||||
}
|
||||
|
@ -313,6 +313,9 @@ fn resolve_names(&@env e, &@ast::crate c) {
|
||||
}
|
||||
}
|
||||
}
|
||||
case (ast::pat_rec(?fields, _)) {
|
||||
for (ast::field_pat f in fields) { walk_pat(e, sc, f.pat); }
|
||||
}
|
||||
case (_) { }
|
||||
}
|
||||
}
|
||||
@ -707,6 +710,12 @@ fn lookup_in_pat(&ident name, &ast::pat pat) -> option::t[def] {
|
||||
if (!option::is_none(found)) { ret found; }
|
||||
}
|
||||
}
|
||||
case (ast::pat_rec(?fields, _)) {
|
||||
for (ast::field_pat f in fields) {
|
||||
auto found = lookup_in_pat(name, *f.pat);
|
||||
if (!option::is_none(found)) { ret found; }
|
||||
}
|
||||
}
|
||||
}
|
||||
ret none[def];
|
||||
}
|
||||
@ -1261,6 +1270,9 @@ fn check_arm(@env e, &ast::arm a, &() x, &vt[()] v) {
|
||||
case (ast::pat_tag(_, ?children)) {
|
||||
for (@ast::pat child in children) { walk_pat(ch, child); }
|
||||
}
|
||||
case (ast::pat_rec(?fields, _)) {
|
||||
for (ast::field_pat f in fields) { walk_pat(ch, f.pat); }
|
||||
}
|
||||
case (_) { }
|
||||
}
|
||||
}
|
||||
|
@ -4839,6 +4839,23 @@ fn trans_pat_match(&@block_ctxt cx, &@ast::pat pat, ValueRef llval,
|
||||
}
|
||||
ret rslt(matched_cx, llval);
|
||||
}
|
||||
case (ast::pat_rec(?field_pats, _)) {
|
||||
auto bcx = cx;
|
||||
auto ccx = cx.fcx.lcx.ccx;
|
||||
auto rec_ty = pat_ty(ccx.tcx, pat);
|
||||
auto fields = alt (ty::struct(ccx.tcx, rec_ty)) {
|
||||
ty::ty_rec(?fields) { fields }
|
||||
};
|
||||
for (ast::field_pat f in field_pats) {
|
||||
let uint ix = ty::field_idx(ccx.sess, f.pat.span,
|
||||
f.ident, fields);
|
||||
auto r = GEP_tup_like(bcx, rec_ty, llval, ~[0, ix as int]);
|
||||
auto v = load_if_immediate(r.bcx, r.val,
|
||||
pat_ty(ccx.tcx, f.pat));
|
||||
bcx = trans_pat_match(r.bcx, f.pat, v, next_cx).bcx;
|
||||
}
|
||||
ret rslt(bcx, llval);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -4896,6 +4913,21 @@ fn trans_pat_binding(&@block_ctxt cx, &@ast::pat pat, ValueRef llval,
|
||||
}
|
||||
ret rslt(this_cx, llval);
|
||||
}
|
||||
case (ast::pat_rec(?field_pats, _)) {
|
||||
auto bcx = cx;
|
||||
auto ccx = cx.fcx.lcx.ccx;
|
||||
auto rec_ty = pat_ty(ccx.tcx, pat);
|
||||
auto fields = alt (ty::struct(ccx.tcx, rec_ty)) {
|
||||
ty::ty_rec(?fields) { fields }
|
||||
};
|
||||
for (ast::field_pat f in field_pats) {
|
||||
let uint ix = ty::field_idx(ccx.sess, f.pat.span,
|
||||
f.ident, fields);
|
||||
auto r = GEP_tup_like(bcx, rec_ty, llval, ~[0, ix as int]);
|
||||
bcx = trans_pat_binding(bcx, f.pat, r.val, true, bound).bcx;
|
||||
}
|
||||
ret rslt(bcx, llval);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1278,6 +1278,11 @@ fn replace_expr_type(&@fn_ctxt fcx, &@ast::expr expr,
|
||||
write::ty_fixup(fcx, expr.id, tup(new_tps, new_tyt._1));
|
||||
}
|
||||
|
||||
// FIXME remove once std::ivec::find makes it into a snapshot
|
||||
fn ivec_find[T](fn(&T) -> bool f, &T[] v) -> option::t[T] {
|
||||
for (T elt in v) { if (f(elt)) { ret some[T](elt); } }
|
||||
ret none[T];
|
||||
}
|
||||
|
||||
// AST fragment checking
|
||||
fn check_lit(@crate_ctxt ccx, &@ast::lit lit) -> ty::t {
|
||||
@ -1395,16 +1400,52 @@ fn check_pat(&@fn_ctxt fcx, &ast::pat_id_map map, &@ast::pat pat,
|
||||
case (_) {
|
||||
// FIXME: Switch expected and actual in this message? I
|
||||
// can never tell.
|
||||
|
||||
fcx.ccx.tcx.sess.span_fatal(pat.span,
|
||||
#fmt("mismatched types: \
|
||||
expected tag, found %s",
|
||||
expected %s, found tag",
|
||||
ty_to_str(fcx.ccx.tcx,
|
||||
expected)));
|
||||
}
|
||||
}
|
||||
write::ty_fixup(fcx, pat.id, path_tpot);
|
||||
}
|
||||
case (ast::pat_rec(?fields, ?etc)) {
|
||||
auto ex_fields;
|
||||
alt (structure_of(fcx, pat.span, expected)) {
|
||||
case (ty::ty_rec(?fields)) { ex_fields = fields; }
|
||||
case (_) {
|
||||
fcx.ccx.tcx.sess.span_fatal
|
||||
(pat.span, #fmt("mismatched types: expected %s, \
|
||||
found record",
|
||||
ty_to_str(fcx.ccx.tcx, expected)));
|
||||
}
|
||||
};
|
||||
auto f_count = ivec::len(fields);
|
||||
auto ex_f_count = ivec::len(ex_fields);
|
||||
if (ex_f_count < f_count || (!etc && ex_f_count > f_count)) {
|
||||
fcx.ccx.tcx.sess.span_fatal
|
||||
(pat.span, #fmt("mismatched types: expected a record \
|
||||
with %u fields, found one with %u \
|
||||
fields", ex_f_count, f_count));
|
||||
}
|
||||
fn matches(&str name, &ty::field f) -> bool {
|
||||
ret str::eq(name, f.ident);
|
||||
}
|
||||
for (ast::field_pat f in fields) {
|
||||
alt (ivec_find(bind matches(f.ident, _), ex_fields)) {
|
||||
some(?field) {
|
||||
check_pat(fcx, map, f.pat, field.mt.ty);
|
||||
}
|
||||
none {
|
||||
fcx.ccx.tcx.sess.span_fatal
|
||||
(pat.span, #fmt("mismatched types: did not \
|
||||
expect a record with a field %s",
|
||||
f.ident));
|
||||
}
|
||||
}
|
||||
}
|
||||
write::ty_only_fixup(fcx, pat.id, expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -118,11 +118,14 @@ type pat = rec(node_id id,
|
||||
pat_ node,
|
||||
span span);
|
||||
|
||||
type field_pat = rec(ident ident, @pat pat);
|
||||
|
||||
tag pat_ {
|
||||
pat_wild;
|
||||
pat_bind(ident);
|
||||
pat_lit(@lit);
|
||||
pat_tag(path, (@pat)[]);
|
||||
pat_rec(field_pat[], bool);
|
||||
}
|
||||
|
||||
type pat_id_map = std::map::hashmap[str, ast::node_id];
|
||||
@ -137,6 +140,9 @@ fn pat_id_map(&@pat pat) -> pat_id_map {
|
||||
pat_tag(_, ?sub) {
|
||||
for (@pat p in sub) { walk(map, p); }
|
||||
}
|
||||
pat_rec(?fields, _) {
|
||||
for (field_pat f in fields) { walk(map, f.pat); }
|
||||
}
|
||||
_ {}
|
||||
}
|
||||
}
|
||||
|
@ -267,6 +267,13 @@ fn noop_fold_pat(&pat_ p, ast_fold fld) -> pat_ {
|
||||
case (pat_tag(?pth, ?pats)) {
|
||||
pat_tag(fld.fold_path(pth), ivec::map(fld.fold_pat, pats))
|
||||
}
|
||||
case (pat_rec(?fields, ?etc)) {
|
||||
auto fs = ~[];
|
||||
for (ast::field_pat f in fields) {
|
||||
fs += ~[rec(ident=f.ident, pat=fld.fold_pat(f.pat))];
|
||||
}
|
||||
pat_rec(fs, etc)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1455,6 +1455,45 @@ fn parse_pat(&parser p) -> @ast::pat {
|
||||
}
|
||||
}
|
||||
}
|
||||
case (token::LBRACE) {
|
||||
p.bump();
|
||||
auto fields = ~[];
|
||||
auto etc = false;
|
||||
auto first = true;
|
||||
while (p.peek() != token::RBRACE) {
|
||||
if (p.peek() == token::DOT) {
|
||||
p.bump();
|
||||
expect(p, token::DOT);
|
||||
expect(p, token::DOT);
|
||||
if (p.peek() != token::RBRACE) {
|
||||
p.fatal("expecting }, found " +
|
||||
token::to_str(p.get_reader(), p.peek()));
|
||||
}
|
||||
etc = true;
|
||||
break;
|
||||
}
|
||||
if (first) { first = false; }
|
||||
else { expect(p, token::COMMA); }
|
||||
auto fieldname = parse_ident(p);
|
||||
auto subpat;
|
||||
if (p.peek() == token::COLON) {
|
||||
p.bump();
|
||||
subpat = parse_pat(p);
|
||||
} else {
|
||||
if (p.get_bad_expr_words().contains_key(fieldname)) {
|
||||
p.fatal("found " + fieldname +
|
||||
" in binding position");
|
||||
}
|
||||
subpat = @rec(id=p.get_id(),
|
||||
node=ast::pat_bind(fieldname),
|
||||
span=rec(lo=lo, hi=hi));
|
||||
}
|
||||
fields += ~[rec(ident=fieldname, pat=subpat)];
|
||||
}
|
||||
hi = p.get_hi_pos();
|
||||
p.bump();
|
||||
pat = ast::pat_rec(fields, etc);
|
||||
}
|
||||
case (?tok) {
|
||||
if (!is_ident(tok) || is_word(p, "true") || is_word(p, "false")) {
|
||||
auto lit = parse_lit(p);
|
||||
|
@ -1120,6 +1120,22 @@ fn print_pat(&ps s, &@ast::pat pat) {
|
||||
pclose(s);
|
||||
}
|
||||
}
|
||||
case (ast::pat_rec(?fields, ?etc)) {
|
||||
bopen(s);
|
||||
fn print_field(&ps s, &ast::field_pat f) {
|
||||
cbox(s, indent_unit);
|
||||
word(s.s, f.ident);
|
||||
word(s.s, ":");
|
||||
print_pat(s, f.pat);
|
||||
end(s);
|
||||
}
|
||||
fn get_span(&ast::field_pat f) -> codemap::span {
|
||||
ret f.pat.span;
|
||||
}
|
||||
commasep_cmnt_ivec(s, consistent, fields, print_field, get_span);
|
||||
if (etc) { space(s.s); word(s.s, "..."); }
|
||||
bclose(s, pat.span);
|
||||
}
|
||||
}
|
||||
s.ann.post(ann_node);
|
||||
}
|
||||
|
@ -190,6 +190,9 @@ fn visit_pat[E](&@pat p, &E e, &vt[E] v) {
|
||||
for (@ty tp in path.node.types) { v.visit_ty(tp, e, v); }
|
||||
for (@pat child in children) { v.visit_pat(child, e, v); }
|
||||
}
|
||||
case (pat_rec(?fields, _)) {
|
||||
for (field_pat f in fields) { v.visit_pat(f.pat, e, v); }
|
||||
}
|
||||
case (_) { }
|
||||
}
|
||||
}
|
||||
|
@ -189,6 +189,9 @@ fn walk_pat(&ast_visitor v, &@ast::pat p) {
|
||||
for (@ast::ty tp in path.node.types) { walk_ty(v, tp); }
|
||||
for (@ast::pat child in children) { walk_pat(v, child); }
|
||||
}
|
||||
case (ast::pat_rec(?fields, _)) {
|
||||
for (ast::field_pat f in fields) { walk_pat(v, f.pat); }
|
||||
}
|
||||
case (_) { }
|
||||
}
|
||||
v.visit_pat_post(p);
|
||||
|
7
src/test/compile-fail/bad-record-pat-2.rs
Normal file
7
src/test/compile-fail/bad-record-pat-2.rs
Normal file
@ -0,0 +1,7 @@
|
||||
// error-pattern:did not expect a record with a field q
|
||||
|
||||
fn main() {
|
||||
alt rec(x=1, y=2) {
|
||||
{x, q} {}
|
||||
}
|
||||
}
|
7
src/test/compile-fail/bad-record-pat.rs
Normal file
7
src/test/compile-fail/bad-record-pat.rs
Normal file
@ -0,0 +1,7 @@
|
||||
// error-pattern:expected a record with 2 fields, found one with 1
|
||||
|
||||
fn main() {
|
||||
alt rec(x=1, y=2) {
|
||||
{x} {}
|
||||
}
|
||||
}
|
15
src/test/run-pass/record-pat.rs
Normal file
15
src/test/run-pass/record-pat.rs
Normal file
@ -0,0 +1,15 @@
|
||||
tag t1 { a(int); b(uint); }
|
||||
type t2 = rec(t1 x, int y);
|
||||
tag t3 { c(t2, uint); }
|
||||
|
||||
fn m(&t3 in) -> int {
|
||||
alt in {
|
||||
c({x: a(?m) ...}, _) { ret m; }
|
||||
c({x: b(?m), y}, ?z) { ret (m + z) as int + y; }
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
assert m(c(rec(x=a(10), y=5), 4u)) == 10;
|
||||
assert m(c(rec(x=b(10u), y=5), 4u)) == 19;
|
||||
}
|
Loading…
Reference in New Issue
Block a user