rustc: Parse by-reference pattern bindings with the "ref" keyword

This commit is contained in:
Patrick Walton 2012-07-31 19:25:24 -07:00
parent a841789a41
commit b414db041b
25 changed files with 203 additions and 146 deletions

View file

@ -20,7 +20,7 @@ type package = {
url: ~str, url: ~str,
method: ~str, method: ~str,
description: ~str, description: ~str,
ref: option<~str>, reference: option<~str>,
tags: ~[~str], tags: ~[~str],
versions: ~[(~str, ~str)] versions: ~[(~str, ~str)]
}; };
@ -497,7 +497,7 @@ fn load_one_source_package(src: source, p: map::hashmap<~str, json::json>) {
} }
}; };
let ref = alt p.find(~"ref") { let reference = alt p.find(~"ref") {
some(json::string(n)) { some(*n) } some(json::string(n)) { some(*n) }
_ { none } _ { none }
}; };
@ -530,7 +530,7 @@ fn load_one_source_package(src: source, p: map::hashmap<~str, json::json>) {
url: url, url: url,
method: method, method: method,
description: description, description: description,
ref: ref, reference: reference,
tags: tags, tags: tags,
versions: ~[] versions: ~[]
}; };
@ -815,10 +815,10 @@ fn install_source(c: cargo, path: ~str) {
} }
} }
fn install_git(c: cargo, wd: ~str, url: ~str, ref: option<~str>) { fn install_git(c: cargo, wd: ~str, url: ~str, reference: option<~str>) {
run::program_output(~"git", ~[~"clone", url, wd]); run::program_output(~"git", ~[~"clone", url, wd]);
if option::is_some(ref) { if option::is_some(reference) {
let r = option::get(ref); let r = option::get(reference);
os::change_dir(wd); os::change_dir(wd);
run::run_program(~"git", ~[~"checkout", r]); run::run_program(~"git", ~[~"checkout", r]);
} }
@ -855,7 +855,7 @@ fn install_package(c: cargo, src: ~str, wd: ~str, pkg: package) {
info(fmt!{"installing %s/%s via %s...", src, pkg.name, method}); info(fmt!{"installing %s/%s via %s...", src, pkg.name, method});
alt method { alt method {
~"git" { install_git(c, wd, url, copy pkg.ref); } ~"git" { install_git(c, wd, url, copy pkg.reference); }
~"file" { install_file(c, wd, url); } ~"file" { install_file(c, wd, url); }
~"curl" { install_curl(c, wd, copy url); } ~"curl" { install_curl(c, wd, copy url); }
_ {} _ {}
@ -1034,12 +1034,12 @@ fn install_query(c: cargo, wd: ~str, target: ~str) {
install_file(c, wd, target); install_file(c, wd, target);
ret; ret;
} else if is_git_url(target) { } else if is_git_url(target) {
let ref = if c.opts.free.len() >= 4u { let reference = if c.opts.free.len() >= 4u {
some(c.opts.free[3u]) some(c.opts.free[3u])
} else { } else {
none none
}; };
install_git(c, wd, target, ref); install_git(c, wd, target, reference);
} else if !valid_pkg_name(target) && has_archive_extension(target) { } else if !valid_pkg_name(target) && has_archive_extension(target) {
install_curl(c, wd, target); install_curl(c, wd, target);
ret; ret;

View file

@ -536,7 +536,7 @@ fn push_slow<T>(&v: ~[const T], +initval: T) {
// Unchecked vector indexing // Unchecked vector indexing
#[inline(always)] #[inline(always)]
unsafe fn ref<T: copy>(v: &[const T], i: uint) -> T { unsafe fn get_ref<T: copy>(v: &[const T], i: uint) -> T {
as_buf(v, |p, _len| *ptr::offset(p, i)) as_buf(v, |p, _len| *ptr::offset(p, i))
} }
@ -555,7 +555,7 @@ fn push_all<T: copy>(&v: ~[const T], rhs: &[const T]) {
reserve(v, v.len() + rhs.len()); reserve(v, v.len() + rhs.len());
for uint::range(0u, rhs.len()) |i| { for uint::range(0u, rhs.len()) |i| {
push(v, unsafe { ref(rhs, i) }) push(v, unsafe { get_ref(rhs, i) })
} }
} }

View file

@ -145,6 +145,12 @@ type pat = {id: node_id, node: pat_, span: span};
#[auto_serialize] #[auto_serialize]
type field_pat = {ident: ident, pat: @pat}; type field_pat = {ident: ident, pat: @pat};
#[auto_serialize]
enum binding_mode {
bind_by_value,
bind_by_ref
}
#[auto_serialize] #[auto_serialize]
enum pat_ { enum pat_ {
pat_wild, pat_wild,
@ -155,7 +161,7 @@ enum pat_ {
// which it is. The resolver determines this, and // which it is. The resolver determines this, and
// records this pattern's node_id in an auxiliary // records this pattern's node_id in an auxiliary
// set (of "pat_idents that refer to nullary enums") // 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 pat_enum(@path, option<~[@pat]>), // "none" means a * pattern where
// we don't bind the fields to names // we don't bind the fields to names
pat_rec(~[field_pat], bool), pat_rec(~[field_pat], bool),

View file

@ -158,7 +158,7 @@ fn map_block(b: blk, cx: ctx, v: vt) {
fn number_pat(cx: ctx, pat: @pat) { fn number_pat(cx: ctx, pat: @pat) {
do ast_util::walk_pat(pat) |p| { do ast_util::walk_pat(pat) |p| {
alt p.node { alt p.node {
pat_ident(_, _) { pat_ident(*) {
cx.map.insert(p.id, node_local(cx.local_id)); cx.map.insert(p.id, node_local(cx.local_id));
cx.local_id += 1u; cx.local_id += 1u;
} }

View file

@ -568,7 +568,7 @@ pure fn is_item_impl(item: @ast::item) -> bool {
fn walk_pat(pat: @pat, it: fn(@pat)) { fn walk_pat(pat: @pat, it: fn(@pat)) {
it(pat); it(pat);
alt pat.node { alt pat.node {
pat_ident(pth, some(p)) { walk_pat(p, it); } pat_ident(_, pth, some(p)) { walk_pat(p, it); }
pat_rec(fields, _) { pat_rec(fields, _) {
for fields.each |f| { walk_pat(f.pat, it); } 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); } for s.each |p| { walk_pat(p, it); }
} }
pat_box(s) | pat_uniq(s) { walk_pat(s, 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(_, _) {} | pat_enum(_, _) {}
} }
} }

View file

@ -228,7 +228,7 @@ impl helpers of ext_ctxt_helpers for ext_ctxt {
let path = @{span: span, global: false, idents: ~[nm], let path = @{span: span, global: false, idents: ~[nm],
rp: none, types: ~[]}; rp: none, types: ~[]};
@{id: self.next_id(), @{id: self.next_id(),
node: ast::pat_ident(path, none), node: ast::pat_ident(ast::bind_by_ref, path, none),
span: span} 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) // Generate pattern var(v1, v2, v3)
|pats| { |pats| {
if vec::is_empty(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 { } else {
ast::pat_enum(cx.path(v_span, ~[v_name]), some(pats)) ast::pat_enum(cx.path(v_span, ~[v_name]), some(pats))
} }

View file

@ -116,8 +116,10 @@ impl ast_builder of ext_ctxt_ast_builder for ext_ctxt {
@{node: {is_mutbl: false, @{node: {is_mutbl: false,
ty: self.ty_infer(), ty: self.ty_infer(),
pat: @{id: self.next_id(), pat: @{id: self.next_id(),
node: ast::pat_ident( node: ast::pat_ident(ast::bind_by_ref,
path(ident, self.empty_span()), none), path(ident,
self.empty_span()),
none),
span: self.empty_span()}, span: self.empty_span()},
init: some({op: ast::init_move, init: some({op: ast::init_move,
expr: e}), expr: e}),

View file

@ -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_ty(p: parser) -> @ast::ty { p.parse_ty(false) }
fn parse_stmt(p: parser) -> @ast::stmt { p.parse_stmt(~[]) } fn parse_stmt(p: parser) -> @ast::stmt { p.parse_stmt(~[]) }
fn parse_expr(p: parser) -> @ast::expr { p.parse_expr() } 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 { fn parse_item(p: parser) -> @ast::item {
alt p.parse_item(~[], ast::public) { alt p.parse_item(~[], ast::public) {

View file

@ -326,7 +326,7 @@ fn parse_nt(p: parser, name: ~str) -> nonterminal {
}} }}
~"block" { token::nt_block(p.parse_block()) } ~"block" { token::nt_block(p.parse_block()) }
~"stmt" { token::nt_stmt(p.parse_stmt(~[])) } ~"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()) } ~"expr" { token::nt_expr(p.parse_expr()) }
~"ty" { token::nt_ty(p.parse_ty(false /* no need to disambiguate*/)) } ~"ty" { token::nt_ty(p.parse_ty(false /* no need to disambiguate*/)) }
// this could be handled like a token, since it is one // this could be handled like a token, since it is one

View file

@ -332,8 +332,9 @@ fn noop_fold_arm(a: arm, fld: ast_fold) -> arm {
fn noop_fold_pat(p: pat_, fld: ast_fold) -> pat_ { fn noop_fold_pat(p: pat_, fld: ast_fold) -> pat_ {
ret alt p { ret alt p {
pat_wild { pat_wild } pat_wild { pat_wild }
pat_ident(pth, sub) { pat_ident(binding_mode, pth, sub) {
pat_ident(fld.fold_path(pth), pat_ident(binding_mode,
fld.fold_path(pth),
option::map(sub, |x| fld.fold_pat(x))) option::map(sub, |x| fld.fold_pat(x)))
} }
pat_lit(e) { pat_lit(fld.fold_expr(e)) } pat_lit(e) { pat_lit(fld.fold_expr(e)) }

View file

@ -15,14 +15,12 @@ import common::{seq_sep_trailing_disallowed, seq_sep_trailing_allowed,
import dvec::{dvec, extensions}; import dvec::{dvec, extensions};
import vec::{push}; import vec::{push};
import ast::{_mod, add, alt_check, alt_exhaustive, arg, arm, attribute, import ast::{_mod, add, alt_check, alt_exhaustive, arg, arm, attribute,
bitand, bitor, bitxor, blk, blk_check_mode, bound_const, bind_by_ref, bind_by_value, bitand, bitor, bitxor, blk,
bound_copy, bound_send, bound_trait, bound_owned, blk_check_mode, bound_const, bound_copy, bound_send, bound_trait,
box, by_copy, by_move, bound_owned, box, by_copy, by_move, by_mutbl_ref, by_ref, by_val,
by_mutbl_ref, by_ref, by_val, capture_clause, capture_item, capture_clause, capture_item, cdir_dir_mod, cdir_src_mod,
cdir_dir_mod, cdir_src_mod, cdir_view_item, class_immutable, class_member, class_method,
cdir_view_item, class_immutable, class_mutable, crate, crate_cfg, crate_directive, decl,
class_member, class_method, class_mutable,
crate, crate_cfg, crate_directive, decl,
decl_item, decl_local, default_blk, deref, div, expl, expr, decl_item, decl_local, default_blk, deref, div, expl, expr,
expr_, expr_addr_of, expr_alt, expr_again, expr_assert, expr_, expr_addr_of, expr_alt, expr_again, expr_assert,
expr_assign, expr_assign_op, expr_binary, expr_block, expr_break, expr_assign, expr_assign_op, expr_binary, expr_block, expr_break,
@ -1585,13 +1583,13 @@ class parser {
fn parse_pats() -> ~[@pat] { fn parse_pats() -> ~[@pat] {
let mut pats = ~[]; let mut pats = ~[];
loop { loop {
vec::push(pats, self.parse_pat()); vec::push(pats, self.parse_pat(true));
if self.token == token::BINOP(token::OR) { self.bump(); } if self.token == token::BINOP(token::OR) { self.bump(); }
else { ret pats; } else { ret pats; }
}; };
} }
fn parse_pat() -> @pat { fn parse_pat(refutable: bool) -> @pat {
let lo = self.span.lo; let lo = self.span.lo;
let mut hi = self.span.hi; let mut hi = self.span.hi;
let mut pat; let mut pat;
@ -1599,7 +1597,7 @@ class parser {
token::UNDERSCORE { self.bump(); pat = pat_wild; } token::UNDERSCORE { self.bump(); pat = pat_wild; }
token::AT { token::AT {
self.bump(); self.bump();
let sub = self.parse_pat(); let sub = self.parse_pat(refutable);
hi = sub.span.hi; hi = sub.span.hi;
// HACK: parse @"..." as a literal of a vstore @str // HACK: parse @"..." as a literal of a vstore @str
pat = alt sub.node { pat = alt sub.node {
@ -1614,7 +1612,7 @@ class parser {
} }
token::TILDE { token::TILDE {
self.bump(); self.bump();
let sub = self.parse_pat(); let sub = self.parse_pat(refutable);
hi = sub.span.hi; hi = sub.span.hi;
// HACK: parse ~"..." as a literal of a vstore ~str // HACK: parse ~"..." as a literal of a vstore ~str
pat = alt sub.node { pat = alt sub.node {
@ -1660,11 +1658,13 @@ class parser {
let mut subpat; let mut subpat;
if self.token == token::COLON { if self.token == token::COLON {
self.bump(); self.bump();
subpat = self.parse_pat(); subpat = self.parse_pat(refutable);
} else { } else {
subpat = @{id: self.get_id(), subpat = @{
node: pat_ident(fieldpath, none), id: self.get_id(),
span: mk_sp(lo, hi)}; node: pat_ident(bind_by_ref, fieldpath, none),
span: mk_sp(lo, hi)
};
} }
vec::push(fields, {ident: fieldname, pat: subpat}); vec::push(fields, {ident: fieldname, pat: subpat});
} }
@ -1681,10 +1681,10 @@ class parser {
let expr = self.mk_expr(lo, hi, expr_lit(lit)); let expr = self.mk_expr(lo, hi, expr_lit(lit));
pat = pat_lit(expr); pat = pat_lit(expr);
} else { } else {
let mut fields = ~[self.parse_pat()]; let mut fields = ~[self.parse_pat(refutable)];
while self.token == token::COMMA { while self.token == token::COMMA {
self.bump(); self.bump();
vec::push(fields, self.parse_pat()); vec::push(fields, self.parse_pat(refutable));
} }
if vec::len(fields) == 1u { self.expect(token::COMMA); } if vec::len(fields) == 1u { self.expect(token::COMMA); }
hi = self.span.hi; hi = self.span.hi;
@ -1704,50 +1704,80 @@ class parser {
hi = val.span.hi; hi = val.span.hi;
pat = pat_lit(val); 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 { } else {
let enum_path = self.parse_path_with_tps(true); let binding_mode;
hi = enum_path.span.hi; if self.eat_keyword(~"ref") {
let mut args: ~[@pat] = ~[]; binding_mode = bind_by_ref;
let mut star_pat = false; } else {
alt self.token { alt self.token {
token::LPAREN { token::BINOP(token::PLUS) => {
alt self.look_ahead(1u) { // XXX: Temporary thing pending a snapshot.
token::BINOP(token::STAR) { self.bump();
// This is a "top constructor only" pat binding_mode = bind_by_value;
self.bump(); self.bump(); }
star_pat = true; _ if refutable => {
self.expect(token::RPAREN); // XXX: Should be bind_by_value, but that's not
} // backward compatible.
_ { binding_mode = bind_by_ref;
args = self.parse_unspanned_seq( }
token::LPAREN, token::RPAREN, _ => {
seq_sep_trailing_disallowed(token::COMMA), binding_mode = bind_by_value;
|p| p.parse_pat()); }
hi = self.span.hi;
}
} }
}
_ { }
} }
// at this point, we're not sure whether it's a enum or a bind
if star_pat { if is_plain_ident(self.token) &&
pat = pat_enum(enum_path, none); alt self.look_ahead(1) {
} token::LPAREN | token::LBRACKET | token::LT => {
else if vec::is_empty(args) && false
vec::len(enum_path.idents) == 1u { }
pat = pat_ident(enum_path, none); _ => {
} true
else { }
pat = pat_enum(enum_path, some(args)); } {
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));
}
} }
} }
} }
@ -1758,7 +1788,7 @@ class parser {
fn parse_local(is_mutbl: bool, fn parse_local(is_mutbl: bool,
allow_init: bool) -> @local { allow_init: bool) -> @local {
let lo = self.span.lo; let lo = self.span.lo;
let pat = self.parse_pat(); let pat = self.parse_pat(false);
let mut ty = @{id: self.get_id(), let mut ty = @{id: self.get_id(),
node: ty_infer, node: ty_infer,
span: mk_sp(lo, lo)}; span: mk_sp(lo, lo)};

View file

@ -331,7 +331,7 @@ fn restricted_keyword_table() -> hashmap<~str, ()> {
~"new", ~"new",
~"owned", ~"owned",
~"pure", ~"pure",
~"ret", ~"return", ~"ref", ~"ret", ~"return",
~"struct", ~"struct",
~"true", ~"trait", ~"type", ~"true", ~"trait", ~"type",
~"unchecked", ~"unsafe", ~"unchecked", ~"unsafe",

View file

@ -1302,11 +1302,15 @@ fn print_pat(s: ps, &&pat: @ast::pat) {
is that it doesn't matter */ is that it doesn't matter */
alt pat.node { alt pat.node {
ast::pat_wild { word(s.s, ~"_"); } 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); print_path(s, path, true);
alt sub { alt sub {
some(p) { word(s.s, ~"@"); print_pat(s, p); } some(p) => { word(s.s, ~"@"); print_pat(s, p); }
none {} none => {}
} }
} }
ast::pat_enum(path, args_) { ast::pat_enum(path, args_) {

View file

@ -229,7 +229,7 @@ fn visit_pat<E>(p: @pat, e: E, v: vt<E>) {
pat_box(inner) | pat_uniq(inner) { pat_box(inner) | pat_uniq(inner) {
v.visit_pat(inner, e, v); v.visit_pat(inner, e, v);
} }
pat_ident(path, inner) { pat_ident(_, path, inner) {
visit_path(path, e, v); visit_path(path, e, v);
do option::iter(inner) |subpat| { v.visit_pat(subpat, e, v)}; do option::iter(inner) |subpat| { v.visit_pat(subpat, e, v)};
} }

View file

@ -473,11 +473,13 @@ impl methods for gather_loan_ctxt {
} }
} }
ast::pat_ident(_, none) if self.pat_is_variant(pat) { ast::pat_ident(_, _, none) if self.pat_is_variant(pat) {
// nullary variant // nullary variant
debug!{"nullary variant"}; debug!{"nullary variant"};
} }
ast::pat_ident(id, o_pat) { ast::pat_ident(_, id, o_pat) {
// XXX: Needs to take by-ref/by-val into account.
// x or x @ p --- `x` must remain valid for the scope of the alt // x or x @ p --- `x` must remain valid for the scope of the alt
debug!{"defines identifier %s", pprust::path_to_str(id)}; debug!{"defines identifier %s", pprust::path_to_str(id)};

View file

@ -71,8 +71,8 @@ fn check_arms(tcx: ty::ctxt, arms: ~[arm]) {
fn raw_pat(p: @pat) -> @pat { fn raw_pat(p: @pat) -> @pat {
alt p.node { alt p.node {
pat_ident(_, some(s)) { raw_pat(s) } pat_ident(_, _, some(s)) => { raw_pat(s) }
_ { p } _ => { p }
} }
} }
@ -199,32 +199,34 @@ fn is_useful_specialized(tcx: ty::ctxt, m: matrix, v: ~[@pat], ctor: ctor,
fn pat_ctor_id(tcx: ty::ctxt, p: @pat) -> option<ctor> { fn pat_ctor_id(tcx: ty::ctxt, p: @pat) -> option<ctor> {
let pat = raw_pat(p); let pat = raw_pat(p);
alt pat.node { alt pat.node {
pat_wild { none } pat_wild => { none }
pat_ident(_, _) | pat_enum(_, _) { pat_ident(_, _, _) | pat_enum(_, _) => {
alt tcx.def_map.find(pat.id) { alt tcx.def_map.find(pat.id) {
some(def_variant(_, id)) { some(variant(id)) } some(def_variant(_, id)) { some(variant(id)) }
_ { none } _ { none }
} }
} }
pat_lit(expr) { some(val(eval_const_expr(tcx, expr))) } pat_lit(expr) => { some(val(eval_const_expr(tcx, expr))) }
pat_range(lo, hi) { pat_range(lo, hi) => {
some(range(eval_const_expr(tcx, lo), eval_const_expr(tcx, hi))) some(range(eval_const_expr(tcx, lo), eval_const_expr(tcx, hi)))
} }
pat_box(_) | pat_uniq(_) | pat_rec(_, _) | pat_tup(_) { some(single) } pat_box(_) | pat_uniq(_) | pat_rec(_, _) | pat_tup(_) => {
some(single)
}
} }
} }
fn is_wild(tcx: ty::ctxt, p: @pat) -> bool { fn is_wild(tcx: ty::ctxt, p: @pat) -> bool {
let pat = raw_pat(p); let pat = raw_pat(p);
alt pat.node { alt pat.node {
pat_wild { true } pat_wild => { true }
pat_ident(_, _) { pat_ident(_, _, _) => {
alt tcx.def_map.find(pat.id) { alt tcx.def_map.find(pat.id) {
some(def_variant(_, _)) { false } some(def_variant(_, _)) => { false }
_ { true } _ => { true }
} }
} }
_ { false } _ => { false }
} }
} }
@ -296,7 +298,7 @@ fn specialize(tcx: ty::ctxt, r: ~[@pat], ctor_id: ctor, arity: uint,
alt r0.node { alt r0.node {
pat_wild { some(vec::append(vec::from_elem(arity, wild()), pat_wild { some(vec::append(vec::from_elem(arity, wild()),
vec::tail(r))) } vec::tail(r))) }
pat_ident(_, _) { pat_ident(_, _, _) {
alt tcx.def_map.find(r0.id) { alt tcx.def_map.find(r0.id) {
some(def_variant(_, id)) { some(def_variant(_, id)) {
if variant(id) == ctor_id { some(vec::tail(r)) } if variant(id) == ctor_id { some(vec::tail(r)) }
@ -377,26 +379,26 @@ fn is_refutable(tcx: ty::ctxt, pat: @pat) -> bool {
} }
alt pat.node { alt pat.node {
pat_box(sub) | pat_uniq(sub) | pat_ident(_, some(sub)) { pat_box(sub) | pat_uniq(sub) | pat_ident(_, _, some(sub)) => {
is_refutable(tcx, sub) is_refutable(tcx, sub)
} }
pat_wild | pat_ident(_, none) { false } pat_wild | pat_ident(_, _, none) => { false }
pat_lit(_) | pat_range(_, _) { true } pat_lit(_) | pat_range(_, _) => { true }
pat_rec(fields, _) { pat_rec(fields, _) => {
for fields.each |it| { for fields.each |it| {
if is_refutable(tcx, it.pat) { ret true; } if is_refutable(tcx, it.pat) { ret true; }
} }
false false
} }
pat_tup(elts) { pat_tup(elts) => {
for elts.each |elt| { if is_refutable(tcx, elt) { ret true; } } for elts.each |elt| { if is_refutable(tcx, elt) { ret true; } }
false false
} }
pat_enum(_, some(args)) { pat_enum(_, some(args)) => {
for args.each |p| { if is_refutable(tcx, p) { ret true; } }; for args.each |p| { if is_refutable(tcx, p) { ret true; } };
false false
} }
pat_enum(_,_) { false } pat_enum(_,_) => { false }
} }
} }

View file

@ -24,7 +24,7 @@ fn pat_id_map(dm: resolve3::DefMap, pat: @pat) -> pat_id_map {
fn pat_is_variant(dm: resolve3::DefMap, pat: @pat) -> bool { fn pat_is_variant(dm: resolve3::DefMap, pat: @pat) -> bool {
alt pat.node { alt pat.node {
pat_enum(_, _) { true } pat_enum(_, _) { true }
pat_ident(_, none) { pat_ident(_, _, none) {
alt dm.find(pat.id) { alt dm.find(pat.id) {
some(def_variant(_, _)) { true } some(def_variant(_, _)) { true }
_ { false } _ { false }
@ -38,7 +38,7 @@ fn pat_bindings(dm: resolve3::DefMap, pat: @pat,
it: fn(node_id, span, @path)) { it: fn(node_id, span, @path)) {
do walk_pat(pat) |p| { do walk_pat(pat) |p| {
alt p.node { alt p.node {
pat_ident(pth, _) if !pat_is_variant(dm, p) { pat_ident(_, pth, _) if !pat_is_variant(dm, p) {
it(p.id, p.span, pth); it(p.id, p.span, pth);
} }
_ {} _ {}

View file

@ -208,7 +208,7 @@ fn resolve_arm(arm: ast::arm, cx: ctxt, visitor: visit::vt<ctxt>) {
fn resolve_pat(pat: @ast::pat, cx: ctxt, visitor: visit::vt<ctxt>) { fn resolve_pat(pat: @ast::pat, cx: ctxt, visitor: visit::vt<ctxt>) {
alt pat.node { alt pat.node {
ast::pat_ident(path, _) { ast::pat_ident(_, path, _) {
let defn_opt = cx.def_map.find(pat.id); let defn_opt = cx.def_map.find(pat.id);
alt defn_opt { alt defn_opt {
some(ast::def_variant(_,_)) { some(ast::def_variant(_,_)) {

View file

@ -5,11 +5,11 @@ import metadata::cstore::find_use_stmt_cnum;
import metadata::decoder::{def_like, dl_def, dl_field, dl_impl}; import metadata::decoder::{def_like, dl_def, dl_field, dl_impl};
import middle::lang_items::LanguageItems; import middle::lang_items::LanguageItems;
import middle::lint::{deny, allow, forbid, level, unused_imports, warn}; import middle::lint::{deny, allow, forbid, level, unused_imports, warn};
import syntax::ast::{_mod, add, arm, bitand, bitor, bitxor, blk, bound_const}; import syntax::ast::{_mod, add, arm, bind_by_value, bitand, bitor, bitxor};
import syntax::ast::{bound_copy, bound_owned, bound_send, bound_trait}; import syntax::ast::{blk, bound_const, bound_copy, bound_owned, bound_send};
import syntax::ast::{capture_clause, class_ctor, class_dtor, class_member}; import syntax::ast::{bound_trait, capture_clause, class_ctor, class_dtor};
import syntax::ast::{class_method, crate, crate_num, decl_item, def, def_arg}; import syntax::ast::{class_member, class_method, crate, crate_num, decl_item};
import syntax::ast::{def_binding, def_class, def_const, def_fn}; import syntax::ast::{def, def_arg, def_binding, def_class, def_const, def_fn};
import syntax::ast::{def_foreign_mod, def_id, def_local, def_mod}; import syntax::ast::{def_foreign_mod, def_id, def_local, def_mod};
import syntax::ast::{def_prim_ty, def_region, def_self, def_ty, def_ty_param, import syntax::ast::{def_prim_ty, def_region, def_self, def_ty, def_ty_param,
def_typaram_binder}; def_typaram_binder};
@ -3734,8 +3734,8 @@ class Resolver {
let pat_id = pattern.id; let pat_id = pattern.id;
do walk_pat(pattern) |pattern| { do walk_pat(pattern) |pattern| {
alt pattern.node { alt pattern.node {
pat_ident(path, _) pat_ident(_, path, _)
if !path.global && path.idents.len() == 1u { if !path.global && path.idents.len() == 1u => {
// The meaning of pat_ident with no type parameters // The meaning of pat_ident with no type parameters
// depends on whether an enum variant with that name is in // depends on whether an enum variant with that name is in
@ -3748,14 +3748,14 @@ class Resolver {
let atom = (*self.atom_table).intern(path.idents[0]); let atom = (*self.atom_table).intern(path.idents[0]);
alt self.resolve_enum_variant_or_const(atom) { alt self.resolve_enum_variant_or_const(atom) {
FoundEnumVariant(def) if mode == RefutableMode { FoundEnumVariant(def) if mode == RefutableMode => {
debug!{"(resolving pattern) resolving `%s` to \ debug!{"(resolving pattern) resolving `%s` to \
enum variant", enum variant",
*path.idents[0]}; *path.idents[0]};
self.record_def(pattern.id, def); self.record_def(pattern.id, def);
} }
FoundEnumVariant(_) { FoundEnumVariant(_) => {
self.session.span_err(pattern.span, self.session.span_err(pattern.span,
fmt!{"declaration of `%s` \ fmt!{"declaration of `%s` \
shadows an enum \ shadows an enum \
@ -3764,13 +3764,13 @@ class Resolver {
atom_to_str atom_to_str
(atom)}); (atom)});
} }
FoundConst { FoundConst => {
self.session.span_err(pattern.span, self.session.span_err(pattern.span,
~"pattern variable \ ~"pattern variable \
conflicts with a constant \ conflicts with a constant \
in scope"); in scope");
} }
EnumVariantOrConstNotFound { EnumVariantOrConstNotFound => {
debug!{"(resolving pattern) binding `%s`", debug!{"(resolving pattern) binding `%s`",
*path.idents[0]}; *path.idents[0]};
@ -3836,7 +3836,7 @@ class Resolver {
} }
} }
pat_ident(path, _) | pat_enum(path, _) { pat_ident(_, path, _) | pat_enum(path, _) => {
// These two must be enum variants. // These two must be enum variants.
alt self.resolve_path(path, ValueNS, false, visitor) { alt self.resolve_path(path, ValueNS, false, visitor) {
some(def @ def_variant(*)) { some(def @ def_variant(*)) {
@ -3860,16 +3860,16 @@ class Resolver {
} }
} }
pat_lit(expr) { pat_lit(expr) => {
self.resolve_expr(expr, visitor); self.resolve_expr(expr, visitor);
} }
pat_range(first_expr, last_expr) { pat_range(first_expr, last_expr) => {
self.resolve_expr(first_expr, visitor); self.resolve_expr(first_expr, visitor);
self.resolve_expr(last_expr, visitor); self.resolve_expr(last_expr, visitor);
} }
_ { _ => {
// Nothing to do. // Nothing to do.
} }
} }

View file

@ -79,7 +79,12 @@ fn variant_opt(tcx: ty::ctxt, pat_id: ast::node_id) -> opt {
core::unreachable(); core::unreachable();
} }
type bind_map = ~[{ident: ast::ident, val: ValueRef}]; type bind_map = ~[{
ident: ast::ident,
val: ValueRef,
mode: ast::binding_mode
}];
fn assoc(key: ast::ident, list: bind_map) -> option<ValueRef> { fn assoc(key: ast::ident, list: bind_map) -> option<ValueRef> {
for vec::each(list) |elt| { for vec::each(list) |elt| {
if str::eq(*elt.ident, *key) { ret some(elt.val); } if str::eq(*elt.ident, *key) { ret some(elt.val); }
@ -98,7 +103,7 @@ type match_ = ~[match_branch];
fn has_nested_bindings(m: match_, col: uint) -> bool { fn has_nested_bindings(m: match_, col: uint) -> bool {
for vec::each(m) |br| { for vec::each(m) |br| {
alt br.pats[col].node { alt br.pats[col].node {
ast::pat_ident(_, some(_)) { ret true; } ast::pat_ident(_, _, some(_)) { ret true; }
_ {} _ {}
} }
} }
@ -109,7 +114,7 @@ fn expand_nested_bindings(m: match_, col: uint, val: ValueRef) -> match_ {
let mut result = ~[]; let mut result = ~[];
for vec::each(m) |br| { for vec::each(m) |br| {
alt br.pats[col].node { alt br.pats[col].node {
ast::pat_ident(name, some(inner)) { ast::pat_ident(mode, name, some(inner)) {
let pats = vec::append( let pats = vec::append(
vec::slice(br.pats, 0u, col), vec::slice(br.pats, 0u, col),
vec::append(~[inner], vec::append(~[inner],
@ -118,7 +123,8 @@ fn expand_nested_bindings(m: match_, col: uint, val: ValueRef) -> match_ {
@{pats: pats, @{pats: pats,
bound: vec::append( bound: vec::append(
br.bound, ~[{ident: path_to_ident(name), br.bound, ~[{ident: path_to_ident(name),
val: val}]) val: val,
mode: mode}])
with *br}); with *br});
} }
_ { vec::push(result, br); } _ { vec::push(result, br); }
@ -140,9 +146,11 @@ fn enter_match(dm: DefMap, m: match_, col: uint, val: ValueRef,
vec::view(br.pats, col + 1u, br.pats.len())); vec::view(br.pats, col + 1u, br.pats.len()));
let self = br.pats[col]; let self = br.pats[col];
let bound = alt self.node { let bound = alt self.node {
ast::pat_ident(name, none) if !pat_is_variant(dm, self) { ast::pat_ident(mode, name, none) if !pat_is_variant(dm, self) {
vec::append(br.bound, vec::append(br.bound,
~[{ident: path_to_ident(name), val: val}]) ~[{ident: path_to_ident(name),
val: val,
mode: mode}])
} }
_ { br.bound } _ { br.bound }
}; };
@ -158,7 +166,7 @@ fn enter_default(dm: DefMap, m: match_, col: uint, val: ValueRef) -> match_ {
do enter_match(dm, m, col, val) |p| { do enter_match(dm, m, col, val) |p| {
alt p.node { alt p.node {
ast::pat_wild | ast::pat_rec(_, _) | ast::pat_tup(_) { some(~[]) } ast::pat_wild | ast::pat_rec(_, _) | ast::pat_tup(_) { some(~[]) }
ast::pat_ident(_, none) if !pat_is_variant(dm, p) { ast::pat_ident(_, _, none) if !pat_is_variant(dm, p) {
some(~[]) some(~[])
} }
_ { none } _ { none }
@ -177,7 +185,7 @@ fn enter_opt(tcx: ty::ctxt, m: match_, opt: opt, col: uint,
vec::from_elem(variant_size, dummy))) } vec::from_elem(variant_size, dummy))) }
else { none } else { none }
} }
ast::pat_ident(_, none) if pat_is_variant(tcx.def_map, p) { ast::pat_ident(_, _, none) if pat_is_variant(tcx.def_map, p) {
if opt_eq(tcx, variant_opt(tcx, p.id), opt) { some(~[]) } if opt_eq(tcx, variant_opt(tcx, p.id), opt) { some(~[]) }
else { none } else { none }
} }
@ -359,7 +367,7 @@ fn pick_col(m: match_) -> uint {
fn score(p: @ast::pat) -> uint { fn score(p: @ast::pat) -> uint {
alt p.node { alt p.node {
ast::pat_lit(_) | ast::pat_enum(_, _) | ast::pat_range(_, _) { 1u } ast::pat_lit(_) | ast::pat_enum(_, _) | ast::pat_range(_, _) { 1u }
ast::pat_ident(_, some(p)) { score(p) } ast::pat_ident(_, _, some(p)) { score(p) }
_ { 0u } _ { 0u }
} }
} }
@ -725,7 +733,7 @@ fn bind_irrefutable_pat(bcx: block, pat: @ast::pat, val: ValueRef,
// Necessary since bind_irrefutable_pat is called outside trans_alt // Necessary since bind_irrefutable_pat is called outside trans_alt
alt pat.node { alt pat.node {
ast::pat_ident(_,inner) { ast::pat_ident(_, _,inner) {
if pat_is_variant(bcx.tcx().def_map, pat) { ret bcx; } if pat_is_variant(bcx.tcx().def_map, pat) { ret bcx; }
if make_copy { if make_copy {
let ty = node_id_type(bcx, pat.id); let ty = node_id_type(bcx, pat.id);

View file

@ -4380,7 +4380,7 @@ fn alloc_local(cx: block, local: @ast::local) -> block {
let _icx = cx.insn_ctxt(~"alloc_local"); let _icx = cx.insn_ctxt(~"alloc_local");
let t = node_id_type(cx, local.node.id); let t = node_id_type(cx, local.node.id);
let simple_name = alt local.node.pat.node { let simple_name = alt local.node.pat.node {
ast::pat_ident(pth, none) { some(path_to_ident(pth)) } ast::pat_ident(_, pth, none) { some(path_to_ident(pth)) }
_ { none } _ { none }
}; };
let val = alloc_ty(cx, t); let val = alloc_ty(cx, t);

View file

@ -646,7 +646,7 @@ fn create_local_var(bcx: block, local: @ast::local)
} }
let name = alt local.node.pat.node { let name = alt local.node.pat.node {
ast::pat_ident(pth, _) { ast_util::path_to_ident(pth) } ast::pat_ident(_, pth, _) { ast_util::path_to_ident(pth) }
// FIXME this should be handled (#2533) // FIXME this should be handled (#2533)
_ { fail ~"no single variable name for local"; } _ { fail ~"no single variable name for local"; }
}; };

View file

@ -320,14 +320,14 @@ fn check_fn(ccx: @crate_ctxt,
// Add pattern bindings. // Add pattern bindings.
let visit_pat = fn@(p: @ast::pat, &&e: (), v: visit::vt<()>) { let visit_pat = fn@(p: @ast::pat, &&e: (), v: visit::vt<()>) {
alt p.node { alt p.node {
ast::pat_ident(path, _) ast::pat_ident(_, path, _)
if !pat_util::pat_is_variant(fcx.ccx.tcx.def_map, p) { if !pat_util::pat_is_variant(fcx.ccx.tcx.def_map, p) => {
assign(p.id, none); assign(p.id, none);
debug!{"Pattern binding %s is assigned to %s", debug!{"Pattern binding %s is assigned to %s",
*path.idents[0], *path.idents[0],
fcx.locals.get(p.id).to_str()}; fcx.locals.get(p.id).to_str()};
} }
_ {} _ => {}
} }
visit::visit_pat(p, e, v); visit::visit_pat(p, e, v);
}; };

View file

@ -155,7 +155,7 @@ fn check_pat(pcx: pat_ctxt, pat: @ast::pat, expected: ty::t) {
} }
fcx.write_ty(pat.id, b_ty); fcx.write_ty(pat.id, b_ty);
} }
ast::pat_ident(name, sub) if !pat_is_variant(tcx.def_map, pat) { ast::pat_ident(_, name, sub) if !pat_is_variant(tcx.def_map, pat) {
let vid = lookup_local(fcx, pat.span, pat.id); let vid = lookup_local(fcx, pat.span, pat.id);
let mut typ = ty::mk_var(tcx, vid); let mut typ = ty::mk_var(tcx, vid);
demand::suptype(fcx, pat.span, expected, typ); demand::suptype(fcx, pat.span, expected, typ);
@ -171,7 +171,7 @@ fn check_pat(pcx: pat_ctxt, pat: @ast::pat, expected: ty::t) {
_ {} _ {}
} }
} }
ast::pat_ident(path, c) { ast::pat_ident(_, path, c) {
check_pat_variant(pcx, pat, path, some(~[]), expected); check_pat_variant(pcx, pat, path, some(~[]), expected);
} }
ast::pat_enum(path, subpats) { ast::pat_enum(path, subpats) {

View file

@ -105,7 +105,7 @@ fn visit_local(l: @ast::local, &&rcx: @rcx, v: rvt) {
fn visit_pat(p: @ast::pat, &&rcx: @rcx, v: rvt) { fn visit_pat(p: @ast::pat, &&rcx: @rcx, v: rvt) {
let fcx = rcx.fcx; let fcx = rcx.fcx;
alt p.node { alt p.node {
ast::pat_ident(path, _) ast::pat_ident(_, path, _)
if !pat_util::pat_is_variant(fcx.ccx.tcx.def_map, p) { if !pat_util::pat_is_variant(fcx.ccx.tcx.def_map, p) {
debug!{"visit_pat binding=%s", *path.idents[0]}; debug!{"visit_pat binding=%s", *path.idents[0]};
visit_node(p.id, p.span, rcx); visit_node(p.id, p.span, rcx);