diff options
| author | Patrick Walton <pcwalton@mimiga.net> | 2012-07-31 19:25:24 -0700 |
|---|---|---|
| committer | Patrick Walton <pcwalton@mimiga.net> | 2012-07-31 19:26:25 -0700 |
| commit | b414db041be115d877e5b17bc86ea019420b672c (patch) | |
| tree | d7e15ba792c8376aaabe9727726de34b03e89baf /src/libsyntax | |
| parent | a841789a41941ad73a57cd9972dfbd5fdff02685 (diff) | |
| download | rust-b414db041be115d877e5b17bc86ea019420b672c.tar.gz rust-b414db041be115d877e5b17bc86ea019420b672c.zip | |
rustc: Parse by-reference pattern bindings with the "ref" keyword
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/ast.rs | 8 | ||||
| -rw-r--r-- | src/libsyntax/ast_map.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax/ast_util.rs | 4 | ||||
| -rw-r--r-- | src/libsyntax/ext/auto_serialize.rs | 6 | ||||
| -rw-r--r-- | src/libsyntax/ext/pipes/ast_builder.rs | 6 | ||||
| -rw-r--r-- | src/libsyntax/ext/qquote.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax/ext/tt/earley_parser.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax/fold.rs | 5 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 148 | ||||
| -rw-r--r-- | src/libsyntax/parse/token.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax/print/pprust.rs | 10 | ||||
| -rw-r--r-- | src/libsyntax/visit.rs | 2 |
12 files changed, 121 insertions, 76 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 8c2b6dc3490..0dede78ffd0 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -146,6 +146,12 @@ type pat = {id: node_id, node: pat_, span: span}; type field_pat = {ident: ident, pat: @pat}; #[auto_serialize] +enum binding_mode { + bind_by_value, + bind_by_ref +} + +#[auto_serialize] enum pat_ { pat_wild, // A pat_ident may either be a new bound variable, @@ -155,7 +161,7 @@ enum pat_ { // which it is. The resolver determines this, and // records this pattern's node_id in an auxiliary // set (of "pat_idents that refer to nullary enums") - pat_ident(@path, option<@pat>), + pat_ident(binding_mode, @path, option<@pat>), pat_enum(@path, option<~[@pat]>), // "none" means a * pattern where // we don't bind the fields to names pat_rec(~[field_pat], bool), diff --git a/src/libsyntax/ast_map.rs b/src/libsyntax/ast_map.rs index ebe7a7eb36a..4ef4288376c 100644 --- a/src/libsyntax/ast_map.rs +++ b/src/libsyntax/ast_map.rs @@ -158,7 +158,7 @@ fn map_block(b: blk, cx: ctx, v: vt) { fn number_pat(cx: ctx, pat: @pat) { do ast_util::walk_pat(pat) |p| { alt p.node { - pat_ident(_, _) { + pat_ident(*) { cx.map.insert(p.id, node_local(cx.local_id)); cx.local_id += 1u; } diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index 461d237450c..5f46a693f18 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -568,7 +568,7 @@ pure fn is_item_impl(item: @ast::item) -> bool { fn walk_pat(pat: @pat, it: fn(@pat)) { it(pat); alt pat.node { - pat_ident(pth, some(p)) { walk_pat(p, it); } + pat_ident(_, pth, some(p)) { walk_pat(p, it); } pat_rec(fields, _) { for fields.each |f| { walk_pat(f.pat, it); } } @@ -576,7 +576,7 @@ fn walk_pat(pat: @pat, it: fn(@pat)) { for s.each |p| { walk_pat(p, it); } } pat_box(s) | pat_uniq(s) { walk_pat(s, it); } - pat_wild | pat_lit(_) | pat_range(_, _) | pat_ident(_, _) + pat_wild | pat_lit(_) | pat_range(_, _) | pat_ident(_, _, _) | pat_enum(_, _) {} } } diff --git a/src/libsyntax/ext/auto_serialize.rs b/src/libsyntax/ext/auto_serialize.rs index 57b6dc13b8a..90319feb4d2 100644 --- a/src/libsyntax/ext/auto_serialize.rs +++ b/src/libsyntax/ext/auto_serialize.rs @@ -228,7 +228,7 @@ impl helpers of ext_ctxt_helpers for ext_ctxt { let path = @{span: span, global: false, idents: ~[nm], rp: none, types: ~[]}; @{id: self.next_id(), - node: ast::pat_ident(path, none), + node: ast::pat_ident(ast::bind_by_ref, path, none), span: span} } @@ -834,7 +834,9 @@ fn ser_enum(cx: ext_ctxt, tps: ser_tps_map, e_name: ast::ident, // Generate pattern var(v1, v2, v3) |pats| { if vec::is_empty(pats) { - ast::pat_ident(cx.path(v_span, ~[v_name]), none) + ast::pat_ident(ast::bind_by_ref, + cx.path(v_span, ~[v_name]), + none) } else { ast::pat_enum(cx.path(v_span, ~[v_name]), some(pats)) } diff --git a/src/libsyntax/ext/pipes/ast_builder.rs b/src/libsyntax/ext/pipes/ast_builder.rs index bb5b35233cd..89c53d16ac5 100644 --- a/src/libsyntax/ext/pipes/ast_builder.rs +++ b/src/libsyntax/ext/pipes/ast_builder.rs @@ -116,8 +116,10 @@ impl ast_builder of ext_ctxt_ast_builder for ext_ctxt { @{node: {is_mutbl: false, ty: self.ty_infer(), pat: @{id: self.next_id(), - node: ast::pat_ident( - path(ident, self.empty_span()), none), + node: ast::pat_ident(ast::bind_by_ref, + path(ident, + self.empty_span()), + none), span: self.empty_span()}, init: some({op: ast::init_move, expr: e}), diff --git a/src/libsyntax/ext/qquote.rs b/src/libsyntax/ext/qquote.rs index 9dcb4da14fa..94753ea88e0 100644 --- a/src/libsyntax/ext/qquote.rs +++ b/src/libsyntax/ext/qquote.rs @@ -170,7 +170,7 @@ fn parse_crate(p: parser) -> @ast::crate { p.parse_crate_mod(~[]) } fn parse_ty(p: parser) -> @ast::ty { p.parse_ty(false) } fn parse_stmt(p: parser) -> @ast::stmt { p.parse_stmt(~[]) } fn parse_expr(p: parser) -> @ast::expr { p.parse_expr() } -fn parse_pat(p: parser) -> @ast::pat { p.parse_pat() } +fn parse_pat(p: parser) -> @ast::pat { p.parse_pat(true) } fn parse_item(p: parser) -> @ast::item { alt p.parse_item(~[], ast::public) { diff --git a/src/libsyntax/ext/tt/earley_parser.rs b/src/libsyntax/ext/tt/earley_parser.rs index c7a2713c26e..bd8fcf552da 100644 --- a/src/libsyntax/ext/tt/earley_parser.rs +++ b/src/libsyntax/ext/tt/earley_parser.rs @@ -326,7 +326,7 @@ fn parse_nt(p: parser, name: ~str) -> nonterminal { }} ~"block" { token::nt_block(p.parse_block()) } ~"stmt" { token::nt_stmt(p.parse_stmt(~[])) } - ~"pat" { token::nt_pat(p.parse_pat()) } + ~"pat" { token::nt_pat(p.parse_pat(true)) } ~"expr" { token::nt_expr(p.parse_expr()) } ~"ty" { token::nt_ty(p.parse_ty(false /* no need to disambiguate*/)) } // this could be handled like a token, since it is one diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 5e533f3f494..7900b5eea15 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -332,8 +332,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 { pat_wild } - pat_ident(pth, sub) { - pat_ident(fld.fold_path(pth), + pat_ident(binding_mode, pth, sub) { + pat_ident(binding_mode, + fld.fold_path(pth), option::map(sub, |x| fld.fold_pat(x))) } pat_lit(e) { pat_lit(fld.fold_expr(e)) } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index aaafbf0ef24..89053c4eb1d 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -15,14 +15,12 @@ import common::{seq_sep_trailing_disallowed, seq_sep_trailing_allowed, import dvec::{dvec, extensions}; import vec::{push}; import ast::{_mod, add, alt_check, alt_exhaustive, arg, arm, attribute, - bitand, bitor, bitxor, blk, blk_check_mode, bound_const, - bound_copy, bound_send, bound_trait, bound_owned, - box, by_copy, by_move, - by_mutbl_ref, by_ref, by_val, capture_clause, capture_item, - cdir_dir_mod, cdir_src_mod, - cdir_view_item, class_immutable, - class_member, class_method, class_mutable, - crate, crate_cfg, crate_directive, decl, + bind_by_ref, bind_by_value, bitand, bitor, bitxor, blk, + blk_check_mode, bound_const, bound_copy, bound_send, bound_trait, + bound_owned, box, by_copy, by_move, by_mutbl_ref, by_ref, by_val, + capture_clause, capture_item, cdir_dir_mod, cdir_src_mod, + cdir_view_item, class_immutable, class_member, class_method, + class_mutable, crate, crate_cfg, crate_directive, decl, decl_item, decl_local, default_blk, deref, div, expl, expr, expr_, expr_addr_of, expr_alt, expr_again, expr_assert, expr_assign, expr_assign_op, expr_binary, expr_block, expr_break, @@ -1585,13 +1583,13 @@ class parser { fn parse_pats() -> ~[@pat] { let mut pats = ~[]; loop { - vec::push(pats, self.parse_pat()); + vec::push(pats, self.parse_pat(true)); if self.token == token::BINOP(token::OR) { self.bump(); } else { ret pats; } }; } - fn parse_pat() -> @pat { + fn parse_pat(refutable: bool) -> @pat { let lo = self.span.lo; let mut hi = self.span.hi; let mut pat; @@ -1599,7 +1597,7 @@ class parser { token::UNDERSCORE { self.bump(); pat = pat_wild; } token::AT { self.bump(); - let sub = self.parse_pat(); + let sub = self.parse_pat(refutable); hi = sub.span.hi; // HACK: parse @"..." as a literal of a vstore @str pat = alt sub.node { @@ -1614,7 +1612,7 @@ class parser { } token::TILDE { self.bump(); - let sub = self.parse_pat(); + let sub = self.parse_pat(refutable); hi = sub.span.hi; // HACK: parse ~"..." as a literal of a vstore ~str pat = alt sub.node { @@ -1660,11 +1658,13 @@ class parser { let mut subpat; if self.token == token::COLON { self.bump(); - subpat = self.parse_pat(); + subpat = self.parse_pat(refutable); } else { - subpat = @{id: self.get_id(), - node: pat_ident(fieldpath, none), - span: mk_sp(lo, hi)}; + subpat = @{ + id: self.get_id(), + node: pat_ident(bind_by_ref, fieldpath, none), + span: mk_sp(lo, hi) + }; } vec::push(fields, {ident: fieldname, pat: subpat}); } @@ -1681,10 +1681,10 @@ class parser { let expr = self.mk_expr(lo, hi, expr_lit(lit)); pat = pat_lit(expr); } else { - let mut fields = ~[self.parse_pat()]; + let mut fields = ~[self.parse_pat(refutable)]; while self.token == token::COMMA { self.bump(); - vec::push(fields, self.parse_pat()); + vec::push(fields, self.parse_pat(refutable)); } if vec::len(fields) == 1u { self.expect(token::COMMA); } hi = self.span.hi; @@ -1704,50 +1704,80 @@ class parser { hi = val.span.hi; pat = pat_lit(val); } - } else if is_plain_ident(self.token) && - alt self.look_ahead(1u) { - token::LPAREN | token::LBRACKET | token::LT { false } - _ { true } - } { - let name = self.parse_value_path(); - let sub = if self.eat(token::AT) { some(self.parse_pat()) } - else { none }; - pat = pat_ident(name, sub); } else { - let enum_path = self.parse_path_with_tps(true); - hi = enum_path.span.hi; - let mut args: ~[@pat] = ~[]; - let mut star_pat = false; - alt self.token { - token::LPAREN { - alt self.look_ahead(1u) { - token::BINOP(token::STAR) { - // This is a "top constructor only" pat - self.bump(); self.bump(); - star_pat = true; - self.expect(token::RPAREN); + let binding_mode; + if self.eat_keyword(~"ref") { + binding_mode = bind_by_ref; + } else { + alt self.token { + token::BINOP(token::PLUS) => { + // XXX: Temporary thing pending a snapshot. + self.bump(); + binding_mode = bind_by_value; + } + _ if refutable => { + // XXX: Should be bind_by_value, but that's not + // backward compatible. + binding_mode = bind_by_ref; + } + _ => { + binding_mode = bind_by_value; + } + } + } + + if is_plain_ident(self.token) && + alt self.look_ahead(1) { + token::LPAREN | token::LBRACKET | token::LT => { + false } - _ { - args = self.parse_unspanned_seq( - token::LPAREN, token::RPAREN, - seq_sep_trailing_disallowed(token::COMMA), - |p| p.parse_pat()); - hi = self.span.hi; + _ => { + true } + } { + let name = self.parse_value_path(); + let sub = if self.eat(token::AT) { + some(self.parse_pat(refutable)) + } + else { none }; + pat = pat_ident(binding_mode, name, sub); + } else { + let enum_path = self.parse_path_with_tps(true); + hi = enum_path.span.hi; + let mut args: ~[@pat] = ~[]; + let mut star_pat = false; + alt self.token { + token::LPAREN { + alt self.look_ahead(1u) { + token::BINOP(token::STAR) { + // This is a "top constructor only" pat + self.bump(); self.bump(); + star_pat = true; + self.expect(token::RPAREN); + } + _ { + args = self.parse_unspanned_seq( + token::LPAREN, token::RPAREN, + seq_sep_trailing_disallowed(token::COMMA), + |p| p.parse_pat(refutable)); + hi = self.span.hi; + } + } + } + _ { } + } + // at this point, we're not sure whether it's a enum or a + // bind + if star_pat { + pat = pat_enum(enum_path, none); + } + else if vec::is_empty(args) && + vec::len(enum_path.idents) == 1u { + pat = pat_ident(binding_mode, enum_path, none); + } + else { + pat = pat_enum(enum_path, some(args)); } - } - _ { } - } - // at this point, we're not sure whether it's a enum or a bind - if star_pat { - pat = pat_enum(enum_path, none); - } - else if vec::is_empty(args) && - vec::len(enum_path.idents) == 1u { - pat = pat_ident(enum_path, none); - } - else { - pat = pat_enum(enum_path, some(args)); } } } @@ -1758,7 +1788,7 @@ class parser { fn parse_local(is_mutbl: bool, allow_init: bool) -> @local { let lo = self.span.lo; - let pat = self.parse_pat(); + let pat = self.parse_pat(false); let mut ty = @{id: self.get_id(), node: ty_infer, span: mk_sp(lo, lo)}; diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 1d4e67c5d14..cbea14f3185 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -331,7 +331,7 @@ fn restricted_keyword_table() -> hashmap<~str, ()> { ~"new", ~"owned", ~"pure", - ~"ret", ~"return", + ~"ref", ~"ret", ~"return", ~"struct", ~"true", ~"trait", ~"type", ~"unchecked", ~"unsafe", diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 41e795fd436..b0ef87a8cca 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1302,11 +1302,15 @@ fn print_pat(s: ps, &&pat: @ast::pat) { is that it doesn't matter */ alt pat.node { ast::pat_wild { word(s.s, ~"_"); } - ast::pat_ident(path, sub) { + ast::pat_ident(binding_mode, path, sub) { + alt binding_mode { + ast::bind_by_ref => { word_space(s, ~"ref"); } + ast::bind_by_value => {} + } print_path(s, path, true); alt sub { - some(p) { word(s.s, ~"@"); print_pat(s, p); } - none {} + some(p) => { word(s.s, ~"@"); print_pat(s, p); } + none => {} } } ast::pat_enum(path, args_) { diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 050d7e58120..5cf73da1944 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -229,7 +229,7 @@ fn visit_pat<E>(p: @pat, e: E, v: vt<E>) { pat_box(inner) | pat_uniq(inner) { v.visit_pat(inner, e, v); } - pat_ident(path, inner) { + pat_ident(_, path, inner) { visit_path(path, e, v); do option::iter(inner) |subpat| { v.visit_pat(subpat, e, v)}; } |
