use forward_goto::*;
#[derive(Eq, PartialEq)]
enum Three {
A, B, C
}
#[rewrite_forward_goto]
fn test_easy_method() -> Vec<&'static str>{
let mut result = vec!["begin"];
forward_goto!('test);
result.push("should not happen");
forward_label!('test);
result.push("end");
result
}
#[test]
fn test_easy() {
assert_eq!(test_easy_method(),
vec![
"begin",
"end",
]
);
}
#[rewrite_forward_goto]
fn test_if_method(b: bool) -> Vec<&'static str>{
let mut result = vec!["begin"];
if !b {
forward_goto!('test);
}
result.push("happens if b");
forward_label!('test);
result.push("end");
result
}
#[test]
fn test_if() {
assert_eq!(test_if_method(true),
vec![
"begin",
"happens if b",
"end",
]
);
assert_eq!(test_if_method(false),
vec![
"begin",
"end",
]
);
}
#[rewrite_forward_goto]
fn test_jump_into_if_method(three: Three, b: bool) -> Vec<&'static str>{
let mut result = vec!["begin"];
match three {
Three::A => forward_goto!('test),
Three::B => forward_goto!('test_2),
Three::C => (),
}
result.push("in between");
if b {
result.push("before label");
forward_label!('test);
result.push("after label");
} else {
result.push("before label 2");
forward_label!('test_2);
result.push("after label 2");
}
result.push("end");
result
}
#[test]
fn test_jump_into_if() {
assert_eq!(test_jump_into_if_method(Three::A, true),
vec![
"begin",
"after label",
"end",
]
);
assert_eq!(test_jump_into_if_method(Three::A, false),
vec![
"begin",
"after label",
"end",
]
);
assert_eq!(test_jump_into_if_method(Three::B, true),
vec![
"begin",
"after label 2",
"end",
]
);
assert_eq!(test_jump_into_if_method(Three::B, false),
vec![
"begin",
"after label 2",
"end",
]
);
assert_eq!(test_jump_into_if_method(Three::C, true),
vec![
"begin",
"in between",
"before label",
"after label",
"end",
]
);
assert_eq!(test_jump_into_if_method(Three::C, false),
vec![
"begin",
"in between",
"before label 2",
"after label 2",
"end",
]
);
}
#[rewrite_forward_goto]
fn test_jump_into_double_if_method(three: Three, b1: bool, b2: bool) -> Vec<&'static str>{
let mut result = vec!["begin"];
match three {
Three::A => forward_goto!('test),
Three::B => forward_goto!('test_2),
Three::C => (),
}
result.push("in between");
if b1 {
if b2 {
result.push("before label");
forward_label!('test);
result.push("after label");
} else {
result.push("before label 2");
forward_label!('test_2);
result.push("after label 2");
}
result.push("after after");
} else {
result.push("alternative");
}
result.push("end");
result
}
#[test]
fn test_jump_into_double_if() {
assert_eq!(test_jump_into_double_if_method(Three::A, true, true),
vec![
"begin",
"after label",
"after after",
"end",
]
);
assert_eq!(test_jump_into_double_if_method(Three::A, true, false),
vec![
"begin",
"after label",
"after after",
"end",
]
);
assert_eq!(test_jump_into_double_if_method(Three::A, false, true),
vec![
"begin",
"after label",
"after after",
"end",
]
);
assert_eq!(test_jump_into_double_if_method(Three::A, false, false),
vec![
"begin",
"after label",
"after after",
"end",
]
);
assert_eq!(test_jump_into_double_if_method(Three::B, true, true),
vec![
"begin",
"after label 2",
"after after",
"end",
]
);
assert_eq!(test_jump_into_double_if_method(Three::B, true, false),
vec![
"begin",
"after label 2",
"after after",
"end",
]
);
assert_eq!(test_jump_into_double_if_method(Three::B, false, true),
vec![
"begin",
"after label 2",
"after after",
"end",
]
);
assert_eq!(test_jump_into_double_if_method(Three::B, false, false),
vec![
"begin",
"after label 2",
"after after",
"end",
]
);
assert_eq!(test_jump_into_double_if_method(Three::C, true, true),
vec![
"begin",
"in between",
"before label",
"after label",
"after after",
"end",
]
);
assert_eq!(test_jump_into_double_if_method(Three::C, true, false),
vec![
"begin",
"in between",
"before label 2",
"after label 2",
"after after",
"end",
]
);
assert_eq!(test_jump_into_double_if_method(Three::C, false, true),
vec![
"begin",
"in between",
"alternative",
"end",
]
);
assert_eq!(test_jump_into_double_if_method(Three::C, false, false),
vec![
"begin",
"in between",
"alternative",
"end",
]
);
}
#[rewrite_forward_goto]
fn test_multi_goto_method(three: Three) -> Vec<&'static str>{
let mut result = vec!["begin"];
if three == Three::A {
result.push("before first goto");
forward_goto!('test);
}
if three == Three::B {
result.push("before second goto");
forward_goto!('test);
}
result.push("in between");
forward_label!('test);
result.push("end");
result
}
#[test]
fn test_multi_goto() {
assert_eq!(test_multi_goto_method(Three::A),
vec![
"begin",
"before first goto",
"end",
]
);
assert_eq!(test_multi_goto_method(Three::B),
vec![
"begin",
"before second goto",
"end",
]
);
assert_eq!(test_multi_goto_method(Three::C),
vec![
"begin",
"in between",
"end",
]
);
}
#[rewrite_forward_goto]
fn test_multi_cross_method(three: Three) -> Vec<&'static str>{
let mut result = vec!["begin"];
if three == Three::A {
result.push("before first goto");
forward_goto!('test);
}
if three == Three::B {
result.push("before second goto");
forward_goto!('test_2);
}
result.push("after ifs");
forward_label!('test);
result.push("in between labels");
forward_label!('test_2);
result.push("end");
result
}
#[test]
fn test_multi_cross() {
assert_eq!(test_multi_cross_method(Three::A),
vec![
"begin",
"before first goto",
"in between labels",
"end",
]
);
assert_eq!(test_multi_cross_method(Three::B),
vec![
"begin",
"before second goto",
"end",
]
);
assert_eq!(test_multi_cross_method(Three::C),
vec![
"begin",
"after ifs",
"in between labels",
"end",
]
);
}
#[rewrite_forward_goto]
fn test_multi_stack_like_method(three: Three) -> Vec<&'static str>{
let mut result = vec!["begin"];
if three == Three::A {
result.push("before first goto");
forward_goto!('test);
}
fn f() {}
if three == Three::B {
result.push("before second goto");
forward_goto!('test_2);
}
f();
result.push("after ifs");
forward_label!('test_2);
f();
result.push("in between labels");
forward_label!('test);
result.push("end");
result
}
#[test]
fn test_multi_stack_like() {
assert_eq!(test_multi_stack_like_method(Three::A),
vec![
"begin",
"before first goto",
"end",
]
);
assert_eq!(test_multi_stack_like_method(Three::B),
vec![
"begin",
"before second goto",
"in between labels",
"end",
]
);
assert_eq!(test_multi_stack_like_method(Three::C),
vec![
"begin",
"after ifs",
"in between labels",
"end",
]
);
}
#[rewrite_forward_goto]
fn test_if_merging_method(b: bool) -> Vec<&'static str>{
let mut result = vec!["begin"];
if b {
result.push("before first goto");
forward_goto!('test);
}
{
result.push("before if");
if b {
forward_label!('test);
result.push("after test");
}
result.push("after if");
}
result.push("end");
result
}
#[test]
fn test_if_merging() {
assert_eq!(test_if_merging_method(true),
vec![
"begin",
"before first goto",
"after test",
"after if",
"end",
]
);
assert_eq!(test_if_merging_method(false),
vec![
"begin",
"before if",
"after if",
"end",
]
);
}
#[rewrite_forward_goto]
fn test_jump_in_continuation_method(b: bool) -> Vec<&'static str>{
let mut result = vec!["begin"];
if b {
result.push("before first goto");
forward_goto!('test);
}
{
result.push("before if");
if b {
forward_label!('test);
result.push("after test");
forward_goto!('test_2);
}
result.push("after if");
forward_label!('test_2);
result.push("after test_2");
}
result.push("end");
result
}
#[test]
fn test_jump_in_continuation() {
assert_eq!(test_jump_in_continuation_method(true),
vec![
"begin",
"before first goto",
"after test",
"after test_2",
"end",
]
);
assert_eq!(test_jump_in_continuation_method(false),
vec![
"begin",
"before if",
"after if",
"after test_2",
"end",
]
);
}
#[rewrite_forward_goto]
fn test_jump_into_match_method(three: Three) -> Vec<&'static str>{
let mut result = vec!["begin"];
match three {
Three::A => {
forward_goto!('a);
},
Three::B => {
forward_goto!('b);
},
Three::C => {
forward_goto!('c);
}
};
match 1 as i32 {
1 => {
forward_label!('a);
result.push("a");
},
2 => {
forward_label!('b);
result.push("b");
},
_ => {
forward_label!('c);
result.push("c");
},
};
result.push("end");
result
}
#[test]
fn test_jump_into_match() {
assert_eq!(test_jump_into_match_method(Three::A),
vec![
"begin",
"a",
"end",
]
);
assert_eq!(test_jump_into_match_method(Three::B),
vec![
"begin",
"b",
"end",
]
);
assert_eq!(test_jump_into_match_method(Three::C),
vec![
"begin",
"c",
"end",
]
);
}
#[rewrite_forward_goto]
fn test_jump_from_match_method(three: Three) -> Vec<&'static str>{
let mut result = vec!["begin"];
if three == Three::B {
forward_goto!('b);
}
match three {
Three::A => {
forward_goto!('a);
},
Three::B => {
},
Three::C => {
forward_goto!('c);
}
};
match 1 as i32 {
1 => {
forward_label!('a);
result.push("a");
},
2 => {
forward_label!('b);
result.push("b");
},
_ => {
forward_label!('c);
result.push("c");
},
};
result.push("end");
result
}
#[test]
fn test_jump_from_match() {
assert_eq!(test_jump_from_match_method(Three::A),
vec![
"begin",
"a",
"end",
]
);
assert_eq!(test_jump_from_match_method(Three::B),
vec![
"begin",
"b",
"end",
]
);
assert_eq!(test_jump_from_match_method(Three::C),
vec![
"begin",
"c",
"end",
]
);
}
#[rewrite_forward_goto]
fn test_inner_goto_method(three: Three) -> Vec<&'static str>{
let mut result = vec!["begin"];
if three == Three::A {
forward_goto!('a);
}
{
match three {
Three::A => {
},
Three::B => {
forward_goto!('b);
},
Three::C => {
forward_goto!('c);
}
};
match 1 as i32 {
1 => {
forward_label!('a);
result.push("a");
},
2 => {
forward_label!('b);
result.push("b");
},
_ => {
forward_label!('c);
result.push("c");
},
};
}
result.push("end");
result
}
#[test]
fn test_inner_goto() {
assert_eq!(test_inner_goto_method(Three::A),
vec![
"begin",
"a",
"end",
]
);
assert_eq!(test_inner_goto_method(Three::B),
vec![
"begin",
"b",
"end",
]
);
assert_eq!(test_inner_goto_method(Three::C),
vec![
"begin",
"c",
"end",
]
);
}
#[rewrite_forward_goto]
fn test_side_jump_method(b: bool) -> Vec<&'static str>{
let mut result = vec!["begin"];
if b {
result.push("then");
forward_goto!('other_branch);
} else {
result.push("else");
forward_label!('other_branch);
result.push("after label");
}
result.push("end");
result
}
#[test]
fn test_side_jump() {
assert_eq!(test_side_jump_method(true),
vec![
"begin",
"then",
"after label",
"end",
]
);
assert_eq!(test_side_jump_method(false),
vec![
"begin",
"else",
"after label",
"end",
]
);
}
#[rewrite_forward_goto]
fn test_jump_into_continuation_method(b: bool) -> Vec<&'static str>{
let mut result = vec!["begin"];
if b {
forward_goto!('test_1);
}
result.push("after if");
forward_goto!('test_2);
{
result.push("not executed");
forward_label!('test_1);
result.push("after test_1");
forward_label!('test_2);
result.push("after test_2");
}
result.push("end");
result
}
#[test]
fn test_jump_into_continuation() {
assert_eq!(test_jump_into_continuation_method(true),
vec![
"begin",
"after test_1",
"after test_2",
"end",
]
);
assert_eq!(test_jump_into_continuation_method(false),
vec![
"begin",
"after if",
"after test_2",
"end",
]
);
}