Fix trans for region patterns (&P)

This commit is contained in:
Niko Matsakis 2012-09-23 05:39:39 -07:00
parent ba3eebd41d
commit 0a26edca75
9 changed files with 99 additions and 40 deletions

View File

@ -331,7 +331,7 @@ type ident_interner = util::interner::interner<@~str>;
* so we have to use a unique number. See taskgroup_key! in task.rs
* for another case of this. */
macro_rules! interner_key (
() => (cast::transmute::<(uint, uint), &fn(+@@token::ident_interner)>(
() => (cast::transmute::<(uint, uint), &fn(+v: @@token::ident_interner)>(
(-3 as uint, 0u)))
)

View File

@ -487,6 +487,31 @@ fn enter_uniq(bcx: block, dm: DefMap, m: &[@Match/&r],
}
}
fn enter_region(bcx: block, dm: DefMap, m: &[@Match/&r],
col: uint, val: ValueRef)
-> ~[@Match/&r]
{
debug!("enter_region(bcx=%s, m=%s, col=%u, val=%?)",
bcx.to_str(),
matches_to_str(bcx, m),
col,
bcx.val_str(val));
let _indenter = indenter();
let dummy = @{id: 0, node: ast::pat_wild, span: dummy_sp()};
do enter_match(bcx, dm, m, col, val) |p| {
match p.node {
ast::pat_region(sub) => {
Some(~[sub])
}
_ => {
assert_is_binding_or_wild(bcx, p);
Some(~[dummy])
}
}
}
}
fn get_options(ccx: @crate_ctxt, m: &[@Match], col: uint) -> ~[Opt] {
fn add_to_set(tcx: ty::ctxt, set: &DVec<Opt>, val: Opt) {
if set.any(|l| opt_eq(tcx, &l, &val)) {return;}
@ -585,34 +610,35 @@ fn root_pats_as_necessary(bcx: block, m: &[@Match],
}
}
fn any_box_pat(m: &[@Match], col: uint) -> bool {
for vec::each(m) |br| {
match br.pats[col].node {
ast::pat_box(_) => return true,
_ => ()
}
// Macro for deciding whether any of the remaining matches fit a given kind of
// pattern. Note that, because the macro is well-typed, either ALL of the
// matches should fit that sort of pattern or NONE (however, some of the
// matches may be wildcards like _ or identifiers).
macro_rules! any_pat (
($m:expr, $pattern:pat) => {
vec::any($m, |br| {
match br.pats[col].node {
$pattern => true,
_ => false
}
})
}
return false;
)
fn any_box_pat(m: &[@Match], col: uint) -> bool {
any_pat!(m, ast::pat_box(_))
}
fn any_uniq_pat(m: &[@Match], col: uint) -> bool {
for vec::each(m) |br| {
match br.pats[col].node {
ast::pat_uniq(_) => return true,
_ => ()
}
}
return false;
any_pat!(m, ast::pat_uniq(_))
}
fn any_region_pat(m: &[@Match], col: uint) -> bool {
any_pat!(m, ast::pat_region(_))
}
fn any_tup_pat(m: &[@Match], col: uint) -> bool {
for vec::each(m) |br| {
match br.pats[col].node {
ast::pat_tup(_) => return true,
_ => ()
}
}
return false;
any_pat!(m, ast::pat_tup(_))
}
type mk_fail = fn@() -> BasicBlockRef;
@ -940,6 +966,13 @@ fn compile_submatch(bcx: block,
return;
}
if any_region_pat(m, col) {
let loaded_val = Load(bcx, val);
compile_submatch(bcx, enter_region(bcx, dm, m, col, val),
vec::append(~[loaded_val], vals_left), chk);
return;
}
// Decide what kind of branch we need
let opts = get_options(ccx, m, col);
let mut kind = no_branch;
@ -1248,12 +1281,15 @@ fn bind_irrefutable_pat(bcx: block, pat: @ast::pat, val: ValueRef,
bcx = bind_irrefutable_pat(bcx, *elem, fldptr, make_copy);
}
}
ast::pat_box(inner) | ast::pat_uniq(inner) |
ast::pat_region(inner) => {
ast::pat_box(inner) | ast::pat_uniq(inner) => {
let llbox = Load(bcx, val);
let unboxed = GEPi(bcx, llbox, [0u, abi::box_field_body]);
bcx = bind_irrefutable_pat(bcx, inner, unboxed, true);
}
ast::pat_region(inner) => {
let loaded_val = Load(bcx, val);
bcx = bind_irrefutable_pat(bcx, inner, loaded_val, true);
}
ast::pat_wild | ast::pat_lit(_) | ast::pat_range(_, _) => ()
}
return bcx;

View File

@ -10,7 +10,7 @@ export from_srv, extract, to_str, interner;
* there. */
macro_rules! interner_key (
() => (cast::transmute::<(uint, uint),
&fn(+@@syntax::parse::token::ident_interner)>((-3 as uint, 0u)))
&fn(+v: @@syntax::parse::token::ident_interner)>((-3 as uint, 0u)))
)
// Hack; rather than thread an interner through everywhere, rely on

View File

@ -14,7 +14,7 @@ enum WriteInstr {
Done
}
type Writer = fn~(+WriteInstr);
type Writer = fn~(+v: WriteInstr);
type WriterFactory = fn~(page: doc::Page) -> Writer;
trait WriterUtils {

View File

@ -1,10 +1,11 @@
fn foo<T>(s: &str) {
fn foo(s: &~str) -> bool {
match s {
&"kitty" => fail ~"cat",
_ => ()
&~"kitty" => true,
_ => false
}
}
fn main() {
}
assert foo(&~"kitty");
assert !foo(&~"gata");
}

View File

@ -1,10 +1,11 @@
fn foo<T>(s: &r/uint) {
fn foo(s: &r/uint) -> bool {
match s {
&3 => fail ~"oh",
_ => ()
&3 => true,
_ => false
}
}
fn main() {
}
assert foo(&3);
assert !foo(&4);
}

View File

@ -0,0 +1,6 @@
fn main() {
let (&x, &y, &z) = (&3, &'a', &@"No pets!");
assert x == 3;
assert y == 'a';
assert z == @"No pets!";
}

View File

@ -0,0 +1,13 @@
fn select(x: &r/Option<int>, y: &r/Option<int>) -> &r/Option<int> {
match (x, y) {
(&None, &None) => x,
(&Some(_), _) => x,
(&None, &Some(_)) => y
}
}
fn main() {
let x = None;
let y = Some(3);
assert select(&x, &y).get() == 3;
}

View File

@ -1,9 +1,11 @@
fn foo<T>(x: &T) {
fn foo<T: Copy>(x: &T) -> T{
match x {
&a => fail #fmt("%?", a)
&a => a
}
}
fn main() {
}
assert foo(&3) == 3;
assert foo(&'a') == 'a';
assert foo(&@"Dogs rule, cats drool") == @"Dogs rule, cats drool";
}