fix: condition for selecting split target
Only discriminants must not have loose bound variables
This commit is contained in:
parent
1591bb1640
commit
0cf2c19fc2
3 changed files with 28 additions and 6 deletions
|
|
@ -29,8 +29,12 @@ def MatcherInfo.numAlts (info : MatcherInfo) : Nat :=
|
|||
def MatcherInfo.arity (info : MatcherInfo) : Nat :=
|
||||
info.numParams + 1 + info.numDiscrs + info.numAlts
|
||||
|
||||
def MatcherInfo.getFirstDiscrPos (info : MatcherInfo) : Nat :=
|
||||
info.numParams + 1
|
||||
|
||||
def MatcherInfo.getMotivePos (info : MatcherInfo) : Nat :=
|
||||
info.numParams
|
||||
|
||||
namespace Extension
|
||||
|
||||
structure Entry where
|
||||
|
|
@ -79,15 +83,18 @@ def isMatcherCore (env : Environment) (declName : Name) : Bool :=
|
|||
def isMatcher [Monad m] [MonadEnv m] (declName : Name) : m Bool :=
|
||||
return isMatcherCore (← getEnv) declName
|
||||
|
||||
def isMatcherAppCore (env : Environment) (e : Expr) : Bool :=
|
||||
def isMatcherAppCore? (env : Environment) (e : Expr) : Option MatcherInfo :=
|
||||
let fn := e.getAppFn
|
||||
if fn.isConst then
|
||||
if let some matcherInfo := getMatcherInfoCore? env fn.constName! then
|
||||
e.getAppNumArgs ≥ matcherInfo.arity
|
||||
if e.getAppNumArgs ≥ matcherInfo.arity then some matcherInfo else none
|
||||
else
|
||||
false
|
||||
none
|
||||
else
|
||||
false
|
||||
none
|
||||
|
||||
def isMatcherAppCore (env : Environment) (e : Expr) : Bool :=
|
||||
isMatcherAppCore? env e |>.isSome
|
||||
|
||||
def isMatcherApp [Monad m] [MonadEnv m] (e : Expr) : m Bool :=
|
||||
return isMatcherAppCore (← getEnv) e
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ def splitMatch (mvarId : MVarId) (e : Expr) : MetaM (List MVarId) := do
|
|||
|
||||
/-- Return an `if-then-else` or `match-expr` to split. -/
|
||||
partial def findSplit? (env : Environment) (e : Expr) : Option Expr :=
|
||||
if let some target := e.find? fun e => !e.hasLooseBVars && (e.isIte || e.isDIte || isMatcherAppCore env e) then
|
||||
if let some target := e.find? isCandidate then
|
||||
if e.isIte || e.isDIte then
|
||||
let cond := target.getArg! 1 5
|
||||
-- Try to find a nested `if` in `cond`
|
||||
|
|
@ -109,6 +109,18 @@ partial def findSplit? (env : Environment) (e : Expr) : Option Expr :=
|
|||
some target
|
||||
else
|
||||
none
|
||||
where
|
||||
isCandidate (e : Expr) : Bool := do
|
||||
if e.isIte || e.isDIte then
|
||||
!(e.getArg! 1 5).hasLooseBVars
|
||||
else if let some info := isMatcherAppCore? env e then
|
||||
let args := e.getAppArgs
|
||||
for i in [info.getFirstDiscrPos : info.getFirstDiscrPos + info.numDiscrs] do
|
||||
if args[i].hasLooseBVars then
|
||||
return false
|
||||
return true
|
||||
else
|
||||
false
|
||||
|
||||
end Split
|
||||
|
||||
|
|
@ -121,6 +133,7 @@ def splitTarget? (mvarId : MVarId) : MetaM (Option (List MVarId)) := commitWhenS
|
|||
else
|
||||
splitMatch mvarId e
|
||||
else
|
||||
trace[Meta.Tactic.split] "did not find term to split\n{MessageData.ofGoal mvarId}"
|
||||
return none
|
||||
|
||||
def splitLocalDecl? (mvarId : MVarId) (fvarId : FVarId) : MetaM (Option (List MVarId)) := commitWhenSome? do
|
||||
|
|
@ -137,4 +150,6 @@ def splitLocalDecl? (mvarId : MVarId) (fvarId : FVarId) : MetaM (Option (List MV
|
|||
else
|
||||
return none
|
||||
|
||||
builtin_initialize registerTraceClass `Meta.Tactic.split
|
||||
|
||||
end Lean.Meta
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ def discharge? (useDecide := false) : Simp.Discharge := fun prop => do
|
|||
|
||||
/-- Return the condition of an `if` expression to case split. -/
|
||||
partial def findIfToSplit? (e : Expr) : Option Expr :=
|
||||
if let some iteApp := e.find? fun e => !e.hasLooseBVars && (e.isIte || e.isDIte) then
|
||||
if let some iteApp := e.find? fun e => (e.isIte || e.isDIte) && !(e.getArg! 1 5).hasLooseBVars then
|
||||
let cond := iteApp.getArg! 1 5
|
||||
-- Try to find a nested `if` in `cond`
|
||||
findIfToSplit? cond |>.getD cond
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue