Compare commits
2 Commits
3812aa56ec
...
6ffb227cd6
Author | SHA1 | Date |
---|---|---|
Leni Aniva | 6ffb227cd6 | |
Leni Aniva | feff62a3c5 |
|
@ -22,7 +22,6 @@ structure RecursorWithMotive where
|
||||||
|
|
||||||
-- .bvar index for the motive and major from the body
|
-- .bvar index for the motive and major from the body
|
||||||
iMotive: Nat
|
iMotive: Nat
|
||||||
iMajor: Nat
|
|
||||||
|
|
||||||
namespace RecursorWithMotive
|
namespace RecursorWithMotive
|
||||||
|
|
||||||
|
@ -38,23 +37,23 @@ protected def surrogateMotiveType (info: RecursorWithMotive) (resultant: Expr):
|
||||||
let resultantType ← Meta.inferType resultant
|
let resultantType ← Meta.inferType resultant
|
||||||
return replaceForallBody motiveType resultantType
|
return replaceForallBody motiveType resultantType
|
||||||
|
|
||||||
protected def phantomType (info: RecursorWithMotive) (mvars: Array Expr) (resultant: Expr): MetaM Expr := do
|
protected def conduitType (info: RecursorWithMotive) (mvars: Array Expr) (resultant: Expr): MetaM Expr := do
|
||||||
let goalMotive := mvars.get! (info.nArgs - info.iMotive - 1)
|
let motiveCall := Expr.instantiateRev info.body mvars
|
||||||
let goalMajor := mvars.get! (info.nArgs - info.iMajor - 1)
|
Meta.mkEq motiveCall resultant
|
||||||
Meta.mkEq (.app goalMotive goalMajor) resultant
|
|
||||||
|
|
||||||
end RecursorWithMotive
|
end RecursorWithMotive
|
||||||
|
|
||||||
def getRecursorInformation (recursorType: Expr): Option RecursorWithMotive := do
|
def getRecursorInformation (recursorType: Expr): Option RecursorWithMotive := do
|
||||||
let (args, body) := getForallArgsBody recursorType
|
let (args, body) := getForallArgsBody recursorType
|
||||||
let (iMotive, iMajor) ← match body with
|
if ¬ body.isApp then
|
||||||
| .app (.bvar iMotive) (.bvar iMajor) => pure (iMotive, iMajor)
|
.none
|
||||||
|
let iMotive ← match body.getAppFn with
|
||||||
|
| .bvar iMotive => pure iMotive
|
||||||
| _ => .none
|
| _ => .none
|
||||||
return {
|
return {
|
||||||
args,
|
args,
|
||||||
body,
|
body,
|
||||||
iMotive,
|
iMotive,
|
||||||
iMajor,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def collectMotiveArguments (forallBody: Expr): SSet Nat :=
|
def collectMotiveArguments (forallBody: Expr): SSet Nat :=
|
||||||
|
@ -86,8 +85,6 @@ def motivatedApply: Elab.Tactic.Tactic := λ stx => do
|
||||||
let argGoal ← if bvarIndex = info.iMotive then
|
let argGoal ← if bvarIndex = info.iMotive then
|
||||||
let surrogateMotiveType ← info.surrogateMotiveType resultant
|
let surrogateMotiveType ← info.surrogateMotiveType resultant
|
||||||
Meta.mkFreshExprMVar surrogateMotiveType .syntheticOpaque (userName := `motive)
|
Meta.mkFreshExprMVar surrogateMotiveType .syntheticOpaque (userName := `motive)
|
||||||
else if bvarIndex = info.iMajor then
|
|
||||||
Meta.mkFreshExprMVar argType .syntheticOpaque (userName := `major)
|
|
||||||
else
|
else
|
||||||
Meta.mkFreshExprMVar argType .syntheticOpaque (userName := .anonymous)
|
Meta.mkFreshExprMVar argType .syntheticOpaque (userName := .anonymous)
|
||||||
let prev := prev ++ [argGoal]
|
let prev := prev ++ [argGoal]
|
||||||
|
@ -95,11 +92,11 @@ def motivatedApply: Elab.Tactic.Tactic := λ stx => do
|
||||||
termination_by info.nArgs - i
|
termination_by info.nArgs - i
|
||||||
let mut newMVars ← go 0 #[]
|
let mut newMVars ← go 0 #[]
|
||||||
|
|
||||||
goal.assign (mkAppN recursor newMVars)
|
-- Create the conduit type which proves the result of the motive is equal to the goal
|
||||||
|
let conduitType ← info.conduitType newMVars resultant
|
||||||
let phantomType ← info.phantomType newMVars resultant
|
let goalConduit ← Meta.mkFreshExprMVar conduitType .syntheticOpaque (userName := `conduit)
|
||||||
let goalPhantom ← Meta.mkFreshExprMVar phantomType .syntheticOpaque (userName := `phantom)
|
goal.assign $ ← Meta.mkEqMP goalConduit (mkAppN recursor newMVars)
|
||||||
newMVars := newMVars ++ [goalPhantom]
|
newMVars := newMVars ++ [goalConduit]
|
||||||
|
|
||||||
let nextGoals ← newMVars.toList.map (·.mvarId!) |>.filterM (not <$> ·.isAssigned)
|
let nextGoals ← newMVars.toList.map (·.mvarId!) |>.filterM (not <$> ·.isAssigned)
|
||||||
pure nextGoals
|
pure nextGoals
|
||||||
|
|
|
@ -662,9 +662,9 @@ def test_nat_zero_add: TestM Unit := do
|
||||||
addTest $ LSpec.check s!"mapply {recursor}" ((← state2.serializeGoals (options := ← read)).map (·.devolatilizeVars) =
|
addTest $ LSpec.check s!"mapply {recursor}" ((← state2.serializeGoals (options := ← read)).map (·.devolatilizeVars) =
|
||||||
#[
|
#[
|
||||||
buildNamedGoal "_uniq.67" [("n", "Nat")] "Nat → Prop" (.some "motive"),
|
buildNamedGoal "_uniq.67" [("n", "Nat")] "Nat → Prop" (.some "motive"),
|
||||||
buildNamedGoal "_uniq.68" [("n", "Nat")] "Nat" (.some "major"),
|
buildNamedGoal "_uniq.68" [("n", "Nat")] "Nat",
|
||||||
buildNamedGoal "_uniq.69" [("n", "Nat")] "∀ (t : Nat), Nat.below t → ?motive t",
|
buildNamedGoal "_uniq.69" [("n", "Nat")] "∀ (t : Nat), Nat.below t → ?motive t",
|
||||||
buildNamedGoal "_uniq.70" [("n", "Nat")] "?motive ?major = (n + 0 = n)" (.some "phantom")
|
buildNamedGoal "_uniq.70" [("n", "Nat")] "?motive ?m.68 = (n + 0 = n)" (.some "conduit")
|
||||||
])
|
])
|
||||||
|
|
||||||
let tactic := "exact n"
|
let tactic := "exact n"
|
||||||
|
@ -703,7 +703,18 @@ def test_nat_zero_add: TestM Unit := do
|
||||||
#[buildGoal [("n", "Nat"), ("t", "Nat"), ("h", "Nat.below t")] "t + 0 = t"])
|
#[buildGoal [("n", "Nat"), ("t", "Nat"), ("h", "Nat.below t")] "t + 0 = t"])
|
||||||
|
|
||||||
let tactic := "simp"
|
let tactic := "simp"
|
||||||
let stateF ← match ← state3.tryTactic (goalId := 0) (tactic := tactic) with
|
let state3d ← match ← state3.tryTactic (goalId := 0) (tactic := tactic) with
|
||||||
|
| .success state => pure state
|
||||||
|
| other => do
|
||||||
|
addTest $ assertUnreachable $ other.toString
|
||||||
|
return ()
|
||||||
|
let state2d ← match state3d.continue state2c with
|
||||||
|
| .ok state => pure state
|
||||||
|
| .error e => do
|
||||||
|
addTest $ assertUnreachable e
|
||||||
|
return ()
|
||||||
|
let tactic := "rfl"
|
||||||
|
let stateF ← match ← state2d.tryTactic (goalId := 0) (tactic := tactic) with
|
||||||
| .success state => pure state
|
| .success state => pure state
|
||||||
| other => do
|
| other => do
|
||||||
addTest $ assertUnreachable $ other.toString
|
addTest $ assertUnreachable $ other.toString
|
||||||
|
|
|
@ -31,7 +31,6 @@ def test_type_extract (env: Environment): IO LSpec.TestSeq :=
|
||||||
| .some info => pure info
|
| .some info => pure info
|
||||||
| .none => throwError "Failed to extract recursor info"
|
| .none => throwError "Failed to extract recursor info"
|
||||||
tests := tests ++ LSpec.check "iMotive" (info.iMotive = 2)
|
tests := tests ++ LSpec.check "iMotive" (info.iMotive = 2)
|
||||||
tests := tests ++ LSpec.check "iMajor" (info.iMajor = 1)
|
|
||||||
let motiveType := info.getMotiveType
|
let motiveType := info.getMotiveType
|
||||||
tests := tests ++ LSpec.check "motiveType" ("Nat → Sort ?u.1" =
|
tests := tests ++ LSpec.check "motiveType" ("Nat → Sort ?u.1" =
|
||||||
(← exprToStr motiveType))
|
(← exprToStr motiveType))
|
||||||
|
@ -60,7 +59,7 @@ def test_execute (env: Environment): IO LSpec.TestSeq :=
|
||||||
"Nat → Prop",
|
"Nat → Prop",
|
||||||
"Nat",
|
"Nat",
|
||||||
"∀ (t : Nat), Nat.below t → ?motive t",
|
"∀ (t : Nat), Nat.below t → ?motive t",
|
||||||
"?motive ?major = (n + 0 = n)",
|
"?motive ?m.69 = (n + 0 = n)",
|
||||||
])
|
])
|
||||||
tests := tests ++ test
|
tests := tests ++ test
|
||||||
return tests
|
return tests
|
||||||
|
|
Loading…
Reference in New Issue