diff options
| author | Marijn Haverbeke <marijnh@gmail.com> | 2011-07-11 14:13:20 +0200 |
|---|---|---|
| committer | Marijn Haverbeke <marijnh@gmail.com> | 2011-07-11 15:32:41 +0200 |
| commit | 7595fe5153cfc3e703cec4516616c51af3223bc6 (patch) | |
| tree | b35cdf3f29627c1d5173f8058ac9f0222bf15b17 /src/comp/syntax | |
| parent | 12cb128a0a8cfffeccae910c72831562bd9c3b93 (diff) | |
Implement record patterns
Closes #469.
Diffstat (limited to 'src/comp/syntax')
| -rw-r--r-- | src/comp/syntax/ast.rs | 6 | ||||
| -rw-r--r-- | src/comp/syntax/fold.rs | 7 | ||||
| -rw-r--r-- | src/comp/syntax/parse/parser.rs | 39 | ||||
| -rw-r--r-- | src/comp/syntax/print/pprust.rs | 16 | ||||
| -rw-r--r-- | src/comp/syntax/visit.rs | 3 | ||||
| -rw-r--r-- | src/comp/syntax/walk.rs | 3 |
6 files changed, 74 insertions, 0 deletions
diff --git a/src/comp/syntax/ast.rs b/src/comp/syntax/ast.rs index 37d57dacf3c..6c9c2f2f249 100644 --- a/src/comp/syntax/ast.rs +++ b/src/comp/syntax/ast.rs @@ -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); } + } _ {} } } diff --git a/src/comp/syntax/fold.rs b/src/comp/syntax/fold.rs index 8529542bf44..571473261ff 100644 --- a/src/comp/syntax/fold.rs +++ b/src/comp/syntax/fold.rs @@ -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) + } }; } diff --git a/src/comp/syntax/parse/parser.rs b/src/comp/syntax/parse/parser.rs index 567aa995fd6..29b12763d91 100644 --- a/src/comp/syntax/parse/parser.rs +++ b/src/comp/syntax/parse/parser.rs @@ -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); diff --git a/src/comp/syntax/print/pprust.rs b/src/comp/syntax/print/pprust.rs index 2bc4efb1e59..e62b37807f2 100644 --- a/src/comp/syntax/print/pprust.rs +++ b/src/comp/syntax/print/pprust.rs @@ -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); } diff --git a/src/comp/syntax/visit.rs b/src/comp/syntax/visit.rs index c6e4d1911d4..470a8e4e38d 100644 --- a/src/comp/syntax/visit.rs +++ b/src/comp/syntax/visit.rs @@ -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 (_) { } } } diff --git a/src/comp/syntax/walk.rs b/src/comp/syntax/walk.rs index 77b13f0c9b8..024437e4327 100644 --- a/src/comp/syntax/walk.rs +++ b/src/comp/syntax/walk.rs @@ -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); |
