File: .lake/packages/lean4/src/lean/Lean/Elab/PreDefinition/WF/GuessLex.lean

full_name: Lean.Elab.WF.GuessLex.showInferredTerminationBy
code: register_builtin_option showInferredTerminationBy : Bool := {
  defValue := false
  descr    := "In recursive definitions, show the inferred `termination_by` measure."
}
goal: Lean.Option Bool

full_name: Lean.Elab.WF.GuessLex.initFn._@..lake.packages.lean4.src.lean.Lean.Elab.PreDefinition.WF.GuessLex._hyg.9
code: register_builtin_option showInferredTerminationBy : Bool := {
  defValue := false
  descr    := "In recursive definitions, show the inferred `termination_by` measure."
}
goal: IO (Lean.Option Bool)

full_name: Lean.Elab.WF.GuessLex.originalVarNames
code: /--
Given a predefinition, return the variabe names in the outermost lambdas.
Includes the “fixed prefix”.

The length of the returned array is also used to determine the arity
of the function, so it should match what `packDomain` does.
-/
def originalVarNames (preDef : PreDefinition) : MetaM (Array Name) 
goal: Lean.MetaM (Array Lean.Name)

full_name: Lean.Elab.WF.GuessLex.naryVarNames.freshen
code: /--
Given the original parameter names from `originalVarNames`, find
good variable names to be used when talking about termination arguments:
Use user-given parameter names if present; use x1...xn otherwise.

The names ought to accessible (no macro scopes) and fresh wrt to the current environment,
so that with `showInferredTerminationBy` we can print them to the user reliably.
We do that by appending `'` as needed.

It is possible (but unlikely without malice) that some of the user-given names
shadow each other, and the guessed relation refers to the wrong one. In that
case, the user gets to keep both pieces (and may have to rename variables).
-/
partial
def naryVarNames (xs : Array Name) : MetaM (Array Name) 
goal: Lean.MetaM Lean.Name

full_name: Lean.Elab.WF.GuessLex.naryVarNames
code: /--
Given the original parameter names from `originalVarNames`, find
good variable names to be used when talking about termination arguments:
Use user-given parameter names if present; use x1...xn otherwise.

The names ought to accessible (no macro scopes) and fresh wrt to the current environment,
so that with `showInferredTerminationBy` we can print them to the user reliably.
We do that by appending `'` as needed.

It is possible (but unlikely without malice) that some of the user-given names
shadow each other, and the guessed relation refers to the wrong one. In that
case, the user gets to keep both pieces (and may have to rename variables).
-/
partial
def naryVarNames (xs : Array Name) : MetaM (Array Name) 
goal: Lean.MetaM (Array Lean.Name)

full_name: Lean.Elab.WF.GuessLex.Measure
code: /-- A termination measure with extra fields for use within GuessLex -/
structure Measure extends TerminationArgument where
  /--
  Like `.fn`, but unconditionally with `sizeOf` at the right type.
  We use this one when in `evalRecCall`
  -/
  natFn : Expr
deriving Inhabited
goal: Type

full_name: Lean.Elab.WF.GuessLex.Measure.natFn
code: /-- A termination measure with extra fields for use within GuessLex -/
structure Measure extends TerminationArgument where
  /--
  Like `.fn`, but unconditionally with `sizeOf` at the right type.
  We use this one when in `evalRecCall`
  -/
  natFn : Expr
deriving Inhabited
goal: Lean.Expr

full_name: Lean.Elab.WF.GuessLex.instInhabitedMeasure
code: /-- A termination measure with extra fields for use within GuessLex -/
structure Measure extends TerminationArgument where
  /--
  Like `.fn`, but unconditionally with `sizeOf` at the right type.
  We use this one when in `evalRecCall`
  -/
  natFn : Expr
deriving Inhabited
goal: Inhabited Lean.Elab.WF.GuessLex.Measure

full_name: Lean.Elab.WF.GuessLex.Measure.toString
code: /-- String desription of this measure -/
def Measure.toString (measure : Measure) : MetaM String 
goal: Lean.MetaM String

full_name: Lean.Elab.WF.GuessLex.mayOmitSizeOf
code: /--
Determine if the measure for parameter `x` should be `sizeOf x` or just `x`.

For non-mutual definitions, we omit `sizeOf` when the argument does not depend on
the other varying parameters, and its `WellFoundedRelation` instance goes via `SizeOf`.

For mutual definitions, we omit `sizeOf` only when the argument is (at reducible transparency!) of
type `Nat` (else we'd have to worry about differently-typed measures from different functions to
line up).
-/
def mayOmitSizeOf (is_mutual : Bool) (args : Array Expr) (x : Expr) : MetaM Bool 
goal: Lean.MetaM Bool

full_name: Lean.Elab.WF.GuessLex.withUserNames
code: /-- Sets the user names for the given freevars in `xs`. -/
def withUserNames {α} (xs : Array Expr) (ns : Array Name) (k : MetaM α) : MetaM α 
goal: Lean.MetaM α

full_name: Lean.Elab.WF.GuessLex.simpleMeasures
code: /-- Create one measure for each (eligible) parameter of the given predefintion.  -/
def simpleMeasures (preDefs : Array PreDefinition) (fixedPrefixSize : Nat)
    (userVarNamess : Array (Array Name)) : MetaM (Array (Array Measure)) 
goal: Lean.MetaM (Array (Array Lean.Elab.WF.GuessLex.Measure))

full_name: Lean.Elab.WF.GuessLex.M
code: /-- Internal monad used by `withRecApps` -/
abbrev M (recFnName : Name) (α β : Type) : Type 
goal: Type

full_name: Lean.Elab.WF.GuessLex.withRecApps.processRec
code: /--
Traverses the given expression `e`, and invokes the continuation `k`
at every saturated call to `recFnName`.

The expression `param` is passed along, and refined when going under a matcher
or `casesOn` application.
-/
partial def withRecApps {α} (recFnName : Name) (fixedPrefixSize : Nat) (param : Expr) (e : Expr)
    (k : Expr → Array Expr → MetaM α) : MetaM (Array α) 
goal: Lean.Elab.WF.GuessLex.M recFnName α Unit

full_name: Lean.Elab.WF.GuessLex.withRecApps
code: /--
Traverses the given expression `e`, and invokes the continuation `k`
at every saturated call to `recFnName`.

The expression `param` is passed along, and refined when going under a matcher
or `casesOn` application.
-/
partial def withRecApps {α} (recFnName : Name) (fixedPrefixSize : Nat) (param : Expr) (e : Expr)
    (k : Expr → Array Expr → MetaM α) : MetaM (Array α) 
goal: Lean.MetaM (Array α)

full_name: Lean.Elab.WF.GuessLex.withRecApps.containsRecFn
code: /--
Traverses the given expression `e`, and invokes the continuation `k`
at every saturated call to `recFnName`.

The expression `param` is passed along, and refined when going under a matcher
or `casesOn` application.
-/
partial def withRecApps {α} (recFnName : Name) (fixedPrefixSize : Nat) (param : Expr) (e : Expr)
    (k : Expr → Array Expr → MetaM α) : MetaM (Array α) 
goal: Lean.Elab.WF.GuessLex.M recFnName α Bool

full_name: Lean.Elab.WF.GuessLex.withRecApps.loop
code: /--
Traverses the given expression `e`, and invokes the continuation `k`
at every saturated call to `recFnName`.

The expression `param` is passed along, and refined when going under a matcher
or `casesOn` application.
-/
partial def withRecApps {α} (recFnName : Name) (fixedPrefixSize : Nat) (param : Expr) (e : Expr)
    (k : Expr → Array Expr → MetaM α) : MetaM (Array α) 
goal: Lean.Elab.WF.GuessLex.M recFnName α Unit

full_name: Lean.Elab.WF.GuessLex.withRecApps.processApp
code: /--
Traverses the given expression `e`, and invokes the continuation `k`
at every saturated call to `recFnName`.

The expression `param` is passed along, and refined when going under a matcher
or `casesOn` application.
-/
partial def withRecApps {α} (recFnName : Name) (fixedPrefixSize : Nat) (param : Expr) (e : Expr)
    (k : Expr → Array Expr → MetaM α) : MetaM (Array α) 
goal: Lean.Elab.WF.GuessLex.M recFnName α Unit

full_name: Lean.Elab.WF.GuessLex.SavedLocalContext.savedLocalInstances
code: /--
A `SavedLocalContext` captures the state and local context of a `MetaM`, to be continued later.
-/
structure SavedLocalContext where
  savedLocalContext : LocalContext
  savedLocalInstances : LocalInstances
  savedState : Meta.SavedState
goal: Lean.LocalInstances

full_name: Lean.Elab.WF.GuessLex.SavedLocalContext.savedState
code: /--
A `SavedLocalContext` captures the state and local context of a `MetaM`, to be continued later.
-/
structure SavedLocalContext where
  savedLocalContext : LocalContext
  savedLocalInstances : LocalInstances
  savedState : Meta.SavedState
goal: Lean.Meta.SavedState

full_name: Lean.Elab.WF.GuessLex.SavedLocalContext.savedLocalContext
code: /--
A `SavedLocalContext` captures the state and local context of a `MetaM`, to be continued later.
-/
structure SavedLocalContext where
  savedLocalContext : LocalContext
  savedLocalInstances : LocalInstances
  savedState : Meta.SavedState
goal: Lean.LocalContext

full_name: Lean.Elab.WF.GuessLex.SavedLocalContext
code: /--
A `SavedLocalContext` captures the state and local context of a `MetaM`, to be continued later.
-/
structure SavedLocalContext where
  savedLocalContext : LocalContext
  savedLocalInstances : LocalInstances
  savedState : Meta.SavedState
goal: Type

full_name: Lean.Elab.WF.GuessLex.SavedLocalContext.create
code: /-- Capture the `MetaM` state including local context. -/
def SavedLocalContext.create : MetaM SavedLocalContext 
goal: Lean.MetaM Lean.Elab.WF.GuessLex.SavedLocalContext

full_name: Lean.Elab.WF.GuessLex.SavedLocalContext.run
code: /-- Run a `MetaM` action in the saved state. -/
def SavedLocalContext.run {α} (slc : SavedLocalContext) (k : MetaM α) :
    MetaM α 
goal: Lean.MetaM α

full_name: Lean.Elab.WF.GuessLex.RecCallWithContext
code: /-- A `RecCallWithContext` focuses on a single recursive call in a unary predefinition,
and runs the given action in the context of that call.  -/
structure RecCallWithContext where
  /-- Syntax location of recursive call -/
  ref : Syntax
  /-- Function index of caller -/
  caller : Nat
  /-- Parameters of caller (including fixed prefix) -/
  params : Array Expr
  /-- Function index of callee -/
  callee : Nat
  /-- Arguments to callee (including fixed prefix) -/
  args : Array Expr
  ctxt : SavedLocalContext
goal: Type

full_name: Lean.Elab.WF.GuessLex.RecCallWithContext.ref
code: /-- A `RecCallWithContext` focuses on a single recursive call in a unary predefinition,
and runs the given action in the context of that call.  -/
structure RecCallWithContext where
  /-- Syntax location of recursive call -/
  ref : Syntax
  /-- Function index of caller -/
  caller : Nat
  /-- Parameters of caller (including fixed prefix) -/
  params : Array Expr
  /-- Function index of callee -/
  callee : Nat
  /-- Arguments to callee (including fixed prefix) -/
  args : Array Expr
  ctxt : SavedLocalContext
goal: Lean.Syntax

full_name: Lean.Elab.WF.GuessLex.RecCallWithContext.ctxt
code: /-- A `RecCallWithContext` focuses on a single recursive call in a unary predefinition,
and runs the given action in the context of that call.  -/
structure RecCallWithContext where
  /-- Syntax location of recursive call -/
  ref : Syntax
  /-- Function index of caller -/
  caller : Nat
  /-- Parameters of caller (including fixed prefix) -/
  params : Array Expr
  /-- Function index of callee -/
  callee : Nat
  /-- Arguments to callee (including fixed prefix) -/
  args : Array Expr
  ctxt : SavedLocalContext
goal: Lean.Elab.WF.GuessLex.SavedLocalContext

full_name: Lean.Elab.WF.GuessLex.RecCallWithContext.caller
code: /-- A `RecCallWithContext` focuses on a single recursive call in a unary predefinition,
and runs the given action in the context of that call.  -/
structure RecCallWithContext where
  /-- Syntax location of recursive call -/
  ref : Syntax
  /-- Function index of caller -/
  caller : Nat
  /-- Parameters of caller (including fixed prefix) -/
  params : Array Expr
  /-- Function index of callee -/
  callee : Nat
  /-- Arguments to callee (including fixed prefix) -/
  args : Array Expr
  ctxt : SavedLocalContext
goal: Nat

full_name: Lean.Elab.WF.GuessLex.RecCallWithContext.args
code: /-- A `RecCallWithContext` focuses on a single recursive call in a unary predefinition,
and runs the given action in the context of that call.  -/
structure RecCallWithContext where
  /-- Syntax location of recursive call -/
  ref : Syntax
  /-- Function index of caller -/
  caller : Nat
  /-- Parameters of caller (including fixed prefix) -/
  params : Array Expr
  /-- Function index of callee -/
  callee : Nat
  /-- Arguments to callee (including fixed prefix) -/
  args : Array Expr
  ctxt : SavedLocalContext
goal: Array Lean.Expr

full_name: Lean.Elab.WF.GuessLex.RecCallWithContext.callee
code: /-- A `RecCallWithContext` focuses on a single recursive call in a unary predefinition,
and runs the given action in the context of that call.  -/
structure RecCallWithContext where
  /-- Syntax location of recursive call -/
  ref : Syntax
  /-- Function index of caller -/
  caller : Nat
  /-- Parameters of caller (including fixed prefix) -/
  params : Array Expr
  /-- Function index of callee -/
  callee : Nat
  /-- Arguments to callee (including fixed prefix) -/
  args : Array Expr
  ctxt : SavedLocalContext
goal: Nat

full_name: Lean.Elab.WF.GuessLex.RecCallWithContext.params
code: /-- A `RecCallWithContext` focuses on a single recursive call in a unary predefinition,
and runs the given action in the context of that call.  -/
structure RecCallWithContext where
  /-- Syntax location of recursive call -/
  ref : Syntax
  /-- Function index of caller -/
  caller : Nat
  /-- Parameters of caller (including fixed prefix) -/
  params : Array Expr
  /-- Function index of callee -/
  callee : Nat
  /-- Arguments to callee (including fixed prefix) -/
  args : Array Expr
  ctxt : SavedLocalContext
goal: Array Lean.Expr

full_name: Lean.Elab.WF.GuessLex.RecCallWithContext.create
code: /-- Store the current recursive call and its context. -/
def RecCallWithContext.create (ref : Syntax) (caller : Nat) (params : Array Expr) (callee : Nat)
    (args : Array Expr) : MetaM RecCallWithContext 
goal: Lean.MetaM Lean.Elab.WF.GuessLex.RecCallWithContext

full_name: Lean.Elab.WF.GuessLex.filterSubsumed
code: /--
The elaborator is prone to duplicate terms, including recursive calls, even if the user
only wrote a single one. This duplication is wasteful if we run the tactics on duplicated
calls, and confusing in the output of GuessLex. So prune the list of recursive calls,
and remove those where another call exists that has the same goal and context that is no more
specific.
-/
def filterSubsumed (rcs : Array RecCallWithContext ) : Array RecCallWithContext 
goal: Array Lean.Elab.WF.GuessLex.RecCallWithContext

full_name: Lean.Elab.WF.GuessLex.collectRecCalls
code: /--
Traverse a unary `PreDefinition`, and returns a `WithRecCall` closure for each recursive
call site.
-/
def collectRecCalls (unaryPreDef : PreDefinition) (fixedPrefixSize : Nat)
    (argsPacker : ArgsPacker) : MetaM (Array RecCallWithContext) 
goal: Lean.MetaM (Array Lean.Elab.WF.GuessLex.RecCallWithContext)

full_name: Lean.Elab.WF.GuessLex.isNatCmp
code: /-- Is the expression a `<`-like comparison of `Nat` expressions -/
def isNatCmp (e : Expr) : Option (Expr × Expr) 
goal: Option (Lean.Expr × Lean.Expr)

full_name: Lean.Elab.WF.GuessLex.complexMeasures
code: def complexMeasures (preDefs : Array PreDefinition) (fixedPrefixSize : Nat)
    (userVarNamess : Array (Array Name)) (recCalls : Array RecCallWithContext) :
    MetaM (Array (Array Measure)) 
goal: Lean.MetaM (Array (Array Lean.Elab.WF.GuessLex.Measure))

full_name: Lean.Elab.WF.GuessLex.instDecidableEqGuessLexRel
code: /-- A `GuessLexRel` described how a recursive call affects a measure; whether it
decreases strictly, non-strictly, is equal, or else.  -/
inductive GuessLexRel | lt | eq | le | no_idea
deriving Repr, DecidableEq
goal: DecidableEq Lean.Elab.WF.GuessLex.GuessLexRel

full_name: Lean.Elab.WF.GuessLex.GuessLexRel.eq
code: /-- A `GuessLexRel` described how a recursive call affects a measure; whether it
decreases strictly, non-strictly, is equal, or else.  -/
inductive GuessLexRel | lt | eq | le | no_idea
deriving Repr, DecidableEq
goal: Lean.Elab.WF.GuessLex.GuessLexRel

full_name: Lean.Elab.WF.GuessLex.GuessLexRel.lt
code: /-- A `GuessLexRel` described how a recursive call affects a measure; whether it
decreases strictly, non-strictly, is equal, or else.  -/
inductive GuessLexRel | lt | eq | le | no_idea
deriving Repr, DecidableEq
goal: Lean.Elab.WF.GuessLex.GuessLexRel

full_name: Lean.Elab.WF.GuessLex.instReprGuessLexRel
code: /-- A `GuessLexRel` described how a recursive call affects a measure; whether it
decreases strictly, non-strictly, is equal, or else.  -/
inductive GuessLexRel | lt | eq | le | no_idea
deriving Repr, DecidableEq
goal: Repr Lean.Elab.WF.GuessLex.GuessLexRel

full_name: Lean.Elab.WF.GuessLex.GuessLexRel.no_idea
code: /-- A `GuessLexRel` described how a recursive call affects a measure; whether it
decreases strictly, non-strictly, is equal, or else.  -/
inductive GuessLexRel | lt | eq | le | no_idea
deriving Repr, DecidableEq
goal: Lean.Elab.WF.GuessLex.GuessLexRel

full_name: Lean.Elab.WF.GuessLex.GuessLexRel.le
code: /-- A `GuessLexRel` described how a recursive call affects a measure; whether it
decreases strictly, non-strictly, is equal, or else.  -/
inductive GuessLexRel | lt | eq | le | no_idea
deriving Repr, DecidableEq
goal: Lean.Elab.WF.GuessLex.GuessLexRel

full_name: Lean.Elab.WF.GuessLex.GuessLexRel
code: /-- A `GuessLexRel` described how a recursive call affects a measure; whether it
decreases strictly, non-strictly, is equal, or else.  -/
inductive GuessLexRel | lt | eq | le | no_idea
deriving Repr, DecidableEq
goal: Type

full_name: Lean.Elab.WF.GuessLex.instToStringGuessLexRel
code: instance : ToString GuessLexRel 
goal: ToString Lean.Elab.WF.GuessLex.GuessLexRel

full_name: Lean.Elab.WF.GuessLex.instToFormatGuessLexRel
code: instance : ToFormat GuessLexRel 
goal: Lean.ToFormat Lean.Elab.WF.GuessLex.GuessLexRel

full_name: Lean.Elab.WF.GuessLex.GuessLexRel.toNatRel
code: /-- Given a `GuessLexRel`, produce a binary `Expr` that relates two `Nat` values accordingly. -/
def GuessLexRel.toNatRel : GuessLexRel → Expr
  
goal: Lean.Elab.WF.GuessLex.GuessLexRel → Lean.Expr

full_name: Lean.Elab.WF.GuessLex.evalRecCall
code: /--
For a given recursive call, and a choice of parameter and argument index,
try to prove equality, < or ≤.
-/
def evalRecCall (decrTactic? : Option DecreasingBy) (callerMeasures calleeMeasures : Array Measure)
  (rcc : RecCallWithContext) (callerMeasureIdx calleeMeasureIdx : Nat) : MetaM GuessLexRel 
goal: Lean.MetaM Lean.Elab.WF.GuessLex.GuessLexRel

full_name: Lean.Elab.WF.GuessLex.RecCallCache.mk''
code: structure RecCallCache where mk'' ::
  decrTactic? : Option DecreasingBy
  callerMeasures : Array Measure
  calleeMeasures : Array Measure
  rcc : RecCallWithContext
  cache : IO.Ref (Array (Array (Option GuessLexRel)))
goal: Lean.Elab.WF.GuessLex.RecCallCache

full_name: Lean.Elab.WF.GuessLex.RecCallCache.callerMeasures
code: structure RecCallCache where mk'' ::
  decrTactic? : Option DecreasingBy
  callerMeasures : Array Measure
  calleeMeasures : Array Measure
  rcc : RecCallWithContext
  cache : IO.Ref (Array (Array (Option GuessLexRel)))
goal: Array Lean.Elab.WF.GuessLex.Measure

full_name: Lean.Elab.WF.GuessLex.RecCallCache.calleeMeasures
code: structure RecCallCache where mk'' ::
  decrTactic? : Option DecreasingBy
  callerMeasures : Array Measure
  calleeMeasures : Array Measure
  rcc : RecCallWithContext
  cache : IO.Ref (Array (Array (Option GuessLexRel)))
goal: Array Lean.Elab.WF.GuessLex.Measure

full_name: Lean.Elab.WF.GuessLex.RecCallCache.decrTactic?
code: structure RecCallCache where mk'' ::
  decrTactic? : Option DecreasingBy
  callerMeasures : Array Measure
  calleeMeasures : Array Measure
  rcc : RecCallWithContext
  cache : IO.Ref (Array (Array (Option GuessLexRel)))
goal: Option Lean.Elab.WF.DecreasingBy

full_name: Lean.Elab.WF.GuessLex.RecCallCache.cache
code: structure RecCallCache where mk'' ::
  decrTactic? : Option DecreasingBy
  callerMeasures : Array Measure
  calleeMeasures : Array Measure
  rcc : RecCallWithContext
  cache : IO.Ref (Array (Array (Option GuessLexRel)))
goal: IO.Ref (Array (Array (Option Lean.Elab.WF.GuessLex.GuessLexRel)))

full_name: Lean.Elab.WF.GuessLex.RecCallCache
code: structure RecCallCache where mk'' ::
  decrTactic? : Option DecreasingBy
  callerMeasures : Array Measure
  calleeMeasures : Array Measure
  rcc : RecCallWithContext
  cache : IO.Ref (Array (Array (Option GuessLexRel)))
goal: Type

full_name: Lean.Elab.WF.GuessLex.RecCallCache.rcc
code: structure RecCallCache where mk'' ::
  decrTactic? : Option DecreasingBy
  callerMeasures : Array Measure
  calleeMeasures : Array Measure
  rcc : RecCallWithContext
  cache : IO.Ref (Array (Array (Option GuessLexRel)))
goal: Lean.Elab.WF.GuessLex.RecCallWithContext

full_name: Lean.Elab.WF.GuessLex.RecCallCache.mk
code: /-- Create a cache to memoize calls to `evalRecCall descTactic? rcc` -/
def RecCallCache.mk (decrTactics : Array (Option DecreasingBy)) (measuress : Array (Array Measure))
    (rcc : RecCallWithContext) :
    BaseIO RecCallCache 
goal: BaseIO Lean.Elab.WF.GuessLex.RecCallCache

full_name: Lean.Elab.WF.GuessLex.RecCallCache.eval
code: /-- Run `evalRecCall` and cache there result -/
def RecCallCache.eval (rc: RecCallCache) (callerMeasureIdx calleeMeasureIdx : Nat) : MetaM GuessLexRel 
goal: Lean.MetaM Lean.Elab.WF.GuessLex.GuessLexRel

full_name: Lean.Elab.WF.GuessLex.RecCallCache.prettyEntry
code: /-- Print a single cache entry as a string, without forcing it -/
def RecCallCache.prettyEntry (rcc : RecCallCache) (callerMeasureIdx calleeMeasureIdx : Nat) : MetaM String 
goal: Lean.MetaM String

full_name: Lean.Elab.WF.GuessLex.MutualMeasure.args
code: /-- The measures that we order lexicographically can be comparing arguments,
or numbering the functions -/
inductive MutualMeasure where
  /-- For every function, the given argument index -/
  | args : Array Nat → MutualMeasure
  /-- The given function index is assigned 1, the rest 0 -/
  | func : Nat → MutualMeasure
goal: Array Nat → Lean.Elab.WF.GuessLex.MutualMeasure

full_name: Lean.Elab.WF.GuessLex.MutualMeasure.func
code: /-- The measures that we order lexicographically can be comparing arguments,
or numbering the functions -/
inductive MutualMeasure where
  /-- For every function, the given argument index -/
  | args : Array Nat → MutualMeasure
  /-- The given function index is assigned 1, the rest 0 -/
  | func : Nat → MutualMeasure
goal: Nat → Lean.Elab.WF.GuessLex.MutualMeasure

full_name: Lean.Elab.WF.GuessLex.MutualMeasure
code: /-- The measures that we order lexicographically can be comparing arguments,
or numbering the functions -/
inductive MutualMeasure where
  /-- For every function, the given argument index -/
  | args : Array Nat → MutualMeasure
  /-- The given function index is assigned 1, the rest 0 -/
  | func : Nat → MutualMeasure
goal: Type

full_name: Lean.Elab.WF.GuessLex.inspectCall
code: /-- Evaluate a recursive call at a given `MutualMeasure` -/
def inspectCall (rc : RecCallCache) : MutualMeasure → MetaM GuessLexRel
  
goal: Lean.Elab.WF.GuessLex.MutualMeasure → Lean.MetaM Lean.Elab.WF.GuessLex.GuessLexRel

full_name: Lean.Elab.WF.GuessLex.generateCombinations?
code: /--
Generate all combination of measures. Assumes we have numbered the measures of each function,
and their counts is in `numMeasures`.

This puts the uniform combinations ([0,0,0], [1,1,1]) to the front; they are commonly most useful to
try first, when the mutually recursive functions have similar argument structures
-/
partial def generateCombinations? (numMeasures : Array Nat) (threshold : Nat := 32) :
    Option (Array (Array Nat)) 
goal: Option (Array (Array Nat))

full_name: Lean.Elab.WF.GuessLex.generateCombinations?.goUniform
code: /--
Generate all combination of measures. Assumes we have numbered the measures of each function,
and their counts is in `numMeasures`.

This puts the uniform combinations ([0,0,0], [1,1,1]) to the front; they are commonly most useful to
try first, when the mutually recursive functions have similar argument structures
-/
partial def generateCombinations? (numMeasures : Array Nat) (threshold : Nat := 32) :
    Option (Array (Array Nat)) 
goal: OptionT (StateM (Array (Array Nat))) Unit

full_name: Lean.Elab.WF.GuessLex.generateCombinations?.go
code: /--
Generate all combination of measures. Assumes we have numbered the measures of each function,
and their counts is in `numMeasures`.

This puts the uniform combinations ([0,0,0], [1,1,1]) to the front; they are commonly most useful to
try first, when the mutually recursive functions have similar argument structures
-/
partial def generateCombinations? (numMeasures : Array Nat) (threshold : Nat := 32) :
    Option (Array (Array Nat)) 
goal: OptionT (ReaderT (Array Nat) (StateM (Array (Array Nat)))) Unit

full_name: Lean.Elab.WF.GuessLex.generateMeasures
code: /--
Enumerate all meausures we want to try.

All arguments (resp. combinations thereof) and
possible orderings of functions (if more than one)
-/
def generateMeasures (numTermArgs : Array Nat) : MetaM (Array MutualMeasure) 
goal: Lean.MetaM (Array Lean.Elab.WF.GuessLex.MutualMeasure)

full_name: Lean.Elab.WF.GuessLex.solve.go
code: /--
The core logic of guessing the lexicographic order
Given a matrix that for each call and measure indicates whether that measure is
decreasing, equal, less-or-equal or unknown, It finds a sequence of measures
that is lexicographically decreasing.

The matrix is implemented here as an array of monadic query methods only so that
we can fill is lazily. Morally, this is a pure function
-/
partial def solve {m} {α} [Monad m] (measures : Array α)
  (calls : Array (α → m GuessLexRel)) : m (Option (Array α)) 
goal: m (Option (Array α))

full_name: Lean.Elab.WF.GuessLex.solve
code: /--
The core logic of guessing the lexicographic order
Given a matrix that for each call and measure indicates whether that measure is
decreasing, equal, less-or-equal or unknown, It finds a sequence of measures
that is lexicographically decreasing.

The matrix is implemented here as an array of monadic query methods only so that
we can fill is lazily. Morally, this is a pure function
-/
partial def solve {m} {α} [Monad m] (measures : Array α)
  (calls : Array (α → m GuessLexRel)) : m (Option (Array α)) 
goal: m (Option (Array α))

full_name: Lean.Elab.WF.GuessLex.formatTable
code: /--
Given a matrix (row-major) of strings, arranges them in tabular form.
First column is left-aligned, others right-aligned.
Single space as column separator.
-/
def formatTable : Array (Array String) → String 
goal: Array (Array String) → String

full_name: Lean.Elab.WF.GuessLex.RecCallWithContext.posString
code: /-- Concise textual representation of the source location of a recursive call  -/
def RecCallWithContext.posString (rcc : RecCallWithContext) : MetaM String 
goal: Lean.MetaM String

full_name: Lean.Elab.WF.GuessLex.measureHeader
code: /-- How to present the measure in the table header, possibly abbreviated. -/
def measureHeader (measure : Measure) : StateT (Nat × String) MetaM String 
goal: StateT (Nat × String) Lean.MetaM String

full_name: Lean.Elab.WF.GuessLex.collectHeaders
code: def collectHeaders {α} (a : StateT (Nat × String) MetaM α) : MetaM (α × String) 
goal: Lean.MetaM (α × String)

full_name: Lean.Elab.WF.GuessLex.explainNonMutualFailure
code: /-- Explain what we found out about the recursive calls (non-mutual case) -/
def explainNonMutualFailure (measures : Array Measure) (rcs : Array RecCallCache) : MetaM Format 
goal: Lean.MetaM Lean.Format

full_name: Lean.Elab.WF.GuessLex.explainMutualFailure
code: /-- Explain what we found out about the recursive calls (mutual case) -/
def explainMutualFailure (declNames : Array Name) (measuress : Array (Array Measure))
    (rcs : Array RecCallCache) : MetaM Format 
goal: Lean.MetaM Lean.Format

full_name: Lean.Elab.WF.GuessLex.explainFailure
code: def explainFailure (declNames : Array Name) (measuress : Array (Array Measure))
    (rcs : Array RecCallCache) : MetaM Format 
goal: Lean.MetaM Lean.Format

full_name: Lean.Elab.WF.GuessLex.mkProdElem
code: /--
For `#[x₁, .., xₙ]` create `(x₁, .., xₙ)`.
-/
def mkProdElem (xs : Array Expr) : MetaM Expr 
goal: Lean.MetaM Lean.Expr

full_name: Lean.Elab.WF.GuessLex.toTerminationArguments
code: def toTerminationArguments (preDefs : Array PreDefinition) (fixedPrefixSize : Nat)
    (userVarNamess : Array (Array Name)) (measuress : Array (Array Measure))
    (solution : Array MutualMeasure) : MetaM TerminationArguments 
goal: Lean.MetaM Lean.Elab.WF.TerminationArguments

full_name: Lean.Elab.WF.GuessLex.reportTermArgs
code: /--
Shows the inferred termination argument to the user, and implements `termination_by?`
-/
def reportTermArgs (preDefs : Array PreDefinition) (termArgs : TerminationArguments) : MetaM Unit 
goal: Lean.MetaM Unit

full_name: Lean.Elab.WF.guessLex
code: /--
Main entry point of this module:

Try to find a lexicographic ordering of the arguments for which the recursive definition
terminates. See the module doc string for a high-level overview.
-/
def guessLex (preDefs : Array PreDefinition) (unaryPreDef : PreDefinition)
    (fixedPrefixSize : Nat) (argsPacker : ArgsPacker) :
    MetaM TerminationArguments 
goal: Lean.MetaM Lean.Elab.WF.TerminationArguments