feat: add applyMatchSplitter

It applies the match splitter without using simplification theorems
This commit is contained in:
Leonardo de Moura 2021-09-18 16:30:47 -07:00
parent c795a75045
commit 2775298fef

View file

@ -74,23 +74,22 @@ private def generalizeMatchDiscrs (mvarId : MVarId) (discrs : Array Expr) : Meta
let (fvarIds, mvarId) ← generalize mvarId args
return (fvarIds[:discrs.size], mvarId)
def splitMatch (mvarId : MVarId) (e : Expr) : MetaM (List MVarId) := do
let some app ← matchMatcherApp? e | throwError "match application expected"
let (discrFVarIds, mvarId) ← generalizeMatchDiscrs mvarId app.discrs
trace[Meta.debug] "split [1]:\n{MessageData.ofGoal mvarId}"
def applyMatchSplitter (mvarId : MVarId) (matcherDeclName : Name) (us : Array Level) (params : Array Expr) (discrs : Array Expr) : MetaM (List MVarId) := do
let (discrFVarIds, mvarId) ← generalizeMatchDiscrs mvarId discrs
let (reverted, mvarId) ← revert mvarId discrFVarIds (preserveOrder := true)
let (discrFVarIds, mvarId) ← introNP mvarId discrFVarIds.size
let numExtra := reverted.size - discrFVarIds.size
let discrs := discrFVarIds.map mkFVar
let matchEqns ← Match.getEquationsFor app.matcherName
let some info ← getMatcherInfo? matcherDeclName | throwError "'applyMatchSplitter' failed, '{matcherDeclName}' is not a 'match' auxiliary declaration."
let matchEqns ← Match.getEquationsFor matcherDeclName
withMVarContext mvarId do
let motive ← mkLambdaFVars discrs (← getMVarType mvarId)
-- Fix universe
let mut us := app.matcherLevels
if let some uElimPos := app.uElimPos? then
let mut us := us
if let some uElimPos := info.uElimPos? then
-- Set universe elimination level to zero (Prop).
us := us.set! uElimPos levelZero
let splitter := mkAppN (mkConst matchEqns.splitterName us.toList) app.params
let splitter := mkAppN (mkConst matchEqns.splitterName us.toList) params
let splitter := mkAppN (mkApp splitter motive) discrs
check splitter -- TODO
let mvarIds ← apply mvarId splitter
@ -98,11 +97,18 @@ def splitMatch (mvarId : MVarId) (e : Expr) : MetaM (List MVarId) := do
let numParams := matchEqns.splitterAltNumParams[i]
let (_, mvarId) ← introN mvarId numParams
let (_, mvarId) ← introNP mvarId numExtra
trace[Meta.debug] "before simpMatch:\n{MessageData.ofGoal mvarId}"
let mvarId ← simpMatchTargetCore mvarId app.matcherName matchEqns.eqnNames[i]
return (i+1, mvarId::mvarIds)
return mvarIds.reverse
def splitMatch (mvarId : MVarId) (e : Expr) : MetaM (List MVarId) := do
let some app ← matchMatcherApp? e | throwError "match application expected"
let matchEqns ← Match.getEquationsFor app.matcherName
let mvarIds ← applyMatchSplitter mvarId app.matcherName app.matcherLevels app.params app.discrs
let (_, mvarIds) ← mvarIds.foldlM (init := (0, [])) fun (i, mvarIds) mvarId => do
let mvarId ← simpMatchTargetCore mvarId app.matcherName matchEqns.eqnNames[i]
return (i+1, mvarId::mvarIds)
return mvarIds.reverse
/-- 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? isCandidate then