NNG progress

This commit is contained in:
Jon Eugster
2023-04-25 14:06:17 +02:00
parent f8ae5795cb
commit b1a53aba05
95 changed files with 1818 additions and 1136 deletions
+82
View File
@@ -0,0 +1,82 @@
import Mathlib.Lean.Expr.Basic
import Lean.Elab.Tactic.Basic
import NNG.MyNat.Definition
namespace MyNat
/-!
# Modified `induction` tactic
Modify `induction` tactic to always show `(0 : MyNat)` instead of `MyNat.zero` and
to support the lean3-style `with` keyword.
This is mainly copied and modified from the mathlib-tactic `induction'`.
-/
def rec' {P : ℕ → Prop} (zero : P 0)
(succ : (n : ℕ) → (n_ih : P n) → P (succ n)) (t : ℕ) : P t := by
induction t with
| zero => assumption
| succ n =>
apply succ
assumption
end MyNat
namespace Lean.Parser.Tactic
open Meta Elab Elab.Tactic
open private getAltNumFields in evalCases ElimApp.evalAlts.go in
def ElimApp.evalNames.MyNat (elimInfo : ElimInfo) (alts : Array ElimApp.Alt) (withArg : Syntax)
(numEqs := 0) (numGeneralized := 0) (toClear : Array FVarId := #[]) :
TermElabM (Array MVarId) := do
let mut names : List Syntax := withArg[1].getArgs |>.toList
let mut subgoals := #[]
for { name := altName, mvarId := g, .. } in alts do
let numFields ← getAltNumFields elimInfo altName
let (altVarNames, names') := names.splitAtD numFields (Unhygienic.run `(_))
names := names'
let (fvars, g) ← g.introN numFields <| altVarNames.map (getNameOfIdent' ·[0])
let some (g, subst) ← Cases.unifyEqs? numEqs g {} | pure ()
let (_, g) ← g.introNP numGeneralized
let g ← liftM $ toClear.foldlM (·.tryClear) g
for fvar in fvars, stx in altVarNames do
g.withContext <| (subst.apply <| .fvar fvar).addLocalVarInfoForBinderIdent ⟨stx⟩
subgoals := subgoals.push g
pure subgoals
open private getElimNameInfo generalizeTargets generalizeVars in evalInduction in
/--
Modified `induction` tactic for this game.
Usage: `induction n with d hd`.
*(The actual `induction` tactic has a more complex `with`-argument that works differently)*
-/
elab (name := _root_.MyNat.induction) "induction " tgts:(casesTarget,+)
withArg:((" with " (colGt binderIdent)+)?)
: tactic => do
let targets ← elabCasesTargets tgts.1.getSepArgs
let g :: gs ← getUnsolvedGoals | throwNoGoalsToBeSolved
g.withContext do
let elimInfo ← getElimInfo `MyNat.rec'
let targets ← addImplicitTargets elimInfo targets
evalInduction.checkTargets targets
let targetFVarIds := targets.map (·.fvarId!)
g.withContext do
let forbidden ← mkGeneralizationForbiddenSet targets
let mut s ← getFVarSetToGeneralize targets forbidden
let (fvarIds, g) ← g.revert (← sortFVarIds s.toArray)
let result ← withRef tgts <| ElimApp.mkElimApp elimInfo targets (← g.getTag)
let elimArgs := result.elimApp.getAppArgs
ElimApp.setMotiveArg g elimArgs[elimInfo.motivePos]!.mvarId! targetFVarIds
g.assign result.elimApp
let subgoals ← ElimApp.evalNames.MyNat elimInfo result.alts withArg
(numGeneralized := fvarIds.size) (toClear := targetFVarIds)
setGoals <| (subgoals ++ result.others).toList ++ gs
end Lean.Parser.Tactic
+31
View File
@@ -0,0 +1,31 @@
import Mathlib.Lean.Expr.Basic
import Lean.Elab.Tactic.Basic
/-! # `rfl` tactic
Added `withReducible` to prevent `rfl` proving stuff like `n + 0 = n`.
-/
namespace MyNat
open Lean Meta Elab Tactic
-- @[match_pattern] def MyNat.rfl {α : Sort u} {a : α} : Eq a a := Eq.refl a
/-- Modified `rfl` tactic.
`rfl` closes goals of the form `A = A`.
Note that teh version for this game is somewhat weaker than the real one. -/
syntax (name := rfl) "rfl" : tactic
@[tactic MyNat.rfl] def evalRfl : Tactic := fun _ =>
liftMetaTactic fun mvarId => do withReducible <| mvarId.refl; pure []
-- TODO: `rfl` should be able to prove `R ↔ R`!
-- @[tactic MyNat.rfl] def evalRfl : Tactic := fun _ =>
-- liftMetaTactic fun mvarId => do mvarId.refl; pure []
-- (with_reducible rfl)
end MyNat
+28
View File
@@ -0,0 +1,28 @@
import Mathlib.Lean.Expr.Basic
import Lean.Elab.Tactic.Basic
/-!
# Modified `rw`
Modify `rw` to work like `rewrite`.
This is mainly a copy of the implementation of `rewrite` in Lean core.
-/
namespace MyNat
open Lean.Meta Lean.Elab.Tactic Lean.Parser.Tactic
/--
Modified `rw` tactic. For this game, `rw` works exactly like `rewrite`.
-/
syntax (name := rewriteSeq) "rw" (config)? rwRuleSeq (location)? : tactic
@[tactic MyNat.rewriteSeq] def evalRewriteSeq : Tactic := fun stx => do
let cfg ← elabRewriteConfig stx[1]
let loc := expandOptLocation stx[3]
withRWRulesSeq stx[0] stx[2] fun symm term => do
withLocation loc
(rewriteLocalDecl term symm · cfg)
(rewriteTarget term symm cfg)
(throwTacticEx `rewrite · "did not find instance of the pattern in the current goal")
+51
View File
@@ -0,0 +1,51 @@
import Mathlib.Lean.Expr.Basic
import Lean.Elab.Tactic.Basic
import NNG.Tactic.Rfl
/-! # `simp` tactic
Added `withReducible` to prevent `rfl` proving stuff like `n + 0 = n`.
-/
namespace MyNat
open Lean Meta Elab Tactic
-- @[match_pattern] def MyNat.rfl {α : Sort u} {a : α} : Eq a a := Eq.refl a
/--
The `simp` tactic uses lemmas and hypotheses to simplify the main goal target or
non-dependent hypotheses. It has many variants:
- `simp` simplifies the main goal target using lemmas tagged with the attribute `[simp]`.
- `simp [h₁, h₂, ..., hₙ]` simplifies the main goal target using the lemmas tagged
with the attribute `[simp]` and the given `hᵢ`'s, where the `hᵢ`'s are expressions.
If an `hᵢ` is a defined constant `f`, then the equational lemmas associated with
`f` are used. This provides a convenient way to unfold `f`.
- `simp [*]` simplifies the main goal target using the lemmas tagged with the
attribute `[simp]` and all hypotheses.
- `simp only [h₁, h₂, ..., hₙ]` is like `simp [h₁, h₂, ..., hₙ]` but does not use `[simp]` lemmas.
- `simp [-id₁, ..., -idₙ]` simplifies the main goal target using the lemmas tagged
with the attribute `[simp]`, but removes the ones named `idᵢ`.
- `simp at h₁ h₂ ... hₙ` simplifies the hypotheses `h₁ : T₁` ... `hₙ : Tₙ`. If
the target or another hypothesis depends on `hᵢ`, a new simplified hypothesis
`hᵢ` is introduced, but the old one remains in the local context.
- `simp at *` simplifies all the hypotheses and the target.
- `simp [*] at *` simplifies target and all (propositional) hypotheses using the
other hypotheses.
-/
syntax (name := simp) "simp" (config)? (discharger)? (&" only")?
(" [" withoutPosition((simpStar <|> simpErase <|> simpLemma),*) "]")? (location)? : tactic
/-
"simp " (config)? (discharger)? ("only ")? ("[" simpLemma,* "]")? (location)?
-/
@[builtin_tactic Lean.Parser.Tactic.simp] def evalSimp : Tactic := fun stx => do
let { ctx, dischargeWrapper } ← withMainContext <| mkSimpContext stx (eraseLocal := false)
let usedSimps ← dischargeWrapper.with fun discharge? =>
simpLocation ctx discharge? (expandOptLocation stx[5])
if tactic.simp.trace.get (← getOptions) then
traceSimpCall stx usedSimps
end MyNat