Zulip Chat Archive

Stream: mathlib4

Topic: dsimp conv


Moritz Doll (Sep 16 2022 at 01:21):

So I've looked a bit into the conv-version of dsimp and I have run into two issues: First I don't know what
the syntax argument of mkSimpContext is supposed to do (so in the code I first set it to Lean.Syntax.missing).
Also I messed up the elaboration, so that it changes the usual dsimp and not the conv dsimp and I have no idea how to fix that.

The code

import Mathlib.Tactic.Basic
import Mathlib.Tactic.Core

namespace Lean.Parser.Tactic.Conv
open Elab.Tactic Elab.Tactic.Conv

/- N -/ syntax (name := dsimp) "dsimp" (&" only")? (dsimpArgs)? : conv

def evalDSimp : Tactic := fun stx => withMainContext do
  let { ctx, .. }  mkSimpContext stx (eraseLocal := false) (kind := .dsimp)
  let lhs  getLhs
  let result  Lean.Meta.dsimp lhs ctx
  changeLhs result

elab "dsimp" : tactic => evalDSimp Lean.Syntax.missing

example : (1 + 0) = 1 := by
  dsimp

example : (1 + 0) = 1 := by
  conv =>
    lhs
    dsimp

Moritz Doll (Sep 16 2022 at 01:28):

If I change it to elab "dsimp" : conv => .., then the error becomes "unsupported syntax category 'conv'" and I have no idea what that refers to

Gabriel Ebner (Sep 16 2022 at 07:23):

So there's quite a few things going on here.

Gabriel Ebner (Sep 16 2022 at 07:23):

Let me start at the end.

Gabriel Ebner (Sep 16 2022 at 07:25):

elab "dsimp" : conv => ..

Yes, it would be nice if we had this.. But it is not implemented in core. (As you've noticed we only have it for tactic but not for conv.)

Gabriel Ebner (Sep 16 2022 at 07:25):

The error message means just that: the elab command does not support conv.

Gabriel Ebner (Sep 16 2022 at 07:29):

Even if elab ... : conv worked it does something different than what you think it does. The elab command declares a new syntax parser (in this case dsimp) and then immediately defines an elaborator for this syntax. It would conflict with the syntax defined at the beginning of the file (and produce ambiguous parse trees with choice nodes).

Gabriel Ebner (Sep 16 2022 at 07:34):

If you looked at how the simp conv tactic is implemented in core, it looks like this:

@[builtinTactic Lean.Parser.Tactic.Conv.simp] def evalSimp : Tactic := fun stx => withMainContext do

The builtinTactic attribute is what registers the evalSimp attribute as an elaborator for the simp conv-tactic in core. The reason that this is called builtinTactic is because it uses builtin_initialize to add the tactic elaborator when loading the C++ code.

Gabriel Ebner (Sep 16 2022 at 07:35):

In mathlib, we need to use @[tactic Lean.Parser.Tactic.Conv.simp] instead.

Gabriel Ebner (Sep 16 2022 at 07:43):

mkSimpContext

The mkSimpContext function is super evil. Basically it assumes that the syntax argument is defined in exactly the same way as the builtin simp tactic, just with a different name. If you want to use it, you need to define dsimp as:

syntax (name := dsimp) "dsimp " (config)? (discharger)? (&"only ")? ("[" dsimpArg,* "]")? : conv

Basically it looks at stx[1] and hopes that it is a (config)?. If you leave out the (config)? in the syntax definition, mkSimpContext will fail in exciting ways.

Gabriel Ebner (Sep 16 2022 at 07:43):

(For consistency, I would suggest to use the syntax definition above ^^ and use mkSimpContext.)

Moritz Doll (Sep 16 2022 at 17:08):

Thank you so much Gabriel, it now works :octopus:
I saw the builtinTactic attribute, but I did not know that there is a version for non-builtin tactics. Is this documented anywhere and if not where should it be? maybe in @Arthur Paulino's book?
The reason I changed the syntax was only that I had funny import errors in the beginning and I thought leaving out some arguments might make it easier to get going.

Moritz Doll (Sep 16 2022 at 17:35):

do we have any useful tests for dsimp in mathlib3? I could not find anything in the test/conv folder and the one above does not really test more than that the command does not fail, because conv can finish the goal on its own

Moritz Doll (Sep 16 2022 at 17:36):

nevertheless the info view shows that it works as it should

Gabriel Ebner (Sep 16 2022 at 17:38):

Feel free to invent some tests. I would probably set up a goal like a * 1 + 0 and then two separate tests dsimp and dsimp only [Nat.add_zero].

Moritz Doll (Sep 16 2022 at 18:17):

I've managed to find one test that actually fails if the dsimp is omitted.


Last updated: Dec 20 2023 at 11:08 UTC