Zulip Chat Archive

Stream: lean4

Topic: Parser category for instance parameters


Marcus Rossel (Oct 05 2022 at 12:26):

I'm trying to write a macro that generates a type class instance.
What is the correct category to use for the type parameters of the class?

For example, I want to generate:

instance : MyClass Type1 (someComputation .returning).type2 where
  ...

I tried:

open Lean Macro in
macro "generate_instance" first:term second:term : command => do
  ...

But that results in expected term when writing generate_instance Type1 (someComputation .returning).type2.

Jannis Limperg (Oct 05 2022 at 13:04):

The parser for instance commands is defined like this:

def «instance»       := leading_parser Term.attrKind >> "instance" >> optNamedPrio >> optional (ppSpace >> declId) >> ppIndent declSig >> declVal >> terminationSuffix

I found this in Lean/Parser/Command.lean by searching for 'instance'.

pcpthm (Oct 05 2022 at 15:10):

Alternatively, the parser for a builtin syntax can also be found by the go-to-definition feature https://leanprover.zulipchat.com/#narrow/stream/270676-lean4/topic/structure-like.20custom.20syntax/near/294606430

Marcus Rossel (Oct 06 2022 at 08:25):

@Jannis Limperg I'm guessing that the relevant part in

def «instance» := leading_parser Term.attrKind >> "instance" >> optNamedPrio >> optional (ppSpace >> declId) >> ppIndent declSig >> declVal >> terminationSuffix

... is declSig (which I'm guessing stands for "declaration signature"), right? From its definition:

def declSig := leading_parser many (ppSpace >> (Term.binderIdent <|> Term.bracketedBinder)) >> Term.typeSpec

... I'd take the relevant part to be Term.typeSpec:

def typeSpec := leading_parser " : " >> termParser

... and hence termParser:

def termParser (prec : Nat := 0) : Parser :=
  categoryParser `term prec

But for me that's basically a dead end.
Or does this mean that term is in fact the correct category to use in my example?

Marcus Rossel (Oct 06 2022 at 08:26):

pcpthm said:

Alternatively, the parser for a builtin syntax can also be found by the go-to-definition feature https://leanprover.zulipchat.com/#narrow/stream/270676-lean4/topic/structure-like.20custom.20syntax/near/294606430

This doesn't seem to work for instance (at least when I tried).

Jannis Limperg (Oct 06 2022 at 09:40):

Or does this mean that term is in fact the correct category to use in my example?

No, the correct category (parser, actually, but parsers and syntax categories are, I believe, interchangeable here) is declSig. You'll have to lift your term into a declSig, e.g. with something like this:

let sig <- `(declSig| : $first:term)

If you give an #mwe, I can look into the issue in more detail. It usually takes some experimentation for me to get the syntax system to cooperate. ;)

Marcus Rossel (Oct 06 2022 at 13:54):

@Jannis Limperg Hmm, I don't quite see how to use declSig yet. An MWE would be:

import Lean
open Lean Macro

macro "gen_coe" src:term dst:term : command => do
  `(
    instance : Coe $src $dst where
      coe := sorry
  )

gen_coe Bool (if true then Nat else Int) -- error

Jannis Limperg (Oct 06 2022 at 14:03):

The error seems to be that Lean parses Bool (if true then Nat else Int) as one term (an ill-typed application). This works:

import Lean
open Lean Macro

macro "gen_coe" "[" src:term "]" "[" dst:term "]" : command =>
  `(
    instance : Coe $src $dst where
      coe := sorry
  )

gen_coe [Bool] [Int]

However, I would recommend that you write $src:term and $dst:term in the body of the macro. Without these annotations, you may get weird errors. (Maybe this is no longer the case with TSyntax.)

Sebastian Ullrich (Oct 06 2022 at 14:09):

Yes, that issue should no longer be an issue :)

Sebastian Ullrich (Oct 06 2022 at 14:10):

You can also use src:term:max to make sure it's not parsed as an application

Marcus Rossel (Oct 06 2022 at 14:15):

Thanks you two!


Last updated: Dec 20 2023 at 11:08 UTC