feat: convert ites into dites in the WF module

Motivation: the condition is often used in termination proofs.
This commit is contained in:
Leonardo de Moura 2022-03-19 10:11:50 -07:00
parent 9fed5bda7d
commit c95d5f25a3
4 changed files with 35 additions and 3 deletions

View file

@ -0,0 +1,29 @@
/-
Copyright (c) 2022 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura
-/
import Lean.Meta.Transform
namespace Lean.Meta
/--
Convert `ite` expressions in `e` to `dite`s.
It is useful to make this conversion in the `WF` module because the condition is often used in
termination proofs. -/
def iteToDIte (e : Expr) : MetaM Expr := do
-- TODO: move this file to `Meta` if we decide to use it in other places.
let post (e : Expr) : MetaM TransformStep := do
if e.isAppOfArity ``ite 5 then
let f := e.getAppFn
let args := e.getAppArgs
let c := args[1]
let h ← mkFreshUserName `h
let args := args.set! 3 (Lean.mkLambda h BinderInfo.default c args[3])
let args := args.set! 4 (Lean.mkLambda h BinderInfo.default (mkNot c) args[4])
return .done <| mkAppN (mkConst ``dite f.constLevels!) args
else
return .done e
transform e (post := post)
end Lean.Meta

View file

@ -10,6 +10,7 @@ import Lean.Elab.PreDefinition.WF.PackMutual
import Lean.Elab.PreDefinition.WF.Rel
import Lean.Elab.PreDefinition.WF.Fix
import Lean.Elab.PreDefinition.WF.Eqns
import Lean.Elab.PreDefinition.WF.Ite
namespace Lean.Elab
open WF
@ -84,7 +85,8 @@ def wfRecursion (preDefs : Array PreDefinition) (wf? : Option TerminationWF) (de
addAsAxiom preDef
let fixedPrefixSize ← getFixedPrefix preDefs
trace[Elab.definition.wf] "fixed prefix: {fixedPrefixSize}"
let unaryPreDefs ← packDomain fixedPrefixSize preDefs
let preDefsDIte ← preDefs.mapM fun preDef => return { preDef with value := (← iteToDIte preDef.value) }
let unaryPreDefs ← packDomain fixedPrefixSize preDefsDIte
return (← packMutual fixedPrefixSize preDefs unaryPreDefs, fixedPrefixSize)
let preDefNonRec ← forallBoundedTelescope unaryPreDef.type fixedPrefixSize fun prefixArgs type => do
let packedArgType := type.bindingDomain!

View file

@ -182,7 +182,7 @@ namespace Ex5
mutual
def lex [Monad m] [MonadExceptOf LexErr m] (it : String.Iterator) : m (List Token) := do
if h : it.hasNext then
if it.hasNext then
match it.curr with
| '(' => return { text := "(", tok := Tok.lpar } :: (← lex it.next)
| ')' => return { text := ")", tok := Tok.rpar } :: (← lex it.next)
@ -195,7 +195,7 @@ mutual
return []
def lexnumber [Monad m] [MonadExceptOf LexErr m] (soFar : Nat) (text : List Char) (it : String.Iterator) : m (List Token) :=
if h : it.hasNext then
if it.hasNext then
let c := it.curr
match charDigit c with
| .error _ => return { text := text.reverse.asString, tok := Tok.num soFar } :: (← lex it)

View file

@ -3,4 +3,5 @@ wf2.lean:3:8-3:17: error: failed to prove termination, possible solutions:
- Use `termination_by` to specify a different well-founded relation
- Use `decreasing_by` to specify your own tactic for discharging this kind of goal
x y : Nat
: x < y
⊢ x - 1 < x