-
-
Notifications
You must be signed in to change notification settings - Fork 79
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
fix for new line num nodes from JuliaSyntax #195
Conversation
Codecov ReportPatch coverage:
❗ Your organization is not using the GitHub App Integration. As a result you may experience degraded service beginning May 15th. Please install the Github App Integration for your organization. Read more. Additional details and impacted files@@ Coverage Diff @@
## master #195 +/- ##
==========================================
+ Coverage 73.76% 79.67% +5.91%
==========================================
Files 9 10 +1
Lines 404 428 +24
==========================================
+ Hits 298 341 +43
+ Misses 106 87 -19
☔ View full report in Codecov by Sentry. |
This still feels a bit fragile, but no more fragile than it already was. I call it fragile because julia does not have a |
src/utils.jl
Outdated
# Don't use `unblock` to preserve line nos | ||
return length(ex′.args) == 1 ? ex′.args[1] : ex′ | ||
# Don't use `unblock` to preserve line nos. Check for blocks that contain only a line number node. | ||
return length(ex′.args) == 1 && !isline(ex′.args[1]) ? ex′.args[1] : ex′ |
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.
I'd say that in general, Expr(:block, x)
-> x
is a valid transform, including for line numbers, so I'm a bit reluctant.
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.
Are you saying that you prefer that try is special cased here?
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.
Could you special-case try
? I'm not super into this code, but it looks to me like the special-casing solution would involve replacing the flatten
postwalk
with an explicit tree traversal, which I also wouldn't like very much. I don't know! It's not a fun bug to fix. Let's see if it really fixes JuliaLang/julia#50710 (comment). If not, then is there a reason to merge this? It might break someone else's subtle macrology.
@cstjean , I think I successfully special-cased The |
!isexpr(ex.args[3]) && (ex.args[3] = quote $(ex.args[3]) end) | ||
elseif length(ex.args) == 4 | ||
# try finally end # 4 args, 2nd==3rd==false, 4th is expr | ||
# try catch finally end # 4 args, 2nd is a symbol or false, 3rd and 4th are expr |
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.
To help with the review, here is some context:
Before this PR, the following was being processed incorrectly (the error is not caught):
quote; try; error(); catch; false; finally; println(123); end; end |> striplines |> flatten |> eval
Now flatten
raises an error and refuses to proceed.
However, the following used to work, but now it raises an error (with a workaround suggested in the error message):
quote; try; 1+1; finally; println(123); end; end |> striplines |> flatten |> eval
I do not see how to avoid the silent bug in the first snippet without refusing to process the second snippet as well -- well, except for a full rewrite of flatten
that does not use postwalk
.
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.
I think making sure people do not run into silent bugs is a good enough reason to sacrifice a bit of related accidentally working functionality.
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.
It is also of note that this is highly improbable to be triggered: someone needs to explicitly use striplines
otherwise the line number nodes prevent this ambiguity from happening.
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.
except for a full rewrite of flatten that does not use postwalk.
I think it'd be worth giving this a try, in a separate PR. Sorry that I said I wouldn't like that approach; I just didn't see a completely satisfying (simple and correct) solution anywhere. Mike Innes' original code is beautifully simple and straight-forward, and I'd like to keep that as much as possible.
In ay case, I would start by looking at pre/postwalk
and write the recursive descent flatten
that special-cases try
, so that the third argument's block is never flattened. I don't want to special-case false
, because that's precisely the mistake that Julia's AST did, and that special-case can have ripples downstream.
Thank you for tackling this!
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.
Something like
flatten(x) = x
function flatten(x::Expr)
if isexpr(x, :try)
Expr(:try, flatten(x.args[1]), flatten(x.args[2]), Expr(:block, map(flatten, x.args[3].args)...))
else
flatten1(Expr(x.head, map(flatten, x.args)...))
end
(just a sketch, this is full of mistakes for sure)
In retrospect, that's quite simple and we get to solve all problems perfectly. Sorry for not having suggested it sooner.
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.
I am missing something. I was under the impression that only the following options exist for try blocks:
- 3 argument blocks where the 3rd argument is a block, corresponding to
try catch end
- 4 argument blocks where the 3rd argument is a block, corresponding to
try catch finally end
- 4 argument blocks where the 3rd argument is false, corresponding to
try finally end
- 5 argument blocks where the 4th argument is a block, corresponding to
try catch else finally end
- 5 argument blocks where the 4th argument is false, corresponding to
try catch else end
In your example above it seems like you only permit 3 argument blocks?
Or maybe you did not mean to focus on specifically what the special case for try should look like, rather you are telling me to use a "prewalk" style recursion instead of the current "postwalk" style recursion? I think I agree with that, but I will not have the time to attempt to contribute this for a couple of weeks.
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.
Or maybe you did not mean to focus on specifically what the special case for try should look like, rather you are telling me to use a "prewalk" style recursion instead of the current "postwalk" style recursion?
Yes, that. Of course we need to handle all the cases you mentioned. Sorry that wasn't clear.
It's not a prewalk, in the sense that it doesn't apply the transformation again on the outcome. It's like postwalk, where we simply do not directly apply the transformation to the third argument of the try, but deal with it appropriately.
I think I agree with that, but I will not have the time to attempt to contribute this for a couple of weeks.
👍 Thank you very much for the PR and issue! It helps a lot. I don't think that Julia 1.10 will be ready for a long time, so I don't think it's very pressing. Could even be fixed after release, arguably.
Fixes #194
Fixes JuliaLang/julia#50710