(** THIS FILE WAS AUTOMATICALLY GENERATED BY AENEAS *)
(** [demo] *)
Require Import Primitives.
Import Primitives.
Require Import Coq.ZArith.ZArith.
Require Import List.
Import ListNotations.
Local Open Scope Primitives_scope.
Module Demo.

(** [core::num::{u32}::wrapping_add]:
    Source: '/rustc/library/core/src/num/uint_macros.rs', lines 2583:8-2583:58
    Name pattern: [core::num::{u32}::wrapping_add]
    Visibility: public *)
Axiom core_num_U32_wrapping_add : u32 -> u32 -> result u32.

(** [core::num::{u32}::wrapping_sub]:
    Source: '/rustc/library/core/src/num/uint_macros.rs', lines 2620:8-2620:58
    Name pattern: [core::num::{u32}::wrapping_sub]
    Visibility: public *)
Axiom core_num_U32_wrapping_sub : u32 -> u32 -> result u32.

(** [demo::choose]:
    Source: 'tests/src/demo.rs', lines 8:0-14:1
    Visibility: public *)
Definition choose
  {T : Type} (b : bool) (x : T) (y : T) : result (T * (T -> (T * T))) :=
  if b
  then let back := fun (x1 : T) => (x1, y) in Ok (x, back)
  else let back := fun (y1 : T) => (x, y1) in Ok (y, back)
.

(** [demo::mul2_add1]:
    Source: 'tests/src/demo.rs', lines 16:0-18:1
    Visibility: public *)
Definition mul2_add1 (x : u32) : result u32 :=
  i <- u32_add x x; u32_add i 1%u32
.

(** [demo::use_mul2_add1]:
    Source: 'tests/src/demo.rs', lines 20:0-22:1
    Visibility: public *)
Definition use_mul2_add1 (x : u32) (y : u32) : result u32 :=
  i <- mul2_add1 x; u32_add i y
.

(** [demo::incr]:
    Source: 'tests/src/demo.rs', lines 24:0-26:1
    Visibility: public *)
Definition incr (x : u32) : result u32 :=
  u32_add x 1%u32.

(** [demo::use_incr]:
    Source: 'tests/src/demo.rs', lines 28:0-33:1
    Visibility: public *)
Definition use_incr : result unit :=
  x <- incr 0%u32; x1 <- incr x; _ <- incr x1; Ok tt
.

(** [demo::CList]
    Source: 'tests/src/demo.rs', lines 37:0-40:1
    Visibility: public *)
Inductive CList_t (T : Type) :=
| CList_CCons : T -> CList_t T -> CList_t T
| CList_CNil : CList_t T
.

Arguments CList_CCons { _ }.
Arguments CList_CNil { _ }.

(** [demo::list_nth]:
    Source: 'tests/src/demo.rs', lines 42:0-55:1
    Visibility: public *)
Fixpoint list_nth {T : Type} (n : nat) (l : CList_t T) (i : u32) : result T :=
  match n with
  | O => Fail_ OutOfFuel
  | S n1 =>
    match l with
    | CList_CCons x tl =>
      if i s= 0%u32 then Ok x else (i1 <- u32_sub i 1%u32; list_nth n1 tl i1)
    | CList_CNil => Fail_ Failure
    end
  end
.

(** [demo::list_nth1]: loop 0:
    Source: 'tests/src/demo.rs', lines 58:4-66:1
    Visibility: public *)
Fixpoint list_nth1_loop
  {T : Type} (n : nat) (l : CList_t T) (i : u32) : result T :=
  match n with
  | O => Fail_ OutOfFuel
  | S n1 =>
    match l with
    | CList_CCons x tl =>
      if i s= 0%u32
      then Ok x
      else (i1 <- u32_sub i 1%u32; list_nth1_loop n1 tl i1)
    | CList_CNil => Fail_ Failure
    end
  end
.

(** [demo::list_nth1]:
    Source: 'tests/src/demo.rs', lines 57:0-66:1
    Visibility: public *)
Definition list_nth1
  {T : Type} (n : nat) (l : CList_t T) (i : u32) : result T :=
  list_nth1_loop n l i
.

(** [demo::list_nth_mut]:
    Source: 'tests/src/demo.rs', lines 68:0-81:1
    Visibility: public *)
Fixpoint list_nth_mut
  {T : Type} (n : nat) (l : CList_t T) (i : u32) :
  result (T * (T -> CList_t T))
  :=
  match n with
  | O => Fail_ OutOfFuel
  | S n1 =>
    match l with
    | CList_CCons x tl =>
      if i s= 0%u32
      then let back := fun (t : T) => CList_CCons t tl in Ok (x, back)
      else (
        i1 <- u32_sub i 1%u32;
        p <- list_nth_mut n1 tl i1;
        let (x1, list_nth_mut_back) := p in
        let back :=
          fun (t : T) => let tl1 := list_nth_mut_back t in CList_CCons x tl1
        in
        Ok (x1, back))
    | CList_CNil => Fail_ Failure
    end
  end
.

(** [demo::i32_id]:
    Source: 'tests/src/demo.rs', lines 83:0-89:1
    Visibility: public *)
Fixpoint i32_id (n : nat) (i : i32) : result i32 :=
  match n with
  | O => Fail_ OutOfFuel
  | S n1 =>
    if i s= 0%i32
    then Ok 0%i32
    else (i1 <- i32_sub i 1%i32; i2 <- i32_id n1 i1; i32_add i2 1%i32)
  end
.

(** [demo::list_tail]:
    Source: 'tests/src/demo.rs', lines 91:0-96:1
    Visibility: public *)
Fixpoint list_tail
  {T : Type} (n : nat) (l : CList_t T) :
  result ((CList_t T) * (CList_t T -> CList_t T))
  :=
  match n with
  | O => Fail_ OutOfFuel
  | S n1 =>
    match l with
    | CList_CCons t tl =>
      p <- list_tail n1 tl;
      let (c, list_tail_back) := p in
      let back :=
        fun (c1 : CList_t T) =>
          let tl1 := list_tail_back c1 in CList_CCons t tl1
      in
      Ok (c, back)
    | CList_CNil => Ok (CList_CNil, fun (l1 : CList_t T) => l1)
    end
  end
.

(** Trait declaration: [demo::Counter]
    Source: 'tests/src/demo.rs', lines 100:0-102:1
    Visibility: public *)
Record Counter_t (Self : Type) := mkCounter_t {
  Counter_t_incr : Self -> result (usize * Self);
}.

Arguments mkCounter_t { _ }.
Arguments Counter_t_incr { _ } _.

(** [demo::{impl demo::Counter for usize}::incr]:
    Source: 'tests/src/demo.rs', lines 105:4-109:5
    Visibility: public *)
Definition Usize_Insts_DemoCounter_incr
  (self : usize) : result (usize * usize) :=
  self1 <- usize_add self 1%usize; Ok (self, self1)
.

(** Trait implementation: [demo::{impl demo::Counter for usize}]
    Source: 'tests/src/demo.rs', lines 104:0-110:1 *)
Definition Usize_Insts_DemoCounter : Counter_t usize := {|
  Counter_t_incr := Usize_Insts_DemoCounter_incr;
|}.

(** [demo::use_counter]:
    Source: 'tests/src/demo.rs', lines 112:0-114:1
    Visibility: public *)
Definition use_counter
  {T : Type} (counterInst : Counter_t T) (cnt : T) : result (usize * T) :=
  counterInst.(Counter_t_incr) cnt
.

(** [demo::mod_add]:
    Source: 'tests/src/demo.rs', lines 117:0-125:1 *)
Definition mod_add (a : u32) (b : u32) : result u32 :=
  _ <- massert (a s< 3329%u32);
  _ <- massert (b s< 3329%u32);
  sum <- u32_add a b;
  res <- core_num_U32_wrapping_sub sum 3329%u32;
  mask <- u32_shr res 16%i32;
  let q := u32_and 3329%u32 mask in
  core_num_U32_wrapping_add res q
.

End Demo.
