-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Quote do now works with result in block #7343
Conversation
This seems a bit hacky to me. I'm not yet sure why the problem happened in the first place, as |
Well it has to do with how the quote do magic works. What it does is something like this:
turns into
What this fix does is this:
turns into
This works around the template being expanded within the macro body scope and capturing the result variable by leaving the result variable out until after expansion. Note that the above is just pseudo-code that doesn't actually run, but that is more-or-less how it works |
I know how it works, because I've created the implementations of both |
Oh you wrote it, cool. Really useful tool! Last time I asked Araq about this he said it would be a PITA to fix properly, so at the time I devised the work-around I posted here: #7323 which I've used with great success. When I saw the above issue I decided to share my solution and figured that I could just as well incorporate it into how quote worked to avoid this issue altogether. It's not perfect, but it works, at least until someone decides to fix it properly. |
would it be possible to explicitly capture the |
Yes that should still be possible with this pull request. The wild result variable is converted to an anonymous symbol, and the NimNode with result is passed in as this anonymous symbol. So any result variable in backticks should still be possible. Note that I haven't actually tried that though so there might be something that breaks it. |
(proc(): int = result = 123)() | ||
|
||
mac() | ||
echo test() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
May be use doAssert
here instead of echo
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that would make sense. The original error would prevent this from compiling at all, which is probably why I didn't care to check the actual output of test
. But it would be good to do it none the less.
I like it and I want it. import macros
macro foobar(arg: untyped): untyped =
result = arg
result.add quote do:
`result`
foobar:
echo "Hallo Welt" |
Yes, that is already taken into consideration. I've added the test you wanted now, so you can see that it works. |
This fixes the annoying issue of not be able to use result inside a quote do block. It works by a simple trick. The quote do mechanic is based on dynamically creating a template and immediately calling it with the arguments found within the quote do block. Since this is called in the scope of the macro the result variable is shadowed. This trick works by changing all occurences of result (which shouldn't cause any issues as result isn't used for anything else for the same reason) to another name and then passing in an IdentNode with result as a named parameter with that name. Note that currently this just replaces it with a fixed named variable "res" which should be changed to a non-colliding, dynamically created name.
This fixes the hard coded parameter "res" to be an anonymous symbol instead so it won't collide with other parts of the argument list.
A simple test case based on GitHub issue nim-lang#7323 on how you can't put result in a quote do block. This test verifies that it actually works correctly now.
Since this was fairly old I rebased it against devel to bring it up to speed. Now it should be possible to merge it into 0.19.x+ |
* Fix result not being able to use in quote do This fixes the annoying issue of not be able to use result inside a quote do block. It works by a simple trick. The quote do mechanic is based on dynamically creating a template and immediately calling it with the arguments found within the quote do block. Since this is called in the scope of the macro the result variable is shadowed. This trick works by changing all occurences of result (which shouldn't cause any issues as result isn't used for anything else for the same reason) to another name and then passing in an IdentNode with result as a named parameter with that name. Note that currently this just replaces it with a fixed named variable "res" which should be changed to a non-colliding, dynamically created name. * Fix hard coded parameter "res" to anonymous symbol This fixes the hard coded parameter "res" to be an anonymous symbol instead so it won't collide with other parts of the argument list. * Add test case for result in quote do block A simple test case based on GitHub issue nim-lang#7323 on how you can't put result in a quote do block. This test verifies that it actually works correctly now. * Add test for explicit capturing of result * Rebased against devel
@PMunch can you also take a look at this issue. I actually forget about it and was recently reminded that it exists. Maybe you have a similar simple solution like this one for that problem: |
Hmm, nothing that comes to mind immediately, but I haven't looked at the code for that so it might be just as easy to fix once you look into it. |
Previously the useful "quote do" construct had an issue were the result variable would be shadowed by the macros result variable and thus get the wrong return type. These commits fixes this by adding a hidden parameter to the intermediary template and calling the template with an added
newNimNode("result")
argument. This way all results are only resolved after the macro expansion and thus avoids the shadowing of the macros own result variable.