Skip to content
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 Expr conversion of erroneous operator dot call #374

Merged
merged 3 commits into from
Oct 31, 2023
Merged

Conversation

Liozou
Copy link
Member

@Liozou Liozou commented Oct 28, 2023

Fix #341

The root issue was the unconditional conversion of an Expr(:dotcall, foo, ...) to Expr(:call, Symbol(:., foo), ...) when foo was not an Expr(:., ...). That case corresponds to dotted operators (where foo is the symbol of the operator), but it can actually also occur when there is a parsing error, such as misplacing a non-unitary dotted operator like in the MWE.

I'm not completely sure what Expr should be yielded here, I went for Expr(:dotcall, Expr(:error, Expr(:., foo), ...) because it required minimal change, but let me know if it should be something else!

@codecov
Copy link

codecov bot commented Oct 28, 2023

Codecov Report

Merging #374 (66f7eba) into main (1b048aa) will increase coverage by 0.00%.
Report is 1 commits behind head on main.
The diff coverage is 100.00%.

@@           Coverage Diff           @@
##             main     #374   +/-   ##
=======================================
  Coverage   96.58%   96.58%           
=======================================
  Files          14       14           
  Lines        4160     4161    +1     
=======================================
+ Hits         4018     4019    +1     
  Misses        142      142           
Files Coverage Δ
src/expr.jl 99.69% <100.00%> (+<0.01%) ⬆️

... and 3 files with indirect coverage changes

@c42f
Copy link
Member

c42f commented Oct 29, 2023

Awesome, thanks for the PR!

As for the appropriate Expr here, we currently have the following conversion for .+ (which of course is valid):

julia> parsestmt(SyntaxNode, ".+julia", ignore_errors=true)
line:col│ tree                                   │ file_name
   1:1  │[dotcall-pre]
   1:2+
   1:3  │  julia


julia> dump(Expr(parsestmt(SyntaxNode, ".+julia", ignore_errors=true)))
Expr
  head: Symbol call
  args: Array{Any}((2,))
    1: Symbol .+
    2: Symbol julia

And we have the following tree for ./ which contains the error

julia> parsestmt(SyntaxNode, "./julia", ignore_errors=true)
line:col│ tree                                   │ file_name
   1:1  │[dotcall-pre]
   1:1  │  [error]
   1:1  │    [.]
   1:2/
   1:3  │  julia

Expr(:dotcall) isn't something which consumers of Expr know about - they only know about Expr(:call) so I think we should go with the closest analogy using Expr(:call) that we can find. This should probably be Expr(:call, Expr(:error, Expr(:., :/)), :julia) ?

@Liozou
Copy link
Member Author

Liozou commented Oct 29, 2023

That's perfectly sensible: done in bea7bae, thanks for the correction!

Another question: should I assert that startsym is either a Symbol or an Expr(:error, ...) at the following:

JuliaSyntax.jl/src/expr.jl

Lines 276 to 278 in bea7bae

if startsym isa Symbol
args[1] = Symbol(:., startsym)
end # else startsym could be an Expr(:error), just propagate it

i.e. change the comment into an else clause that errors if startsym is not an Expr(:error, ...)? I don't know if the current policy is to eagerly error when encountering unexpected expressions at that point of the parser, or letting them flow.

Copy link
Member

@c42f c42f left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! I've noted a couple more minor quibbles, but I think this is basically good to go.

I'm in two minds about asserting that the else should be an Expr(:error). On the one hand, the parser shouldn't create any other forms. But on the other hand, people can construct SyntaxNodes programmatically and it might make sense just to convert them rather than throw. I don't really know what's best. Maybe leave as-is :-)

test/expr.jl Outdated Show resolved Hide resolved
src/expr.jl Outdated Show resolved Hide resolved
@Liozou
Copy link
Member Author

Liozou commented Oct 30, 2023

Thanks for the review, much better now!
I had somewhat similar hesitations regarding the error behaviour... But in any case this can be handled in a later PR if need be, it is not directly related to this bugfix anyway.

@c42f c42f merged commit 48ddfc6 into JuliaLang:main Oct 31, 2023
31 checks passed
@c42f
Copy link
Member

c42f commented Oct 31, 2023

Looks lovely, thank youu :)

@Liozou
Copy link
Member Author

Liozou commented Oct 31, 2023

Thank you for all the help!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

MethodError: no method matching isless(::Int64, ::Nothing)
2 participants