Zulip Chat Archive
Stream: lean4
Topic: Using nested Macro
Codegoblin (Apr 23 2024 at 16:16):
Hello,
is it possible, to nest Macros in the way, that the outer Macro "just" calls the macro rules of the underlying macro?
As Example:
declare_syntax_cat under
syntax "start " under* " end" : command
macro_rules
| `(start $stx* end) => `($stx) -- How to call the lower Macro Definition?
syntax "eval " ident : under
macro_rules
| `(under| eval $id) => `(#eval $id)
syntax "check" ident : under
macro_rules
| `(under| check $id) => `(#check $id)
variable (x:Nat)
start
eval x
check x
end
I would like to encapsulate my Macros in a scope beginning with "start" and ending with "end", inside I want to be able to call *-many checks or evals (nothing else should be permitted). They should just evaluate to the macro rules already defined for them (e.g. check x becomes #check x)
Maybe there is also an easier or better way to archive this?
Codegoblin (Apr 26 2024 at 07:42):
I tried to solve my problem with another approach: Instead of using the underlying macro rules, I tried to recapture them in functions. However here I get either typeclass instance problem is stuck, it is often due to metavariables
private def evalMacroSyntax1
(entries : Array (TSyntax `under)) := do
let mut cmds := #[]
for entry in entries do -- error in this line
let cmd ← match entry with
| `(under| check $id) => `(#check $id)
| `(under| eval $id) => `(#eval $id)
| _ => unreachable!
cmds := cmds.push cmd
return cmds
or I get multiple failed to synthesize instance
private def evalMacroSyntax2
(entries : Array (TSyntax `under)) :=
return entries.foldl
(init := (#[]))
fun (entry) => fun
| `(under| check $id) => `(#check $id) -- error here
| `(under| eval $id) => `(#eval $id) -- error here
| _ => unreachable!
These examples are written into the original example.
How can I resolve these errors? How can I avoid crossing such errors in the future?
Sebastian Ullrich (Apr 26 2024 at 07:49):
You should annotate the return types of your functions
Codegoblin (Apr 26 2024 at 09:41):
@Sebastian Ullrich If I give the return type of Array (TSyntax `command) I apparently need to add Id.run, however then I get the error failed to synthesize instance now related to Id.
private def evalMacroSyntax
(entries : Array (TSyntax `under))
: Array (TSyntax `command) := Id.run do
let mut cmds : Array (TSyntax `command) := #[]
for entry in entries do
let cmd ← match entry with
| `(under| check $id) => `(#check $id) -- errors here
| `(under| eval $id) => `(#eval $id) --errors here
| _ => unreachable!
cmds := cmds.push cmd
return cmds
If this is not possible to solve, it's OK, since I can use MacroM Syntax as return value. However, then I cannot join the result with others (of type MacroM Syntax). Or if it is possible, I don't know how to do it.
With the following version I get another error in the last step saying (kernel) declaration has free variables '_eval'. Is this an Error in my variable declaration?
open Lean
declare_syntax_cat under
syntax "eval " ident : under
syntax "check" ident : under
private def evalMacroSyntax
(entries : Array (TSyntax `under))
: MacroM Syntax := do
let mut cmds : Array (TSyntax `command) := #[]
for entry in entries do
let cmd : TSyntax `command ←
match entry with
| `(under| check $id) => `(#check $id)
| `(under| eval $id) => `(#eval $id)
| _ => unreachable! -- there are only two permitted options
cmds := cmds.push cmd
return (mkNullNode cmds)
syntax "start " under+ " end" : command
macro_rules
| `(start $stx* end) => evalMacroSyntax stx
variable (x:Nat)
start -- here i get the error => (kernel) declaration has free variables '_eval'
eval x
check x
end
Sebastian Ullrich (Apr 26 2024 at 09:46):
What do you expect evaluating a free variable to do? You get the same error using #eval x
independently of your macro
Codegoblin (Apr 26 2024 at 09:55):
Oh, indeed. This was a problem in front of the pc. :laughing:
Thanks so far. However, I have one last question: Is it possible to "concatenate" multiple Structures of MacroM Syntax together? Or is the only way here to collect all in an Array and use mkNullNode?
Last updated: May 02 2025 at 03:31 UTC