//! > Test boolean if.

//! > test_runner_name
test_function_lowering

//! > function
fn foo(a: bool, x: felt252) -> felt252 {
    if a {
        1
    } else {
        x
    }
}

//! > function_name
foo

//! > module_code

//! > semantic_diagnostics

//! > lowering_diagnostics

//! > lowering_flat
Parameters: v0: core::bool, v1: core::felt252
blk0 (root):
Statements:
End:
  Match(match_enum(v0) {
    bool::False(v4) => blk1,
    bool::True(v2) => blk2,
  })

blk1:
Statements:
End:
  Return(v1)

blk2:
Statements:
  (v3: core::felt252) <- 1
End:
  Return(v3)

//! > ==========================================================================

//! > Test if analyzer.

//! > test_runner_name
test_function_lowering

//! > function
fn foo(x: felt252) -> felt252 {
    if x == 0 {
        1
    } else {
        x
    }
}

//! > function_name
foo

//! > module_code

//! > semantic_diagnostics

//! > lowering_diagnostics

//! > lowering_flat
Parameters: v0: core::felt252
blk0 (root):
Statements:
End:
  Match(match core::felt252_is_zero(v0) {
    IsZeroResult::Zero => blk1,
    IsZeroResult::NonZero(v14) => blk2,
  })

blk1:
Statements:
  (v8: core::felt252) <- 1
End:
  Return(v8)

blk2:
Statements:
End:
  Return(v0)

//! > ==========================================================================

//! > Test if without else.

//! > test_runner_name
test_function_lowering

//! > function
fn foo(x: felt252) -> felt252 {
    if 0 == x {
        return 10;
    }
    20
}

//! > function_name
foo

//! > module_code

//! > semantic_diagnostics

//! > lowering_diagnostics

//! > lowering_flat
Parameters: v0: core::felt252
blk0 (root):
Statements:
  (v1: core::felt252) <- 0
  (v13: core::felt252) <- core::felt252_sub(v1, v0)
End:
  Match(match core::felt252_is_zero(v13) {
    IsZeroResult::Zero => blk1,
    IsZeroResult::NonZero(v14) => blk2,
  })

blk1:
Statements:
  (v8: core::felt252) <- 10
End:
  Return(v8)

blk2:
Statements:
  (v10: core::felt252) <- 20
End:
  Return(v10)

//! > ==========================================================================

//! > Test if x == y

//! > test_runner_name
test_function_lowering

//! > function
fn foo(x: felt252, y: felt252, z: felt252, w: felt252) -> felt252 {
    if x + y == z - w {
        0
    } else {
        1
    }
}

//! > function_name
foo

//! > module_code

//! > semantic_diagnostics

//! > lowering_diagnostics

//! > lowering_flat
Parameters: v0: core::felt252, v1: core::felt252, v2: core::felt252, v3: core::felt252
blk0 (root):
Statements:
  (v16: core::felt252) <- core::felt252_add(v0, v1)
  (v17: core::felt252) <- core::felt252_sub(v2, v3)
  (v20: core::felt252) <- core::felt252_sub(v16, v17)
End:
  Match(match core::felt252_is_zero(v20) {
    IsZeroResult::Zero => blk1,
    IsZeroResult::NonZero(v21) => blk2,
  })

blk1:
Statements:
  (v12: core::felt252) <- 0
End:
  Return(v12)

blk2:
Statements:
  (v14: core::felt252) <- 1
End:
  Return(v14)

//! > ==========================================================================

//! > Test if a == 0 || a = 5

//! > test_runner_name
test_function_lowering

//! > function
fn foo(a: felt252) -> felt252 {
    if a == 0 || a == 5 {
        0
    } else {
        1
    }
}

//! > function_name
foo

//! > module_code

//! > semantic_diagnostics

//! > lowering_diagnostics

//! > lowering_flat
Parameters: v0: core::felt252
blk0 (root):
Statements:
End:
  Match(match core::felt252_is_zero(v0) {
    IsZeroResult::Zero => blk1,
    IsZeroResult::NonZero(v27) => blk2,
  })

blk1:
Statements:
End:
  Goto(blk4, {})

blk2:
Statements:
  (v11: core::felt252) <- 5
  (v34: core::felt252) <- core::felt252_sub(v0, v11)
End:
  Match(match core::felt252_is_zero(v34) {
    IsZeroResult::Zero => blk3,
    IsZeroResult::NonZero(v35) => blk5,
  })

blk3:
Statements:
End:
  Goto(blk4, {})

blk4:
Statements:
  (v20: core::felt252) <- 0
End:
  Return(v20)

blk5:
Statements:
  (v22: core::felt252) <- 1
End:
  Return(v22)

//! > ==========================================================================

//! > Test if let

//! > test_runner_name
test_function_lowering

//! > function
fn foo(a: myEnum) -> felt252 {
    if let myEnum::A(x) = a {
        x
    } else {
        0
    }
}

//! > function_name
foo

//! > module_code
enum myEnum {
    A: felt252,
    B,
    C,
}

//! > semantic_diagnostics

//! > lowering_diagnostics

//! > lowering_flat
Parameters: v0: test::myEnum
blk0 (root):
Statements:
End:
  Match(match_enum(v0) {
    myEnum::A(v1) => blk1,
    myEnum::B(v2) => blk2,
    myEnum::C(v3) => blk3,
  })

blk1:
Statements:
End:
  Return(v1)

blk2:
Statements:
End:
  Goto(blk4, {})

blk3:
Statements:
End:
  Goto(blk4, {})

blk4:
Statements:
  (v4: core::felt252) <- 0
End:
  Return(v4)

//! > ==========================================================================

//! > Test if let extern enum

//! > test_runner_name
test_function_lowering

//! > function
fn foo() -> felt252 {
    let mut y = 0;
    if let myEnum::A(x) = a() {
        y = y + x
    }
    y = y + 1;
    return y;
}

//! > function_name
foo

//! > module_code
enum myEnum {
    A: felt252,
    B,
    C,
}
extern fn a() -> myEnum nopanic;

//! > semantic_diagnostics

//! > lowering_diagnostics

//! > lowering_flat
Parameters:
blk0 (root):
Statements:
  (v0: core::felt252) <- 0
End:
  Match(match test::a() {
    myEnum::A(v1) => blk1,
    myEnum::B => blk2,
    myEnum::C => blk3,
  })

blk1:
Statements:
  (v6: core::felt252) <- core::felt252_add(v0, v1)
End:
  Goto(blk5, {v6 -> v3})

blk2:
Statements:
End:
  Goto(blk4, {})

blk3:
Statements:
End:
  Goto(blk4, {})

blk4:
Statements:
End:
  Goto(blk5, {v0 -> v3})

blk5:
Statements:
  (v4: core::felt252) <- 1
  (v7: core::felt252) <- core::felt252_add(v3, v4)
End:
  Return(v7)

//! > ==========================================================================

//! > Test if let tuple

//! > test_runner_name
test_function_lowering

//! > function
fn foo() -> felt252 {
    let mut y = 0;
    if let (myEnum::A(x), true) = (a(), 5 == 6) {
        y = y + x
    }
    y = y + 1;
    return y;
}

//! > function_name
foo

//! > module_code
enum myEnum {
    A: felt252,
    B,
    C,
}
extern fn a() -> myEnum nopanic;

//! > semantic_diagnostics

//! > lowering_diagnostics

//! > lowering_flat
Parameters:
blk0 (root):
Statements:
  (v0: core::felt252) <- 0
  (v1: core::felt252) <- 5
  (v4: core::felt252) <- 6
  (v30: core::felt252) <- core::felt252_sub(v1, v4)
End:
  Match(match core::felt252_is_zero(v30) {
    IsZeroResult::Zero => blk1,
    IsZeroResult::NonZero(v31) => blk2,
  })

blk1:
Statements:
  (v32: ()) <- struct_construct()
  (v33: core::bool) <- bool::True(v32)
End:
  Goto(blk3, {v33 -> v7})

blk2:
Statements:
  (v34: ()) <- struct_construct()
  (v35: core::bool) <- bool::False(v34)
End:
  Goto(blk3, {v35 -> v7})

blk3:
Statements:
End:
  Match(match test::a() {
    myEnum::A(v8) => blk4,
    myEnum::B => blk7,
    myEnum::C => blk10,
  })

blk4:
Statements:
End:
  Match(match_enum(v7) {
    bool::False(v16) => blk5,
    bool::True(v17) => blk6,
  })

blk5:
Statements:
End:
  Goto(blk13, {})

blk6:
Statements:
  (v36: core::felt252) <- core::felt252_add(v0, v8)
End:
  Goto(blk14, {v36 -> v25})

blk7:
Statements:
End:
  Match(match_enum(v7) {
    bool::False(v19) => blk8,
    bool::True(v20) => blk9,
  })

blk8:
Statements:
End:
  Goto(blk13, {})

blk9:
Statements:
End:
  Goto(blk13, {})

blk10:
Statements:
End:
  Match(match_enum(v7) {
    bool::False(v22) => blk11,
    bool::True(v23) => blk12,
  })

blk11:
Statements:
End:
  Goto(blk13, {})

blk12:
Statements:
End:
  Goto(blk13, {})

blk13:
Statements:
End:
  Goto(blk14, {v0 -> v25})

blk14:
Statements:
  (v26: core::felt252) <- 1
  (v37: core::felt252) <- core::felt252_add(v25, v26)
End:
  Return(v37)

//! > ==========================================================================

//! > Test if let unsupported tuple

//! > test_runner_name
test_function_lowering

//! > function
fn foo() -> felt252 {
    let mut y = 0;
    if let (myEnum::A(x), 3) = (a(), 3) {
        y = y + x
    }
    y = y + 1;
    return y;
}

//! > function_name
foo

//! > module_code
enum myEnum {
    A: felt252,
    B,
    C,
}
extern fn a() -> myEnum nopanic;

//! > semantic_diagnostics

//! > lowering_diagnostics
error: Unsupported value in if-let. Currently, if-let on tuples only supports enums as tuple members.
 --> lib.cairo:9:32
    if let (myEnum::A(x), 3) = (a(), 3) {
                               ^******^

//! > lowering_flat
Parameters:

//! > ==========================================================================

//! > Test if let numeric

//! > test_runner_name
test_function_lowering

//! > function
fn foo() -> felt252 {
    let mut y = 0;
    if let x = y {
        y = y + x
    }
    y = y + 1;
    return y;
}

//! > function_name
foo

//! > module_code

//! > semantic_diagnostics

//! > lowering_diagnostics
error: Numeric values are not supported in if-let conditions.
 --> lib.cairo:3:5
    if let x = y {
    ^************^

//! > lowering_flat
Parameters:

//! > ==========================================================================

//! > Test if let underscore

//! > test_runner_name
test_function_lowering

//! > function
fn foo(a: myEnum) -> felt252 {
    let mut y = 0;
    if let _ = a {
        y = y + 5;
    }
    y = y + 1;
    return y;
}

//! > function_name
foo

//! > module_code
enum myEnum {
    A: felt252,
    B,
    C,
}

//! > semantic_diagnostics

//! > lowering_diagnostics

//! > lowering_flat
Parameters: v0: test::myEnum
blk0 (root):
Statements:
  (v1: core::felt252) <- 0
End:
  Match(match_enum(v0) {
    myEnum::A(v2) => blk1,
    myEnum::B(v3) => blk2,
    myEnum::C(v4) => blk3,
  })

blk1:
Statements:
End:
  Goto(blk4, {})

blk2:
Statements:
End:
  Goto(blk4, {})

blk3:
Statements:
End:
  Goto(blk4, {})

blk4:
Statements:
  (v5: core::felt252) <- 5
  (v10: core::felt252) <- core::felt252_add(v1, v5)
  (v8: core::felt252) <- 1
  (v11: core::felt252) <- core::felt252_add(v10, v8)
End:
  Return(v11)

//! > ==========================================================================

//! > Test if let unreachable-else

//! > test_runner_name
test_function_lowering

//! > function
fn foo(a: myEnum) -> felt252 {
    let mut y = 0;
    if let _ = a {
        y = y + 5;
    } else {
        y = y + 8;
    }
    y = y + 1;
    return y;
}

//! > function_name
foo

//! > module_code
enum myEnum {
    A: felt252,
    B,
    C,
}

//! > semantic_diagnostics

//! > lowering_diagnostics
error: Unreachable else clause.
 --> lib.cairo:10:12
    } else {
           ^

//! > lowering_flat
Parameters: v0: test::myEnum
blk0 (root):
Statements:
  (v1: core::felt252) <- 0
End:
  Match(match_enum(v0) {
    myEnum::A(v2) => blk1,
    myEnum::B(v3) => blk2,
    myEnum::C(v4) => blk3,
  })

blk1:
Statements:
End:
  Goto(blk4, {})

blk2:
Statements:
End:
  Goto(blk4, {})

blk3:
Statements:
End:
  Goto(blk4, {})

blk4:
Statements:
  (v5: core::felt252) <- 5
  (v10: core::felt252) <- core::felt252_add(v1, v5)
  (v8: core::felt252) <- 1
  (v11: core::felt252) <- core::felt252_add(v10, v8)
End:
  Return(v11)

//! > ==========================================================================

//! > Test if let unsupported type

//! > test_runner_name
test_function_lowering

//! > function
fn foo(a: MyStruct) -> felt252 {
    let mut y = 0;
    if let _ = a {
        y = y + 5;
    } else {
        y = y + 8;
    }
    y = y + 1;
    return y;
}

//! > function_name
foo

//! > module_code
struct MyStruct {
    A: felt252,
    B: felt252,
}

//! > semantic_diagnostics

//! > lowering_diagnostics
error: Unsupported type in if-let. Type: `test::MyStruct`.
 --> lib.cairo:7:16
    if let _ = a {
               ^

//! > lowering_flat
Parameters: v0: test::MyStruct

//! > ==========================================================================

//! > Test if let in loop

//! > test_runner_name
test_function_lowering

//! > function
fn foo(a: myEnum) -> felt252 {
    loop {
        // Some statements to prevent the loop function from being inlined.
        let mut x = 0;
        x += 1;
        x += 1;
        x += 1;
        x += 1;
        x += 1;
        x += 1;
        x += 1;
        x += 1;
        if let _ = a {
            break 2;
        }
    }
}

//! > function_name
foo

//! > module_code
#[derive(Drop, Copy)]
enum myEnum {
    A: felt252,
    B: felt252,
}

//! > semantic_diagnostics

//! > lowering_diagnostics

//! > lowering_flat
Parameters: v0: test::myEnum
blk0 (root):
Statements:
End:
  Match(match_enum(v0) {
    myEnum::A(v2) => blk1,
    myEnum::B(v3) => blk2,
  })

blk1:
Statements:
End:
  Goto(blk3, {})

blk2:
Statements:
End:
  Goto(blk3, {})

blk3:
Statements:
  (v4: core::felt252) <- 2
End:
  Return(v4)
