Zulip Chat Archive
Stream: lean4
Topic: Disabling Macro Hygine?
Siddharth Bhat (Oct 10 2021 at 02:24):
I wish to write a macro which elaborates in the context of another macro. I use identifiers like i32
to refer to types. Unfortunately, since these types are identifiers, the hygiene system changes them to things like i32._@._hyg.746
. These fail macro expansion (since they don't look like i<int>
). Question: Can I disable hygiene for certain (known) identifiers?
For some context: I have a macro [mlir_op| ...]
provides a low-level macro for building ASTs. A high level macro prettyOp
expands into [mlir_op| "std.prettyOp" : i32]
. It is during this expansion that the i32
becomes i32._@._hyg.746
, which fails the parserule for [mlir_type| $x:ident ]
.
import Lean.Parser
import Lean.Parser.Extra
open Lean
open Lean.Parser
mutual
inductive MLIRTy : Type where
| int : Int -> MLIRTy
inductive Op : Type where
| mk: (name: String) -> (ty: MLIRTy) -> Op
end
declare_syntax_cat mlir_op
declare_syntax_cat mlir_type
syntax ident: mlir_type
syntax "[mlir_type|" mlir_type "]" : term
macro_rules
| `([mlir_type| $x:ident ]) => do
let xstr := x.getId.toString
if xstr.front == 'i'
then do
let xstr' := xstr.drop 1
match xstr'.toInt? with
| some i =>
let lit := Lean.Syntax.mkNumLit xstr'
`(MLIRTy.int $lit)
| none =>
Macro.throwError $ "cannot convert suffix of i to int: " ++ xstr
else Macro.throwError "expected i<int>" -- `(MLIRTy.int 1337)
def tyi32NoGap : MLIRTy := [mlir_type| i32]
syntax strLit ":" mlir_type : mlir_op
syntax "[mlir_op|" mlir_op "]" : term
macro_rules
| `([mlir_op| $name:strLit : $ty:mlir_type ]) => do
`(Op.mk $name [mlir_type| $ty])
syntax "prettyOp" : mlir_op -- operation that returns an i32
macro_rules
| `([mlir_op|prettyOp]) => do `( [mlir_op| "std.prettyOp" : i32] )
def prettyBad0 := [mlir_op| prettyOp]
#print prettyBad0
David Renshaw (Oct 10 2021 at 02:28):
Does set_option hygiene false
work for you? See e.g. https://github.com/leanprover/lean4/blob/fb27537b8ee686251f5e51d7daf6c467731994c3/tests/lean/unhygienic.lean#L15
Siddharth Bhat (Oct 10 2021 at 02:30):
Yes, this seems to do the trick! In particular, changing the rule for the macro expansion of prettyOp
to be:
set_option hygiene false in
macro_rules
| `([mlir_op|prettyOp]) => do `( [mlir_op| "std.prettyOp" : i32] )
works.
Now I must ask another question: Is this an abuse of the Lean macro system? Should Can I achieve the same effect in a different way? I am worried that disabling hygiene will have other effects that I don't anticipate.
Gabriel Ebner (Oct 10 2021 at 07:30):
You can use eraseMacroScopes to get the name the user typed (i).
I think you can also match on the i directly (i instead of $x:ident), but I'm not sure how that interacts with hygiene.
Last updated: Dec 20 2023 at 11:08 UTC