Zulip Chat Archive
Stream: lean4
Topic: Macro using ← notation
Parth Shastri (Oct 29 2022 at 23:09):
I want to define a macro which expands into something of the form ← e
. However, I am getting an error saying that it must be nested inside a do expression. Is there a way to write such a macro?
macro "yield " t:term : term => `(← M.yield $t)
#check do _ := ← M.yield ()
#check do _ := yield () -- invalid use of `(<- ...)`, must be nested inside a 'do' expression
Marcus Rossel (Oct 30 2022 at 09:50):
Does it work if you have your macro return a doElem
instead of a term
?
macro "yield " t:term : doElem => `(← M.yield $t)
Parth Shastri (Oct 30 2022 at 15:49):
No, I want to use the macro in term position. Here's another example:
structure State
def foo : State → State
| s => s
def bar : State → StateM State Unit
| _ => return ()
macro "getFooState" : term => `(return foo (← getThe State))
macro "fooState" : term => `(foo (← getThe State))
#check do bar (foo (← getThe State))
#check do bar (← getFooState) -- this works, but still requires wrapping with (← _)
#check do bar fooState -- invalid use of `(<- ...)`, must be nested inside a 'do' expression
Parth Shastri (Oct 30 2022 at 17:34):
I figured out a hacky way to do this. I'm not yet sure how to make it extensible, as right now it requires declaring ahead of time all of the macros that are to be pre-expanded.
structure State
def foo : State → State
| s => s
def bar : State → StateM State Unit
| _ => return ()
macro (name := fooStateMacro) "fooState" : term => `(foo (← getThe State))
def doMacros : NameSet := .ofList [``fooStateMacro]
partial def expandDoMacros (stx : Syntax) : MacroM Syntax :=
match stx with
| .node info kind args => do
if doMacros.contains kind then
if let some stx := ← expandMacro? stx then
return ← expandDoMacros stx
return .node info kind (← args.mapM expandDoMacros)
| _ => return stx
macro (name := processedDoMacros) "processedDoMacros% " t:term : term => return t
def processDoMacros (stx : TSyntax `term) : MacroM (TSyntax `term) :=
if stx.raw.getKind == ``processedDoMacros
then throw .unsupportedSyntax
else do `(processedDoMacros% $(⟨← expandDoMacros stx⟩))
macro_rules | `(doElem| return $t) => do `(doElem| return $(← processDoMacros t))
-- macro_rules | `(doElem| $t:term) => do `(doElem| $(← processDoMacros t))
macro_rules | `(doElem| $t:term) => return .node1 (← MonadRef.mkInfoFromRefPos) `Lean.Parser.Term.doExpr (← processDoMacros t)
#check do bar (foo (← getThe State))
#check do bar fooState
#check return ← bar (foo (← getThe State))
#check return ← bar fooState
Chris Bailey (Oct 30 2022 at 17:53):
Macro expansion and elaboration are interleaved, and I think the built-in parsers and elaborators happen to be written in a way that makes bolting on this specific extension inconvenient. The arrow part of your expansion (← getThe State)
gets parsed as a liftMethod
and the builtin term elaborator for that is set to throw the error you're getting if it's elaborated outside of the other do
machinery.
Florin Dinu (Oct 30 2022 at 18:22):
Hi! I'm new to Lean, I've installed it and can't run a simple script (both with nightly and stable toolchains). I've made a file called test.lean in which I wrote 2 lines
import Leanpkg
#eval Leanpkg.leanVersionString
When I run lean test.lean I get
test.lean:1:0: error: unknown package 'Leanpkg'
test.lean:2:6: error: unknown identifier 'Leanpkg.leanVersionString'
test.lean:2:0: error: unknown constant 'sorryAx'
Kevin Buzzard (Oct 30 2022 at 18:24):
This is a thread about macros using certain notation. Can you ask your question in a new thread?
Florin Dinu (Oct 30 2022 at 18:25):
Kevin Buzzard said:
This is a thread about macros using certain notation. Can you ask your question in a new thread?
Sorry, I'm new to Zulip Chat, didn't know this is a thread.
James Gallicchio (Nov 03 2022 at 05:57):
Maybe when the do notation is eventually rewritten, it'll become easier to extend :fingers_crossed:
Parth Shastri (Nov 03 2022 at 21:54):
The essence of my workaround is a way to mark a macro as needing to be expanded before do notation is elaborated (doMacros
is the list of such macros). While this allows creating term macros that expands to uses of ←
, it is still very limited.
Last updated: Dec 20 2023 at 11:08 UTC