@@ -11,40 +11,100 @@ open Lean
11
11
open System (FilePath)
12
12
open Lean (HashMap)
13
13
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
15
26
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 := ""
18
41
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 ←
20
56
registerSimplePersistentEnvExtension {
21
- addEntryFn := RenameMap.insertPair
22
- addImportedFn := fun es => mkStateFromImportedEntries (RenameMap.insertPair ) {} es
57
+ addEntryFn := (·.insert)
58
+ addImportedFn := mkStateFromImportedEntries (·.insert ) {}
23
59
}
24
60
25
61
def getRenameMap (env : Environment) : RenameMap :=
26
62
renameExtension.getState env
27
63
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 }
30
66
31
67
open Lean.Elab Lean.Elab.Command
32
68
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
+ -/
33
83
syntax (name := align) "#align " ident ident : command
34
84
35
85
@[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
37
90
liftCoreM $ addNameAlignment id3.getId id4.getId
38
91
| _ => throwUnsupportedSyntax
39
92
93
+ /-- Show information about the alignment status of a lean 3 definition. -/
40
94
syntax (name := lookup3) "#lookup3 " ident : command
41
95
42
96
@[command_elab lookup3] def elabLookup3 : CommandElab
43
97
| `(#lookup3%$tk $id3:ident) => do
44
98
let n3 := id3.getId
45
- match getRenameMap (← getEnv) |>.find? n3 with
99
+ let m := getRenameMap (← getEnv)
100
+ match m.find? n3 with
46
101
| 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})"
48
110
| _ => throwUnsupportedSyntax
49
-
50
- end Mathlib.Prelude.Rename
0 commit comments