@@ -225,6 +225,26 @@ You can enable this with `@[to_additive!]`-/
225
225
def replaceAll [Functor M] [MonadOptions M] : M Bool :=
226
226
(·.getBool `to_additive.replaceAll) <$> getOptions
227
227
228
+ /-- `Config` is the type of the arguments that can be provided to `to_additive`. -/
229
+ structure Config : Type where
230
+ /-- Replace all multiplicative declarations, do not use the heuristic. -/
231
+ replaceAll : Bool := false
232
+ /-- View the trace of the to_additive procedure.
233
+ Equivalent to `set_option trace.to_additive true`. -/
234
+ trace : Bool := false
235
+ /-- The name of the target (the additive declaration).-/
236
+ tgt : Name := Name.anonymous
237
+ /-- An optional doc string.-/
238
+ doc : Option String := none
239
+ /-- If `allowAutoName` is `false` (default) then
240
+ `@[to_additive]` will check whether the given name can be auto-generated. -/
241
+ allowAutoName : Bool := false
242
+ /-- The `Syntax` element corresponding to the original multiplicative declaration
243
+ (or the `to_additive` attribute if it is added later),
244
+ which we need for adding definition ranges. -/
245
+ ref : Syntax
246
+ deriving Repr
247
+
228
248
variable [Monad M] [MonadOptions M] [MonadEnv M]
229
249
230
250
/-- Auxilliary function for `additiveTest`. The bool argument *only* matters when applied
@@ -390,7 +410,7 @@ using the transforms dictionary.
390
410
`pre` is the declaration that got the `@[to_additive]` attribute and `tgt_pre` is the target of this
391
411
declaration. -/
392
412
partial def transformDeclAux
393
- (ref : Option Syntax ) (pre tgt_pre : Name) : Name → CoreM Unit := fun src ↦ do
413
+ (cfg : Config ) (pre tgt_pre : Name) : Name → CoreM Unit := fun src ↦ do
394
414
-- if this declaration is not `pre` or an internal declaration, we do nothing.
395
415
if not (src == pre || isInternal' src) then
396
416
if (findTranslation? (← getEnv) src).isSome then
@@ -413,19 +433,19 @@ partial def transformDeclAux
413
433
let prefixes : NameSet := .ofList [pre, env.mainModule ++ `_auxLemma]
414
434
-- we first transform all auxiliary declarations generated when elaborating `pre`
415
435
for n in srcDecl.type.listNamesWithPrefixes prefixes do
416
- transformDeclAux none pre tgt_pre n
436
+ transformDeclAux cfg pre tgt_pre n
417
437
if let some value := srcDecl.value? then
418
438
for n in value.listNamesWithPrefixes prefixes do
419
- transformDeclAux none pre tgt_pre n
439
+ transformDeclAux cfg pre tgt_pre n
420
440
-- if the auxilliary declaration doesn't have prefix `pre`, then we have to add this declaration
421
441
-- to the translation dictionary, since otherwise we cannot find the additive name.
422
442
if !pre.isPrefixOf src then
423
443
insertTranslation src tgt
424
444
-- now transform the source declaration
425
445
let trgDecl : ConstantInfo ← MetaM.run' $ updateDecl tgt srcDecl
426
- if ¬ trgDecl.hasValue then
427
- throwError "Expected {trgDecl.name } to have a value."
428
- trace[to_additive] "generating\n {trgDecl.name } :=\n {trgDecl.value!}"
446
+ if ! trgDecl.hasValue then
447
+ throwError "Expected {tgt } to have a value."
448
+ trace[to_additive] "generating\n {tgt } :=\n {trgDecl.value!}"
429
449
try
430
450
-- make sure that the type is correct,
431
451
-- and emit a more helpful error message if it fails
@@ -434,25 +454,17 @@ partial def transformDeclAux
434
454
| Exception.error _ msg => throwError "@[to_additive] failed.
435
455
Type mismatch in additive declaration. For help, see the docstring
436
456
of `to_additive.attr`, section `Troubleshooting`.
437
- Failed to add declaration\n {trgDecl.name }:\n {msg}"
457
+ Failed to add declaration\n {tgt }:\n {msg}"
438
458
| _ => panic! "unreachable"
439
459
if isNoncomputable env src then
440
460
addDecl trgDecl.toDeclaration!
441
- setEnv $ addNoncomputable (← getEnv) trgDecl.name
461
+ setEnv $ addNoncomputable (← getEnv) tgt
442
462
else
443
463
addAndCompile trgDecl.toDeclaration!
444
464
-- now add declaration ranges so jump-to-definition works
445
465
addDeclarationRanges tgt {
446
466
range := ← getDeclarationRange (← getRef)
447
- selectionRange := ← getDeclarationRange (ref.getD (← getRef))
448
- }
449
- if let some ref := ref then
450
- -- TODO: make a function for this
451
- pushInfoLeaf <| .ofTermInfo {
452
- elaborator := .anonymous, lctx := {}, expectedType? := none
453
- stx := ref, isBinder := true
454
- expr := ← mkConstWithLevelParams trgDecl.name
455
- }
467
+ selectionRange := ← getDeclarationRange cfg.ref }
456
468
if isProtected (← getEnv) src then
457
469
setEnv $ addProtected (← getEnv) tgt
458
470
@@ -491,8 +503,8 @@ Make a new copy of a declaration, replacing fragments of the names of identifier
491
503
the body using the `translations` dictionary.
492
504
This is used to implement `@[to_additive]`.
493
505
-/
494
- def transformDecl (ref : Option Syntax ) (src tgt : Name) : CoreM Unit := do
495
- transformDeclAux ref src tgt src
506
+ def transformDecl (cfg : Config ) (src tgt : Name) : CoreM Unit := do
507
+ transformDeclAux cfg src tgt src
496
508
/- We need to generate all equation lemmas for `src` and `tgt`, even for non-recursive
497
509
definitions. If we don't do that, the equation lemma for `src` might be generated later
498
510
when doing a `rw`, but it won't be generated for `tgt`. -/
@@ -534,26 +546,6 @@ def firstMultiplicativeArg (nm : Name) : MetaM Nat := do
534
546
| [] => return 0
535
547
| (head :: tail) => return tail.foldr Nat.min head
536
548
537
- /-- `ValueType` is the type of the arguments that can be provided to `to_additive`. -/
538
- structure ValueType : Type where
539
- /-- Replace all multiplicative declarations, do not use the heuristic. -/
540
- replaceAll : Bool := false
541
- /-- View the trace of the to_additive procedure.
542
- Equivalent to `set_option trace.to_additive true`. -/
543
- trace : Bool := false
544
- /-- The name of the target (the additive declaration).-/
545
- tgt : Name := Name.anonymous
546
- /-- An optional doc string.-/
547
- doc : Option String := none
548
- /-- If `allowAutoName` is `false` (default) then
549
- `@[to_additive]` will check whether the given name can be auto-generated. -/
550
- allowAutoName : Bool := false
551
- /-- The `Syntax` element corresponding to the original multiplicative declaration
552
- (or the `to_additive` attribute if it is added later),
553
- which we need for adding definition ranges. -/
554
- ref : Syntax
555
- deriving Repr
556
-
557
549
/-- Helper for `capitalizeLike`. -/
558
550
partial def capitalizeLikeAux (s : String) (i : String.Pos := 0 ) (p : String) : String :=
559
551
if p.atEnd i || s.atEnd i then
@@ -729,38 +721,44 @@ def proceedFields (src tgt : Name) : CoreM Unit := do
729
721
-- `Name.mapPrefix` will do that automatically.
730
722
731
723
private def elabToAdditiveAux (ref : Syntax) (replaceAll trace : Bool) (tgt : Option Syntax)
732
- (doc : Option Syntax) : ValueType :=
724
+ (doc : Option Syntax) : Config :=
733
725
{ replaceAll := replaceAll
734
726
trace := trace
735
727
tgt := match tgt with | some tgt => tgt.getId | none => Name.anonymous
736
728
doc := doc.bind (·.isStrLit?)
737
729
allowAutoName := false
738
730
ref }
739
731
740
- private def elabToAdditive : Syntax → CoreM ValueType
732
+ private def elabToAdditive : Syntax → CoreM Config
741
733
| `(attr| to_additive%$tk $[!%$replaceAll]? $[?%$trace]? $[$tgt]? $[$doc]?) =>
742
734
return elabToAdditiveAux ((tgt.map (·.raw)).getD tk) replaceAll.isSome trace.isSome tgt doc
743
735
| _ => throwUnsupportedSyntax
744
736
745
- /-- `addToAdditiveAttr src val ` adds a `@[to_additive]` attribute to `src` with configuration `val `.
737
+ /-- `addToAdditiveAttr src cfg ` adds a `@[to_additive]` attribute to `src` with configuration `cfg `.
746
738
See the attribute implementation for more details. -/
747
- def addToAdditiveAttr (src : Name) (val : ValueType ) : AttrM Unit :=
748
- withOptions (· |>.setBool `to_additive.replaceAll val .replaceAll
749
- |>.updateBool `trace.to_additive (val .trace || ·)) <| do
750
- let tgt ← targetName src val .tgt val .allowAutoName
739
+ def addToAdditiveAttr (src : Name) (cfg : Config ) : AttrM Unit :=
740
+ withOptions (· |>.setBool `to_additive.replaceAll cfg .replaceAll
741
+ |>.updateBool `trace.to_additive (cfg .trace || ·)) <| do
742
+ let tgt ← targetName src cfg .tgt cfg .allowAutoName
751
743
insertTranslation src tgt
752
744
let firstMultArg ← MetaM.run' <| firstMultiplicativeArg src
753
745
if firstMultArg != 0 then
754
746
trace[to_additive_detail] "Setting relevant_arg for {src} to be {firstMultArg}."
755
747
relevantArgAttr.add src firstMultArg
756
- if (← getEnv).contains tgt then
748
+ let alreadyExists := (← getEnv).contains tgt
749
+ if alreadyExists then
757
750
-- since `tgt` already exists, we just need to add translations `src.x ↦ tgt.x'`
758
751
-- for any subfields.
759
752
proceedFields src tgt
760
753
else
761
754
-- tgt doesn't exist, so let's make it
762
- transformDecl val.ref src tgt
763
- if let some doc := val.doc then
755
+ transformDecl cfg src tgt
756
+ -- add pop-up information when mousing over `additive_name` of `@[to_additive additive_name]`
757
+ -- (the information will be over the attribute of no additive name is given)
758
+ pushInfoLeaf <| .ofTermInfo {
759
+ elaborator := .anonymous, lctx := {}, expectedType? := none, isBinder := !alreadyExists,
760
+ stx := cfg.ref, expr := ← mkConstWithLevelParams tgt }
761
+ if let some doc := cfg.doc then
764
762
addDocString tgt doc
765
763
return ()
766
764
@@ -969,8 +967,8 @@ initialize registerBuiltinAttribute {
969
967
add := fun src stx kind ↦ do
970
968
if (kind != AttributeKind.global) then
971
969
throwError "`to_additive` can't be used as a local attribute"
972
- let val ← elabToAdditive stx
973
- addToAdditiveAttr src val
970
+ let cfg ← elabToAdditive stx
971
+ addToAdditiveAttr src cfg
974
972
-- Because `@[simp]` runs after compilation,
975
973
-- we have to as well to be able to copy attributes correctly.
976
974
applicationTime := .afterCompilation
0 commit comments