-- THIS FILE WAS AUTOMATICALLY GENERATED BY AENEAS
-- [traits]
import Base
open Primitives

namespace traits

/- Trait declaration: [traits::BoolTrait] -/
structure BoolTrait (Self : Type) where
  get_bool : Self → Result Bool

/- [traits::Bool::{0}::get_bool]: forward function -/
def Bool.get_bool (self : Bool) : Result Bool :=
  Result.ret self

/- Trait implementation: [traits::Bool::{0}] -/
def Bool.BoolTraitInst : BoolTrait Bool := {
  get_bool := Bool.get_bool
}

/- [traits::BoolTrait::ret_true]: forward function -/
def BoolTrait.ret_true
  {Self : Type} (self_clause : BoolTrait Self) (self : Self) : Result Bool :=
  Result.ret true

/- [traits::test_bool_trait_bool]: forward function -/
def test_bool_trait_bool (x : Bool) : Result Bool :=
  do
    let b ← Bool.get_bool x
    if b
    then BoolTrait.ret_true Bool.BoolTraitInst x
    else Result.ret false

/- [traits::Option::{1}::get_bool]: forward function -/
def Option.get_bool (T : Type) (self : Option T) : Result Bool :=
  match self with
  | none => Result.ret false
  | some t => Result.ret true

/- Trait implementation: [traits::Option::{1}] -/
def Option.BoolTraitInst (T : Type) : BoolTrait (Option T) := {
  get_bool := Option.get_bool T
}

/- [traits::test_bool_trait_option]: forward function -/
def test_bool_trait_option (T : Type) (x : Option T) : Result Bool :=
  do
    let b ← Option.get_bool T x
    if b
    then BoolTrait.ret_true (Option.BoolTraitInst T) x
    else Result.ret false

/- [traits::test_bool_trait]: forward function -/
def test_bool_trait (T : Type) (inst : BoolTrait T) (x : T) : Result Bool :=
  inst.get_bool x

/- Trait declaration: [traits::ToU64] -/
structure ToU64 (Self : Type) where
  to_u64 : Self → Result U64

/- [traits::u64::{2}::to_u64]: forward function -/
def u64.to_u64 (self : U64) : Result U64 :=
  Result.ret self

/- Trait implementation: [traits::u64::{2}] -/
def u64.ToU64Inst : ToU64 U64 := {
  to_u64 := u64.to_u64
}

/- [traits::Tuple2::{3}::to_u64]: forward function -/
def Tuple2.to_u64 (A : Type) (inst : ToU64 A) (self : (A × A)) : Result U64 :=
  do
    let (t, t0) := self
    let i ← inst.to_u64 t
    let i0 ← inst.to_u64 t0
    i + i0

/- Trait implementation: [traits::Tuple2::{3}] -/
def Tuple2.ToU64Inst (A : Type) (inst : ToU64 A) : ToU64 (A × A) := {
  to_u64 := Tuple2.to_u64 A inst
}

/- [traits::f]: forward function -/
def f (T : Type) (inst : ToU64 T) (x : (T × T)) : Result U64 :=
  Tuple2.to_u64 T inst x

/- [traits::g]: forward function -/
def g (T : Type) (inst : ToU64 (T × T)) (x : (T × T)) : Result U64 :=
  inst.to_u64 x

/- [traits::h0]: forward function -/
def h0 (x : U64) : Result U64 :=
  u64.to_u64 x

/- [traits::Wrapper] -/
structure Wrapper (T : Type) where
  x : T

/- [traits::Wrapper::{4}::to_u64]: forward function -/
def Wrapper.to_u64
  (T : Type) (inst : ToU64 T) (self : Wrapper T) : Result U64 :=
  inst.to_u64 self.x

/- Trait implementation: [traits::Wrapper::{4}] -/
def Wrapper.ToU64Inst (T : Type) (inst : ToU64 T) : ToU64 (Wrapper T) := {
  to_u64 := Wrapper.to_u64 T inst
}

/- [traits::h1]: forward function -/
def h1 (x : Wrapper U64) : Result U64 :=
  Wrapper.to_u64 U64 u64.ToU64Inst x

/- [traits::h2]: forward function -/
def h2 (T : Type) (inst : ToU64 T) (x : Wrapper T) : Result U64 :=
  Wrapper.to_u64 T inst x

/- Trait declaration: [traits::ToType] -/
structure ToType (Self T : Type) where
  to_type : Self → Result T

/- [traits::u64::{5}::to_type]: forward function -/
def u64.to_type (self : U64) : Result Bool :=
  Result.ret (self > 0#u64)

/- Trait implementation: [traits::u64::{5}] -/
def u64.ToTypeInst : ToType U64 Bool := {
  to_type := u64.to_type
}

/- Trait declaration: [traits::OfType] -/
structure OfType (Self : Type) where
  of_type : forall (T : Type) (inst : ToType T Self), T → Result Self

/- [traits::h3]: forward function -/
def h3
  (T1 T2 : Type) (inst : OfType T1) (inst0 : ToType T2 T1) (y : T2) :
  Result T1
  :=
  inst.of_type T2 inst0 y

/- Trait declaration: [traits::OfTypeBis] -/
structure OfTypeBis (Self T : Type) where
  parent_clause_0 : ToType T Self
  of_type : T → Result Self

/- [traits::h4]: forward function -/
def h4
  (T1 T2 : Type) (inst : OfTypeBis T1 T2) (inst0 : ToType T2 T1) (y : T2) :
  Result T1
  :=
  inst.of_type y

/- [traits::TestType] -/
structure TestType (T : Type) where
  _0 : T

/- [traits::TestType::{6}::test::TestType1] -/
structure TestType.test.TestType1 where
  _0 : U64

/- Trait declaration: [traits::TestType::{6}::test::TestTrait] -/
structure TestType.test.TestTrait (Self : Type) where
  test : Self → Result Bool

/- [traits::TestType::{6}::test::TestType1::{0}::test]: forward function -/
def TestType.test.TestType1.test
  (self : TestType.test.TestType1) : Result Bool :=
  Result.ret (self._0 > 1#u64)

/- Trait implementation: [traits::TestType::{6}::test::TestType1::{0}] -/
def TestType.test.TestType1.TestTypetestTestTraitInst : TestType.test.TestTrait
  TestType.test.TestType1 := {
  test := TestType.test.TestType1.test
}

/- [traits::TestType::{6}::test]: forward function -/
def TestType.test
  (T : Type) (inst : ToU64 T) (self : TestType T) (x : T) : Result Bool :=
  do
    let x0 ← inst.to_u64 x
    if x0 > 0#u64
    then TestType.test.TestType1.test { _0 := 0#u64 }
    else Result.ret false

/- [traits::BoolWrapper] -/
structure BoolWrapper where
  _0 : Bool

/- [traits::BoolWrapper::{7}::to_type]: forward function -/
def BoolWrapper.to_type
  (T : Type) (inst : ToType Bool T) (self : BoolWrapper) : Result T :=
  inst.to_type self._0

/- Trait implementation: [traits::BoolWrapper::{7}] -/
def BoolWrapper.ToTypeInst (T : Type) (inst : ToType Bool T) : ToType
  BoolWrapper T := {
  to_type := BoolWrapper.to_type T inst
}

/- [traits::WithConstTy::LEN2] -/
def with_const_ty_len2_body : Result Usize := Result.ret 32#usize
def with_const_ty_len2_c : Usize :=
  eval_global with_const_ty_len2_body (by simp)

/- Trait declaration: [traits::WithConstTy] -/
structure WithConstTy (Self : Type) (LEN : Usize) where
  LEN1 : Usize
  LEN2 : Usize
  V : Type
  W : Type
  W_clause_0 : ToU64 W
  f : W → Array U8 LEN → Result W

/- [traits::Bool::{8}::LEN1] -/
def bool_len1_body : Result Usize := Result.ret 12#usize
def bool_len1_c : Usize := eval_global bool_len1_body (by simp)

/- [traits::Bool::{8}::f]: merged forward/backward function
   (there is a single backward function, and the forward function returns ()) -/
def Bool.f (i : U64) (a : Array U8 32#usize) : Result U64 :=
  Result.ret i

/- Trait implementation: [traits::Bool::{8}] -/
def Bool.WithConstTyInst : WithConstTy Bool 32#usize := {
  LEN1 := bool_len1_c
  LEN2 := with_const_ty_len2_c
  V := U8
  W := U64
  W_clause_0 := u64.ToU64Inst
  f := Bool.f
}

/- [traits::use_with_const_ty1]: forward function -/
def use_with_const_ty1
  (H : Type) (LEN : Usize) (inst : WithConstTy H LEN) : Result Usize :=
  let i := inst.LEN1
  Result.ret i

/- [traits::use_with_const_ty2]: forward function -/
def use_with_const_ty2
  (H : Type) (LEN : Usize) (inst : WithConstTy H LEN) (w : inst.W) :
  Result Unit
  :=
  Result.ret ()

/- [traits::use_with_const_ty3]: forward function -/
def use_with_const_ty3
  (H : Type) (LEN : Usize) (inst : WithConstTy H LEN) (x : inst.W) :
  Result U64
  :=
  inst.W_clause_0.to_u64 x

/- [traits::test_where1]: forward function -/
def test_where1 (T : Type) (_x : T) : Result Unit :=
  Result.ret ()

/- [traits::test_where2]: forward function -/
def test_where2
  (T : Type) (inst : WithConstTy T 32#usize) (_x : U32) : Result Unit :=
  Result.ret ()

/- [alloc::string::String] -/
axiom alloc.string.String : Type

/- Trait declaration: [traits::ParentTrait0] -/
structure ParentTrait0 (Self : Type) where
  W : Type
  get_name : Self → Result alloc.string.String
  get_w : Self → Result W

/- Trait declaration: [traits::ParentTrait1] -/
structure ParentTrait1 (Self : Type) where

/- Trait declaration: [traits::ChildTrait] -/
structure ChildTrait (Self : Type) where
  parent_clause_0 : ParentTrait0 Self
  parent_clause_1 : ParentTrait1 Self

/- [traits::test_child_trait1]: forward function -/
def test_child_trait1
  (T : Type) (inst : ChildTrait T) (x : T) : Result alloc.string.String :=
  inst.parent_clause_0.get_name x

/- [traits::test_child_trait2]: forward function -/
def test_child_trait2
  (T : Type) (inst : ChildTrait T) (x : T) : Result inst.parent_clause_0.W :=
  inst.parent_clause_0.get_w x

/- [traits::order1]: forward function -/
def order1
  (T U : Type) (inst : ParentTrait0 T) (inst0 : ParentTrait0 U) :
  Result Unit
  :=
  Result.ret ()

/- Trait declaration: [traits::ChildTrait1] -/
structure ChildTrait1 (Self : Type) where
  parent_clause_0 : ParentTrait1 Self

/- Trait implementation: [traits::usize::{9}] -/
def usize.ParentTrait1Inst : ParentTrait1 Usize := {
}

/- Trait implementation: [traits::usize::{10}] -/
def usize.ChildTrait1Inst : ChildTrait1 Usize := {
  parent_clause_0 := usize.ParentTrait1Inst
}

/- Trait declaration: [traits::Iterator] -/
structure Iterator (Self : Type) where
  Item : Type

/- Trait declaration: [traits::IntoIterator] -/
structure IntoIterator (Self : Type) where
  Item : Type
  IntoIter : Type
  IntoIter_clause_0 : Iterator IntoIter
  into_iter : Self → Result IntoIter

/- Trait declaration: [traits::FromResidual] -/
structure FromResidual (Self T : Type) where

/- Trait declaration: [traits::Try] -/
structure Try (Self : Type) where
  parent_clause_0 : FromResidual Self Residual
  Residual : Type

/- Trait declaration: [traits::CFnOnce] -/
structure CFnOnce (Self Args : Type) where
  Output : Type
  call_once : Self → Args → Result Output

/- Trait declaration: [traits::CFnMut] -/
structure CFnMut (Self Args : Type) where
  parent_clause_0 : CFnOnce Self Args
  call_mut : Self → Args → Result parent_clause_0.Output
  call_mut_back : Self → Args → parent_clause_0.Output → Result Self

/- Trait declaration: [traits::CFn] -/
structure CFn (Self Args : Type) where
  parent_clause_0 : CFnMut Self Args
  call_mut : Self → Args → Result parent_clause_0.parent_clause_0.Output

/- Trait declaration: [core::ops::function::FnOnce] -/
structure core.ops.function.FnOnce (Self Args : Type) where
  Output : Type
  call_once : Self → Args → Result Output

/- Trait declaration: [core::ops::function::FnMut] -/
structure core.ops.function.FnMut (Self Args : Type) where
  parent_clause_0 : core.ops.function.FnOnce Self Args
  call_mut : Self → Args → Result parent_clause_0.Output
  call_mut_back : Self → Args → parent_clause_0.Output → Result Self

/- Trait declaration: [core::ops::function::Fn] -/
structure core.ops.function.Fn (Self Args : Type) where
  parent_clause_0 : core.ops.function.FnMut Self Args
  call : Self → Args → Result parent_clause_0.parent_clause_0.Output

/- [traits::map_option]: forward function -/
def map_option
  (T F : Type) (inst : core.ops.function.Fn F T) (x : Option T) (f0 : F) :
  Result (Option T)
  :=
  match x with
  | none => Result.ret none
  | some x0 => do
                 let t ← inst.call f0 x0
                 Result.ret (some t)

/- Trait declaration: [traits::WithTarget] -/
structure WithTarget (Self : Type) where
  Target : Type

/- Trait declaration: [traits::ParentTrait2] -/
structure ParentTrait2 (Self : Type) where
  U : Type
  U_clause_0 : WithTarget U

/- Trait declaration: [traits::ChildTrait2] -/
structure ChildTrait2 (Self : Type) where
  parent_clause_0 : ParentTrait2 Self
  convert : parent_clause_0.U → Result parent_clause_0.U_clause_0.Target

/- Trait implementation: [traits::u32::{11}] -/
def u32.WithTargetInst : WithTarget U32 := {
  Target := U32
}

/- Trait implementation: [traits::u32::{12}] -/
def u32.ParentTrait2Inst : ParentTrait2 U32 := {
  U := U32
  U_clause_0 := u32.WithTargetInst
}

/- [traits::u32::{13}::convert]: forward function -/
def u32.convert (x : U32) : Result U32 :=
  Result.ret x

/- Trait implementation: [traits::u32::{13}] -/
def u32.ChildTrait2Inst : ChildTrait2 U32 := {
  parent_clause_0 := u32.ParentTrait2Inst
  convert := u32.convert
}

/- [traits::incr_u32]: forward function -/
def incr_u32 (x : U32) : Result U32 :=
  x + 1#u32

end traits
