The linters in Batteries can be used to spot mistakes in Lean. See the message on [Zulip](https://leanprover.zulipchat.com/#narrow/stream/270676-lean4/topic/Go-to-def.20on.20typeclass.20fields.20and.20type-dependent.20notation/near/442613564). These are the different linters with errors: - unusedArguments: There are many unused instance arguments, especially a redundant `[Monad m]` is very common - checkUnivs: There was a problem with universes in a definition in `Init.Control.StateCps`. I fixed it by adding a `variable` statement for the implicit arguments in the file. - defLemma: many proofs are written as `def` instead of `theorem`, most notably `rfl`. Because `rfl` is used as a match pattern, it must be a def. Is this desirable? The keyword `abbrev` is sometimes used for an alias of a theorem, which also results in a def. I would want to replace it with the `alias` keyword to fix this, but it isn't available. - dupNamespace: I fixed some of these, but left `Tactic.Tactic` and `Parser.Parser` as they are as these seem intended. - unusedHaveSuffices: I cleaned up a few proofs with unused `have` or `suffices` - explicitVarsOfIff: I didn't fix any of these, because that would be a breaking change. - simpNF: I didn't fix any of these, because I think that requires knowing the intended simplification order.
75 lines
2.3 KiB
Text
75 lines
2.3 KiB
Text
import Lean.Meta
|
|
|
|
open Lean
|
|
open Lean.Meta
|
|
|
|
def dbgOpt : Options :=
|
|
let opt : Options := {};
|
|
let opt := opt.setBool `trace.Meta true;
|
|
-- let opt := opt.setBool `trace.Meta.check false;
|
|
opt
|
|
|
|
def print (msg : MessageData) : MetaM Unit := do
|
|
trace[Meta.debug] msg
|
|
|
|
def check (x : MetaM Bool) : MetaM Unit :=
|
|
unless (← x) do throwError "check failed"
|
|
|
|
def getAssignment (m : Expr) : MetaM Expr :=
|
|
do let v? ← getExprMVarAssignment? m.mvarId!;
|
|
(match v? with
|
|
| some v => pure v
|
|
| none => throwError "metavariable is not assigned")
|
|
|
|
unsafe def run (mods : Array Name) (x : MetaM Unit) (opts : Options := dbgOpt) : IO Unit :=
|
|
withImportModules (mods.map $ fun m => {module := m}) {} 0 fun env => do
|
|
let x : MetaM Unit := do { x; printTraces };
|
|
discard $ x.toIO { options := opts, fileName := "", fileMap := default } { env := env };
|
|
pure ()
|
|
|
|
def nat := mkConst `Nat
|
|
def succ := mkConst `Nat.succ
|
|
def add := mkAppN (mkConst `Add.add [levelZero]) #[nat, mkConst `Nat.add]
|
|
|
|
def tst1 : MetaM Unit :=
|
|
do let d : DiscrTree Nat := {};
|
|
let mvar ← mkFreshExprMVar nat;
|
|
let d ← d.insert (mkAppN add #[mvar, mkNatLit 10]) 1 {}
|
|
let d ← d.insert (mkAppN add #[mkNatLit 0, mkNatLit 10]) 2 {}
|
|
let d ← d.insert (mkAppN (mkConst `Nat.add) #[mkNatLit 0, mkNatLit 20]) 3 {}
|
|
let d ← d.insert (mkAppN add #[mvar, mkNatLit 20]) 4 {}
|
|
let d ← d.insert mvar 5 {}
|
|
print (format d);
|
|
let vs ← d.getMatch (mkAppN add #[mkNatLit 1, mkNatLit 10]) {};
|
|
print (format vs);
|
|
let t := mkAppN add #[mvar, mvar];
|
|
print t;
|
|
let vs ← d.getMatch t {};
|
|
print (format vs);
|
|
let vs ← d.getUnify t {};
|
|
print (format vs);
|
|
let vs ← d.getUnify mvar {};
|
|
print (format vs);
|
|
let vs ← d.getUnify (mkAppN add #[mkNatLit 0, mvar]) {};
|
|
print (format vs);
|
|
let vs ← d.getUnify (mkAppN add #[mvar, mkNatLit 20]) {};
|
|
print (format vs);
|
|
pure ()
|
|
|
|
set_option trace.Meta.debug true in
|
|
/--
|
|
info: [Meta.debug] (Add.add => (node
|
|
(Nat => (node
|
|
(* => (node (* => (node (10 => (node #[1])) (20 => (node #[4])))) (0 => (node (10 => (node #[2]))))))))))
|
|
(* => (node #[5]))
|
|
(Nat.add => (node (0 => (node (20 => (node #[3]))))))
|
|
[Meta.debug] #[5, 1]
|
|
[Meta.debug] Add.add ?m.4899 ?m.4899
|
|
[Meta.debug] #[5]
|
|
[Meta.debug] #[5, 1, 4, 2]
|
|
[Meta.debug] #[1, 4, 2, 5, 3]
|
|
[Meta.debug] #[5, 1, 4, 2]
|
|
[Meta.debug] #[5, 4]
|
|
-/
|
|
#guard_msgs in
|
|
run_meta tst1
|