use tear::twist;
use tear::{next, last, resume};
use tear::anybox;
use tear::Looping;
type L = Looping<i32, ()>;
const JUST_BREAK :L = Looping::Break { label: None };
const BREAK_0 :L = Looping::Break { label: Some(0) };
#[cfg(not(any(feature = "experimental", feature = "ignore-ui")))] #[test] fn bad_input () {
use trybuild;
let t = trybuild::TestCases::new();
t.compile_fail("tests/label/*.rs");
}
#[test] fn just_break () {
let mut x = 0;
'a: loop {
loop {
twist! { -label 'a | JUST_BREAK }
panic!("Should break before this");
}
x = 1;
break;
}
assert_eq![ x, 1, "Only broke the innermost loop" ];
}
#[test] fn break_label () {
'a: loop {
loop {
twist! { -label 'a | BREAK_0 }
panic!("Should break before this");
}
panic!("Didn't break the label")
}
}
#[test] fn resume () {
let mut x :i32 = 5;
'a: loop {
x = twist! { -label 'a | resume!(1) };
break;
}
assert_eq![ x, 1 ];
}
#[test] fn continue_loop () {
let mut x :i32 = 0;
'a: loop {
x += 1;
twist! { -label 'a |
if x < 4 { next!() }
else { last!() }
}
}
assert_eq![ x, 4 ];
}
#[test] fn continue_label () {
let mut x :i32 = 0;
'a: loop {
x += 1;
twist! { -label 'a |
if x < 4 { next!(0) }
else { last!() }
}
x -= 1;
}
assert_eq![ x, 4 ];
}
#[test] fn break_label_two () {
'a: loop {
'b: loop {
twist! { -label 'a, 'b | last!(0) }
panic!("Should break before this");
}
panic!("Didn't break the label")
}
}
#[test] fn breakval () {
let x = 'a: loop {
'b: loop {
twist! { -label 'a :i32, 'b | Looping::BreakVal { label: Some(0), value: 8 } }
panic!("Should break before this");
}
panic!("Didn't break the label")
};
assert_eq![ x, 8 ];
}
#[test] fn breakval_multiple () {
let mut y = 0;
let x = 'a: loop {
let z :i32 = 'b: loop {
loop {
y += 1;
twist! { -label 'a :i32, 'b :i32 |
if y > 5 { Looping::BreakVal { label: Some(0), value: 8 } }
else { Looping::BreakVal { label: Some(1), value: 3 } }
}
y -= 1;
}
};
assert_eq![ z, 3 ];
};
assert_eq![ y, 6 ];
assert_eq![ x, 8 ];
}
#[test] fn break_and_breakval () {
let mut y = 0;
let mut a = 0;
let x = 'a: loop {
'c: loop {
let z = 'b: loop {
'd: loop {
let v = twist! { -label 'a :i32, 'c, 'b :i32, 'd |
if y < 5 { Looping::Resume (6) }
else if a < 8 { Looping::Break { label: Some(3) } }
else if y == 5 { y += 1; Looping::BreakVal { label: Some(2), value: 3 } }
else { Looping::BreakVal { label: Some(0), value: 4 } }
};
assert_eq![ v, 6 ]; println!("1/5");
y += 1;
}
a += 1;
};
assert_eq![ z, 3 ]; println!("2/5");
}
};
assert_eq![ y, 6 ]; println!("3/5");
assert_eq![ x, 4 ]; println!("4/5");
assert_eq![ a, 8 ]; println!("5/5");
}
#[test] fn innermost_breakval () {
let mut c = 0;
let v = 'v: loop {
'a: loop {
let x = loop {
twist! { -val i32, -label 'a, 'v :i32 |
if c < 3 { Looping::BreakVal { label: None, value: 0 } }
else if c == 3 { c += 1; Looping::Break { label: Some(0) } }
else { Looping::BreakVal { label: Some(1), value: 7 } }
}
};
assert_eq![ x, 0 ]; println!("1/3");
c += 1;
}
};
assert_eq![ v, 7 ]; println!("2/3");
assert_eq![ c, 4 ]; println!("3/3");
}
#[test] fn anybox () {
struct S { d :i32 }
let x = anybox!(S { d: 5 });
let s = match x.downcast::<S>() {
Ok(v) => *v,
_ => panic!("Failed to get our S back"),
};
assert_eq![ s.d, 5 ];
}
#[test] fn box_breakval () {
let mut i = 0;
let mut f = || {
let ii = i;
i += 1;
if ii == 0 { Looping::BreakVal { label: Some(1), value: anybox!(2) } }
else if ii == 1 { Looping::BreakVal { label: Some(2), value: anybox!("yeah".to_string()) } }
else { Looping::Break { label: Some(0) } }
};
'a: loop {
let b = 'b: loop {
let c = 'c: loop {
loop {
twist! { -box -label 'a, 'b :i32, 'c :String | f() }
break;
}
};
assert_eq![ c, "yeah".to_string() ]; println!("1/2");
};
assert_eq![ b, 2 ]; println!("2/2");
}
}
#[test] fn box_breakval_innermost () {
use std::any::Any;
fn create_closure () -> impl FnMut() -> Looping<(), Box<dyn Any>> {
let mut i = 0;
move || {
let v = match i {
x if x == 0 => Looping::BreakVal { label: None, value: anybox!(0) },
x if x == 1 => Looping::Break { label: Some(0) },
_ => unreachable!(),
};
i += 1;
v
}
}
let mut f = create_closure();
'a: loop {
let v = loop {
twist! { -box -val i32, -label 'a | f() }
};
assert_eq![ v, 0 ]; println!("1/1");
}
}
#[test] fn breakval_multiple_map () {
let v :i32 = 'a: loop {
'b: loop {
let x = twist! { -label 'a :i32, 'b | Some(4) => |_| Looping::BreakVal { label: Some(0), value: 0 } };
break 'a (x * 2);
}
break 3;
};
assert_eq![ v, 8 ];
}