@@ -10,6 +10,7 @@ import Mathlib.Lean.Expr.ReplaceRec
10
10
import Mathlib.Lean.Expr
11
11
import Lean
12
12
import Lean.Data
13
+ import Lean.Elab.Term
13
14
import Std.Lean.NameMapAttribute
14
15
15
16
/-!
@@ -166,7 +167,7 @@ def applyReplacementFun : Expr → MetaM Expr :=
166
167
Lean.Expr.replaceRecMeta fun r e => do
167
168
trace[to_additive_detail] "applyReplacementFun: replace at {e}"
168
169
match e with
169
- | .lit (.natVal 1 ) => pure <| mkNatLit 0
170
+ | .lit (.natVal 1 ) => pure <| mkRawNatLit 0
170
171
| .const n₀ ls => do
171
172
let n₁ := Name.mapPrefix (findTranslation? <|← getEnv) n₀
172
173
trace[to_additive_detail] "applyReplacementFun: {n₀} → {n₁}"
@@ -258,15 +259,14 @@ using the transforms dictionary.
258
259
`pre` is the declaration that got the `@[to_additive]` attribute and `tgt_pre` is the target of this
259
260
declaration. -/
260
261
partial def transformDeclAux
261
- (pre tgt_pre : Name) : Name → CoreM Unit := fun src => do
262
+ (ref : Option Syntax) ( pre tgt_pre : Name) : Name → CoreM Unit := fun src => do
262
263
-- if this declaration is not `pre` or an internal declaration, we do nothing.
263
264
if not (src == pre || isInternal' src) then
264
265
if (findTranslation? (← getEnv) src).isSome then
265
- return ()
266
- else throwError
267
- ("The declaration {pre} depends on the declaration {src} which is in the namespace {pre}," ++
268
- " but does not have the `@[to_additive]` attribute. This is not supported. " ++
269
- "Workaround: move {src} to a different namespace." )
266
+ return
267
+ throwError "The declaration {pre} depends on the declaration {src} which is in the namespace {
268
+ pre}, but does not have the `@[to_additive]` attribute. This is not supported.\n {""
269
+ }Workaround: move {src} to a different namespace."
270
270
let env ← getEnv
271
271
-- we find the additive name of `src`
272
272
let tgt := src.mapPrefix (fun n => if n == pre then some tgt_pre else none)
@@ -276,10 +276,10 @@ partial def transformDeclAux
276
276
let srcDecl ← getConstInfo src
277
277
-- we first transform all the declarations of the form `pre._proof_i`
278
278
for n in srcDecl.type.listNamesWithPrefix pre do
279
- transformDeclAux pre tgt_pre n
279
+ transformDeclAux none pre tgt_pre n
280
280
if let some value := srcDecl.value? then
281
281
for n in value.listNamesWithPrefix pre do
282
- transformDeclAux pre tgt_pre n
282
+ transformDeclAux none pre tgt_pre n
283
283
-- now transform the source declaration
284
284
let trgDecl : ConstantInfo ← MetaM.run' $ updateDecl tgt srcDecl
285
285
if ¬ trgDecl.hasValue then
@@ -296,6 +296,18 @@ partial def transformDeclAux
296
296
Failed to add declaration\n {trgDecl.name}:\n {msg}"
297
297
| _ => panic! "unreachable"
298
298
addAndCompile trgDecl.toDeclaration!
299
+ -- now add declaration ranges so jump-to-definition works
300
+ addDeclarationRanges tgt {
301
+ range := ← getDeclarationRange (← getRef)
302
+ selectionRange := ← getDeclarationRange (ref.getD (← getRef))
303
+ }
304
+ if let some ref := ref then
305
+ -- TODO: make a function for this
306
+ pushInfoLeaf <| .ofTermInfo {
307
+ elaborator := .anonymous, lctx := {}, expectedType? := none
308
+ stx := ref, isBinder := true
309
+ expr := ← mkConstWithLevelParams trgDecl.name
310
+ }
299
311
if isProtected (← getEnv) src then
300
312
setEnv $ addProtected (← getEnv) tgt
301
313
@@ -308,34 +320,33 @@ allow us to iterate the attributes applied to a given decalaration.
308
320
-/
309
321
def copyAttributes (src tgt : Name) : CoreM Unit := do
310
322
-- [ todo ] other simp theorems
311
- let some ext ← getSimpExtension? `simp | return ()
323
+ let some ext ← getSimpExtension? `simp | return
312
324
let thms ← ext.getTheorems
313
325
if (¬ thms.isLemma (.decl src)) || thms.isLemma (.decl tgt) then
314
- return ()
326
+ return
315
327
-- [ todo ] how to get prio data from SimpTheorems?
316
- MetaM.run' $ Lean.Meta.addSimpTheorem ext tgt
328
+ Lean.Meta.addSimpTheorem ext tgt
317
329
(post := true )
318
330
(inv := false )
319
331
(attrKind := AttributeKind.global)
320
- (prio := 1000 )
321
- return ()
332
+ (prio := 1000 ) |>.run'
322
333
323
334
/--
324
335
Make a new copy of a declaration, replacing fragments of the names of identifiers in the type and
325
336
the body using the `translations` dictionary.
326
337
This is used to implement `@[to_additive]`.
327
338
-/
328
- def transformDecl (src tgt : Name) : CoreM Unit := do
329
- transformDeclAux src tgt src
339
+ def transformDecl (ref : Option Syntax) ( src tgt : Name) : CoreM Unit := do
340
+ transformDeclAux ref src tgt src
330
341
let eqns? ← MetaM.run' (getEqnsFor? src true )
331
342
-- now transform all of the equational lemmas
332
343
if let some eqns := eqns? then
333
344
for src_eqn in eqns do
334
- transformDeclAux src tgt src_eqn
345
+ transformDeclAux none src tgt src_eqn
335
346
-- [ todo ] copy attributes for equations
336
347
-- [ todo ] add equation lemmas to tgt_eqn
337
348
copyAttributes src tgt
338
- return ()
349
+
339
350
/--
340
351
Find the first argument of `nm` that has a multiplicative type-class on it.
341
352
Returns 1 if there are no types with a multiplicative class as arguments.
@@ -360,7 +371,6 @@ def firstMultiplicativeArg (nm : Name) : MetaM (Option Nat) := do
360
371
| [] => return none
361
372
| (head :: tail) => return some <| tail.foldr Nat.min head
362
373
363
-
364
374
/-- `ValueType` is the type of the arguments that can be provided to `to_additive`. -/
365
375
structure ValueType : Type where
366
376
/-- Replace all multiplicative declarations, do not use the heuristic. -/
@@ -375,6 +385,10 @@ structure ValueType : Type where
375
385
/-- If `allow_auto_name` is `false` (default) then
376
386
`@[to_additive]` will check whether the given name can be auto-generated. -/
377
387
allowAutoName : Bool := false
388
+ /-- The `Syntax` element corresponding to the original multiplicative declaration
389
+ (or the `to_additive` attribute if it is added later),
390
+ which we need for adding definition ranges. -/
391
+ ref : Syntax
378
392
deriving Repr
379
393
380
394
/-- `add_comm_prefix x s` returns `"comm_" ++ s` if `x = tt` and `s` otherwise. -/
@@ -464,18 +478,19 @@ def proceedFields (src tgt : Name) : CoreM Unit := do
464
478
-- [ todo ] run to_additive on the constructors of n:
465
479
-- aux (fun n => (env.constructorsOf n).mmap $ ...
466
480
467
- private def elabToAdditiveAux
468
- (replaceAll trace : Bool) (tgt : Option Syntax) (doc : Option Syntax) : ValueType :=
481
+ private def elabToAdditiveAux (ref : Syntax) (replaceAll trace : Bool) (tgt : Option Syntax)
482
+ (doc : Option Syntax) : ValueType :=
469
483
{ replaceAll := replaceAll
470
484
trace := trace
471
485
tgt := match tgt with | some tgt => tgt.getId | none => Name.anonymous
472
486
doc := doc.bind (·.isStrLit?)
473
487
allowAutoName := false
488
+ ref
474
489
}
475
490
476
491
private def elabToAdditive : Syntax → CoreM ValueType
477
- | `(attr| to_additive $[!%$replaceAll]? $[?%$trace]? $[$tgt]? $[$doc]?) =>
478
- return elabToAdditiveAux replaceAll.isSome trace.isSome tgt doc
492
+ | `(attr| to_additive%$tk $[!%$replaceAll]? $[?%$trace]? $[$tgt]? $[$doc]?) =>
493
+ return elabToAdditiveAux ((tgt.map (·.raw)).getD tk) replaceAll.isSome trace.isSome tgt doc
479
494
| _ => throwUnsupportedSyntax
480
495
481
496
/-!
@@ -701,10 +716,12 @@ initialize registerBuiltinAttribute {
701
716
withOptions
702
717
(fun o => o |>.setBool `to_additive.replaceAll val.replaceAll
703
718
|>.setBool `trace.to_additive shouldTrace)
704
- (transformDecl src tgt)
719
+ (transformDecl val.ref src tgt)
705
720
if let some doc := val.doc then
706
721
addDocString tgt doc
707
- return ()
722
+ -- Because `@[simp]` runs after compilation,
723
+ -- we have to as well to be able to copy attributes correctly.
724
+ applicationTime := .afterCompilation
708
725
}
709
726
710
727
0 commit comments