-
-
Notifications
You must be signed in to change notification settings - Fork 5.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
Improve how some kind of Expr are displayed by the show method #32423
Conversation
This is awesome, thanks! Welcome. |
Some other small tweaks following Jeff Bezanson suggestions (see JuliaLang#32423).
"Base.@int128_str \"11111111111111111111\"". Restricted the class of "special syntax" macrocalls which benefit of the modifications this PR is about, according to discussion at JuliaLang#32423
I see that having merged with #32412 fixed only the buildbot/tester_win32 run, but the buildbot/tester_win64 still fails, even though with different symptoms: this time it doesn't shows any error(but it shows some warnings), it simply times out at some point. |
That failure simply looks like a fluke: it timed out. We see this from time to time, so I wouldn't worry about it. |
Thanks @musm for the reply. Is there something specific I should do, or the failing test will at some point be subject to a rebuilt? Or could I forget about it and leave it in this failed state? |
Could you rebase this now that #32412 is merged? |
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.
This is a really great first contribution. Thanks!
I'm a little worried about the change to the printing of $
. Does it make sense for nested quoted code?
Just to link up some threads, here's some related (complementary) improvements to show I've been toying with: #32408, #32201 (comment) |
76d4cc0
to
5ee7dc2
Compare
Some other small tweaks following Jeff Bezanson suggestions (see JuliaLang#32423).
"Base.@int128_str \"11111111111111111111\"". Restricted the class of "special syntax" macrocalls which benefit of the modifications this PR is about, according to discussion at JuliaLang#32423
5ee7dc2
to
f6c74d3
Compare
Rebased as requested to accomodate for #32412 having been merged. |
I've realized that printing unquotes as |
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 looks to me that you're on the right track to sorting out the problems with $
using quote_level
.
Does quote_level
need to interact with the interpolation syntax used to print unusual Expr
s in the unhandled
section and inside show_unquoted(io::IO, ex::QuoteNode, indent::Int, prec::Int)
?
Regarding @c42f question about the need for interactions between |
julia> eval(Expr(:quote, (Expr(:$, :x))))
ERROR: UndefVarError: x not defined
Stacktrace:
[1] eval at ./boot.jl:328 [inlined]
[2] eval(::Expr) at ./client.jl:404
[3] top-level scope at none:0
julia> eval(QuoteNode((Expr(:$, :x))))
:($(Expr(:$, :x))) I mention it because it's one of the expressions which is itself printed as an interpolated expression when it's |
Do you have more time to push this forward? It's such a big improvement it would be a pity to not finish it off. It would be good to rebase to fix the conflicts, and maybe beneficial to squash the commits while you're at it. After that, there's one remaining question in my mind: does this printing handle all cases where exotic Expr(:block, Expr(:exotic_head, Expr(:$, :x))) |
I apologies for the long absence and for the late reply: in these past moths i was really busy in completing my master degree, and this will continue until the end of October. After that I think I should be able to find some time to reprise this PR. |
No problem at all! |
Fixe some failing doctests in doc/src/mamual/metaprogramming.md. Some other small tweaks following Jeff Bezanson suggestions (see JuliaLang#32423). Fixe a bug which caused errors when trying to show stuff like "Base.@int128_str \"11111111111111111111\"". Restrict the class of "special syntax" macrocalls which benefit of the modifications this PR is about, according to discussion at JuliaLang#32423 Change how nested interpolations are displayed (omitting unrequired parenthesis). Add test for nested quotes and interpolations. Correct small bug preventing correct display of "t[a b;]". Update metaprogramming docs to better reflect changes in how quoting and unquoting get displayed. Implement quote level counting mechanism to handle displaying of Expr "with more unquotes than quotes". Adde more tests for quote_level mechanism. Include unhandled case into quote_level mechanism. Rebase and squash previous commits. Fix conflicts due to introduction of var"#funky name" syntax. Add a couple of tests for exotic heads mixed with nested quoting and interpolation.
|
For more on this, see Lines 990 to 1004 in f0772c5
|
I have handled macrocall expressions whose macroname argument is "qualified", as in |
a84664b
to
dabfef5
Compare
Fixe some failing doctests in doc/src/mamual/metaprogramming.md. Some other small tweaks following Jeff Bezanson suggestions (see JuliaLang#32423). Fixe a bug which caused errors when trying to show stuff like "Base.@int128_str \"11111111111111111111\"". Restrict the class of "special syntax" macrocalls which benefit of the modifications this PR is about, according to discussion at JuliaLang#32423 Change how nested interpolations are displayed (omitting unrequired parenthesis). Add test for nested quotes and interpolations. Correct small bug preventing correct display of "t[a b;]". Update metaprogramming docs to better reflect changes in how quoting and unquoting get displayed. Implement quote level counting mechanism to handle displaying of Expr "with more unquotes than quotes". Adde more tests for quote_level mechanism. Include unhandled case into quote_level mechanism. Rebase and squash previous commits. Fix conflicts due to introduction of var"#funky name" syntax. Add a couple of tests for exotic heads mixed with nested quoting and interpolation. Handle repr of macrocall expressions with qualified macroname argument.
base/show.jl
Outdated
show_unquoted_quote_expr(io, args[1]::Symbol, indent, 0, quote_level+1) | ||
elseif head === :quote && nargs == 1 && Meta.isexpr(args[1], :block) | ||
if length(args[1].args) == 1 | ||
# one argument: Expr(:quote, Expr(:block, a_single_arg)) |
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 don't think this is correct, since when these are parsed there will not be a :block
expr. I think this whole branch can just be removed.
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.
On the countrary, tests suggest that this branch is needed to correctly handle cases like
macro m(a, b)
quote
\$a + \$b
end
end
In fact, without the branch
julia> repr(Meta.parse("""
macro m(a, b)
quote
\$a + \$b
end
end"""))
":(macro m(a, b)\n #= none:2 =#\n :(begin\n #= none:3 =#\n \$a + \$b\n end)\n end)"
while with it in place, more satisfactorily the result is
julia> repr(Meta.parse("""
macro m(a, b)
quote
\$a + \$b
end
end"""))
":(macro m(a, b)\n #= none:2 =#\n quote\n #= none:3 =#\n \$a + \$b\n end\n end)"
Another case that fails without the branch is
quote
quote
\$\$x
end
end
with both quotes turned into :(begin ... end)
upon repr(Meta.parse("..."))
ing it:
julia> repr(Meta.parse("""
quote
quote
\$\$x
end
end
"""))
":(:(begin\n #= none:2 =#\n :(begin\n #= none:3 =#\n \$\$x\n end)\n end))"
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.
In fact I've checked now, and actually "quote \$x end"
is parsed as a quote Expr
containing a block Expr
:
julia> dump(Meta.parse("quote \$x end"))
Expr
head: Symbol quote
args: Array{Any}((1,))
1: Expr
head: Symbol block
args: Array{Any}((2,))
1: LineNumberNode
line: Int64 1
file: Symbol none
2: Expr
head: Symbol $
args: Array{Any}((1,))
1: Symbol x
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, those cases are fine. The problem is when the block
Expr has one element, e.g. it prints the value of Expr(:quote, Expr(:block, :(a+b)))
as :(:(a + b))
.
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.
After some thinking, I must say that I very much prefer having
julia> show(Expr(:quote, Expr(:block, :(a + b))))
:(:(a + b))
than
julia> show(Expr(:quote, Expr(:block, :(a + b))))
:(:(begin
a + b
end))
since the former is coherent with the case in which the block has more than one argument, where, for reasons mentioned in my last two comments, the block itself is actually hidden upon show
ing:
julia> show(Expr(:quote, Expr(:block, :(a + b), :(c + d))))
:(quote
a + b
c + d
end)
Nevertheless, the final word is of course yours.
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.
Sounds good to me. Another option could be :(:(a + b;))
which parses as a block with a single entry and no line number node. What I'm not entirely sure about is whether that works in all cases?
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.
Now I see your point. After some experimenting I think my preference is for @JeffBezanson 's suggestion. With that, we get a nicely consistent picture:
julia> show(Expr(:quote, Expr(:block)))
:(quote
end)
julia> show(Expr(:quote, Expr(:block, :(a + b))))
:(quote
a + b
end)
julia> show(Expr(:quote, Expr(:block, :(a + b), :(c + d))))
:(quote
a + b
c + d
end)
@c42f 's suggestion is somewhat cleaner, as there are no line numbers appearing in the call Meta.parse(repr(Expr(:quote, Expr(:block, :(a + b)))))
but I find :(:(a + b;))
and in particular :(:(a;))
to be a little confusing, and I definitely dislike it if instead of a + b
or a
there is some more complicated expression, possibly spread over more than one line: compare
julia> show(Expr(:quote, Expr(:block, Expr(:if, :(a == b), :(a + b), :(a - b)))))
:(:(if a == b
a + b
else
a - b
end;))
with
julia> show(Expr(:quote, Expr(:block, Expr(:if, :(a == b), :(a + b), :(a - b)))))
:(quote
if a == b
a + b
else
a - b
end
end)
By the way, this is my opinion, and I must admit that I may dislike semicolons more than they possibly deserve.
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 have updated the test_repr macro, adding a stronger form of the previous condition which have to be satisfied for the test to pass. The current solution, which neglect the one-argument inner block, fails the stronger test, while both of the suggestions due to @JeffBezanson and @c42f pass it. Now it is only a matter of deciding which solution to endorse.
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.
Once this is settled, with a cleaner local history I will merge with the upstream and fix conflicts.
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.
Let's use the quote ... end
syntax as you prefer. I don't think there is any particular promise that :(x;)
will not include a line number; in fact many people would probably prefer if it did include one.
Fixe some failing doctests in doc/src/mamual/metaprogramming.md. Some other small tweaks following Jeff Bezanson suggestions (see JuliaLang#32423). Fixe a bug which caused errors when trying to show stuff like "Base.@int128_str \"11111111111111111111\"". Restrict the class of "special syntax" macrocalls which benefit of the modifications this PR is about, according to discussion at JuliaLang#32423 Change how nested interpolations are displayed (omitting unrequired parenthesis). Add test for nested quotes and interpolations. Correct small bug preventing correct display of "t[a b;]". Update metaprogramming docs to better reflect changes in how quoting and unquoting get displayed. Implement quote level counting mechanism to handle displaying of Expr "with more unquotes than quotes". Adde more tests for quote_level mechanism. Include unhandled case into quote_level mechanism. Rebase and squash previous commits. Fix conflicts due to introduction of var"#funky name" syntax. Add a couple of tests for exotic heads mixed with nested quoting and interpolation. Handle repr of macrocall expressions with qualified macroname argument.
Improve test_repr macro, testing whether removing line numbers spoils something.
8f98a39
to
7d8c4b6
Compare
I have added to the Having said that, "Rule 1" (or its weaker form) was satisfied for free in all cases bar for
|
@JeffBezanson @c42f With this I think I have reached satisfaction with this PR. Let me know if you think there is more to do, or if you want me to squash some commits. |
It seems strongly unlikely to me that quote_level "belongs" in IOContext. I know it seems like a simpler way to pass around arguments, but it's actually dynamic scope and so has a different use case (although one can usually be used to emulate the other, poorly). |
@vtjnash I don't disagree, but I'd like to better understand your objection to using
I suspect variables like Regarding an alternative to using |
This is subtle, but it's exactly backwards: the IOContext is for setting options when using By contrast, that means Yes, they could be paired into a edit: fixed to say |
Sure, I'd say it might or might not be helpful; a bit hard to judge without trying it out. It might turn out cleanly if paired with a utility function like |
Thanks @ChiaffarelliMarco ! Let's revert the |
Completely agreed 💯. The benefit of merging this soon is high compared to getting some minor implementation details "just right". Further cleanup can definitely happen in a separate PR. Doing it separately makes sense anyway if combined with a similar refactor for the other AST-showing context parameters. |
46bf334
to
b9430c7
Compare
Well, thanks for the feedback. I have reverted to the old quote_level mechanism. |
Thanks for seeing this through @ChiaffarelliMarco ! It's taken quite a while, but we got there! |
Yes, great work @ChiaffarelliMarco, I look forward to having these improvements 🎉 |
Rather than adding a new |
@stevengj this was done previously but removed; see discussion starting at #32423 (comment) |
Fix some failing doctests in doc/src/mamual/metaprogramming.md. Some other small tweaks following Jeff Bezanson suggestions (see #32423). Fix a bug which caused errors when trying to show stuff like "Base.@int128_str \"11111111111111111111\"". Restrict the class of "special syntax" macrocalls which benefit of the modifications this PR is about, according to discussion at #32423 Change how nested interpolations are displayed (omitting unrequired parenthesis). Add test for nested quotes and interpolations. Correct small bug preventing correct display of "t[a b;]". Update metaprogramming docs to better reflect changes in how quoting and unquoting get displayed. Implement quote level counting mechanism to handle displaying of Expr "with more unquotes than quotes". Add more tests for quote_level mechanism. Include unhandled case into quote_level mechanism. Add a couple of tests for exotic heads mixed with nested quoting and interpolation. Handle repr of macrocall expressions with qualified macroname argument. * Handle nested quotes and blocks. Improve test_repr macro, testing whether removing line numbers spoils something. * Add test for Rule 1, which requires Meta.parse(string(ex)) == ex.
The improvements concerns the following Expr:
T[a b] T[a b; c d]
quote $a+$b end
-"special macros"
`a b c` r"foo" foo"bar"zot
-"long" numeric literals, which are implemented as macros
11111111111111111111 0xfffffffffffffffff 11111111111111111111111111111111111111111111111111111111111111
Also, now the function test_repr in test/show.jl can (and indeed does) directly and successfully compare
Meta.parse(x)
with
eval(Meta.parse(repr(Meta.parse(x))))
Notice that I'm not to be credited with the latter achievement, since master branch also could have
(but did not) directly and successfully use the same comparison. I suppose the person to be credited
with solving the issue preventing this way of testing to succeed failed to actually update the test routine.