File: .lake/packages/lean4/src/lean/Lean/Compiler/LCNF/Simp/ConstantFold.lean

full_name: Lean.Compiler.LCNF.Simp.ConstantFold.FolderM
code: /--
A constant folding monad, the additional state stores auxiliary declarations
required to build the new constant.
-/
abbrev FolderM 
goal: Type

full_name: Lean.Compiler.LCNF.Simp.ConstantFold.Folder
code: /--
A constant folder for a specific function, takes all the arguments of a
certain function and produces a new `Expr` + auxiliary declarations in
the `FolderM` monad on success. If the folding fails it returns `none`.
-/
abbrev Folder 
goal: Type

full_name: Lean.Compiler.LCNF.Simp.ConstantFold.Literal.getLit
code: /--
A typeclass for detecting and producing literals of arbitrary types
inside of LCNF.
-/
class Literal (α : Type) where
  /--
  Attempt to turn the provided `Expr` into a value of type `α` if
  it is whatever concept of a literal `α` has. Note that this function
  does assume that the provided `Expr` does indeed have type `α`.
  -/
  getLit : FVarId → CompilerM (Option α)
  /--
  Turn a value of type `α` into a series of auxiliary `LetDecl`s + a
  final `Expr` putting them all together into a literal of type `α`,
  where again the idea of what a literal is depends on `α`.
  -/
  mkLit : α → FolderM LetValue
goal: Lean.FVarId → Lean.Compiler.LCNF.CompilerM (Option α)

full_name: Lean.Compiler.LCNF.Simp.ConstantFold.Literal.mkLit
code: /--
A typeclass for detecting and producing literals of arbitrary types
inside of LCNF.
-/
class Literal (α : Type) where
  /--
  Attempt to turn the provided `Expr` into a value of type `α` if
  it is whatever concept of a literal `α` has. Note that this function
  does assume that the provided `Expr` does indeed have type `α`.
  -/
  getLit : FVarId → CompilerM (Option α)
  /--
  Turn a value of type `α` into a series of auxiliary `LetDecl`s + a
  final `Expr` putting them all together into a literal of type `α`,
  where again the idea of what a literal is depends on `α`.
  -/
  mkLit : α → FolderM LetValue
goal: α → Lean.Compiler.LCNF.Simp.ConstantFold.FolderM Lean.Compiler.LCNF.LetValue

full_name: Lean.Compiler.LCNF.Simp.ConstantFold.Literal
code: /--
A typeclass for detecting and producing literals of arbitrary types
inside of LCNF.
-/
class Literal (α : Type) where
  /--
  Attempt to turn the provided `Expr` into a value of type `α` if
  it is whatever concept of a literal `α` has. Note that this function
  does assume that the provided `Expr` does indeed have type `α`.
  -/
  getLit : FVarId → CompilerM (Option α)
  /--
  Turn a value of type `α` into a series of auxiliary `LetDecl`s + a
  final `Expr` putting them all together into a literal of type `α`,
  where again the idea of what a literal is depends on `α`.
  -/
  mkLit : α → FolderM LetValue
goal: Type

full_name: Lean.Compiler.LCNF.Simp.ConstantFold.mkAuxLetDecl
code: /--
A wrapper around `LCNF.mkAuxLetDecl` that will automatically store the
`LetDecl` in the state of `FolderM`.
-/
def mkAuxLetDecl (e : LetValue) (prefixName := `_x) : FolderM FVarId 
goal: Lean.Compiler.LCNF.Simp.ConstantFold.FolderM Lean.FVarId

full_name: Lean.Compiler.LCNF.Simp.ConstantFold.mkAuxLit
code: /--
A wrapper around `mkAuxLetDecl` that also calls `mkLit`.
-/
def mkAuxLit [Literal α] (x : α) (prefixName := `_x) : FolderM FVarId 
goal: Lean.Compiler.LCNF.Simp.ConstantFold.FolderM Lean.FVarId

full_name: Lean.Compiler.LCNF.Simp.ConstantFold.getNatLit
code: partial def getNatLit (fvarId : FVarId) : CompilerM (Option Nat) 
goal: Lean.Compiler.LCNF.CompilerM (Option Nat)

full_name: Lean.Compiler.LCNF.Simp.ConstantFold.mkNatLit
code: def mkNatLit (n : Nat) : FolderM LetValue 
goal: Lean.Compiler.LCNF.Simp.ConstantFold.FolderM Lean.Compiler.LCNF.LetValue

full_name: Lean.Compiler.LCNF.Simp.ConstantFold.instLiteralNat
code: instance : Literal Nat 
goal: Lean.Compiler.LCNF.Simp.ConstantFold.Literal Nat

full_name: Lean.Compiler.LCNF.Simp.ConstantFold.getStringLit
code: def getStringLit (fvarId : FVarId) : CompilerM (Option String) 
goal: Lean.Compiler.LCNF.CompilerM (Option String)

full_name: Lean.Compiler.LCNF.Simp.ConstantFold.mkStringLit
code: def mkStringLit (n : String) : FolderM LetValue 
goal: Lean.Compiler.LCNF.Simp.ConstantFold.FolderM Lean.Compiler.LCNF.LetValue

full_name: Lean.Compiler.LCNF.Simp.ConstantFold.instLiteralString
code: instance : Literal String 
goal: Lean.Compiler.LCNF.Simp.ConstantFold.Literal String

full_name: Lean.Compiler.LCNF.Simp.ConstantFold.getBoolLit
code: def getBoolLit (fvarId : FVarId) : CompilerM (Option Bool) 
goal: Lean.Compiler.LCNF.CompilerM (Option Bool)

full_name: Lean.Compiler.LCNF.Simp.ConstantFold.mkBoolLit
code: def mkBoolLit (b : Bool) : FolderM LetValue 
goal: Lean.Compiler.LCNF.Simp.ConstantFold.FolderM Lean.Compiler.LCNF.LetValue

full_name: Lean.Compiler.LCNF.Simp.ConstantFold.instLiteralBool
code: instance : Literal Bool 
goal: Lean.Compiler.LCNF.Simp.ConstantFold.Literal Bool

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Compiler.LCNF.Simp.ConstantFold.0.Lean.Compiler.LCNF.Simp.ConstantFold.getLitAux
code: private partial def getLitAux [Inhabited α] (fvarId : FVarId) (ofNat : Nat → α) (ofNatName : Name) : CompilerM (Option α) 
goal: Lean.Compiler.LCNF.CompilerM (Option α)

full_name: Lean.Compiler.LCNF.Simp.ConstantFold.mkNatWrapperInstance
code: def mkNatWrapperInstance [Inhabited α] (ofNat : Nat → α) (ofNatName : Name) (toNat : α → Nat) : Literal α 
goal: Lean.Compiler.LCNF.Simp.ConstantFold.Literal α

full_name: Lean.Compiler.LCNF.Simp.ConstantFold.instLiteralUInt8
code: instance : Literal UInt8 
goal: Lean.Compiler.LCNF.Simp.ConstantFold.Literal UInt8

full_name: Lean.Compiler.LCNF.Simp.ConstantFold.instLiteralUInt16
code: instance : Literal UInt16 
goal: Lean.Compiler.LCNF.Simp.ConstantFold.Literal UInt16

full_name: Lean.Compiler.LCNF.Simp.ConstantFold.instLiteralUInt32
code: instance : Literal UInt32 
goal: Lean.Compiler.LCNF.Simp.ConstantFold.Literal UInt32

full_name: Lean.Compiler.LCNF.Simp.ConstantFold.instLiteralUInt64
code: instance : Literal UInt64 
goal: Lean.Compiler.LCNF.Simp.ConstantFold.Literal UInt64

full_name: Lean.Compiler.LCNF.Simp.ConstantFold.instLiteralChar
code: instance : Literal Char 
goal: Lean.Compiler.LCNF.Simp.ConstantFold.Literal Char

full_name: Lean.Compiler.LCNF.Simp.ConstantFold.getPseudoListLiteral.go
code: /--
Turns an expression chain of the form
```
let _x.1 := @List.nil _
let _x.2 := @List.cons _ a _x.1
let _x.3 := @List.cons _ b _x.2
let _x.4 := @List.cons _ c _x.3
let _x.5 := @List.cons _ d _x.4
let _x.6 := @List.cons _ e _x.5
```
into: `[a, b, c, d ,e]` + The type contained in the list
-/
partial def getPseudoListLiteral (fvarId : FVarId) : CompilerM (Option (List FVarId × Expr × Level)) 
goal: Lean.Compiler.LCNF.CompilerM (Option (List Lean.FVarId × Lean.Expr × Lean.Level))

full_name: Lean.Compiler.LCNF.Simp.ConstantFold.getPseudoListLiteral
code: /--
Turns an expression chain of the form
```
let _x.1 := @List.nil _
let _x.2 := @List.cons _ a _x.1
let _x.3 := @List.cons _ b _x.2
let _x.4 := @List.cons _ c _x.3
let _x.5 := @List.cons _ d _x.4
let _x.6 := @List.cons _ e _x.5
```
into: `[a, b, c, d ,e]` + The type contained in the list
-/
partial def getPseudoListLiteral (fvarId : FVarId) : CompilerM (Option (List FVarId × Expr × Level)) 
goal: Lean.Compiler.LCNF.CompilerM (Option (List Lean.FVarId × Lean.Expr × Lean.Level))

full_name: Lean.Compiler.LCNF.Simp.ConstantFold.mkPseudoArrayLiteral
code: /--
Turn an `#[a, b, c]` into:
```
let _x.12 := 3
let _x.8 := @Array.mkEmpty _ _x.12
let _x.22 := @Array.push _ _x.8 x
let _x.24 := @Array.push _ _x.22 y
let _x.26 := @Array.push _ _x.24 z
_x.26
```
-/
def mkPseudoArrayLiteral (elements : Array FVarId) (typ : Expr) (typLevel : Level) : FolderM LetValue 
goal: Lean.Compiler.LCNF.Simp.ConstantFold.FolderM Lean.Compiler.LCNF.LetValue

full_name: Lean.Compiler.LCNF.Simp.ConstantFold.foldArrayLiteral
code: /--
Evaluate array literals at compile time, that is turn:
```
let _x.1 := @List.nil _
let _x.2 := @List.cons _ z _x.1
let _x.3 := @List.cons _ y _x.2
let _x.4 := @List.cons _ x _x.3
let _x.5 := @List.toArray _ _x.4
```
To its array form:
```
let _x.12 := 3
let _x.8 := @Array.mkEmpty _ _x.12
let _x.22 := @Array.push _ _x.8 x
let _x.24 := @Array.push _ _x.22 y
let _x.26 := @Array.push _ _x.24 z
```
-/
def foldArrayLiteral : Folder 
goal: Lean.Compiler.LCNF.Simp.ConstantFold.Folder

full_name: Lean.Compiler.LCNF.Simp.ConstantFold.Folder.mkUnary
code: /--
Turn a unary function such as `Nat.succ` into a constant folder.
-/
def Folder.mkUnary [Literal α] [Literal β] (folder : α → β) : Folder 
goal: Lean.Compiler.LCNF.Simp.ConstantFold.Folder

full_name: Lean.Compiler.LCNF.Simp.ConstantFold.Folder.mkBinary
code: /--
Turn a binary function such as `Nat.add` into a constant folder.
-/
def Folder.mkBinary [Literal α] [Literal β] [Literal γ] (folder : α → β → γ) : Folder 
goal: Lean.Compiler.LCNF.Simp.ConstantFold.Folder

full_name: Lean.Compiler.LCNF.Simp.ConstantFold.Folder.mkBinaryDecisionProcedure
code: def Folder.mkBinaryDecisionProcedure [Literal α] [Literal β] {r : α → β → Prop} (folder : (a : α) → (b : β) → Decidable (r a b)) : Folder 
goal: Lean.Compiler.LCNF.Simp.ConstantFold.Folder

full_name: Lean.Compiler.LCNF.Simp.ConstantFold.Folder.leftNeutral
code: /--
Provide a folder for an operation with a left neutral element.
-/
def Folder.leftNeutral [Literal α] [BEq α] (neutral : α) : Folder 
goal: Lean.Compiler.LCNF.Simp.ConstantFold.Folder

full_name: Lean.Compiler.LCNF.Simp.ConstantFold.Folder.rightNeutral
code: /--
Provide a folder for an operation with a right neutral element.
-/
def Folder.rightNeutral [Literal α] [BEq α] (neutral : α) : Folder 
goal: Lean.Compiler.LCNF.Simp.ConstantFold.Folder

full_name: Lean.Compiler.LCNF.Simp.ConstantFold.Folder.leftAnnihilator
code: /--
Provide a folder for an operation with a left annihilator.
-/
def Folder.leftAnnihilator [Literal α] [BEq α] (annihilator : α) (zero : α) : Folder 
goal: Lean.Compiler.LCNF.Simp.ConstantFold.Folder

full_name: Lean.Compiler.LCNF.Simp.ConstantFold.Folder.rightAnnihilator
code: /--
Provide a folder for an operation with a right annihilator.
-/
def Folder.rightAnnihilator [Literal α] [BEq α] (annihilator : α) (zero : α) : Folder 
goal: Lean.Compiler.LCNF.Simp.ConstantFold.Folder

full_name: Lean.Compiler.LCNF.Simp.ConstantFold.Folder.divShift
code: def Folder.divShift [Literal α] [BEq α] (shiftRight : Name) (pow2 : α → α) (log2 : α → α) : Folder 
goal: Lean.Compiler.LCNF.Simp.ConstantFold.Folder

full_name: Lean.Compiler.LCNF.Simp.ConstantFold.Folder.mulRhsShift
code: def Folder.mulRhsShift [Literal α] [BEq α] (shiftLeft : Name) (pow2 : α → α) (log2 : α → α) : Folder 
goal: Lean.Compiler.LCNF.Simp.ConstantFold.Folder

full_name: Lean.Compiler.LCNF.Simp.ConstantFold.Folder.mulLhsShift
code: def Folder.mulLhsShift [Literal α] [BEq α] (shiftLeft : Name) (pow2 : α → α) (log2 : α → α) : Folder 
goal: Lean.Compiler.LCNF.Simp.ConstantFold.Folder

full_name: Lean.Compiler.LCNF.Simp.ConstantFold.Folder.first
code: /--
Pick the first folder out of `folders` that succeeds.
-/
def Folder.first (folders : Array Folder) : Folder 
goal: Lean.Compiler.LCNF.Simp.ConstantFold.Folder

full_name: Lean.Compiler.LCNF.Simp.ConstantFold.Folder.leftRightNeutral
code: /--
Provide a folder for an operation that has the same left and right neutral element.
-/
def Folder.leftRightNeutral [Literal α] [BEq α] (neutral : α) : Folder 
goal: Lean.Compiler.LCNF.Simp.ConstantFold.Folder

full_name: Lean.Compiler.LCNF.Simp.ConstantFold.Folder.leftRightAnnihilator
code: /--
Provide a folder for an operation that has the same left and right annihilator.
-/
def Folder.leftRightAnnihilator [Literal α] [BEq α] (annihilator : α) (zero : α) : Folder 
goal: Lean.Compiler.LCNF.Simp.ConstantFold.Folder

full_name: Lean.Compiler.LCNF.Simp.ConstantFold.higherOrderLiteralFolders
code: /--
Literal folders for higher order datastructures.
-/
def higherOrderLiteralFolders : List (Name × Folder) 
goal: List (Lean.Name × Lean.Compiler.LCNF.Simp.ConstantFold.Folder)

full_name: Lean.Compiler.LCNF.Simp.ConstantFold.Folder.mulShift
code: def Folder.mulShift [Literal α] [BEq α] (shiftLeft : Name) (pow2 : α → α) (log2 : α → α) : Folder 
goal: Lean.Compiler.LCNF.Simp.ConstantFold.Folder

full_name: Lean.Compiler.LCNF.Simp.ConstantFold.arithmeticFolders
code: /--
All arithmetic folders.
-/
def arithmeticFolders : List (Name × Folder) 
goal: List (Lean.Name × Lean.Compiler.LCNF.Simp.ConstantFold.Folder)

full_name: Lean.Compiler.LCNF.Simp.ConstantFold.relationFolders
code: def relationFolders : List (Name × Folder) 
goal: List (Lean.Name × Lean.Compiler.LCNF.Simp.ConstantFold.Folder)

full_name: Lean.Compiler.LCNF.Simp.ConstantFold.stringFolders
code: /--
All string folders.
-/
def stringFolders : List (Name × Folder) 
goal: List (Lean.Name × Lean.Compiler.LCNF.Simp.ConstantFold.Folder)

full_name: Lean.Compiler.LCNF.Simp.ConstantFold.applyFolders
code: /--
Apply all known folders to `decl`.
-/
def applyFolders (decl : LetDecl) (folders : SMap Name Folder) : CompilerM (Option (Array CodeDecl)) 
goal: Lean.Compiler.LCNF.CompilerM (Option (Array Lean.Compiler.LCNF.CodeDecl))

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Compiler.LCNF.Simp.ConstantFold.0.Lean.Compiler.LCNF.Simp.ConstantFold.getFolderCoreUnsafe
code: private unsafe def getFolderCoreUnsafe (env : Environment) (opts : Options) (declName : Name) : ExceptT String Id Folder 
goal: ExceptT String Id Lean.Compiler.LCNF.Simp.ConstantFold.Folder

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Compiler.LCNF.Simp.ConstantFold.0.Lean.Compiler.LCNF.Simp.ConstantFold.getFolderCore
code: @[implemented_by getFolderCoreUnsafe]
private opaque getFolderCore (env : Environment) (opts : Options) (declName : Name) : ExceptT String Id Folder
goal: ExceptT String Id Lean.Compiler.LCNF.Simp.ConstantFold.Folder

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Compiler.LCNF.Simp.ConstantFold.0.Lean.Compiler.LCNF.Simp.ConstantFold.getFolder
code: private def getFolder (declName : Name) : CoreM Folder 
goal: Lean.CoreM Lean.Compiler.LCNF.Simp.ConstantFold.Folder

full_name: Lean.Compiler.LCNF.Simp.ConstantFold.builtinFolders
code: def builtinFolders : SMap Name Folder 
goal: Lean.SMap Lean.Name Lean.Compiler.LCNF.Simp.ConstantFold.Folder

full_name: Lean.Compiler.LCNF.Simp.ConstantFold.FolderOleanEntry
code: structure FolderOleanEntry where
  declName : Name
  folderDeclName : Name
goal: Type

full_name: Lean.Compiler.LCNF.Simp.ConstantFold.FolderOleanEntry.folderDeclName
code: structure FolderOleanEntry where
  declName : Name
  folderDeclName : Name
goal: Lean.Name

full_name: Lean.Compiler.LCNF.Simp.ConstantFold.FolderOleanEntry.declName
code: structure FolderOleanEntry where
  declName : Name
  folderDeclName : Name
goal: Lean.Name

full_name: Lean.Compiler.LCNF.Simp.ConstantFold.FolderEntry
code: structure FolderEntry extends FolderOleanEntry where
  folder : Folder
goal: Type

full_name: Lean.Compiler.LCNF.Simp.ConstantFold.FolderEntry.folder
code: structure FolderEntry extends FolderOleanEntry where
  folder : Folder
goal: Lean.Compiler.LCNF.Simp.ConstantFold.Folder

full_name: Lean.Compiler.LCNF.Simp.ConstantFold.folderExt
code: builtin_initialize folderExt : PersistentEnvExtension FolderOleanEntry FolderEntry (List FolderOleanEntry × SMap Name Folder) ←
  registerPersistentEnvExtension {
    mkInitial := return ([], builtinFolders)
    addImportedFn := fun entriesArray => do
      let ctx ← read
      let mut folders := builtinFolders
      for entries in entriesArray do
        for { declName, folderDeclName } in entries do
          let folder ← IO.ofExcept <| getFolderCore ctx.env ctx.opts folderDeclName
          folders := folders.insert declName folder
      return ([], folders.switch)
    addEntryFn := fun (entries, map) entry => (entry.toFolderOleanEntry :: entries, map.insert entry.declName entry.folder)
    exportEntriesFn := fun (entries, _) => entries.reverse.toArray
  }
goal: Lean.PersistentEnvExtension Lean.Compiler.LCNF.Simp.ConstantFold.FolderOleanEntry
  Lean.Compiler.LCNF.Simp.ConstantFold.FolderEntry
  (List Lean.Compiler.LCNF.Simp.ConstantFold.FolderOleanEntry ×
    Lean.SMap Lean.Name Lean.Compiler.LCNF.Simp.ConstantFold.Folder)

full_name: Lean.Compiler.LCNF.Simp.ConstantFold.initFn._@..lake.packages.lean4.src.lean.Lean.Compiler.LCNF.Simp.ConstantFold._hyg.4843
code: builtin_initialize folderExt : PersistentEnvExtension FolderOleanEntry FolderEntry (List FolderOleanEntry × SMap Name Folder) ←
  registerPersistentEnvExtension {
    mkInitial := return ([], builtinFolders)
    addImportedFn := fun entriesArray => do
      let ctx ← read
      let mut folders := builtinFolders
      for entries in entriesArray do
        for { declName, folderDeclName } in entries do
          let folder ← IO.ofExcept <| getFolderCore ctx.env ctx.opts folderDeclName
          folders := folders.insert declName folder
      return ([], folders.switch)
    addEntryFn := fun (entries, map) entry => (entry.toFolderOleanEntry :: entries, map.insert entry.declName entry.folder)
    exportEntriesFn := fun (entries, _) => entries.reverse.toArray
  }
goal: IO
  (Lean.PersistentEnvExtension Lean.Compiler.LCNF.Simp.ConstantFold.FolderOleanEntry
    Lean.Compiler.LCNF.Simp.ConstantFold.FolderEntry
    (List Lean.Compiler.LCNF.Simp.ConstantFold.FolderOleanEntry ×
      Lean.SMap Lean.Name Lean.Compiler.LCNF.Simp.ConstantFold.Folder))

full_name: Lean.Compiler.LCNF.Simp.ConstantFold.registerFolder
code: def registerFolder (declName : Name) (folderDeclName : Name) : CoreM Unit 
goal: Lean.CoreM Unit

full_name: Lean.Compiler.LCNF.Simp.ConstantFold.getFolders
code: def getFolders : CoreM (SMap Name Folder) 
goal: Lean.CoreM (Lean.SMap Lean.Name Lean.Compiler.LCNF.Simp.ConstantFold.Folder)

full_name: Lean.Compiler.LCNF.Simp.ConstantFold.foldConstants
code: /--
Apply a list of default folders to `decl`
-/
def foldConstants (decl : LetDecl) : CompilerM (Option (Array CodeDecl)) 
goal: Lean.Compiler.LCNF.CompilerM (Option (Array Lean.Compiler.LCNF.CodeDecl))