Skip to content

Commit f493ef4

Browse files
committed
feat: track "synthetic" and "dubious" #align (#488)
Companion PR to leanprover-community/mathport#187
1 parent 63a677d commit f493ef4

File tree

2 files changed

+93
-18
lines changed

2 files changed

+93
-18
lines changed

Mathlib/Mathport/Rename.lean

Lines changed: 73 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,40 +11,100 @@ open Lean
1111
open System (FilePath)
1212
open Lean (HashMap)
1313

14-
abbrev RenameMap := HashMap Name Name
14+
/-- This structure keeps track of alignments from lean 3 names to lean 4 names and vice versa. -/
15+
structure RenameMap where
16+
/-- This maps `n3 ↦ (dubious, n4)` where `n3` is the lean 3 name and `n4` is the corresponding
17+
lean 4 name. `dubious` is either empty, or a warning message to be displayed when `n3` is
18+
translated, which indicates that the translation from `n3` to `n4` is approximate and may cause
19+
downstream errors. -/
20+
toLean4 : NameMap (String × Name) := {}
21+
/-- This maps `n4 ↦ (n3, clashes)` where `n4` is the lean 4 name and `n3::clashes` is the list of
22+
all (non-`synthetic`) declarations that map to `n4`. (That is, we do not assume the mapping
23+
from lean 3 to lean 4 name is injective.) -/
24+
toLean3 : NameMap (Name × List Name) := {}
25+
deriving Inhabited
1526

16-
def RenameMap.insertPair (m : RenameMap) : Name × Name → RenameMap
17-
| (n3, n4) => m.insert n3 n4
27+
/-- An `olean` entry for the rename extension. -/
28+
structure NameEntry where
29+
/-- The lean 3 name. -/
30+
n3 : Name
31+
/-- The lean 4 name. -/
32+
n4 : Name
33+
/-- If true, this lean 3 -> lean 4 mapping will not be entered into the converse map.
34+
This is used for "internal" definitions that should never be referred to in the source syntax. -/
35+
synthetic := false
36+
/-- A dubious translation is one where there is a type mismatch
37+
from the translated lean 3 definition to a pre-existing lean 4 definition.
38+
Type errors are likely in downstream theorems.
39+
The string stored here is printed in the event that `n3` is encountered by synport. -/
40+
dubious := ""
1841

19-
initialize renameExtension : SimplePersistentEnvExtension (Name × Name) RenameMap ←
42+
/-- Insert a name entry into the `RenameMap`. -/
43+
def RenameMap.insert (m : RenameMap) (e : NameEntry) : RenameMap :=
44+
let ⟨to4, to3⟩ := m
45+
let to4 := to4.insert e.n3 (e.dubious, e.n4)
46+
let to3 := if e.synthetic then to3 else
47+
match to3.find? e.n4 with
48+
| none => to3.insert e.n4 (e.n3, [])
49+
| some (a, l) => if (a::l).contains e.n3 then to3 else to3.insert e.n4 (a, e.n3 :: l)
50+
⟨to4, to3⟩
51+
52+
/-- Look up a lean 4 name from the lean 3 name. Also return the `dubious` error message. -/
53+
def RenameMap.find? (m : RenameMap) : Name → Option (String × Name) := m.toLean4.find?
54+
55+
initialize renameExtension : SimplePersistentEnvExtension NameEntry RenameMap ←
2056
registerSimplePersistentEnvExtension {
21-
addEntryFn := RenameMap.insertPair
22-
addImportedFn := fun es => mkStateFromImportedEntries (RenameMap.insertPair) {} es
57+
addEntryFn := (·.insert)
58+
addImportedFn := mkStateFromImportedEntries (·.insert) {}
2359
}
2460

2561
def getRenameMap (env : Environment) : RenameMap :=
2662
renameExtension.getState env
2763

28-
def addNameAlignment (n3 n4 : Name) : CoreM Unit := do
29-
modifyEnv fun env => renameExtension.addEntry env (n3, n4)
64+
def addNameAlignment (n3 n4 : Name) (synthetic := false) (dubious := "") : CoreM Unit := do
65+
modifyEnv fun env => renameExtension.addEntry env { n3, n4, synthetic, dubious }
3066

3167
open Lean.Elab Lean.Elab.Command
3268

69+
/--
70+
`#align lean_3.def_name Lean4.defName` will record an "alignment" from the lean 3 name
71+
to the corresponding lean 4 name. This information is used by the
72+
[mathport](https://github.com/leanprover-community/mathport) utility to translate later uses of
73+
the definition.
74+
75+
If there is no alignment for a given definition, mathport will attempt to convert
76+
from the lean 3 `snake_case` style to `UpperCamelCase` for namespaces and types and
77+
`lowerCamelCase` for definitions, and `snake_case` for theorems. But for various reasons,
78+
it may fail either to determine whether it is a type, definition, or theorem, or to determine
79+
that a specific definition is in fact being called. Or a specific definition may need a different
80+
name altogether because the existing name is already taken in lean 4 for something else. For
81+
these reasons, you should use `#align` on any theorem that needs to be renamed from the default.
82+
-/
3383
syntax (name := align) "#align " ident ident : command
3484

3585
@[command_elab align] def elabAlign : CommandElab
36-
| `(#align $id3:ident $id4:ident) =>
86+
| `(#align $id3:ident $id4:ident) => do
87+
if (← getInfoState).enabled then
88+
if (← getEnv).contains id4.getId then
89+
addConstInfo id4 id4.getId none
3790
liftCoreM $ addNameAlignment id3.getId id4.getId
3891
| _ => throwUnsupportedSyntax
3992

93+
/-- Show information about the alignment status of a lean 3 definition. -/
4094
syntax (name := lookup3) "#lookup3 " ident : command
4195

4296
@[command_elab lookup3] def elabLookup3 : CommandElab
4397
| `(#lookup3%$tk $id3:ident) => do
4498
let n3 := id3.getId
45-
match getRenameMap (← getEnv) |>.find? n3 with
99+
let m := getRenameMap (← getEnv)
100+
match m.find? n3 with
46101
| none => logInfoAt tk s!"name `{n3} not found"
47-
| some n4 => logInfoAt tk s!"{n4}"
102+
| some (dubious, n4) => do
103+
let mut msg := m!"{n4}"
104+
if !dubious.isEmpty then
105+
msg := msg ++ s!" (dubious: {dubious})"
106+
logInfoAt tk <|
107+
match m.toLean3.find? n4 with
108+
| none | some (_, []) => msg
109+
| some (n, l) => m!"{msg} (aliases {n :: l})"
48110
| _ => throwUnsupportedSyntax
49-
50-
end Mathlib.Prelude.Rename

Mathlib/Mathport/Syntax.lean

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,36 +11,51 @@ import Mathlib.Logic.Equiv.LocalEquiv
1111
import Mathlib.Tactic.Alias
1212
import Mathlib.Tactic.ApplyWith
1313
import Mathlib.Tactic.ApplyRules
14+
import Mathlib.Tactic.ByContra
1415
import Mathlib.Tactic.Cases
1516
import Mathlib.Tactic.CasesM
17+
import Mathlib.Tactic.Clear_
1618
import Mathlib.Tactic.Clear!
1719
import Mathlib.Tactic.ClearExcept
18-
import Mathlib.Tactic.Clear_
1920
import Mathlib.Tactic.CommandQuote
2021
import Mathlib.Tactic.Constructor
22+
import Mathlib.Tactic.Contrapose
23+
import Mathlib.Tactic.Conv
2124
import Mathlib.Tactic.Core
2225
import Mathlib.Tactic.Existsi
2326
import Mathlib.Tactic.FinCases
2427
import Mathlib.Tactic.Find
28+
import Mathlib.Tactic.GuardHypNums
2529
import Mathlib.Tactic.InferParam
2630
import Mathlib.Tactic.Inhabit
31+
import Mathlib.Tactic.IrreducibleDef
2732
import Mathlib.Tactic.LeftRight
2833
import Mathlib.Tactic.LibrarySearch
2934
import Mathlib.Tactic.NormCast
3035
import Mathlib.Tactic.NormNum
36+
import Mathlib.Tactic.PermuteGoals
3137
import Mathlib.Tactic.PushNeg
3238
import Mathlib.Tactic.Recover
33-
import Mathlib.Tactic.Replace
3439
import Mathlib.Tactic.Relation.Rfl
40+
import Mathlib.Tactic.Rename
41+
import Mathlib.Tactic.RenameBVar
42+
import Mathlib.Tactic.Replace
43+
import Mathlib.Tactic.RestateAxiom
3544
import Mathlib.Tactic.Ring
45+
import Mathlib.Tactic.RunCmd
46+
import Mathlib.Tactic.SeqFocus
3647
import Mathlib.Tactic.Set
37-
import Mathlib.Tactic.SimpTrace
48+
import Mathlib.Tactic.SimpRw
3849
import Mathlib.Tactic.Simps
50+
import Mathlib.Tactic.SimpTrace
3951
import Mathlib.Tactic.SolveByElim
40-
import Mathlib.Tactic.Trace
4152
import Mathlib.Tactic.Substs
42-
import Mathlib.Util.WithWeakNamespace
53+
import Mathlib.Tactic.SwapVar
54+
import Mathlib.Tactic.Trace
55+
import Mathlib.Tactic.TypeCheck
56+
import Mathlib.Tactic.Use
4357
import Mathlib.Util.Syntax
58+
import Mathlib.Util.WithWeakNamespace
4459

4560
-- To fix upstream:
4661
-- * bracketedExplicitBinders doesn't support optional types

0 commit comments

Comments
 (0)