File: .lake/packages/lean4/src/lean/Lean/Compiler/IR/Basic.lean

full_name: Lean.IR.FunId
code: /-- Function identifier -/
abbrev FunId 
goal: Type

full_name: Lean.IR.Index
code: abbrev Index 
goal: Type

full_name: Lean.IR.VarId.idx
code: /-- Variable identifier -/
structure VarId where
  idx : Index
  deriving Inhabited, Repr
goal: Lean.IR.Index

full_name: Lean.IR.instInhabitedVarId
code: /-- Variable identifier -/
structure VarId where
  idx : Index
  deriving Inhabited, Repr
goal: Inhabited Lean.IR.VarId

full_name: Lean.IR.instReprVarId
code: /-- Variable identifier -/
structure VarId where
  idx : Index
  deriving Inhabited, Repr
goal: Repr Lean.IR.VarId

full_name: Lean.IR.VarId
code: /-- Variable identifier -/
structure VarId where
  idx : Index
  deriving Inhabited, Repr
goal: Type

full_name: Lean.IR.JoinPointId
code: /-- Join point identifier -/
structure JoinPointId where
  idx : Index
  deriving Inhabited, Repr
goal: Type

full_name: Lean.IR.JoinPointId.idx
code: /-- Join point identifier -/
structure JoinPointId where
  idx : Index
  deriving Inhabited, Repr
goal: Lean.IR.Index

full_name: Lean.IR.instReprJoinPointId
code: /-- Join point identifier -/
structure JoinPointId where
  idx : Index
  deriving Inhabited, Repr
goal: Repr Lean.IR.JoinPointId

full_name: Lean.IR.instInhabitedJoinPointId
code: /-- Join point identifier -/
structure JoinPointId where
  idx : Index
  deriving Inhabited, Repr
goal: Inhabited Lean.IR.JoinPointId

full_name: Lean.IR.Index.lt
code: abbrev Index.lt (a b : Index) : Bool 
goal: Bool

full_name: Lean.IR.instBEqVarId
code: instance : BEq VarId 
goal: BEq Lean.IR.VarId

full_name: Lean.IR.instToStringVarId
code: instance : ToString VarId 
goal: ToString Lean.IR.VarId

full_name: Lean.IR.instToFormatVarId
code: instance : ToFormat VarId 
goal: Lean.ToFormat Lean.IR.VarId

full_name: Lean.IR.instHashableVarId
code: instance : Hashable VarId 
goal: Hashable Lean.IR.VarId

full_name: Lean.IR.instBEqJoinPointId
code: instance : BEq JoinPointId 
goal: BEq Lean.IR.JoinPointId

full_name: Lean.IR.instToStringJoinPointId
code: instance : ToString JoinPointId 
goal: ToString Lean.IR.JoinPointId

full_name: Lean.IR.instToFormatJoinPointId
code: instance : ToFormat JoinPointId 
goal: Lean.ToFormat Lean.IR.JoinPointId

full_name: Lean.IR.instHashableJoinPointId
code: instance : Hashable JoinPointId 
goal: Hashable Lean.IR.JoinPointId

full_name: Lean.IR.MData
code: abbrev MData 
goal: Type

full_name: Lean.IR.MData.empty
code: abbrev MData.empty : MData 
goal: Lean.IR.MData

full_name: Lean.IR.IRType.tobject
code: /-- Low Level IR types. Most are self explanatory.

   - `usize` represents the C++ `size_t` Type. We have it here
      because it is 32-bit in 32-bit machines, and 64-bit in 64-bit machines,
      and we want the C++ backend for our Compiler to generate platform independent code.

   - `irrelevant` for Lean types, propositions and proofs.

   - `object` a pointer to a value in the heap.

   - `tobject` a pointer to a value in the heap or tagged pointer
      (i.e., the least significant bit is 1) storing a scalar value.

   - `struct` and `union` are used to return small values (e.g., `Option`, `Prod`, `Except`)
      on the stack.

Remark: the RC operations for `tobject` are slightly more expensive because we
first need to test whether the `tobject` is really a pointer or not.

Remark: the Lean runtime assumes that sizeof(void*) == sizeof(sizeT).
Lean cannot be compiled on old platforms where this is not True.

Since values of type `struct` and `union` are only used to return values,
We assume they must be used/consumed "linearly". We use the term "linear" here
to mean "exactly once" in each execution. That is, given `x : S`, where `S` is a struct,
then one of the following must hold in each (execution) branch.
1- `x` occurs only at a single `ret x` instruction. That is, it is being consumed by being returned.
2- `x` occurs only at a single `ctor`. That is, it is being "consumed" by being stored into another `struct/union`.
3- We extract (aka project) every single field of `x` exactly once. That is, we are consuming `x` by consuming each
   of one of its components. Minor refinement: we don't need to consume scalar fields or struct/union
   fields that do not contain object fields.
-/
inductive IRType where
  | float | uint8 | uint16 | uint32 | uint64 | usize
  | irrelevant | object | tobject
  | struct (leanTypeName : Option Name) (types : Array IRType) : IRType
  | union (leanTypeName : Name) (types : Array IRType) : IRType
  deriving Inhabited, Repr
goal: Lean.IR.IRType

full_name: Lean.IR.IRType.uint32
code: /-- Low Level IR types. Most are self explanatory.

   - `usize` represents the C++ `size_t` Type. We have it here
      because it is 32-bit in 32-bit machines, and 64-bit in 64-bit machines,
      and we want the C++ backend for our Compiler to generate platform independent code.

   - `irrelevant` for Lean types, propositions and proofs.

   - `object` a pointer to a value in the heap.

   - `tobject` a pointer to a value in the heap or tagged pointer
      (i.e., the least significant bit is 1) storing a scalar value.

   - `struct` and `union` are used to return small values (e.g., `Option`, `Prod`, `Except`)
      on the stack.

Remark: the RC operations for `tobject` are slightly more expensive because we
first need to test whether the `tobject` is really a pointer or not.

Remark: the Lean runtime assumes that sizeof(void*) == sizeof(sizeT).
Lean cannot be compiled on old platforms where this is not True.

Since values of type `struct` and `union` are only used to return values,
We assume they must be used/consumed "linearly". We use the term "linear" here
to mean "exactly once" in each execution. That is, given `x : S`, where `S` is a struct,
then one of the following must hold in each (execution) branch.
1- `x` occurs only at a single `ret x` instruction. That is, it is being consumed by being returned.
2- `x` occurs only at a single `ctor`. That is, it is being "consumed" by being stored into another `struct/union`.
3- We extract (aka project) every single field of `x` exactly once. That is, we are consuming `x` by consuming each
   of one of its components. Minor refinement: we don't need to consume scalar fields or struct/union
   fields that do not contain object fields.
-/
inductive IRType where
  | float | uint8 | uint16 | uint32 | uint64 | usize
  | irrelevant | object | tobject
  | struct (leanTypeName : Option Name) (types : Array IRType) : IRType
  | union (leanTypeName : Name) (types : Array IRType) : IRType
  deriving Inhabited, Repr
goal: Lean.IR.IRType

full_name: Lean.IR.IRType.irrelevant
code: /-- Low Level IR types. Most are self explanatory.

   - `usize` represents the C++ `size_t` Type. We have it here
      because it is 32-bit in 32-bit machines, and 64-bit in 64-bit machines,
      and we want the C++ backend for our Compiler to generate platform independent code.

   - `irrelevant` for Lean types, propositions and proofs.

   - `object` a pointer to a value in the heap.

   - `tobject` a pointer to a value in the heap or tagged pointer
      (i.e., the least significant bit is 1) storing a scalar value.

   - `struct` and `union` are used to return small values (e.g., `Option`, `Prod`, `Except`)
      on the stack.

Remark: the RC operations for `tobject` are slightly more expensive because we
first need to test whether the `tobject` is really a pointer or not.

Remark: the Lean runtime assumes that sizeof(void*) == sizeof(sizeT).
Lean cannot be compiled on old platforms where this is not True.

Since values of type `struct` and `union` are only used to return values,
We assume they must be used/consumed "linearly". We use the term "linear" here
to mean "exactly once" in each execution. That is, given `x : S`, where `S` is a struct,
then one of the following must hold in each (execution) branch.
1- `x` occurs only at a single `ret x` instruction. That is, it is being consumed by being returned.
2- `x` occurs only at a single `ctor`. That is, it is being "consumed" by being stored into another `struct/union`.
3- We extract (aka project) every single field of `x` exactly once. That is, we are consuming `x` by consuming each
   of one of its components. Minor refinement: we don't need to consume scalar fields or struct/union
   fields that do not contain object fields.
-/
inductive IRType where
  | float | uint8 | uint16 | uint32 | uint64 | usize
  | irrelevant | object | tobject
  | struct (leanTypeName : Option Name) (types : Array IRType) : IRType
  | union (leanTypeName : Name) (types : Array IRType) : IRType
  deriving Inhabited, Repr
goal: Lean.IR.IRType

full_name: Lean.IR.IRType.struct
code: /-- Low Level IR types. Most are self explanatory.

   - `usize` represents the C++ `size_t` Type. We have it here
      because it is 32-bit in 32-bit machines, and 64-bit in 64-bit machines,
      and we want the C++ backend for our Compiler to generate platform independent code.

   - `irrelevant` for Lean types, propositions and proofs.

   - `object` a pointer to a value in the heap.

   - `tobject` a pointer to a value in the heap or tagged pointer
      (i.e., the least significant bit is 1) storing a scalar value.

   - `struct` and `union` are used to return small values (e.g., `Option`, `Prod`, `Except`)
      on the stack.

Remark: the RC operations for `tobject` are slightly more expensive because we
first need to test whether the `tobject` is really a pointer or not.

Remark: the Lean runtime assumes that sizeof(void*) == sizeof(sizeT).
Lean cannot be compiled on old platforms where this is not True.

Since values of type `struct` and `union` are only used to return values,
We assume they must be used/consumed "linearly". We use the term "linear" here
to mean "exactly once" in each execution. That is, given `x : S`, where `S` is a struct,
then one of the following must hold in each (execution) branch.
1- `x` occurs only at a single `ret x` instruction. That is, it is being consumed by being returned.
2- `x` occurs only at a single `ctor`. That is, it is being "consumed" by being stored into another `struct/union`.
3- We extract (aka project) every single field of `x` exactly once. That is, we are consuming `x` by consuming each
   of one of its components. Minor refinement: we don't need to consume scalar fields or struct/union
   fields that do not contain object fields.
-/
inductive IRType where
  | float | uint8 | uint16 | uint32 | uint64 | usize
  | irrelevant | object | tobject
  | struct (leanTypeName : Option Name) (types : Array IRType) : IRType
  | union (leanTypeName : Name) (types : Array IRType) : IRType
  deriving Inhabited, Repr
goal: Lean.IR.IRType

full_name: Lean.IR.IRType.float
code: /-- Low Level IR types. Most are self explanatory.

   - `usize` represents the C++ `size_t` Type. We have it here
      because it is 32-bit in 32-bit machines, and 64-bit in 64-bit machines,
      and we want the C++ backend for our Compiler to generate platform independent code.

   - `irrelevant` for Lean types, propositions and proofs.

   - `object` a pointer to a value in the heap.

   - `tobject` a pointer to a value in the heap or tagged pointer
      (i.e., the least significant bit is 1) storing a scalar value.

   - `struct` and `union` are used to return small values (e.g., `Option`, `Prod`, `Except`)
      on the stack.

Remark: the RC operations for `tobject` are slightly more expensive because we
first need to test whether the `tobject` is really a pointer or not.

Remark: the Lean runtime assumes that sizeof(void*) == sizeof(sizeT).
Lean cannot be compiled on old platforms where this is not True.

Since values of type `struct` and `union` are only used to return values,
We assume they must be used/consumed "linearly". We use the term "linear" here
to mean "exactly once" in each execution. That is, given `x : S`, where `S` is a struct,
then one of the following must hold in each (execution) branch.
1- `x` occurs only at a single `ret x` instruction. That is, it is being consumed by being returned.
2- `x` occurs only at a single `ctor`. That is, it is being "consumed" by being stored into another `struct/union`.
3- We extract (aka project) every single field of `x` exactly once. That is, we are consuming `x` by consuming each
   of one of its components. Minor refinement: we don't need to consume scalar fields or struct/union
   fields that do not contain object fields.
-/
inductive IRType where
  | float | uint8 | uint16 | uint32 | uint64 | usize
  | irrelevant | object | tobject
  | struct (leanTypeName : Option Name) (types : Array IRType) : IRType
  | union (leanTypeName : Name) (types : Array IRType) : IRType
  deriving Inhabited, Repr
goal: Lean.IR.IRType

full_name: Lean.IR.IRType.usize
code: /-- Low Level IR types. Most are self explanatory.

   - `usize` represents the C++ `size_t` Type. We have it here
      because it is 32-bit in 32-bit machines, and 64-bit in 64-bit machines,
      and we want the C++ backend for our Compiler to generate platform independent code.

   - `irrelevant` for Lean types, propositions and proofs.

   - `object` a pointer to a value in the heap.

   - `tobject` a pointer to a value in the heap or tagged pointer
      (i.e., the least significant bit is 1) storing a scalar value.

   - `struct` and `union` are used to return small values (e.g., `Option`, `Prod`, `Except`)
      on the stack.

Remark: the RC operations for `tobject` are slightly more expensive because we
first need to test whether the `tobject` is really a pointer or not.

Remark: the Lean runtime assumes that sizeof(void*) == sizeof(sizeT).
Lean cannot be compiled on old platforms where this is not True.

Since values of type `struct` and `union` are only used to return values,
We assume they must be used/consumed "linearly". We use the term "linear" here
to mean "exactly once" in each execution. That is, given `x : S`, where `S` is a struct,
then one of the following must hold in each (execution) branch.
1- `x` occurs only at a single `ret x` instruction. That is, it is being consumed by being returned.
2- `x` occurs only at a single `ctor`. That is, it is being "consumed" by being stored into another `struct/union`.
3- We extract (aka project) every single field of `x` exactly once. That is, we are consuming `x` by consuming each
   of one of its components. Minor refinement: we don't need to consume scalar fields or struct/union
   fields that do not contain object fields.
-/
inductive IRType where
  | float | uint8 | uint16 | uint32 | uint64 | usize
  | irrelevant | object | tobject
  | struct (leanTypeName : Option Name) (types : Array IRType) : IRType
  | union (leanTypeName : Name) (types : Array IRType) : IRType
  deriving Inhabited, Repr
goal: Lean.IR.IRType

full_name: Lean.IR.instInhabitedIRType
code: /-- Low Level IR types. Most are self explanatory.

   - `usize` represents the C++ `size_t` Type. We have it here
      because it is 32-bit in 32-bit machines, and 64-bit in 64-bit machines,
      and we want the C++ backend for our Compiler to generate platform independent code.

   - `irrelevant` for Lean types, propositions and proofs.

   - `object` a pointer to a value in the heap.

   - `tobject` a pointer to a value in the heap or tagged pointer
      (i.e., the least significant bit is 1) storing a scalar value.

   - `struct` and `union` are used to return small values (e.g., `Option`, `Prod`, `Except`)
      on the stack.

Remark: the RC operations for `tobject` are slightly more expensive because we
first need to test whether the `tobject` is really a pointer or not.

Remark: the Lean runtime assumes that sizeof(void*) == sizeof(sizeT).
Lean cannot be compiled on old platforms where this is not True.

Since values of type `struct` and `union` are only used to return values,
We assume they must be used/consumed "linearly". We use the term "linear" here
to mean "exactly once" in each execution. That is, given `x : S`, where `S` is a struct,
then one of the following must hold in each (execution) branch.
1- `x` occurs only at a single `ret x` instruction. That is, it is being consumed by being returned.
2- `x` occurs only at a single `ctor`. That is, it is being "consumed" by being stored into another `struct/union`.
3- We extract (aka project) every single field of `x` exactly once. That is, we are consuming `x` by consuming each
   of one of its components. Minor refinement: we don't need to consume scalar fields or struct/union
   fields that do not contain object fields.
-/
inductive IRType where
  | float | uint8 | uint16 | uint32 | uint64 | usize
  | irrelevant | object | tobject
  | struct (leanTypeName : Option Name) (types : Array IRType) : IRType
  | union (leanTypeName : Name) (types : Array IRType) : IRType
  deriving Inhabited, Repr
goal: Inhabited Lean.IR.IRType

full_name: Lean.IR.IRType.union
code: /-- Low Level IR types. Most are self explanatory.

   - `usize` represents the C++ `size_t` Type. We have it here
      because it is 32-bit in 32-bit machines, and 64-bit in 64-bit machines,
      and we want the C++ backend for our Compiler to generate platform independent code.

   - `irrelevant` for Lean types, propositions and proofs.

   - `object` a pointer to a value in the heap.

   - `tobject` a pointer to a value in the heap or tagged pointer
      (i.e., the least significant bit is 1) storing a scalar value.

   - `struct` and `union` are used to return small values (e.g., `Option`, `Prod`, `Except`)
      on the stack.

Remark: the RC operations for `tobject` are slightly more expensive because we
first need to test whether the `tobject` is really a pointer or not.

Remark: the Lean runtime assumes that sizeof(void*) == sizeof(sizeT).
Lean cannot be compiled on old platforms where this is not True.

Since values of type `struct` and `union` are only used to return values,
We assume they must be used/consumed "linearly". We use the term "linear" here
to mean "exactly once" in each execution. That is, given `x : S`, where `S` is a struct,
then one of the following must hold in each (execution) branch.
1- `x` occurs only at a single `ret x` instruction. That is, it is being consumed by being returned.
2- `x` occurs only at a single `ctor`. That is, it is being "consumed" by being stored into another `struct/union`.
3- We extract (aka project) every single field of `x` exactly once. That is, we are consuming `x` by consuming each
   of one of its components. Minor refinement: we don't need to consume scalar fields or struct/union
   fields that do not contain object fields.
-/
inductive IRType where
  | float | uint8 | uint16 | uint32 | uint64 | usize
  | irrelevant | object | tobject
  | struct (leanTypeName : Option Name) (types : Array IRType) : IRType
  | union (leanTypeName : Name) (types : Array IRType) : IRType
  deriving Inhabited, Repr
goal: Lean.IR.IRType

full_name: Lean.IR.IRType.uint16
code: /-- Low Level IR types. Most are self explanatory.

   - `usize` represents the C++ `size_t` Type. We have it here
      because it is 32-bit in 32-bit machines, and 64-bit in 64-bit machines,
      and we want the C++ backend for our Compiler to generate platform independent code.

   - `irrelevant` for Lean types, propositions and proofs.

   - `object` a pointer to a value in the heap.

   - `tobject` a pointer to a value in the heap or tagged pointer
      (i.e., the least significant bit is 1) storing a scalar value.

   - `struct` and `union` are used to return small values (e.g., `Option`, `Prod`, `Except`)
      on the stack.

Remark: the RC operations for `tobject` are slightly more expensive because we
first need to test whether the `tobject` is really a pointer or not.

Remark: the Lean runtime assumes that sizeof(void*) == sizeof(sizeT).
Lean cannot be compiled on old platforms where this is not True.

Since values of type `struct` and `union` are only used to return values,
We assume they must be used/consumed "linearly". We use the term "linear" here
to mean "exactly once" in each execution. That is, given `x : S`, where `S` is a struct,
then one of the following must hold in each (execution) branch.
1- `x` occurs only at a single `ret x` instruction. That is, it is being consumed by being returned.
2- `x` occurs only at a single `ctor`. That is, it is being "consumed" by being stored into another `struct/union`.
3- We extract (aka project) every single field of `x` exactly once. That is, we are consuming `x` by consuming each
   of one of its components. Minor refinement: we don't need to consume scalar fields or struct/union
   fields that do not contain object fields.
-/
inductive IRType where
  | float | uint8 | uint16 | uint32 | uint64 | usize
  | irrelevant | object | tobject
  | struct (leanTypeName : Option Name) (types : Array IRType) : IRType
  | union (leanTypeName : Name) (types : Array IRType) : IRType
  deriving Inhabited, Repr
goal: Lean.IR.IRType

full_name: Lean.IR.instReprIRType
code: /-- Low Level IR types. Most are self explanatory.

   - `usize` represents the C++ `size_t` Type. We have it here
      because it is 32-bit in 32-bit machines, and 64-bit in 64-bit machines,
      and we want the C++ backend for our Compiler to generate platform independent code.

   - `irrelevant` for Lean types, propositions and proofs.

   - `object` a pointer to a value in the heap.

   - `tobject` a pointer to a value in the heap or tagged pointer
      (i.e., the least significant bit is 1) storing a scalar value.

   - `struct` and `union` are used to return small values (e.g., `Option`, `Prod`, `Except`)
      on the stack.

Remark: the RC operations for `tobject` are slightly more expensive because we
first need to test whether the `tobject` is really a pointer or not.

Remark: the Lean runtime assumes that sizeof(void*) == sizeof(sizeT).
Lean cannot be compiled on old platforms where this is not True.

Since values of type `struct` and `union` are only used to return values,
We assume they must be used/consumed "linearly". We use the term "linear" here
to mean "exactly once" in each execution. That is, given `x : S`, where `S` is a struct,
then one of the following must hold in each (execution) branch.
1- `x` occurs only at a single `ret x` instruction. That is, it is being consumed by being returned.
2- `x` occurs only at a single `ctor`. That is, it is being "consumed" by being stored into another `struct/union`.
3- We extract (aka project) every single field of `x` exactly once. That is, we are consuming `x` by consuming each
   of one of its components. Minor refinement: we don't need to consume scalar fields or struct/union
   fields that do not contain object fields.
-/
inductive IRType where
  | float | uint8 | uint16 | uint32 | uint64 | usize
  | irrelevant | object | tobject
  | struct (leanTypeName : Option Name) (types : Array IRType) : IRType
  | union (leanTypeName : Name) (types : Array IRType) : IRType
  deriving Inhabited, Repr
goal: Repr Lean.IR.IRType

full_name: Lean.IR.IRType.uint64
code: /-- Low Level IR types. Most are self explanatory.

   - `usize` represents the C++ `size_t` Type. We have it here
      because it is 32-bit in 32-bit machines, and 64-bit in 64-bit machines,
      and we want the C++ backend for our Compiler to generate platform independent code.

   - `irrelevant` for Lean types, propositions and proofs.

   - `object` a pointer to a value in the heap.

   - `tobject` a pointer to a value in the heap or tagged pointer
      (i.e., the least significant bit is 1) storing a scalar value.

   - `struct` and `union` are used to return small values (e.g., `Option`, `Prod`, `Except`)
      on the stack.

Remark: the RC operations for `tobject` are slightly more expensive because we
first need to test whether the `tobject` is really a pointer or not.

Remark: the Lean runtime assumes that sizeof(void*) == sizeof(sizeT).
Lean cannot be compiled on old platforms where this is not True.

Since values of type `struct` and `union` are only used to return values,
We assume they must be used/consumed "linearly". We use the term "linear" here
to mean "exactly once" in each execution. That is, given `x : S`, where `S` is a struct,
then one of the following must hold in each (execution) branch.
1- `x` occurs only at a single `ret x` instruction. That is, it is being consumed by being returned.
2- `x` occurs only at a single `ctor`. That is, it is being "consumed" by being stored into another `struct/union`.
3- We extract (aka project) every single field of `x` exactly once. That is, we are consuming `x` by consuming each
   of one of its components. Minor refinement: we don't need to consume scalar fields or struct/union
   fields that do not contain object fields.
-/
inductive IRType where
  | float | uint8 | uint16 | uint32 | uint64 | usize
  | irrelevant | object | tobject
  | struct (leanTypeName : Option Name) (types : Array IRType) : IRType
  | union (leanTypeName : Name) (types : Array IRType) : IRType
  deriving Inhabited, Repr
goal: Lean.IR.IRType

full_name: Lean.IR.IRType.object
code: /-- Low Level IR types. Most are self explanatory.

   - `usize` represents the C++ `size_t` Type. We have it here
      because it is 32-bit in 32-bit machines, and 64-bit in 64-bit machines,
      and we want the C++ backend for our Compiler to generate platform independent code.

   - `irrelevant` for Lean types, propositions and proofs.

   - `object` a pointer to a value in the heap.

   - `tobject` a pointer to a value in the heap or tagged pointer
      (i.e., the least significant bit is 1) storing a scalar value.

   - `struct` and `union` are used to return small values (e.g., `Option`, `Prod`, `Except`)
      on the stack.

Remark: the RC operations for `tobject` are slightly more expensive because we
first need to test whether the `tobject` is really a pointer or not.

Remark: the Lean runtime assumes that sizeof(void*) == sizeof(sizeT).
Lean cannot be compiled on old platforms where this is not True.

Since values of type `struct` and `union` are only used to return values,
We assume they must be used/consumed "linearly". We use the term "linear" here
to mean "exactly once" in each execution. That is, given `x : S`, where `S` is a struct,
then one of the following must hold in each (execution) branch.
1- `x` occurs only at a single `ret x` instruction. That is, it is being consumed by being returned.
2- `x` occurs only at a single `ctor`. That is, it is being "consumed" by being stored into another `struct/union`.
3- We extract (aka project) every single field of `x` exactly once. That is, we are consuming `x` by consuming each
   of one of its components. Minor refinement: we don't need to consume scalar fields or struct/union
   fields that do not contain object fields.
-/
inductive IRType where
  | float | uint8 | uint16 | uint32 | uint64 | usize
  | irrelevant | object | tobject
  | struct (leanTypeName : Option Name) (types : Array IRType) : IRType
  | union (leanTypeName : Name) (types : Array IRType) : IRType
  deriving Inhabited, Repr
goal: Lean.IR.IRType

full_name: Lean.IR.IRType.uint8
code: /-- Low Level IR types. Most are self explanatory.

   - `usize` represents the C++ `size_t` Type. We have it here
      because it is 32-bit in 32-bit machines, and 64-bit in 64-bit machines,
      and we want the C++ backend for our Compiler to generate platform independent code.

   - `irrelevant` for Lean types, propositions and proofs.

   - `object` a pointer to a value in the heap.

   - `tobject` a pointer to a value in the heap or tagged pointer
      (i.e., the least significant bit is 1) storing a scalar value.

   - `struct` and `union` are used to return small values (e.g., `Option`, `Prod`, `Except`)
      on the stack.

Remark: the RC operations for `tobject` are slightly more expensive because we
first need to test whether the `tobject` is really a pointer or not.

Remark: the Lean runtime assumes that sizeof(void*) == sizeof(sizeT).
Lean cannot be compiled on old platforms where this is not True.

Since values of type `struct` and `union` are only used to return values,
We assume they must be used/consumed "linearly". We use the term "linear" here
to mean "exactly once" in each execution. That is, given `x : S`, where `S` is a struct,
then one of the following must hold in each (execution) branch.
1- `x` occurs only at a single `ret x` instruction. That is, it is being consumed by being returned.
2- `x` occurs only at a single `ctor`. That is, it is being "consumed" by being stored into another `struct/union`.
3- We extract (aka project) every single field of `x` exactly once. That is, we are consuming `x` by consuming each
   of one of its components. Minor refinement: we don't need to consume scalar fields or struct/union
   fields that do not contain object fields.
-/
inductive IRType where
  | float | uint8 | uint16 | uint32 | uint64 | usize
  | irrelevant | object | tobject
  | struct (leanTypeName : Option Name) (types : Array IRType) : IRType
  | union (leanTypeName : Name) (types : Array IRType) : IRType
  deriving Inhabited, Repr
goal: Lean.IR.IRType

full_name: Lean.IR.IRType
code: /-- Low Level IR types. Most are self explanatory.

   - `usize` represents the C++ `size_t` Type. We have it here
      because it is 32-bit in 32-bit machines, and 64-bit in 64-bit machines,
      and we want the C++ backend for our Compiler to generate platform independent code.

   - `irrelevant` for Lean types, propositions and proofs.

   - `object` a pointer to a value in the heap.

   - `tobject` a pointer to a value in the heap or tagged pointer
      (i.e., the least significant bit is 1) storing a scalar value.

   - `struct` and `union` are used to return small values (e.g., `Option`, `Prod`, `Except`)
      on the stack.

Remark: the RC operations for `tobject` are slightly more expensive because we
first need to test whether the `tobject` is really a pointer or not.

Remark: the Lean runtime assumes that sizeof(void*) == sizeof(sizeT).
Lean cannot be compiled on old platforms where this is not True.

Since values of type `struct` and `union` are only used to return values,
We assume they must be used/consumed "linearly". We use the term "linear" here
to mean "exactly once" in each execution. That is, given `x : S`, where `S` is a struct,
then one of the following must hold in each (execution) branch.
1- `x` occurs only at a single `ret x` instruction. That is, it is being consumed by being returned.
2- `x` occurs only at a single `ctor`. That is, it is being "consumed" by being stored into another `struct/union`.
3- We extract (aka project) every single field of `x` exactly once. That is, we are consuming `x` by consuming each
   of one of its components. Minor refinement: we don't need to consume scalar fields or struct/union
   fields that do not contain object fields.
-/
inductive IRType where
  | float | uint8 | uint16 | uint32 | uint64 | usize
  | irrelevant | object | tobject
  | struct (leanTypeName : Option Name) (types : Array IRType) : IRType
  | union (leanTypeName : Name) (types : Array IRType) : IRType
  deriving Inhabited, Repr
goal: Type

full_name: Lean.IR.IRType.beq
code: partial def beq : IRType → IRType → Bool
  
goal: Lean.IR.IRType → Lean.IR.IRType → Bool

full_name: Lean.IR.IRType.instBEq
code: instance : BEq IRType 
goal: BEq Lean.IR.IRType

full_name: Lean.IR.IRType.isScalar
code: def isScalar : IRType → Bool
  
goal: Lean.IR.IRType → Bool

full_name: Lean.IR.IRType.isObj
code: def isObj : IRType → Bool
  
goal: Lean.IR.IRType → Bool

full_name: Lean.IR.IRType.isIrrelevant
code: def isIrrelevant : IRType → Bool
  
goal: Lean.IR.IRType → Bool

full_name: Lean.IR.IRType.isStruct
code: def isStruct : IRType → Bool
  
goal: Lean.IR.IRType → Bool

full_name: Lean.IR.IRType.isUnion
code: def isUnion : IRType → Bool
  
goal: Lean.IR.IRType → Bool

full_name: Lean.IR.Arg
code: /-- Arguments to applications, constructors, etc.
   We use `irrelevant` for Lean types, propositions and proofs that have been erased.
   Recall that for a Function `f`, we also generate `f._rarg` which does not take
   `irrelevant` arguments. However, `f._rarg` is only safe to be used in full applications. -/
inductive Arg where
  | var (id : VarId)
  | irrelevant
  deriving Inhabited
goal: Type

full_name: Lean.IR.Arg.irrelevant
code: /-- Arguments to applications, constructors, etc.
   We use `irrelevant` for Lean types, propositions and proofs that have been erased.
   Recall that for a Function `f`, we also generate `f._rarg` which does not take
   `irrelevant` arguments. However, `f._rarg` is only safe to be used in full applications. -/
inductive Arg where
  | var (id : VarId)
  | irrelevant
  deriving Inhabited
goal: Lean.IR.Arg

full_name: Lean.IR.instInhabitedArg
code: /-- Arguments to applications, constructors, etc.
   We use `irrelevant` for Lean types, propositions and proofs that have been erased.
   Recall that for a Function `f`, we also generate `f._rarg` which does not take
   `irrelevant` arguments. However, `f._rarg` is only safe to be used in full applications. -/
inductive Arg where
  | var (id : VarId)
  | irrelevant
  deriving Inhabited
goal: Inhabited Lean.IR.Arg

full_name: Lean.IR.Arg.var
code: /-- Arguments to applications, constructors, etc.
   We use `irrelevant` for Lean types, propositions and proofs that have been erased.
   Recall that for a Function `f`, we also generate `f._rarg` which does not take
   `irrelevant` arguments. However, `f._rarg` is only safe to be used in full applications. -/
inductive Arg where
  | var (id : VarId)
  | irrelevant
  deriving Inhabited
goal: Lean.IR.Arg

full_name: Lean.IR.Arg.beq
code: protected def Arg.beq : Arg → Arg → Bool
  
goal: Lean.IR.Arg → Lean.IR.Arg → Bool

full_name: Lean.IR.instBEqArg
code: instance : BEq Arg 
goal: BEq Lean.IR.Arg

full_name: Lean.IR.mkVarArg
code: @[export lean_ir_mk_var_arg] def mkVarArg (id : VarId) : Arg 
goal: Lean.IR.Arg

full_name: Lean.IR.LitVal.num
code: inductive LitVal where
  | num (v : Nat)
  | str (v : String)
goal: Lean.IR.LitVal

full_name: Lean.IR.LitVal.str
code: inductive LitVal where
  | num (v : Nat)
  | str (v : String)
goal: Lean.IR.LitVal

full_name: Lean.IR.LitVal
code: inductive LitVal where
  | num (v : Nat)
  | str (v : String)
goal: Type

full_name: Lean.IR.LitVal.beq
code: def LitVal.beq : LitVal → LitVal → Bool
  
goal: Lean.IR.LitVal → Lean.IR.LitVal → Bool

full_name: Lean.IR.instBEqLitVal
code: instance : BEq LitVal 
goal: BEq Lean.IR.LitVal

full_name: Lean.IR.CtorInfo.name
code: /-- Constructor information.

   - `name` is the Name of the Constructor in Lean.
   - `cidx` is the Constructor index (aka tag).
   - `size` is the number of arguments of type `object/tobject`.
   - `usize` is the number of arguments of type `usize`.
   - `ssize` is the number of bytes used to store scalar values.

Recall that a Constructor object contains a header, then a sequence of
pointers to other Lean objects, a sequence of `USize` (i.e., `size_t`)
scalar values, and a sequence of other scalar values. -/
structure CtorInfo where
  name : Name
  cidx : Nat
  size : Nat
  usize : Nat
  ssize : Nat
  deriving Repr
goal: Lean.Name

full_name: Lean.IR.CtorInfo.usize
code: /-- Constructor information.

   - `name` is the Name of the Constructor in Lean.
   - `cidx` is the Constructor index (aka tag).
   - `size` is the number of arguments of type `object/tobject`.
   - `usize` is the number of arguments of type `usize`.
   - `ssize` is the number of bytes used to store scalar values.

Recall that a Constructor object contains a header, then a sequence of
pointers to other Lean objects, a sequence of `USize` (i.e., `size_t`)
scalar values, and a sequence of other scalar values. -/
structure CtorInfo where
  name : Name
  cidx : Nat
  size : Nat
  usize : Nat
  ssize : Nat
  deriving Repr
goal: Nat

full_name: Lean.IR.CtorInfo.size
code: /-- Constructor information.

   - `name` is the Name of the Constructor in Lean.
   - `cidx` is the Constructor index (aka tag).
   - `size` is the number of arguments of type `object/tobject`.
   - `usize` is the number of arguments of type `usize`.
   - `ssize` is the number of bytes used to store scalar values.

Recall that a Constructor object contains a header, then a sequence of
pointers to other Lean objects, a sequence of `USize` (i.e., `size_t`)
scalar values, and a sequence of other scalar values. -/
structure CtorInfo where
  name : Name
  cidx : Nat
  size : Nat
  usize : Nat
  ssize : Nat
  deriving Repr
goal: Nat

full_name: Lean.IR.CtorInfo
code: /-- Constructor information.

   - `name` is the Name of the Constructor in Lean.
   - `cidx` is the Constructor index (aka tag).
   - `size` is the number of arguments of type `object/tobject`.
   - `usize` is the number of arguments of type `usize`.
   - `ssize` is the number of bytes used to store scalar values.

Recall that a Constructor object contains a header, then a sequence of
pointers to other Lean objects, a sequence of `USize` (i.e., `size_t`)
scalar values, and a sequence of other scalar values. -/
structure CtorInfo where
  name : Name
  cidx : Nat
  size : Nat
  usize : Nat
  ssize : Nat
  deriving Repr
goal: Type

full_name: Lean.IR.CtorInfo.cidx
code: /-- Constructor information.

   - `name` is the Name of the Constructor in Lean.
   - `cidx` is the Constructor index (aka tag).
   - `size` is the number of arguments of type `object/tobject`.
   - `usize` is the number of arguments of type `usize`.
   - `ssize` is the number of bytes used to store scalar values.

Recall that a Constructor object contains a header, then a sequence of
pointers to other Lean objects, a sequence of `USize` (i.e., `size_t`)
scalar values, and a sequence of other scalar values. -/
structure CtorInfo where
  name : Name
  cidx : Nat
  size : Nat
  usize : Nat
  ssize : Nat
  deriving Repr
goal: Nat

full_name: Lean.IR.instReprCtorInfo
code: /-- Constructor information.

   - `name` is the Name of the Constructor in Lean.
   - `cidx` is the Constructor index (aka tag).
   - `size` is the number of arguments of type `object/tobject`.
   - `usize` is the number of arguments of type `usize`.
   - `ssize` is the number of bytes used to store scalar values.

Recall that a Constructor object contains a header, then a sequence of
pointers to other Lean objects, a sequence of `USize` (i.e., `size_t`)
scalar values, and a sequence of other scalar values. -/
structure CtorInfo where
  name : Name
  cidx : Nat
  size : Nat
  usize : Nat
  ssize : Nat
  deriving Repr
goal: Repr Lean.IR.CtorInfo

full_name: Lean.IR.CtorInfo.ssize
code: /-- Constructor information.

   - `name` is the Name of the Constructor in Lean.
   - `cidx` is the Constructor index (aka tag).
   - `size` is the number of arguments of type `object/tobject`.
   - `usize` is the number of arguments of type `usize`.
   - `ssize` is the number of bytes used to store scalar values.

Recall that a Constructor object contains a header, then a sequence of
pointers to other Lean objects, a sequence of `USize` (i.e., `size_t`)
scalar values, and a sequence of other scalar values. -/
structure CtorInfo where
  name : Name
  cidx : Nat
  size : Nat
  usize : Nat
  ssize : Nat
  deriving Repr
goal: Nat

full_name: Lean.IR.CtorInfo.beq
code: def CtorInfo.beq : CtorInfo → CtorInfo → Bool
  
goal: Lean.IR.CtorInfo → Lean.IR.CtorInfo → Bool

full_name: Lean.IR.instBEqCtorInfo
code: instance : BEq CtorInfo 
goal: BEq Lean.IR.CtorInfo

full_name: Lean.IR.CtorInfo.isRef
code: def CtorInfo.isRef (info : CtorInfo) : Bool 
goal: Bool

full_name: Lean.IR.CtorInfo.isScalar
code: def CtorInfo.isScalar (info : CtorInfo) : Bool 
goal: Bool

full_name: Lean.IR.Expr.sproj
code: inductive Expr where
  /-- We use `ctor` mainly for constructing Lean object/tobject values `lean_ctor_object` in the runtime.
  This instruction is also used to creat `struct` and `union` return values.
  For `union`, only `i.cidx` is relevant. For `struct`, `i` is irrelevant. -/
  | ctor (i : CtorInfo) (ys : Array Arg)
  | reset (n : Nat) (x : VarId)
  /-- `reuse x in ctor_i ys` instruction in the paper. -/
  | reuse (x : VarId) (i : CtorInfo) (updtHeader : Bool) (ys : Array Arg)
  /-- Extract the `tobject` value at Position `sizeof(void*)*i` from `x`.
  We also use `proj` for extracting fields from `struct` return values, and casting `union` return values. -/
  |  proj (i : Nat) (x : VarId)
  /-- Extract the `Usize` value at Position `sizeof(void*)*i` from `x`. -/
  | uproj (i : Nat) (x : VarId)
  /-- Extract the scalar value at Position `sizeof(void*)*n + offset` from `x`. -/
  | sproj (n : Nat) (offset : Nat) (x : VarId)
  /-- Full application. -/
  | fap (c : FunId) (ys : Array Arg)
  /-- Partial application that creates a `pap` value (aka closure in our nonstandard terminology). -/
  | pap (c : FunId) (ys : Array Arg)
  /-- Application. `x` must be a `pap` value. -/
  | ap  (x : VarId) (ys : Array Arg)
  /-- Given `x : ty` where `ty` is a scalar type, this operation returns a value of Type `tobject`.
  For small scalar values, the Result is a tagged pointer, and no memory allocation is performed. -/
  | box (ty : IRType) (x : VarId)
  /-- Given `x : [t]object`, obtain the scalar value. -/
  | unbox (x : VarId)
  | lit (v : LitVal)
  /-- Return `1 : uint8` Iff `RC(x) > 1` -/
  | isShared (x : VarId)
goal: Lean.IR.Expr

full_name: Lean.IR.Expr.box
code: inductive Expr where
  /-- We use `ctor` mainly for constructing Lean object/tobject values `lean_ctor_object` in the runtime.
  This instruction is also used to creat `struct` and `union` return values.
  For `union`, only `i.cidx` is relevant. For `struct`, `i` is irrelevant. -/
  | ctor (i : CtorInfo) (ys : Array Arg)
  | reset (n : Nat) (x : VarId)
  /-- `reuse x in ctor_i ys` instruction in the paper. -/
  | reuse (x : VarId) (i : CtorInfo) (updtHeader : Bool) (ys : Array Arg)
  /-- Extract the `tobject` value at Position `sizeof(void*)*i` from `x`.
  We also use `proj` for extracting fields from `struct` return values, and casting `union` return values. -/
  |  proj (i : Nat) (x : VarId)
  /-- Extract the `Usize` value at Position `sizeof(void*)*i` from `x`. -/
  | uproj (i : Nat) (x : VarId)
  /-- Extract the scalar value at Position `sizeof(void*)*n + offset` from `x`. -/
  | sproj (n : Nat) (offset : Nat) (x : VarId)
  /-- Full application. -/
  | fap (c : FunId) (ys : Array Arg)
  /-- Partial application that creates a `pap` value (aka closure in our nonstandard terminology). -/
  | pap (c : FunId) (ys : Array Arg)
  /-- Application. `x` must be a `pap` value. -/
  | ap  (x : VarId) (ys : Array Arg)
  /-- Given `x : ty` where `ty` is a scalar type, this operation returns a value of Type `tobject`.
  For small scalar values, the Result is a tagged pointer, and no memory allocation is performed. -/
  | box (ty : IRType) (x : VarId)
  /-- Given `x : [t]object`, obtain the scalar value. -/
  | unbox (x : VarId)
  | lit (v : LitVal)
  /-- Return `1 : uint8` Iff `RC(x) > 1` -/
  | isShared (x : VarId)
goal: Lean.IR.Expr

full_name: Lean.IR.Expr.isShared
code: inductive Expr where
  /-- We use `ctor` mainly for constructing Lean object/tobject values `lean_ctor_object` in the runtime.
  This instruction is also used to creat `struct` and `union` return values.
  For `union`, only `i.cidx` is relevant. For `struct`, `i` is irrelevant. -/
  | ctor (i : CtorInfo) (ys : Array Arg)
  | reset (n : Nat) (x : VarId)
  /-- `reuse x in ctor_i ys` instruction in the paper. -/
  | reuse (x : VarId) (i : CtorInfo) (updtHeader : Bool) (ys : Array Arg)
  /-- Extract the `tobject` value at Position `sizeof(void*)*i` from `x`.
  We also use `proj` for extracting fields from `struct` return values, and casting `union` return values. -/
  |  proj (i : Nat) (x : VarId)
  /-- Extract the `Usize` value at Position `sizeof(void*)*i` from `x`. -/
  | uproj (i : Nat) (x : VarId)
  /-- Extract the scalar value at Position `sizeof(void*)*n + offset` from `x`. -/
  | sproj (n : Nat) (offset : Nat) (x : VarId)
  /-- Full application. -/
  | fap (c : FunId) (ys : Array Arg)
  /-- Partial application that creates a `pap` value (aka closure in our nonstandard terminology). -/
  | pap (c : FunId) (ys : Array Arg)
  /-- Application. `x` must be a `pap` value. -/
  | ap  (x : VarId) (ys : Array Arg)
  /-- Given `x : ty` where `ty` is a scalar type, this operation returns a value of Type `tobject`.
  For small scalar values, the Result is a tagged pointer, and no memory allocation is performed. -/
  | box (ty : IRType) (x : VarId)
  /-- Given `x : [t]object`, obtain the scalar value. -/
  | unbox (x : VarId)
  | lit (v : LitVal)
  /-- Return `1 : uint8` Iff `RC(x) > 1` -/
  | isShared (x : VarId)
goal: Lean.IR.Expr

full_name: Lean.IR.Expr
code: inductive Expr where
  /-- We use `ctor` mainly for constructing Lean object/tobject values `lean_ctor_object` in the runtime.
  This instruction is also used to creat `struct` and `union` return values.
  For `union`, only `i.cidx` is relevant. For `struct`, `i` is irrelevant. -/
  | ctor (i : CtorInfo) (ys : Array Arg)
  | reset (n : Nat) (x : VarId)
  /-- `reuse x in ctor_i ys` instruction in the paper. -/
  | reuse (x : VarId) (i : CtorInfo) (updtHeader : Bool) (ys : Array Arg)
  /-- Extract the `tobject` value at Position `sizeof(void*)*i` from `x`.
  We also use `proj` for extracting fields from `struct` return values, and casting `union` return values. -/
  |  proj (i : Nat) (x : VarId)
  /-- Extract the `Usize` value at Position `sizeof(void*)*i` from `x`. -/
  | uproj (i : Nat) (x : VarId)
  /-- Extract the scalar value at Position `sizeof(void*)*n + offset` from `x`. -/
  | sproj (n : Nat) (offset : Nat) (x : VarId)
  /-- Full application. -/
  | fap (c : FunId) (ys : Array Arg)
  /-- Partial application that creates a `pap` value (aka closure in our nonstandard terminology). -/
  | pap (c : FunId) (ys : Array Arg)
  /-- Application. `x` must be a `pap` value. -/
  | ap  (x : VarId) (ys : Array Arg)
  /-- Given `x : ty` where `ty` is a scalar type, this operation returns a value of Type `tobject`.
  For small scalar values, the Result is a tagged pointer, and no memory allocation is performed. -/
  | box (ty : IRType) (x : VarId)
  /-- Given `x : [t]object`, obtain the scalar value. -/
  | unbox (x : VarId)
  | lit (v : LitVal)
  /-- Return `1 : uint8` Iff `RC(x) > 1` -/
  | isShared (x : VarId)
goal: Type

full_name: Lean.IR.Expr.reset
code: inductive Expr where
  /-- We use `ctor` mainly for constructing Lean object/tobject values `lean_ctor_object` in the runtime.
  This instruction is also used to creat `struct` and `union` return values.
  For `union`, only `i.cidx` is relevant. For `struct`, `i` is irrelevant. -/
  | ctor (i : CtorInfo) (ys : Array Arg)
  | reset (n : Nat) (x : VarId)
  /-- `reuse x in ctor_i ys` instruction in the paper. -/
  | reuse (x : VarId) (i : CtorInfo) (updtHeader : Bool) (ys : Array Arg)
  /-- Extract the `tobject` value at Position `sizeof(void*)*i` from `x`.
  We also use `proj` for extracting fields from `struct` return values, and casting `union` return values. -/
  |  proj (i : Nat) (x : VarId)
  /-- Extract the `Usize` value at Position `sizeof(void*)*i` from `x`. -/
  | uproj (i : Nat) (x : VarId)
  /-- Extract the scalar value at Position `sizeof(void*)*n + offset` from `x`. -/
  | sproj (n : Nat) (offset : Nat) (x : VarId)
  /-- Full application. -/
  | fap (c : FunId) (ys : Array Arg)
  /-- Partial application that creates a `pap` value (aka closure in our nonstandard terminology). -/
  | pap (c : FunId) (ys : Array Arg)
  /-- Application. `x` must be a `pap` value. -/
  | ap  (x : VarId) (ys : Array Arg)
  /-- Given `x : ty` where `ty` is a scalar type, this operation returns a value of Type `tobject`.
  For small scalar values, the Result is a tagged pointer, and no memory allocation is performed. -/
  | box (ty : IRType) (x : VarId)
  /-- Given `x : [t]object`, obtain the scalar value. -/
  | unbox (x : VarId)
  | lit (v : LitVal)
  /-- Return `1 : uint8` Iff `RC(x) > 1` -/
  | isShared (x : VarId)
goal: Lean.IR.Expr

full_name: Lean.IR.Expr.ap
code: inductive Expr where
  /-- We use `ctor` mainly for constructing Lean object/tobject values `lean_ctor_object` in the runtime.
  This instruction is also used to creat `struct` and `union` return values.
  For `union`, only `i.cidx` is relevant. For `struct`, `i` is irrelevant. -/
  | ctor (i : CtorInfo) (ys : Array Arg)
  | reset (n : Nat) (x : VarId)
  /-- `reuse x in ctor_i ys` instruction in the paper. -/
  | reuse (x : VarId) (i : CtorInfo) (updtHeader : Bool) (ys : Array Arg)
  /-- Extract the `tobject` value at Position `sizeof(void*)*i` from `x`.
  We also use `proj` for extracting fields from `struct` return values, and casting `union` return values. -/
  |  proj (i : Nat) (x : VarId)
  /-- Extract the `Usize` value at Position `sizeof(void*)*i` from `x`. -/
  | uproj (i : Nat) (x : VarId)
  /-- Extract the scalar value at Position `sizeof(void*)*n + offset` from `x`. -/
  | sproj (n : Nat) (offset : Nat) (x : VarId)
  /-- Full application. -/
  | fap (c : FunId) (ys : Array Arg)
  /-- Partial application that creates a `pap` value (aka closure in our nonstandard terminology). -/
  | pap (c : FunId) (ys : Array Arg)
  /-- Application. `x` must be a `pap` value. -/
  | ap  (x : VarId) (ys : Array Arg)
  /-- Given `x : ty` where `ty` is a scalar type, this operation returns a value of Type `tobject`.
  For small scalar values, the Result is a tagged pointer, and no memory allocation is performed. -/
  | box (ty : IRType) (x : VarId)
  /-- Given `x : [t]object`, obtain the scalar value. -/
  | unbox (x : VarId)
  | lit (v : LitVal)
  /-- Return `1 : uint8` Iff `RC(x) > 1` -/
  | isShared (x : VarId)
goal: Lean.IR.Expr

full_name: Lean.IR.Expr.fap
code: inductive Expr where
  /-- We use `ctor` mainly for constructing Lean object/tobject values `lean_ctor_object` in the runtime.
  This instruction is also used to creat `struct` and `union` return values.
  For `union`, only `i.cidx` is relevant. For `struct`, `i` is irrelevant. -/
  | ctor (i : CtorInfo) (ys : Array Arg)
  | reset (n : Nat) (x : VarId)
  /-- `reuse x in ctor_i ys` instruction in the paper. -/
  | reuse (x : VarId) (i : CtorInfo) (updtHeader : Bool) (ys : Array Arg)
  /-- Extract the `tobject` value at Position `sizeof(void*)*i` from `x`.
  We also use `proj` for extracting fields from `struct` return values, and casting `union` return values. -/
  |  proj (i : Nat) (x : VarId)
  /-- Extract the `Usize` value at Position `sizeof(void*)*i` from `x`. -/
  | uproj (i : Nat) (x : VarId)
  /-- Extract the scalar value at Position `sizeof(void*)*n + offset` from `x`. -/
  | sproj (n : Nat) (offset : Nat) (x : VarId)
  /-- Full application. -/
  | fap (c : FunId) (ys : Array Arg)
  /-- Partial application that creates a `pap` value (aka closure in our nonstandard terminology). -/
  | pap (c : FunId) (ys : Array Arg)
  /-- Application. `x` must be a `pap` value. -/
  | ap  (x : VarId) (ys : Array Arg)
  /-- Given `x : ty` where `ty` is a scalar type, this operation returns a value of Type `tobject`.
  For small scalar values, the Result is a tagged pointer, and no memory allocation is performed. -/
  | box (ty : IRType) (x : VarId)
  /-- Given `x : [t]object`, obtain the scalar value. -/
  | unbox (x : VarId)
  | lit (v : LitVal)
  /-- Return `1 : uint8` Iff `RC(x) > 1` -/
  | isShared (x : VarId)
goal: Lean.IR.Expr

full_name: Lean.IR.Expr.pap
code: inductive Expr where
  /-- We use `ctor` mainly for constructing Lean object/tobject values `lean_ctor_object` in the runtime.
  This instruction is also used to creat `struct` and `union` return values.
  For `union`, only `i.cidx` is relevant. For `struct`, `i` is irrelevant. -/
  | ctor (i : CtorInfo) (ys : Array Arg)
  | reset (n : Nat) (x : VarId)
  /-- `reuse x in ctor_i ys` instruction in the paper. -/
  | reuse (x : VarId) (i : CtorInfo) (updtHeader : Bool) (ys : Array Arg)
  /-- Extract the `tobject` value at Position `sizeof(void*)*i` from `x`.
  We also use `proj` for extracting fields from `struct` return values, and casting `union` return values. -/
  |  proj (i : Nat) (x : VarId)
  /-- Extract the `Usize` value at Position `sizeof(void*)*i` from `x`. -/
  | uproj (i : Nat) (x : VarId)
  /-- Extract the scalar value at Position `sizeof(void*)*n + offset` from `x`. -/
  | sproj (n : Nat) (offset : Nat) (x : VarId)
  /-- Full application. -/
  | fap (c : FunId) (ys : Array Arg)
  /-- Partial application that creates a `pap` value (aka closure in our nonstandard terminology). -/
  | pap (c : FunId) (ys : Array Arg)
  /-- Application. `x` must be a `pap` value. -/
  | ap  (x : VarId) (ys : Array Arg)
  /-- Given `x : ty` where `ty` is a scalar type, this operation returns a value of Type `tobject`.
  For small scalar values, the Result is a tagged pointer, and no memory allocation is performed. -/
  | box (ty : IRType) (x : VarId)
  /-- Given `x : [t]object`, obtain the scalar value. -/
  | unbox (x : VarId)
  | lit (v : LitVal)
  /-- Return `1 : uint8` Iff `RC(x) > 1` -/
  | isShared (x : VarId)
goal: Lean.IR.Expr

full_name: Lean.IR.Expr.unbox
code: inductive Expr where
  /-- We use `ctor` mainly for constructing Lean object/tobject values `lean_ctor_object` in the runtime.
  This instruction is also used to creat `struct` and `union` return values.
  For `union`, only `i.cidx` is relevant. For `struct`, `i` is irrelevant. -/
  | ctor (i : CtorInfo) (ys : Array Arg)
  | reset (n : Nat) (x : VarId)
  /-- `reuse x in ctor_i ys` instruction in the paper. -/
  | reuse (x : VarId) (i : CtorInfo) (updtHeader : Bool) (ys : Array Arg)
  /-- Extract the `tobject` value at Position `sizeof(void*)*i` from `x`.
  We also use `proj` for extracting fields from `struct` return values, and casting `union` return values. -/
  |  proj (i : Nat) (x : VarId)
  /-- Extract the `Usize` value at Position `sizeof(void*)*i` from `x`. -/
  | uproj (i : Nat) (x : VarId)
  /-- Extract the scalar value at Position `sizeof(void*)*n + offset` from `x`. -/
  | sproj (n : Nat) (offset : Nat) (x : VarId)
  /-- Full application. -/
  | fap (c : FunId) (ys : Array Arg)
  /-- Partial application that creates a `pap` value (aka closure in our nonstandard terminology). -/
  | pap (c : FunId) (ys : Array Arg)
  /-- Application. `x` must be a `pap` value. -/
  | ap  (x : VarId) (ys : Array Arg)
  /-- Given `x : ty` where `ty` is a scalar type, this operation returns a value of Type `tobject`.
  For small scalar values, the Result is a tagged pointer, and no memory allocation is performed. -/
  | box (ty : IRType) (x : VarId)
  /-- Given `x : [t]object`, obtain the scalar value. -/
  | unbox (x : VarId)
  | lit (v : LitVal)
  /-- Return `1 : uint8` Iff `RC(x) > 1` -/
  | isShared (x : VarId)
goal: Lean.IR.Expr

full_name: Lean.IR.Expr.ctor
code: inductive Expr where
  /-- We use `ctor` mainly for constructing Lean object/tobject values `lean_ctor_object` in the runtime.
  This instruction is also used to creat `struct` and `union` return values.
  For `union`, only `i.cidx` is relevant. For `struct`, `i` is irrelevant. -/
  | ctor (i : CtorInfo) (ys : Array Arg)
  | reset (n : Nat) (x : VarId)
  /-- `reuse x in ctor_i ys` instruction in the paper. -/
  | reuse (x : VarId) (i : CtorInfo) (updtHeader : Bool) (ys : Array Arg)
  /-- Extract the `tobject` value at Position `sizeof(void*)*i` from `x`.
  We also use `proj` for extracting fields from `struct` return values, and casting `union` return values. -/
  |  proj (i : Nat) (x : VarId)
  /-- Extract the `Usize` value at Position `sizeof(void*)*i` from `x`. -/
  | uproj (i : Nat) (x : VarId)
  /-- Extract the scalar value at Position `sizeof(void*)*n + offset` from `x`. -/
  | sproj (n : Nat) (offset : Nat) (x : VarId)
  /-- Full application. -/
  | fap (c : FunId) (ys : Array Arg)
  /-- Partial application that creates a `pap` value (aka closure in our nonstandard terminology). -/
  | pap (c : FunId) (ys : Array Arg)
  /-- Application. `x` must be a `pap` value. -/
  | ap  (x : VarId) (ys : Array Arg)
  /-- Given `x : ty` where `ty` is a scalar type, this operation returns a value of Type `tobject`.
  For small scalar values, the Result is a tagged pointer, and no memory allocation is performed. -/
  | box (ty : IRType) (x : VarId)
  /-- Given `x : [t]object`, obtain the scalar value. -/
  | unbox (x : VarId)
  | lit (v : LitVal)
  /-- Return `1 : uint8` Iff `RC(x) > 1` -/
  | isShared (x : VarId)
goal: Lean.IR.Expr

full_name: Lean.IR.Expr.lit
code: inductive Expr where
  /-- We use `ctor` mainly for constructing Lean object/tobject values `lean_ctor_object` in the runtime.
  This instruction is also used to creat `struct` and `union` return values.
  For `union`, only `i.cidx` is relevant. For `struct`, `i` is irrelevant. -/
  | ctor (i : CtorInfo) (ys : Array Arg)
  | reset (n : Nat) (x : VarId)
  /-- `reuse x in ctor_i ys` instruction in the paper. -/
  | reuse (x : VarId) (i : CtorInfo) (updtHeader : Bool) (ys : Array Arg)
  /-- Extract the `tobject` value at Position `sizeof(void*)*i` from `x`.
  We also use `proj` for extracting fields from `struct` return values, and casting `union` return values. -/
  |  proj (i : Nat) (x : VarId)
  /-- Extract the `Usize` value at Position `sizeof(void*)*i` from `x`. -/
  | uproj (i : Nat) (x : VarId)
  /-- Extract the scalar value at Position `sizeof(void*)*n + offset` from `x`. -/
  | sproj (n : Nat) (offset : Nat) (x : VarId)
  /-- Full application. -/
  | fap (c : FunId) (ys : Array Arg)
  /-- Partial application that creates a `pap` value (aka closure in our nonstandard terminology). -/
  | pap (c : FunId) (ys : Array Arg)
  /-- Application. `x` must be a `pap` value. -/
  | ap  (x : VarId) (ys : Array Arg)
  /-- Given `x : ty` where `ty` is a scalar type, this operation returns a value of Type `tobject`.
  For small scalar values, the Result is a tagged pointer, and no memory allocation is performed. -/
  | box (ty : IRType) (x : VarId)
  /-- Given `x : [t]object`, obtain the scalar value. -/
  | unbox (x : VarId)
  | lit (v : LitVal)
  /-- Return `1 : uint8` Iff `RC(x) > 1` -/
  | isShared (x : VarId)
goal: Lean.IR.Expr

full_name: Lean.IR.Expr.reuse
code: inductive Expr where
  /-- We use `ctor` mainly for constructing Lean object/tobject values `lean_ctor_object` in the runtime.
  This instruction is also used to creat `struct` and `union` return values.
  For `union`, only `i.cidx` is relevant. For `struct`, `i` is irrelevant. -/
  | ctor (i : CtorInfo) (ys : Array Arg)
  | reset (n : Nat) (x : VarId)
  /-- `reuse x in ctor_i ys` instruction in the paper. -/
  | reuse (x : VarId) (i : CtorInfo) (updtHeader : Bool) (ys : Array Arg)
  /-- Extract the `tobject` value at Position `sizeof(void*)*i` from `x`.
  We also use `proj` for extracting fields from `struct` return values, and casting `union` return values. -/
  |  proj (i : Nat) (x : VarId)
  /-- Extract the `Usize` value at Position `sizeof(void*)*i` from `x`. -/
  | uproj (i : Nat) (x : VarId)
  /-- Extract the scalar value at Position `sizeof(void*)*n + offset` from `x`. -/
  | sproj (n : Nat) (offset : Nat) (x : VarId)
  /-- Full application. -/
  | fap (c : FunId) (ys : Array Arg)
  /-- Partial application that creates a `pap` value (aka closure in our nonstandard terminology). -/
  | pap (c : FunId) (ys : Array Arg)
  /-- Application. `x` must be a `pap` value. -/
  | ap  (x : VarId) (ys : Array Arg)
  /-- Given `x : ty` where `ty` is a scalar type, this operation returns a value of Type `tobject`.
  For small scalar values, the Result is a tagged pointer, and no memory allocation is performed. -/
  | box (ty : IRType) (x : VarId)
  /-- Given `x : [t]object`, obtain the scalar value. -/
  | unbox (x : VarId)
  | lit (v : LitVal)
  /-- Return `1 : uint8` Iff `RC(x) > 1` -/
  | isShared (x : VarId)
goal: Lean.IR.Expr

full_name: Lean.IR.Expr.proj
code: inductive Expr where
  /-- We use `ctor` mainly for constructing Lean object/tobject values `lean_ctor_object` in the runtime.
  This instruction is also used to creat `struct` and `union` return values.
  For `union`, only `i.cidx` is relevant. For `struct`, `i` is irrelevant. -/
  | ctor (i : CtorInfo) (ys : Array Arg)
  | reset (n : Nat) (x : VarId)
  /-- `reuse x in ctor_i ys` instruction in the paper. -/
  | reuse (x : VarId) (i : CtorInfo) (updtHeader : Bool) (ys : Array Arg)
  /-- Extract the `tobject` value at Position `sizeof(void*)*i` from `x`.
  We also use `proj` for extracting fields from `struct` return values, and casting `union` return values. -/
  |  proj (i : Nat) (x : VarId)
  /-- Extract the `Usize` value at Position `sizeof(void*)*i` from `x`. -/
  | uproj (i : Nat) (x : VarId)
  /-- Extract the scalar value at Position `sizeof(void*)*n + offset` from `x`. -/
  | sproj (n : Nat) (offset : Nat) (x : VarId)
  /-- Full application. -/
  | fap (c : FunId) (ys : Array Arg)
  /-- Partial application that creates a `pap` value (aka closure in our nonstandard terminology). -/
  | pap (c : FunId) (ys : Array Arg)
  /-- Application. `x` must be a `pap` value. -/
  | ap  (x : VarId) (ys : Array Arg)
  /-- Given `x : ty` where `ty` is a scalar type, this operation returns a value of Type `tobject`.
  For small scalar values, the Result is a tagged pointer, and no memory allocation is performed. -/
  | box (ty : IRType) (x : VarId)
  /-- Given `x : [t]object`, obtain the scalar value. -/
  | unbox (x : VarId)
  | lit (v : LitVal)
  /-- Return `1 : uint8` Iff `RC(x) > 1` -/
  | isShared (x : VarId)
goal: Lean.IR.Expr

full_name: Lean.IR.Expr.uproj
code: inductive Expr where
  /-- We use `ctor` mainly for constructing Lean object/tobject values `lean_ctor_object` in the runtime.
  This instruction is also used to creat `struct` and `union` return values.
  For `union`, only `i.cidx` is relevant. For `struct`, `i` is irrelevant. -/
  | ctor (i : CtorInfo) (ys : Array Arg)
  | reset (n : Nat) (x : VarId)
  /-- `reuse x in ctor_i ys` instruction in the paper. -/
  | reuse (x : VarId) (i : CtorInfo) (updtHeader : Bool) (ys : Array Arg)
  /-- Extract the `tobject` value at Position `sizeof(void*)*i` from `x`.
  We also use `proj` for extracting fields from `struct` return values, and casting `union` return values. -/
  |  proj (i : Nat) (x : VarId)
  /-- Extract the `Usize` value at Position `sizeof(void*)*i` from `x`. -/
  | uproj (i : Nat) (x : VarId)
  /-- Extract the scalar value at Position `sizeof(void*)*n + offset` from `x`. -/
  | sproj (n : Nat) (offset : Nat) (x : VarId)
  /-- Full application. -/
  | fap (c : FunId) (ys : Array Arg)
  /-- Partial application that creates a `pap` value (aka closure in our nonstandard terminology). -/
  | pap (c : FunId) (ys : Array Arg)
  /-- Application. `x` must be a `pap` value. -/
  | ap  (x : VarId) (ys : Array Arg)
  /-- Given `x : ty` where `ty` is a scalar type, this operation returns a value of Type `tobject`.
  For small scalar values, the Result is a tagged pointer, and no memory allocation is performed. -/
  | box (ty : IRType) (x : VarId)
  /-- Given `x : [t]object`, obtain the scalar value. -/
  | unbox (x : VarId)
  | lit (v : LitVal)
  /-- Return `1 : uint8` Iff `RC(x) > 1` -/
  | isShared (x : VarId)
goal: Lean.IR.Expr

full_name: Lean.IR.mkCtorExpr
code: @[export lean_ir_mk_ctor_expr]  def mkCtorExpr (n : Name) (cidx : Nat) (size : Nat) (usize : Nat) (ssize : Nat) (ys : Array Arg) : Expr 
goal: Lean.IR.Expr

full_name: Lean.IR.mkProjExpr
code: @[export lean_ir_mk_proj_expr]  def mkProjExpr (i : Nat) (x : VarId) : Expr 
goal: Lean.IR.Expr

full_name: Lean.IR.mkUProjExpr
code: @[export lean_ir_mk_uproj_expr] def mkUProjExpr (i : Nat) (x : VarId) : Expr 
goal: Lean.IR.Expr

full_name: Lean.IR.mkSProjExpr
code: @[export lean_ir_mk_sproj_expr] def mkSProjExpr (n : Nat) (offset : Nat) (x : VarId) : Expr 
goal: Lean.IR.Expr

full_name: Lean.IR.mkFAppExpr
code: @[export lean_ir_mk_fapp_expr]  def mkFAppExpr (c : FunId) (ys : Array Arg) : Expr 
goal: Lean.IR.Expr

full_name: Lean.IR.mkPAppExpr
code: @[export lean_ir_mk_papp_expr]  def mkPAppExpr (c : FunId) (ys : Array Arg) : Expr 
goal: Lean.IR.Expr

full_name: Lean.IR.mkAppExpr
code: @[export lean_ir_mk_app_expr]   def mkAppExpr (x : VarId) (ys : Array Arg) : Expr 
goal: Lean.IR.Expr

full_name: Lean.IR.mkNumExpr
code: @[export lean_ir_mk_num_expr]   def mkNumExpr (v : Nat) : Expr 
goal: Lean.IR.Expr

full_name: Lean.IR.mkStrExpr
code: @[export lean_ir_mk_str_expr]   def mkStrExpr (v : String) : Expr 
goal: Lean.IR.Expr

full_name: Lean.IR.instReprParam
code: structure Param where
  x : VarId
  borrow : Bool
  ty : IRType
  deriving Inhabited, Repr
goal: Repr Lean.IR.Param

full_name: Lean.IR.Param.borrow
code: structure Param where
  x : VarId
  borrow : Bool
  ty : IRType
  deriving Inhabited, Repr
goal: Bool

full_name: Lean.IR.Param
code: structure Param where
  x : VarId
  borrow : Bool
  ty : IRType
  deriving Inhabited, Repr
goal: Type

full_name: Lean.IR.Param.ty
code: structure Param where
  x : VarId
  borrow : Bool
  ty : IRType
  deriving Inhabited, Repr
goal: Lean.IR.IRType

full_name: Lean.IR.Param.x
code: structure Param where
  x : VarId
  borrow : Bool
  ty : IRType
  deriving Inhabited, Repr
goal: Lean.IR.VarId

full_name: Lean.IR.instInhabitedParam
code: structure Param where
  x : VarId
  borrow : Bool
  ty : IRType
  deriving Inhabited, Repr
goal: Inhabited Lean.IR.Param

full_name: Lean.IR.mkParam
code: @[export lean_ir_mk_param]
def mkParam (x : VarId) (borrow : Bool) (ty : IRType) : Param 
goal: Lean.IR.Param

full_name: Lean.IR.AltCore
code: inductive AltCore (FnBody : Type) : Type where
  | ctor (info : CtorInfo) (b : FnBody) : AltCore FnBody
  | default (b : FnBody) : AltCore FnBody
goal: Type

full_name: Lean.IR.AltCore.ctor
code: inductive AltCore (FnBody : Type) : Type where
  | ctor (info : CtorInfo) (b : FnBody) : AltCore FnBody
  | default (b : FnBody) : AltCore FnBody
goal: Lean.IR.AltCore FnBody

full_name: Lean.IR.AltCore.default
code: inductive AltCore (FnBody : Type) : Type where
  | ctor (info : CtorInfo) (b : FnBody) : AltCore FnBody
  | default (b : FnBody) : AltCore FnBody
goal: Lean.IR.AltCore FnBody

full_name: Lean.IR.FnBody.uset
code: inductive FnBody where
  /-- `let x : ty := e; b` -/
  | vdecl (x : VarId) (ty : IRType) (e : Expr) (b : FnBody)
  /-- Join point Declaration `block_j (xs) := e; b` -/
  | jdecl (j : JoinPointId) (xs : Array Param) (v : FnBody) (b : FnBody)
  /-- Store `y` at Position `sizeof(void*)*i` in `x`. `x` must be a Constructor object and `RC(x)` must be 1.
  This operation is not part of λPure is only used during optimization. -/
  | set (x : VarId) (i : Nat) (y : Arg) (b : FnBody)
  | setTag (x : VarId) (cidx : Nat) (b : FnBody)
  /-- Store `y : Usize` at Position `sizeof(void*)*i` in `x`. `x` must be a Constructor object and `RC(x)` must be 1. -/
  | uset (x : VarId) (i : Nat) (y : VarId) (b : FnBody)
  /-- Store `y : ty` at Position `sizeof(void*)*i + offset` in `x`. `x` must be a Constructor object and `RC(x)` must be 1.
  `ty` must not be `object`, `tobject`, `irrelevant` nor `Usize`. -/
  | sset (x : VarId) (i : Nat) (offset : Nat) (y : VarId) (ty : IRType) (b : FnBody)
  /-- RC increment for `object`. If c == `true`, then `inc` must check whether `x` is a tagged pointer or not.
  If `persistent == true` then `x` is statically known to be a persistent object. -/
  | inc (x : VarId) (n : Nat) (c : Bool) (persistent : Bool) (b : FnBody)
  /-- RC decrement for `object`. If c == `true`, then `inc` must check whether `x` is a tagged pointer or not.
  If `persistent == true` then `x` is statically known to be a persistent object. -/
  | dec (x : VarId) (n : Nat) (c : Bool) (persistent : Bool) (b : FnBody)
  | del (x : VarId) (b : FnBody)
  | mdata (d : MData) (b : FnBody)
  | case (tid : Name) (x : VarId) (xType : IRType) (cs : Array (AltCore FnBody))
  | ret (x : Arg)
  /-- Jump to join point `j` -/
  | jmp (j : JoinPointId) (ys : Array Arg)
  | unreachable
goal: Lean.IR.FnBody

full_name: Lean.IR.FnBody.case
code: inductive FnBody where
  /-- `let x : ty := e; b` -/
  | vdecl (x : VarId) (ty : IRType) (e : Expr) (b : FnBody)
  /-- Join point Declaration `block_j (xs) := e; b` -/
  | jdecl (j : JoinPointId) (xs : Array Param) (v : FnBody) (b : FnBody)
  /-- Store `y` at Position `sizeof(void*)*i` in `x`. `x` must be a Constructor object and `RC(x)` must be 1.
  This operation is not part of λPure is only used during optimization. -/
  | set (x : VarId) (i : Nat) (y : Arg) (b : FnBody)
  | setTag (x : VarId) (cidx : Nat) (b : FnBody)
  /-- Store `y : Usize` at Position `sizeof(void*)*i` in `x`. `x` must be a Constructor object and `RC(x)` must be 1. -/
  | uset (x : VarId) (i : Nat) (y : VarId) (b : FnBody)
  /-- Store `y : ty` at Position `sizeof(void*)*i + offset` in `x`. `x` must be a Constructor object and `RC(x)` must be 1.
  `ty` must not be `object`, `tobject`, `irrelevant` nor `Usize`. -/
  | sset (x : VarId) (i : Nat) (offset : Nat) (y : VarId) (ty : IRType) (b : FnBody)
  /-- RC increment for `object`. If c == `true`, then `inc` must check whether `x` is a tagged pointer or not.
  If `persistent == true` then `x` is statically known to be a persistent object. -/
  | inc (x : VarId) (n : Nat) (c : Bool) (persistent : Bool) (b : FnBody)
  /-- RC decrement for `object`. If c == `true`, then `inc` must check whether `x` is a tagged pointer or not.
  If `persistent == true` then `x` is statically known to be a persistent object. -/
  | dec (x : VarId) (n : Nat) (c : Bool) (persistent : Bool) (b : FnBody)
  | del (x : VarId) (b : FnBody)
  | mdata (d : MData) (b : FnBody)
  | case (tid : Name) (x : VarId) (xType : IRType) (cs : Array (AltCore FnBody))
  | ret (x : Arg)
  /-- Jump to join point `j` -/
  | jmp (j : JoinPointId) (ys : Array Arg)
  | unreachable
goal: Lean.IR.FnBody

full_name: Lean.IR.FnBody
code: inductive FnBody where
  /-- `let x : ty := e; b` -/
  | vdecl (x : VarId) (ty : IRType) (e : Expr) (b : FnBody)
  /-- Join point Declaration `block_j (xs) := e; b` -/
  | jdecl (j : JoinPointId) (xs : Array Param) (v : FnBody) (b : FnBody)
  /-- Store `y` at Position `sizeof(void*)*i` in `x`. `x` must be a Constructor object and `RC(x)` must be 1.
  This operation is not part of λPure is only used during optimization. -/
  | set (x : VarId) (i : Nat) (y : Arg) (b : FnBody)
  | setTag (x : VarId) (cidx : Nat) (b : FnBody)
  /-- Store `y : Usize` at Position `sizeof(void*)*i` in `x`. `x` must be a Constructor object and `RC(x)` must be 1. -/
  | uset (x : VarId) (i : Nat) (y : VarId) (b : FnBody)
  /-- Store `y : ty` at Position `sizeof(void*)*i + offset` in `x`. `x` must be a Constructor object and `RC(x)` must be 1.
  `ty` must not be `object`, `tobject`, `irrelevant` nor `Usize`. -/
  | sset (x : VarId) (i : Nat) (offset : Nat) (y : VarId) (ty : IRType) (b : FnBody)
  /-- RC increment for `object`. If c == `true`, then `inc` must check whether `x` is a tagged pointer or not.
  If `persistent == true` then `x` is statically known to be a persistent object. -/
  | inc (x : VarId) (n : Nat) (c : Bool) (persistent : Bool) (b : FnBody)
  /-- RC decrement for `object`. If c == `true`, then `inc` must check whether `x` is a tagged pointer or not.
  If `persistent == true` then `x` is statically known to be a persistent object. -/
  | dec (x : VarId) (n : Nat) (c : Bool) (persistent : Bool) (b : FnBody)
  | del (x : VarId) (b : FnBody)
  | mdata (d : MData) (b : FnBody)
  | case (tid : Name) (x : VarId) (xType : IRType) (cs : Array (AltCore FnBody))
  | ret (x : Arg)
  /-- Jump to join point `j` -/
  | jmp (j : JoinPointId) (ys : Array Arg)
  | unreachable
goal: Type

full_name: Lean.IR.FnBody.sset
code: inductive FnBody where
  /-- `let x : ty := e; b` -/
  | vdecl (x : VarId) (ty : IRType) (e : Expr) (b : FnBody)
  /-- Join point Declaration `block_j (xs) := e; b` -/
  | jdecl (j : JoinPointId) (xs : Array Param) (v : FnBody) (b : FnBody)
  /-- Store `y` at Position `sizeof(void*)*i` in `x`. `x` must be a Constructor object and `RC(x)` must be 1.
  This operation is not part of λPure is only used during optimization. -/
  | set (x : VarId) (i : Nat) (y : Arg) (b : FnBody)
  | setTag (x : VarId) (cidx : Nat) (b : FnBody)
  /-- Store `y : Usize` at Position `sizeof(void*)*i` in `x`. `x` must be a Constructor object and `RC(x)` must be 1. -/
  | uset (x : VarId) (i : Nat) (y : VarId) (b : FnBody)
  /-- Store `y : ty` at Position `sizeof(void*)*i + offset` in `x`. `x` must be a Constructor object and `RC(x)` must be 1.
  `ty` must not be `object`, `tobject`, `irrelevant` nor `Usize`. -/
  | sset (x : VarId) (i : Nat) (offset : Nat) (y : VarId) (ty : IRType) (b : FnBody)
  /-- RC increment for `object`. If c == `true`, then `inc` must check whether `x` is a tagged pointer or not.
  If `persistent == true` then `x` is statically known to be a persistent object. -/
  | inc (x : VarId) (n : Nat) (c : Bool) (persistent : Bool) (b : FnBody)
  /-- RC decrement for `object`. If c == `true`, then `inc` must check whether `x` is a tagged pointer or not.
  If `persistent == true` then `x` is statically known to be a persistent object. -/
  | dec (x : VarId) (n : Nat) (c : Bool) (persistent : Bool) (b : FnBody)
  | del (x : VarId) (b : FnBody)
  | mdata (d : MData) (b : FnBody)
  | case (tid : Name) (x : VarId) (xType : IRType) (cs : Array (AltCore FnBody))
  | ret (x : Arg)
  /-- Jump to join point `j` -/
  | jmp (j : JoinPointId) (ys : Array Arg)
  | unreachable
goal: Lean.IR.FnBody

full_name: Lean.IR.FnBody.mdata
code: inductive FnBody where
  /-- `let x : ty := e; b` -/
  | vdecl (x : VarId) (ty : IRType) (e : Expr) (b : FnBody)
  /-- Join point Declaration `block_j (xs) := e; b` -/
  | jdecl (j : JoinPointId) (xs : Array Param) (v : FnBody) (b : FnBody)
  /-- Store `y` at Position `sizeof(void*)*i` in `x`. `x` must be a Constructor object and `RC(x)` must be 1.
  This operation is not part of λPure is only used during optimization. -/
  | set (x : VarId) (i : Nat) (y : Arg) (b : FnBody)
  | setTag (x : VarId) (cidx : Nat) (b : FnBody)
  /-- Store `y : Usize` at Position `sizeof(void*)*i` in `x`. `x` must be a Constructor object and `RC(x)` must be 1. -/
  | uset (x : VarId) (i : Nat) (y : VarId) (b : FnBody)
  /-- Store `y : ty` at Position `sizeof(void*)*i + offset` in `x`. `x` must be a Constructor object and `RC(x)` must be 1.
  `ty` must not be `object`, `tobject`, `irrelevant` nor `Usize`. -/
  | sset (x : VarId) (i : Nat) (offset : Nat) (y : VarId) (ty : IRType) (b : FnBody)
  /-- RC increment for `object`. If c == `true`, then `inc` must check whether `x` is a tagged pointer or not.
  If `persistent == true` then `x` is statically known to be a persistent object. -/
  | inc (x : VarId) (n : Nat) (c : Bool) (persistent : Bool) (b : FnBody)
  /-- RC decrement for `object`. If c == `true`, then `inc` must check whether `x` is a tagged pointer or not.
  If `persistent == true` then `x` is statically known to be a persistent object. -/
  | dec (x : VarId) (n : Nat) (c : Bool) (persistent : Bool) (b : FnBody)
  | del (x : VarId) (b : FnBody)
  | mdata (d : MData) (b : FnBody)
  | case (tid : Name) (x : VarId) (xType : IRType) (cs : Array (AltCore FnBody))
  | ret (x : Arg)
  /-- Jump to join point `j` -/
  | jmp (j : JoinPointId) (ys : Array Arg)
  | unreachable
goal: Lean.IR.FnBody

full_name: Lean.IR.FnBody.set
code: inductive FnBody where
  /-- `let x : ty := e; b` -/
  | vdecl (x : VarId) (ty : IRType) (e : Expr) (b : FnBody)
  /-- Join point Declaration `block_j (xs) := e; b` -/
  | jdecl (j : JoinPointId) (xs : Array Param) (v : FnBody) (b : FnBody)
  /-- Store `y` at Position `sizeof(void*)*i` in `x`. `x` must be a Constructor object and `RC(x)` must be 1.
  This operation is not part of λPure is only used during optimization. -/
  | set (x : VarId) (i : Nat) (y : Arg) (b : FnBody)
  | setTag (x : VarId) (cidx : Nat) (b : FnBody)
  /-- Store `y : Usize` at Position `sizeof(void*)*i` in `x`. `x` must be a Constructor object and `RC(x)` must be 1. -/
  | uset (x : VarId) (i : Nat) (y : VarId) (b : FnBody)
  /-- Store `y : ty` at Position `sizeof(void*)*i + offset` in `x`. `x` must be a Constructor object and `RC(x)` must be 1.
  `ty` must not be `object`, `tobject`, `irrelevant` nor `Usize`. -/
  | sset (x : VarId) (i : Nat) (offset : Nat) (y : VarId) (ty : IRType) (b : FnBody)
  /-- RC increment for `object`. If c == `true`, then `inc` must check whether `x` is a tagged pointer or not.
  If `persistent == true` then `x` is statically known to be a persistent object. -/
  | inc (x : VarId) (n : Nat) (c : Bool) (persistent : Bool) (b : FnBody)
  /-- RC decrement for `object`. If c == `true`, then `inc` must check whether `x` is a tagged pointer or not.
  If `persistent == true` then `x` is statically known to be a persistent object. -/
  | dec (x : VarId) (n : Nat) (c : Bool) (persistent : Bool) (b : FnBody)
  | del (x : VarId) (b : FnBody)
  | mdata (d : MData) (b : FnBody)
  | case (tid : Name) (x : VarId) (xType : IRType) (cs : Array (AltCore FnBody))
  | ret (x : Arg)
  /-- Jump to join point `j` -/
  | jmp (j : JoinPointId) (ys : Array Arg)
  | unreachable
goal: Lean.IR.FnBody

full_name: Lean.IR.FnBody.del
code: inductive FnBody where
  /-- `let x : ty := e; b` -/
  | vdecl (x : VarId) (ty : IRType) (e : Expr) (b : FnBody)
  /-- Join point Declaration `block_j (xs) := e; b` -/
  | jdecl (j : JoinPointId) (xs : Array Param) (v : FnBody) (b : FnBody)
  /-- Store `y` at Position `sizeof(void*)*i` in `x`. `x` must be a Constructor object and `RC(x)` must be 1.
  This operation is not part of λPure is only used during optimization. -/
  | set (x : VarId) (i : Nat) (y : Arg) (b : FnBody)
  | setTag (x : VarId) (cidx : Nat) (b : FnBody)
  /-- Store `y : Usize` at Position `sizeof(void*)*i` in `x`. `x` must be a Constructor object and `RC(x)` must be 1. -/
  | uset (x : VarId) (i : Nat) (y : VarId) (b : FnBody)
  /-- Store `y : ty` at Position `sizeof(void*)*i + offset` in `x`. `x` must be a Constructor object and `RC(x)` must be 1.
  `ty` must not be `object`, `tobject`, `irrelevant` nor `Usize`. -/
  | sset (x : VarId) (i : Nat) (offset : Nat) (y : VarId) (ty : IRType) (b : FnBody)
  /-- RC increment for `object`. If c == `true`, then `inc` must check whether `x` is a tagged pointer or not.
  If `persistent == true` then `x` is statically known to be a persistent object. -/
  | inc (x : VarId) (n : Nat) (c : Bool) (persistent : Bool) (b : FnBody)
  /-- RC decrement for `object`. If c == `true`, then `inc` must check whether `x` is a tagged pointer or not.
  If `persistent == true` then `x` is statically known to be a persistent object. -/
  | dec (x : VarId) (n : Nat) (c : Bool) (persistent : Bool) (b : FnBody)
  | del (x : VarId) (b : FnBody)
  | mdata (d : MData) (b : FnBody)
  | case (tid : Name) (x : VarId) (xType : IRType) (cs : Array (AltCore FnBody))
  | ret (x : Arg)
  /-- Jump to join point `j` -/
  | jmp (j : JoinPointId) (ys : Array Arg)
  | unreachable
goal: Lean.IR.FnBody

full_name: Lean.IR.FnBody.vdecl
code: inductive FnBody where
  /-- `let x : ty := e; b` -/
  | vdecl (x : VarId) (ty : IRType) (e : Expr) (b : FnBody)
  /-- Join point Declaration `block_j (xs) := e; b` -/
  | jdecl (j : JoinPointId) (xs : Array Param) (v : FnBody) (b : FnBody)
  /-- Store `y` at Position `sizeof(void*)*i` in `x`. `x` must be a Constructor object and `RC(x)` must be 1.
  This operation is not part of λPure is only used during optimization. -/
  | set (x : VarId) (i : Nat) (y : Arg) (b : FnBody)
  | setTag (x : VarId) (cidx : Nat) (b : FnBody)
  /-- Store `y : Usize` at Position `sizeof(void*)*i` in `x`. `x` must be a Constructor object and `RC(x)` must be 1. -/
  | uset (x : VarId) (i : Nat) (y : VarId) (b : FnBody)
  /-- Store `y : ty` at Position `sizeof(void*)*i + offset` in `x`. `x` must be a Constructor object and `RC(x)` must be 1.
  `ty` must not be `object`, `tobject`, `irrelevant` nor `Usize`. -/
  | sset (x : VarId) (i : Nat) (offset : Nat) (y : VarId) (ty : IRType) (b : FnBody)
  /-- RC increment for `object`. If c == `true`, then `inc` must check whether `x` is a tagged pointer or not.
  If `persistent == true` then `x` is statically known to be a persistent object. -/
  | inc (x : VarId) (n : Nat) (c : Bool) (persistent : Bool) (b : FnBody)
  /-- RC decrement for `object`. If c == `true`, then `inc` must check whether `x` is a tagged pointer or not.
  If `persistent == true` then `x` is statically known to be a persistent object. -/
  | dec (x : VarId) (n : Nat) (c : Bool) (persistent : Bool) (b : FnBody)
  | del (x : VarId) (b : FnBody)
  | mdata (d : MData) (b : FnBody)
  | case (tid : Name) (x : VarId) (xType : IRType) (cs : Array (AltCore FnBody))
  | ret (x : Arg)
  /-- Jump to join point `j` -/
  | jmp (j : JoinPointId) (ys : Array Arg)
  | unreachable
goal: Lean.IR.FnBody

full_name: Lean.IR.FnBody.jdecl
code: inductive FnBody where
  /-- `let x : ty := e; b` -/
  | vdecl (x : VarId) (ty : IRType) (e : Expr) (b : FnBody)
  /-- Join point Declaration `block_j (xs) := e; b` -/
  | jdecl (j : JoinPointId) (xs : Array Param) (v : FnBody) (b : FnBody)
  /-- Store `y` at Position `sizeof(void*)*i` in `x`. `x` must be a Constructor object and `RC(x)` must be 1.
  This operation is not part of λPure is only used during optimization. -/
  | set (x : VarId) (i : Nat) (y : Arg) (b : FnBody)
  | setTag (x : VarId) (cidx : Nat) (b : FnBody)
  /-- Store `y : Usize` at Position `sizeof(void*)*i` in `x`. `x` must be a Constructor object and `RC(x)` must be 1. -/
  | uset (x : VarId) (i : Nat) (y : VarId) (b : FnBody)
  /-- Store `y : ty` at Position `sizeof(void*)*i + offset` in `x`. `x` must be a Constructor object and `RC(x)` must be 1.
  `ty` must not be `object`, `tobject`, `irrelevant` nor `Usize`. -/
  | sset (x : VarId) (i : Nat) (offset : Nat) (y : VarId) (ty : IRType) (b : FnBody)
  /-- RC increment for `object`. If c == `true`, then `inc` must check whether `x` is a tagged pointer or not.
  If `persistent == true` then `x` is statically known to be a persistent object. -/
  | inc (x : VarId) (n : Nat) (c : Bool) (persistent : Bool) (b : FnBody)
  /-- RC decrement for `object`. If c == `true`, then `inc` must check whether `x` is a tagged pointer or not.
  If `persistent == true` then `x` is statically known to be a persistent object. -/
  | dec (x : VarId) (n : Nat) (c : Bool) (persistent : Bool) (b : FnBody)
  | del (x : VarId) (b : FnBody)
  | mdata (d : MData) (b : FnBody)
  | case (tid : Name) (x : VarId) (xType : IRType) (cs : Array (AltCore FnBody))
  | ret (x : Arg)
  /-- Jump to join point `j` -/
  | jmp (j : JoinPointId) (ys : Array Arg)
  | unreachable
goal: Lean.IR.FnBody

full_name: Lean.IR.FnBody.dec
code: inductive FnBody where
  /-- `let x : ty := e; b` -/
  | vdecl (x : VarId) (ty : IRType) (e : Expr) (b : FnBody)
  /-- Join point Declaration `block_j (xs) := e; b` -/
  | jdecl (j : JoinPointId) (xs : Array Param) (v : FnBody) (b : FnBody)
  /-- Store `y` at Position `sizeof(void*)*i` in `x`. `x` must be a Constructor object and `RC(x)` must be 1.
  This operation is not part of λPure is only used during optimization. -/
  | set (x : VarId) (i : Nat) (y : Arg) (b : FnBody)
  | setTag (x : VarId) (cidx : Nat) (b : FnBody)
  /-- Store `y : Usize` at Position `sizeof(void*)*i` in `x`. `x` must be a Constructor object and `RC(x)` must be 1. -/
  | uset (x : VarId) (i : Nat) (y : VarId) (b : FnBody)
  /-- Store `y : ty` at Position `sizeof(void*)*i + offset` in `x`. `x` must be a Constructor object and `RC(x)` must be 1.
  `ty` must not be `object`, `tobject`, `irrelevant` nor `Usize`. -/
  | sset (x : VarId) (i : Nat) (offset : Nat) (y : VarId) (ty : IRType) (b : FnBody)
  /-- RC increment for `object`. If c == `true`, then `inc` must check whether `x` is a tagged pointer or not.
  If `persistent == true` then `x` is statically known to be a persistent object. -/
  | inc (x : VarId) (n : Nat) (c : Bool) (persistent : Bool) (b : FnBody)
  /-- RC decrement for `object`. If c == `true`, then `inc` must check whether `x` is a tagged pointer or not.
  If `persistent == true` then `x` is statically known to be a persistent object. -/
  | dec (x : VarId) (n : Nat) (c : Bool) (persistent : Bool) (b : FnBody)
  | del (x : VarId) (b : FnBody)
  | mdata (d : MData) (b : FnBody)
  | case (tid : Name) (x : VarId) (xType : IRType) (cs : Array (AltCore FnBody))
  | ret (x : Arg)
  /-- Jump to join point `j` -/
  | jmp (j : JoinPointId) (ys : Array Arg)
  | unreachable
goal: Lean.IR.FnBody

full_name: Lean.IR.FnBody.setTag
code: inductive FnBody where
  /-- `let x : ty := e; b` -/
  | vdecl (x : VarId) (ty : IRType) (e : Expr) (b : FnBody)
  /-- Join point Declaration `block_j (xs) := e; b` -/
  | jdecl (j : JoinPointId) (xs : Array Param) (v : FnBody) (b : FnBody)
  /-- Store `y` at Position `sizeof(void*)*i` in `x`. `x` must be a Constructor object and `RC(x)` must be 1.
  This operation is not part of λPure is only used during optimization. -/
  | set (x : VarId) (i : Nat) (y : Arg) (b : FnBody)
  | setTag (x : VarId) (cidx : Nat) (b : FnBody)
  /-- Store `y : Usize` at Position `sizeof(void*)*i` in `x`. `x` must be a Constructor object and `RC(x)` must be 1. -/
  | uset (x : VarId) (i : Nat) (y : VarId) (b : FnBody)
  /-- Store `y : ty` at Position `sizeof(void*)*i + offset` in `x`. `x` must be a Constructor object and `RC(x)` must be 1.
  `ty` must not be `object`, `tobject`, `irrelevant` nor `Usize`. -/
  | sset (x : VarId) (i : Nat) (offset : Nat) (y : VarId) (ty : IRType) (b : FnBody)
  /-- RC increment for `object`. If c == `true`, then `inc` must check whether `x` is a tagged pointer or not.
  If `persistent == true` then `x` is statically known to be a persistent object. -/
  | inc (x : VarId) (n : Nat) (c : Bool) (persistent : Bool) (b : FnBody)
  /-- RC decrement for `object`. If c == `true`, then `inc` must check whether `x` is a tagged pointer or not.
  If `persistent == true` then `x` is statically known to be a persistent object. -/
  | dec (x : VarId) (n : Nat) (c : Bool) (persistent : Bool) (b : FnBody)
  | del (x : VarId) (b : FnBody)
  | mdata (d : MData) (b : FnBody)
  | case (tid : Name) (x : VarId) (xType : IRType) (cs : Array (AltCore FnBody))
  | ret (x : Arg)
  /-- Jump to join point `j` -/
  | jmp (j : JoinPointId) (ys : Array Arg)
  | unreachable
goal: Lean.IR.FnBody

full_name: Lean.IR.FnBody.inc
code: inductive FnBody where
  /-- `let x : ty := e; b` -/
  | vdecl (x : VarId) (ty : IRType) (e : Expr) (b : FnBody)
  /-- Join point Declaration `block_j (xs) := e; b` -/
  | jdecl (j : JoinPointId) (xs : Array Param) (v : FnBody) (b : FnBody)
  /-- Store `y` at Position `sizeof(void*)*i` in `x`. `x` must be a Constructor object and `RC(x)` must be 1.
  This operation is not part of λPure is only used during optimization. -/
  | set (x : VarId) (i : Nat) (y : Arg) (b : FnBody)
  | setTag (x : VarId) (cidx : Nat) (b : FnBody)
  /-- Store `y : Usize` at Position `sizeof(void*)*i` in `x`. `x` must be a Constructor object and `RC(x)` must be 1. -/
  | uset (x : VarId) (i : Nat) (y : VarId) (b : FnBody)
  /-- Store `y : ty` at Position `sizeof(void*)*i + offset` in `x`. `x` must be a Constructor object and `RC(x)` must be 1.
  `ty` must not be `object`, `tobject`, `irrelevant` nor `Usize`. -/
  | sset (x : VarId) (i : Nat) (offset : Nat) (y : VarId) (ty : IRType) (b : FnBody)
  /-- RC increment for `object`. If c == `true`, then `inc` must check whether `x` is a tagged pointer or not.
  If `persistent == true` then `x` is statically known to be a persistent object. -/
  | inc (x : VarId) (n : Nat) (c : Bool) (persistent : Bool) (b : FnBody)
  /-- RC decrement for `object`. If c == `true`, then `inc` must check whether `x` is a tagged pointer or not.
  If `persistent == true` then `x` is statically known to be a persistent object. -/
  | dec (x : VarId) (n : Nat) (c : Bool) (persistent : Bool) (b : FnBody)
  | del (x : VarId) (b : FnBody)
  | mdata (d : MData) (b : FnBody)
  | case (tid : Name) (x : VarId) (xType : IRType) (cs : Array (AltCore FnBody))
  | ret (x : Arg)
  /-- Jump to join point `j` -/
  | jmp (j : JoinPointId) (ys : Array Arg)
  | unreachable
goal: Lean.IR.FnBody

full_name: Lean.IR.FnBody.ret
code: inductive FnBody where
  /-- `let x : ty := e; b` -/
  | vdecl (x : VarId) (ty : IRType) (e : Expr) (b : FnBody)
  /-- Join point Declaration `block_j (xs) := e; b` -/
  | jdecl (j : JoinPointId) (xs : Array Param) (v : FnBody) (b : FnBody)
  /-- Store `y` at Position `sizeof(void*)*i` in `x`. `x` must be a Constructor object and `RC(x)` must be 1.
  This operation is not part of λPure is only used during optimization. -/
  | set (x : VarId) (i : Nat) (y : Arg) (b : FnBody)
  | setTag (x : VarId) (cidx : Nat) (b : FnBody)
  /-- Store `y : Usize` at Position `sizeof(void*)*i` in `x`. `x` must be a Constructor object and `RC(x)` must be 1. -/
  | uset (x : VarId) (i : Nat) (y : VarId) (b : FnBody)
  /-- Store `y : ty` at Position `sizeof(void*)*i + offset` in `x`. `x` must be a Constructor object and `RC(x)` must be 1.
  `ty` must not be `object`, `tobject`, `irrelevant` nor `Usize`. -/
  | sset (x : VarId) (i : Nat) (offset : Nat) (y : VarId) (ty : IRType) (b : FnBody)
  /-- RC increment for `object`. If c == `true`, then `inc` must check whether `x` is a tagged pointer or not.
  If `persistent == true` then `x` is statically known to be a persistent object. -/
  | inc (x : VarId) (n : Nat) (c : Bool) (persistent : Bool) (b : FnBody)
  /-- RC decrement for `object`. If c == `true`, then `inc` must check whether `x` is a tagged pointer or not.
  If `persistent == true` then `x` is statically known to be a persistent object. -/
  | dec (x : VarId) (n : Nat) (c : Bool) (persistent : Bool) (b : FnBody)
  | del (x : VarId) (b : FnBody)
  | mdata (d : MData) (b : FnBody)
  | case (tid : Name) (x : VarId) (xType : IRType) (cs : Array (AltCore FnBody))
  | ret (x : Arg)
  /-- Jump to join point `j` -/
  | jmp (j : JoinPointId) (ys : Array Arg)
  | unreachable
goal: Lean.IR.FnBody

full_name: Lean.IR.FnBody.unreachable
code: inductive FnBody where
  /-- `let x : ty := e; b` -/
  | vdecl (x : VarId) (ty : IRType) (e : Expr) (b : FnBody)
  /-- Join point Declaration `block_j (xs) := e; b` -/
  | jdecl (j : JoinPointId) (xs : Array Param) (v : FnBody) (b : FnBody)
  /-- Store `y` at Position `sizeof(void*)*i` in `x`. `x` must be a Constructor object and `RC(x)` must be 1.
  This operation is not part of λPure is only used during optimization. -/
  | set (x : VarId) (i : Nat) (y : Arg) (b : FnBody)
  | setTag (x : VarId) (cidx : Nat) (b : FnBody)
  /-- Store `y : Usize` at Position `sizeof(void*)*i` in `x`. `x` must be a Constructor object and `RC(x)` must be 1. -/
  | uset (x : VarId) (i : Nat) (y : VarId) (b : FnBody)
  /-- Store `y : ty` at Position `sizeof(void*)*i + offset` in `x`. `x` must be a Constructor object and `RC(x)` must be 1.
  `ty` must not be `object`, `tobject`, `irrelevant` nor `Usize`. -/
  | sset (x : VarId) (i : Nat) (offset : Nat) (y : VarId) (ty : IRType) (b : FnBody)
  /-- RC increment for `object`. If c == `true`, then `inc` must check whether `x` is a tagged pointer or not.
  If `persistent == true` then `x` is statically known to be a persistent object. -/
  | inc (x : VarId) (n : Nat) (c : Bool) (persistent : Bool) (b : FnBody)
  /-- RC decrement for `object`. If c == `true`, then `inc` must check whether `x` is a tagged pointer or not.
  If `persistent == true` then `x` is statically known to be a persistent object. -/
  | dec (x : VarId) (n : Nat) (c : Bool) (persistent : Bool) (b : FnBody)
  | del (x : VarId) (b : FnBody)
  | mdata (d : MData) (b : FnBody)
  | case (tid : Name) (x : VarId) (xType : IRType) (cs : Array (AltCore FnBody))
  | ret (x : Arg)
  /-- Jump to join point `j` -/
  | jmp (j : JoinPointId) (ys : Array Arg)
  | unreachable
goal: Lean.IR.FnBody

full_name: Lean.IR.FnBody.jmp
code: inductive FnBody where
  /-- `let x : ty := e; b` -/
  | vdecl (x : VarId) (ty : IRType) (e : Expr) (b : FnBody)
  /-- Join point Declaration `block_j (xs) := e; b` -/
  | jdecl (j : JoinPointId) (xs : Array Param) (v : FnBody) (b : FnBody)
  /-- Store `y` at Position `sizeof(void*)*i` in `x`. `x` must be a Constructor object and `RC(x)` must be 1.
  This operation is not part of λPure is only used during optimization. -/
  | set (x : VarId) (i : Nat) (y : Arg) (b : FnBody)
  | setTag (x : VarId) (cidx : Nat) (b : FnBody)
  /-- Store `y : Usize` at Position `sizeof(void*)*i` in `x`. `x` must be a Constructor object and `RC(x)` must be 1. -/
  | uset (x : VarId) (i : Nat) (y : VarId) (b : FnBody)
  /-- Store `y : ty` at Position `sizeof(void*)*i + offset` in `x`. `x` must be a Constructor object and `RC(x)` must be 1.
  `ty` must not be `object`, `tobject`, `irrelevant` nor `Usize`. -/
  | sset (x : VarId) (i : Nat) (offset : Nat) (y : VarId) (ty : IRType) (b : FnBody)
  /-- RC increment for `object`. If c == `true`, then `inc` must check whether `x` is a tagged pointer or not.
  If `persistent == true` then `x` is statically known to be a persistent object. -/
  | inc (x : VarId) (n : Nat) (c : Bool) (persistent : Bool) (b : FnBody)
  /-- RC decrement for `object`. If c == `true`, then `inc` must check whether `x` is a tagged pointer or not.
  If `persistent == true` then `x` is statically known to be a persistent object. -/
  | dec (x : VarId) (n : Nat) (c : Bool) (persistent : Bool) (b : FnBody)
  | del (x : VarId) (b : FnBody)
  | mdata (d : MData) (b : FnBody)
  | case (tid : Name) (x : VarId) (xType : IRType) (cs : Array (AltCore FnBody))
  | ret (x : Arg)
  /-- Jump to join point `j` -/
  | jmp (j : JoinPointId) (ys : Array Arg)
  | unreachable
goal: Lean.IR.FnBody

full_name: Lean.IR.instInhabitedFnBody
code: instance : Inhabited FnBody 
goal: Inhabited Lean.IR.FnBody

full_name: Lean.IR.FnBody.nil
code: abbrev FnBody.nil 
goal: Lean.IR.FnBody

full_name: Lean.IR.mkVDecl
code: @[export lean_ir_mk_vdecl] def mkVDecl (x : VarId) (ty : IRType) (e : Expr) (b : FnBody) : FnBody 
goal: Lean.IR.FnBody

full_name: Lean.IR.mkJDecl
code: @[export lean_ir_mk_jdecl] def mkJDecl (j : JoinPointId) (xs : Array Param) (v : FnBody) (b : FnBody) : FnBody 
goal: Lean.IR.FnBody

full_name: Lean.IR.mkUSet
code: @[export lean_ir_mk_uset] def mkUSet (x : VarId) (i : Nat) (y : VarId) (b : FnBody) : FnBody 
goal: Lean.IR.FnBody

full_name: Lean.IR.mkSSet
code: @[export lean_ir_mk_sset] def mkSSet (x : VarId) (i : Nat) (offset : Nat) (y : VarId) (ty : IRType) (b : FnBody) : FnBody 
goal: Lean.IR.FnBody

full_name: Lean.IR.mkCase
code: @[export lean_ir_mk_case] def mkCase (tid : Name) (x : VarId) (cs : Array (AltCore FnBody)) : FnBody 
goal: Lean.IR.FnBody

full_name: Lean.IR.mkRet
code: @[export lean_ir_mk_ret] def mkRet (x : Arg) : FnBody 
goal: Lean.IR.FnBody

full_name: Lean.IR.mkJmp
code: @[export lean_ir_mk_jmp] def mkJmp (j : JoinPointId) (ys : Array Arg) : FnBody 
goal: Lean.IR.FnBody

full_name: Lean.IR.mkUnreachable
code: @[export lean_ir_mk_unreachable] def mkUnreachable : Unit → FnBody 
goal: Unit → Lean.IR.FnBody

full_name: Lean.IR.Alt
code: abbrev Alt 
goal: Type

full_name: Lean.IR.Alt.ctor
code: @[match_pattern] abbrev Alt.ctor    
goal: Lean.IR.AltCore Lean.IR.FnBody

full_name: Lean.IR.Alt.default
code: @[match_pattern] abbrev Alt.default 
goal: Lean.IR.AltCore Lean.IR.FnBody

full_name: Lean.IR.instInhabitedAlt
code: instance : Inhabited Alt 
goal: Inhabited Lean.IR.Alt

full_name: Lean.IR.FnBody.isTerminal
code: def FnBody.isTerminal : FnBody → Bool
  
goal: Lean.IR.FnBody → Bool

full_name: Lean.IR.FnBody.body
code: def FnBody.body : FnBody → FnBody
  
goal: Lean.IR.FnBody → Lean.IR.FnBody

full_name: Lean.IR.FnBody.setBody
code: def FnBody.setBody : FnBody → FnBody → FnBody
  
goal: Lean.IR.FnBody → Lean.IR.FnBody → Lean.IR.FnBody

full_name: Lean.IR.FnBody.resetBody
code: @[inline] def FnBody.resetBody (b : FnBody) : FnBody 
goal: Lean.IR.FnBody

full_name: Lean.IR.FnBody.split
code: /-- If b is a non terminal, then return a pair `(c, b')` s.t. `b == c <;> b'`,
   and c.body == FnBody.nil -/
@[inline] def FnBody.split (b : FnBody) : FnBody × FnBody 
goal: Lean.IR.FnBody × Lean.IR.FnBody

full_name: Lean.IR.AltCore.body
code: def AltCore.body : Alt → FnBody
  
goal: Lean.IR.Alt → Lean.IR.FnBody

full_name: Lean.IR.AltCore.setBody
code: def AltCore.setBody : Alt → FnBody → Alt
  
goal: Lean.IR.Alt → Lean.IR.FnBody → Lean.IR.Alt

full_name: Lean.IR.AltCore.modifyBody
code: @[inline] def AltCore.modifyBody (f : FnBody → FnBody) : AltCore FnBody → Alt
  
goal: Lean.IR.AltCore Lean.IR.FnBody → Lean.IR.Alt

full_name: Lean.IR.AltCore.mmodifyBody
code: @[inline] def AltCore.mmodifyBody {m : Type → Type} [Monad m] (f : FnBody → m FnBody) : AltCore FnBody → m Alt
  
goal: Lean.IR.AltCore Lean.IR.FnBody → m Lean.IR.Alt

full_name: Lean.IR.Alt.isDefault
code: def Alt.isDefault : Alt → Bool
  
goal: Lean.IR.Alt → Bool

full_name: Lean.IR.push
code: def push (bs : Array FnBody) (b : FnBody) : Array FnBody 
goal: Array Lean.IR.FnBody

full_name: Lean.IR.flattenAux
code: partial def flattenAux (b : FnBody) (r : Array FnBody) : (Array FnBody) × FnBody 
goal: Array Lean.IR.FnBody × Lean.IR.FnBody

full_name: Lean.IR.FnBody.flatten
code: def FnBody.flatten (b : FnBody) : (Array FnBody) × FnBody 
goal: Array Lean.IR.FnBody × Lean.IR.FnBody

full_name: Lean.IR.reshapeAux
code: partial def reshapeAux (a : Array FnBody) (i : Nat) (b : FnBody) : FnBody 
goal: Lean.IR.FnBody

full_name: Lean.IR.reshape
code: def reshape (bs : Array FnBody) (term : FnBody) : FnBody 
goal: Lean.IR.FnBody

full_name: Lean.IR.modifyJPs
code: @[inline] def modifyJPs (bs : Array FnBody) (f : FnBody → FnBody) : Array FnBody 
goal: Array Lean.IR.FnBody

full_name: Lean.IR.mmodifyJPs
code: @[inline] def mmodifyJPs {m : Type → Type} [Monad m] (bs : Array FnBody) (f : FnBody → m FnBody) : m (Array FnBody) 
goal: m (Array Lean.IR.FnBody)

full_name: Lean.IR.mkAlt
code: @[export lean_ir_mk_alt] def mkAlt (n : Name) (cidx : Nat) (size : Nat) (usize : Nat) (ssize : Nat) (b : FnBody) : Alt 
goal: Lean.IR.Alt

full_name: Lean.IR.DeclInfo
code: /-- Extra information associated with a declaration. -/
structure DeclInfo where
  /-- If `some <blame>`, then declaration depends on `<blame>` which uses a `sorry` axiom. -/
  sorryDep? : Option Name := none
goal: Type

full_name: Lean.IR.DeclInfo.sorryDep?
code: /-- Extra information associated with a declaration. -/
structure DeclInfo where
  /-- If `some <blame>`, then declaration depends on `<blame>` which uses a `sorry` axiom. -/
  sorryDep? : Option Name := none
goal: Option Lean.Name

full_name: Lean.IR.Decl
code: inductive Decl where
  | fdecl  (f : FunId) (xs : Array Param) (type : IRType) (body : FnBody) (info : DeclInfo)
  | extern (f : FunId) (xs : Array Param) (type : IRType) (ext : ExternAttrData)
  deriving Inhabited
goal: Type

full_name: Lean.IR.Decl.fdecl
code: inductive Decl where
  | fdecl  (f : FunId) (xs : Array Param) (type : IRType) (body : FnBody) (info : DeclInfo)
  | extern (f : FunId) (xs : Array Param) (type : IRType) (ext : ExternAttrData)
  deriving Inhabited
goal: Lean.IR.Decl

full_name: Lean.IR.Decl.extern
code: inductive Decl where
  | fdecl  (f : FunId) (xs : Array Param) (type : IRType) (body : FnBody) (info : DeclInfo)
  | extern (f : FunId) (xs : Array Param) (type : IRType) (ext : ExternAttrData)
  deriving Inhabited
goal: Lean.IR.Decl

full_name: Lean.IR.instInhabitedDecl
code: inductive Decl where
  | fdecl  (f : FunId) (xs : Array Param) (type : IRType) (body : FnBody) (info : DeclInfo)
  | extern (f : FunId) (xs : Array Param) (type : IRType) (ext : ExternAttrData)
  deriving Inhabited
goal: Inhabited Lean.IR.Decl

full_name: Lean.IR.Decl.name
code: def name : Decl → FunId
  
goal: Lean.IR.Decl → Lean.IR.FunId

full_name: Lean.IR.Decl.params
code: def params : Decl → Array Param
  
goal: Lean.IR.Decl → Array Lean.IR.Param

full_name: Lean.IR.Decl.resultType
code: def resultType : Decl → IRType
  
goal: Lean.IR.Decl → Lean.IR.IRType

full_name: Lean.IR.Decl.isExtern
code: def isExtern : Decl → Bool
  
goal: Lean.IR.Decl → Bool

full_name: Lean.IR.Decl.getInfo
code: def getInfo : Decl → DeclInfo
  
goal: Lean.IR.Decl → Lean.IR.DeclInfo

full_name: Lean.IR.Decl.updateBody!
code: def updateBody! (d : Decl) (bNew : FnBody) : Decl 
goal: Lean.IR.Decl

full_name: Lean.IR.mkDecl
code: @[export lean_ir_mk_decl] def mkDecl (f : FunId) (xs : Array Param) (ty : IRType) (b : FnBody) : Decl 
goal: Lean.IR.Decl

full_name: Lean.IR.mkExternDecl
code: @[export lean_ir_mk_extern_decl] def mkExternDecl (f : FunId) (xs : Array Param) (ty : IRType) (e : ExternAttrData) : Decl 
goal: Lean.IR.Decl

full_name: Lean.IR.mkDummyExternDecl
code: @[export lean_ir_mk_dummy_extern_decl] def mkDummyExternDecl (f : FunId) (xs : Array Param) (ty : IRType) : Decl 
goal: Lean.IR.Decl

full_name: Lean.IR.IndexSet
code: /-- Set of variable and join point names -/
abbrev IndexSet 
goal: Type

full_name: Lean.IR.instInhabitedIndexSet
code: instance : Inhabited IndexSet 
goal: Inhabited Lean.IR.IndexSet

full_name: Lean.IR.mkIndexSet
code: def mkIndexSet (idx : Index) : IndexSet 
goal: Lean.IR.IndexSet

full_name: Lean.IR.LocalContextEntry.joinPoint
code: inductive LocalContextEntry where
  | param     : IRType → LocalContextEntry
  | localVar  : IRType → Expr → LocalContextEntry
  | joinPoint : Array Param → FnBody → LocalContextEntry
goal: Array Lean.IR.Param → Lean.IR.FnBody → Lean.IR.LocalContextEntry

full_name: Lean.IR.LocalContextEntry
code: inductive LocalContextEntry where
  | param     : IRType → LocalContextEntry
  | localVar  : IRType → Expr → LocalContextEntry
  | joinPoint : Array Param → FnBody → LocalContextEntry
goal: Type

full_name: Lean.IR.LocalContextEntry.localVar
code: inductive LocalContextEntry where
  | param     : IRType → LocalContextEntry
  | localVar  : IRType → Expr → LocalContextEntry
  | joinPoint : Array Param → FnBody → LocalContextEntry
goal: Lean.IR.IRType → Lean.IR.Expr → Lean.IR.LocalContextEntry

full_name: Lean.IR.LocalContextEntry.param
code: inductive LocalContextEntry where
  | param     : IRType → LocalContextEntry
  | localVar  : IRType → Expr → LocalContextEntry
  | joinPoint : Array Param → FnBody → LocalContextEntry
goal: Lean.IR.IRType → Lean.IR.LocalContextEntry

full_name: Lean.IR.LocalContext
code: abbrev LocalContext 
goal: Type

full_name: Lean.IR.LocalContext.addLocal
code: def LocalContext.addLocal (ctx : LocalContext) (x : VarId) (t : IRType) (v : Expr) : LocalContext 
goal: Lean.IR.LocalContext

full_name: Lean.IR.LocalContext.addJP
code: def LocalContext.addJP (ctx : LocalContext) (j : JoinPointId) (xs : Array Param) (b : FnBody) : LocalContext 
goal: Lean.IR.LocalContext

full_name: Lean.IR.LocalContext.addParam
code: def LocalContext.addParam (ctx : LocalContext) (p : Param) : LocalContext 
goal: Lean.IR.LocalContext

full_name: Lean.IR.LocalContext.addParams
code: def LocalContext.addParams (ctx : LocalContext) (ps : Array Param) : LocalContext 
goal: Lean.IR.LocalContext

full_name: Lean.IR.LocalContext.isJP
code: def LocalContext.isJP (ctx : LocalContext) (idx : Index) : Bool 
goal: Bool

full_name: Lean.IR.LocalContext.getJPBody
code: def LocalContext.getJPBody (ctx : LocalContext) (j : JoinPointId) : Option FnBody 
goal: Option Lean.IR.FnBody

full_name: Lean.IR.LocalContext.getJPParams
code: def LocalContext.getJPParams (ctx : LocalContext) (j : JoinPointId) : Option (Array Param) 
goal: Option (Array Lean.IR.Param)

full_name: Lean.IR.LocalContext.isParam
code: def LocalContext.isParam (ctx : LocalContext) (idx : Index) : Bool 
goal: Bool

full_name: Lean.IR.LocalContext.isLocalVar
code: def LocalContext.isLocalVar (ctx : LocalContext) (idx : Index) : Bool 
goal: Bool

full_name: Lean.IR.LocalContext.contains
code: def LocalContext.contains (ctx : LocalContext) (idx : Index) : Bool 
goal: Bool

full_name: Lean.IR.LocalContext.eraseJoinPointDecl
code: def LocalContext.eraseJoinPointDecl (ctx : LocalContext) (j : JoinPointId) : LocalContext 
goal: Lean.IR.LocalContext

full_name: Lean.IR.LocalContext.getType
code: def LocalContext.getType (ctx : LocalContext) (x : VarId) : Option IRType 
goal: Option Lean.IR.IRType

full_name: Lean.IR.LocalContext.getValue
code: def LocalContext.getValue (ctx : LocalContext) (x : VarId) : Option Expr 
goal: Option Lean.IR.Expr

full_name: Lean.IR.IndexRenaming
code: abbrev IndexRenaming 
goal: Type

full_name: Lean.IR.AlphaEqv.aeqv
code: class AlphaEqv (α : Type) where
  aeqv : IndexRenaming → α → α → Bool
goal: Lean.IR.IndexRenaming → α → α → Bool

full_name: Lean.IR.AlphaEqv
code: class AlphaEqv (α : Type) where
  aeqv : IndexRenaming → α → α → Bool
goal: Type

full_name: Lean.IR.VarId.alphaEqv
code: def VarId.alphaEqv (ρ : IndexRenaming) (v₁ v₂ : VarId) : Bool 
goal: Bool

full_name: Lean.IR.instAlphaEqvVarId
code: instance : AlphaEqv VarId 
goal: Lean.IR.AlphaEqv Lean.IR.VarId

full_name: Lean.IR.Arg.alphaEqv
code: def Arg.alphaEqv (ρ : IndexRenaming) : Arg → Arg → Bool
  
goal: Lean.IR.Arg → Lean.IR.Arg → Bool

full_name: Lean.IR.instAlphaEqvArg
code: instance : AlphaEqv Arg 
goal: Lean.IR.AlphaEqv Lean.IR.Arg

full_name: Lean.IR.args.alphaEqv
code: def args.alphaEqv (ρ : IndexRenaming) (args₁ args₂ : Array Arg) : Bool 
goal: Bool

full_name: Lean.IR.instAlphaEqvArrayArg
code: instance: AlphaEqv (Array Arg) 
goal: Lean.IR.AlphaEqv (Array Lean.IR.Arg)

full_name: Lean.IR.Expr.alphaEqv
code: def Expr.alphaEqv (ρ : IndexRenaming) : Expr → Expr → Bool
  
goal: Lean.IR.Expr → Lean.IR.Expr → Bool

full_name: Lean.IR.instAlphaEqvExpr
code: instance : AlphaEqv Expr
goal: Lean.IR.AlphaEqv Lean.IR.Expr

full_name: Lean.IR.addVarRename
code: def addVarRename (ρ : IndexRenaming) (x₁ x₂ : Nat) 
goal: Lean.IR.IndexRenaming

full_name: Lean.IR.addParamRename
code: def addParamRename (ρ : IndexRenaming) (p₁ p₂ : Param) : Option IndexRenaming 
goal: Option Lean.IR.IndexRenaming

full_name: Lean.IR.addParamsRename
code: def addParamsRename (ρ : IndexRenaming) (ps₁ ps₂ : Array Param) : Option IndexRenaming 
goal: Option Lean.IR.IndexRenaming

full_name: Lean.IR.FnBody.alphaEqv
code: partial def FnBody.alphaEqv : IndexRenaming → FnBody → FnBody → Bool
  
goal: Lean.IR.IndexRenaming → Lean.IR.FnBody → Lean.IR.FnBody → Bool

full_name: Lean.IR.FnBody.beq
code: def FnBody.beq (b₁ b₂ : FnBody) : Bool 
goal: Bool

full_name: Lean.IR.instBEqFnBody
code: instance : BEq FnBody 
goal: BEq Lean.IR.FnBody

full_name: Lean.IR.VarIdSet
code: abbrev VarIdSet 
goal: Type

full_name: Lean.IR.instInhabitedVarIdSet
code: instance : Inhabited VarIdSet 
goal: Inhabited Lean.IR.VarIdSet

full_name: Lean.IR.mkIf
code: def mkIf (x : VarId) (t e : FnBody) : FnBody 
goal: Lean.IR.FnBody

full_name: Lean.IR.getUnboxOpName
code: def getUnboxOpName (t : IRType) : String 
goal: String