(* Generated by coq-of-rust *)
Require Import CoqOfRust.CoqOfRust.

(*
fn sum((x, y): (i32, i32)) -> i32 {
    x + y
}
*)
Definition sum (ε : list Value.t) (τ : list Ty.t) (α : list Value.t) : M :=
  match ε, τ, α with
  | [], [], [ β0 ] =>
    ltac:(M.monadic
      (let β0 := M.alloc (| β0 |) in
      M.match_operator (|
        β0,
        [
          fun γ =>
            ltac:(M.monadic
              (let γ0_0 := M.SubPointer.get_tuple_field (| γ, 0 |) in
              let γ0_1 := M.SubPointer.get_tuple_field (| γ, 1 |) in
              let x := M.copy (| γ0_0 |) in
              let y := M.copy (| γ0_1 |) in
              BinOp.Wrap.add (| M.read (| x |), M.read (| y |) |)))
        ]
      |)))
  | _, _, _ => M.impossible "wrong number of arguments"
  end.

Axiom Function_sum : M.IsFunction "pattern_in_function_parameters::sum" sum.

(*
fn steps_between(&start: &char, &end: &char) -> Option<usize> {
    let start = start as u32;
    let end = end as u32;
    if start <= end {
        let count = end - start;
        if start < 0xD800 && 0xE000 <= end {
            usize::try_from(count - 0x800).ok()
        } else {
            usize::try_from(count).ok()
        }
    } else {
        None
    }
}
*)
Definition steps_between (ε : list Value.t) (τ : list Ty.t) (α : list Value.t) : M :=
  match ε, τ, α with
  | [], [], [ β0; β1 ] =>
    ltac:(M.monadic
      (let β0 := M.alloc (| β0 |) in
      let β1 := M.alloc (| β1 |) in
      M.match_operator (|
        β0,
        [
          fun γ =>
            ltac:(M.monadic
              (let γ := M.read (| γ |) in
              let start := M.copy (| γ |) in
              M.match_operator (|
                β1,
                [
                  fun γ =>
                    ltac:(M.monadic
                      (let γ := M.read (| γ |) in
                      let end_ := M.copy (| γ |) in
                      M.read (|
                        let~ start := M.alloc (| M.rust_cast (M.read (| start |)) |) in
                        let~ end_ := M.alloc (| M.rust_cast (M.read (| end_ |)) |) in
                        M.match_operator (|
                          M.alloc (| Value.Tuple [] |),
                          [
                            fun γ =>
                              ltac:(M.monadic
                                (let γ :=
                                  M.use
                                    (M.alloc (|
                                      BinOp.le (| M.read (| start |), M.read (| end_ |) |)
                                    |)) in
                                let _ :=
                                  M.is_constant_or_break_match (|
                                    M.read (| γ |),
                                    Value.Bool true
                                  |) in
                                let~ count :=
                                  M.alloc (|
                                    BinOp.Wrap.sub (| M.read (| end_ |), M.read (| start |) |)
                                  |) in
                                M.match_operator (|
                                  M.alloc (| Value.Tuple [] |),
                                  [
                                    fun γ =>
                                      ltac:(M.monadic
                                        (let γ :=
                                          M.use
                                            (M.alloc (|
                                              LogicalOp.and (|
                                                BinOp.lt (|
                                                  M.read (| start |),
                                                  Value.Integer IntegerKind.U32 55296
                                                |),
                                                ltac:(M.monadic
                                                  (BinOp.le (|
                                                    Value.Integer IntegerKind.U32 57344,
                                                    M.read (| end_ |)
                                                  |)))
                                              |)
                                            |)) in
                                        let _ :=
                                          M.is_constant_or_break_match (|
                                            M.read (| γ |),
                                            Value.Bool true
                                          |) in
                                        M.alloc (|
                                          M.call_closure (|
                                            M.get_associated_function (|
                                              Ty.apply
                                                (Ty.path "core::result::Result")
                                                []
                                                [
                                                  Ty.path "usize";
                                                  Ty.path "core::num::error::TryFromIntError"
                                                ],
                                              "ok",
                                              []
                                            |),
                                            [
                                              M.call_closure (|
                                                M.get_trait_method (|
                                                  "core::convert::TryFrom",
                                                  Ty.path "usize",
                                                  [ Ty.path "u32" ],
                                                  "try_from",
                                                  []
                                                |),
                                                [
                                                  BinOp.Wrap.sub (|
                                                    M.read (| count |),
                                                    Value.Integer IntegerKind.U32 2048
                                                  |)
                                                ]
                                              |)
                                            ]
                                          |)
                                        |)));
                                    fun γ =>
                                      ltac:(M.monadic
                                        (M.alloc (|
                                          M.call_closure (|
                                            M.get_associated_function (|
                                              Ty.apply
                                                (Ty.path "core::result::Result")
                                                []
                                                [
                                                  Ty.path "usize";
                                                  Ty.path "core::num::error::TryFromIntError"
                                                ],
                                              "ok",
                                              []
                                            |),
                                            [
                                              M.call_closure (|
                                                M.get_trait_method (|
                                                  "core::convert::TryFrom",
                                                  Ty.path "usize",
                                                  [ Ty.path "u32" ],
                                                  "try_from",
                                                  []
                                                |),
                                                [ M.read (| count |) ]
                                              |)
                                            ]
                                          |)
                                        |)))
                                  ]
                                |)));
                            fun γ =>
                              ltac:(M.monadic
                                (M.alloc (| Value.StructTuple "core::option::Option::None" [] |)))
                          ]
                        |)
                      |)))
                ]
              |)))
        ]
      |)))
  | _, _, _ => M.impossible "wrong number of arguments"
  end.

Axiom Function_steps_between :
  M.IsFunction "pattern_in_function_parameters::steps_between" steps_between.
