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

(*
fn id(x: u64) -> u64 {
    x
}
*)
Definition id (ε : list Value.t) (τ : list Ty.t) (α : list Value.t) : M :=
  match ε, τ, α with
  | [], [], [ x ] =>
    ltac:(M.monadic
      (let x := M.alloc (| x |) in
      M.read (| x |)))
  | _, _, _ => M.impossible "wrong number of arguments"
  end.

Axiom Function_id : M.IsFunction "example01::id" id.

(* fn tri(a: u64, b: u64, c: u64) {} *)
Definition tri (ε : list Value.t) (τ : list Ty.t) (α : list Value.t) : M :=
  match ε, τ, α with
  | [], [], [ a; b; c ] =>
    ltac:(M.monadic
      (let a := M.alloc (| a |) in
      let b := M.alloc (| b |) in
      let c := M.alloc (| c |) in
      Value.Tuple []))
  | _, _, _ => M.impossible "wrong number of arguments"
  end.

Axiom Function_tri : M.IsFunction "example01::tri" tri.

(*
fn main() {
    id(0);
    id(id(0));
    id(id(id(0)));
    id(id(id(id(0))));
    tri(id(1), id(2), 3);
}
*)
Definition main (ε : list Value.t) (τ : list Ty.t) (α : list Value.t) : M :=
  match ε, τ, α with
  | [], [], [] =>
    ltac:(M.monadic
      (M.read (|
        let~ _ :=
          M.alloc (|
            M.call_closure (|
              M.get_function (| "example01::id", [] |),
              [ Value.Integer IntegerKind.U64 0 ]
            |)
          |) in
        let~ _ :=
          M.alloc (|
            M.call_closure (|
              M.get_function (| "example01::id", [] |),
              [
                M.call_closure (|
                  M.get_function (| "example01::id", [] |),
                  [ Value.Integer IntegerKind.U64 0 ]
                |)
              ]
            |)
          |) in
        let~ _ :=
          M.alloc (|
            M.call_closure (|
              M.get_function (| "example01::id", [] |),
              [
                M.call_closure (|
                  M.get_function (| "example01::id", [] |),
                  [
                    M.call_closure (|
                      M.get_function (| "example01::id", [] |),
                      [ Value.Integer IntegerKind.U64 0 ]
                    |)
                  ]
                |)
              ]
            |)
          |) in
        let~ _ :=
          M.alloc (|
            M.call_closure (|
              M.get_function (| "example01::id", [] |),
              [
                M.call_closure (|
                  M.get_function (| "example01::id", [] |),
                  [
                    M.call_closure (|
                      M.get_function (| "example01::id", [] |),
                      [
                        M.call_closure (|
                          M.get_function (| "example01::id", [] |),
                          [ Value.Integer IntegerKind.U64 0 ]
                        |)
                      ]
                    |)
                  ]
                |)
              ]
            |)
          |) in
        let~ _ :=
          M.alloc (|
            M.call_closure (|
              M.get_function (| "example01::tri", [] |),
              [
                M.call_closure (|
                  M.get_function (| "example01::id", [] |),
                  [ Value.Integer IntegerKind.U64 1 ]
                |);
                M.call_closure (|
                  M.get_function (| "example01::id", [] |),
                  [ Value.Integer IntegerKind.U64 2 ]
                |);
                Value.Integer IntegerKind.U64 3
              ]
            |)
          |) in
        M.alloc (| Value.Tuple [] |)
      |)))
  | _, _, _ => M.impossible "wrong number of arguments"
  end.

Axiom Function_main : M.IsFunction "example01::main" main.
