Conversation
8b5a6e0 to
1f607ca
Compare
|
Capturing some discussion from this morning: There appears to be general support for this version of the proposal, so I will move forwards with cleanup and getting this ready to merge. Some specific concerns:
|
Updated accordingly |
|
I haven't felt much need for labeled breaks, but the use case of cleanup statements, which I would like syntactic support for, I think would be well served by a built-in dedicated construct like https://github.com/c42f/ResourceContexts.jl. |
If one refactors code from "lots of loopy goto" to "semi-structured control flow that makes reducibility of the CFG apparent", then one needs to introduce a bunch of additional nested All that being said... isn't this all doable by having a (small caveat: rewriting into |
|
IIUC a labeled continue targeting the innermost loop is equivalent to a normal continue, and when targeting the Nth loop from the inside, it’s equivalent to a labeled break of the N-1th loop, so I don’t see the need |
|
That doesn't sound right but feel free to see if you can reduce the
I'm much in favor of it. Sure, it doesn't scale great to deep nesting but for the common cases it's much more concise than the label syntax. |
Consider: The I further like the fact that labeled |
|
You are right - I didn't think carefully enough. |
|
Labeled continue is already implemented by this PR |
Syntax versioning (intentionally) uses a binding partitioned constant to set the syntax version. This gives well defined meaning to changing the parser of the course of a module's lifetime, but open's up the question which world age `include` uses to determine the syntax version. I think the correct answer is that `include` should look at the latest world age, since it also implicitly raises the world age for the statements it executes, so it would be somewhat inconsistent for the parse to happen in the caller's world age. Fixes #60624. Also addresses a somewhat hilarious interaction with backdating where the syntax version depended on the value of `--depwarn` (causing test failures in #60481).
|
👍 I like the feature. Can we drop the colons to be consistent with |
|
There is no intention for the label to be computed. However, the value could be a variable of course as in |
|
To me |
|
Sure. We can also call the macro something different though, since you can't |
|
Triage brings up that Triage is conflicted on the advantage over Things we want from any syntax:
@Keno is going to vibecode the proposal with which we will discuss next time (unless he comes up with a better option before then. |
) Syntax versioning (intentionally) uses a binding partitioned constant to set the syntax version. This gives well defined meaning to changing the parser of the course of a module's lifetime, but open's up the question which world age `include` uses to determine the syntax version. I think the correct answer is that `include` should look at the latest world age, since it also implicitly raises the world age for the statements it executes, so it would be somewhat inconsistent for the parse to happen in the caller's world age. Fixes #60624. Also addresses a somewhat hilarious interaction with backdating where the syntax version depended on the value of `--depwarn` (causing test failures in #60481). --------- Co-authored-by: Keno Fischer <Keno@users.noreply.github.com> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
I implemented this, but I think I will not PR it - I think it's too clever. I've played with a few more variants, but I keep coming back to the proposal as currently in this PR. I also think we should keep the function break_with_underscore()
@label x begin
for i in 1:10
if i > 5
break x i * 3
end
end
0
end
endis very jarring on the eyes. That said, maybe that can be mitigated with syntax highlighting - I'll play with that as well. |
|
I don't feel like the syntax highlighting is a slam dunk - that example only has two colors, so it's really isolating the label semantically but that doesn't seem typical to me. I'm not sure how to color that, e.g., for Github's highlighter since that already uses red, white, and blue for return i * 3on its own |
I just need it to be colored differently than any juxtaposed identifier. |
498f727 to
e33e549
Compare
|
It seems that this PR needs further updates on the new lowering implementation. julia> @label _ begin
for i = 1:10
x = i
break _ x
end
end
1
julia> JuliaLowering.include_string(Main, """
@label _ begin
for i = 1:10
x = i
break _ x
end
end
""")
ERROR: LoweringError:
for i = 1:10
x = i
break _ x
# ╙ ── Invalid break label: expected identifier
end
end
Detailed provenance:
_
└─ _
├─ _
│ └─ @ string:4
└─ (macrocall @label _ (block (for (iteration (in i (call-i 1 : 10))) (block (= x i) (break _ x)))))
└─ (macrocall (macro_name ✘ label) ✘ _ ✘ (block nothing ✘ (for nothing (iteration (in ✘ i ✘ = (call-i ✘ 1 : 10))) (block ✘ (= x ✘ = ✘ i) ✘ (break nothing ✘ _ ✘ x) ✘) nothing) ✘ nothing))
└─ @ string:1 |
|
Thanks. Will fix. I changed the design of that back and forth like three times and must have forgotten to change it back |
Adds back JuliaLowering support for `break _` (ref #60481 (comment)) Improves error message for label mismatch (fixes #60817) Written by Claude
Adds back JuliaLowering support for `break _` (ref #60481 (comment)) Improves error message for label mismatch (fixes #60817) Written by Claude
|
Is there any reason we can't make the This error message is a bit internal: |
- symbolic_block -> symbolicblock (since I did symbolicgoto, symboliclabel too) - should fix Expr-incompatibility as well (default conversion) - add new continue/break/symbolicblock forms to validator - fix scope of new identifier in JL `@label` (hygiene by default means we need to specify the scope layer if we're generating new identifiers in the macro)
I think that would be fine, but also doesn't seem necessary - we can just improve the error message. The important bit to me was the we could emit continue blocks in a macro, in case a package wants to have their own looping structure. |
- symbolic_block -> symbolicblock (since I did symbolicgoto, symboliclabel too) - should fix Expr-incompatibility as well (default conversion) - add new continue/break/symbolicblock forms to validator - fix scope of new identifier in JL `@label` (hygiene by default means we need to specify the scope layer if we're generating new identifiers in the macro)
- symbolic_block -> symbolicblock (since I did symbolicgoto, symboliclabel too) - should fix Expr-incompatibility as well (default conversion) - add new continue/break/symbolicblock forms to validator - fix scope of new identifier in JL `@label` (hygiene by default means we need to specify the scope layer if we're generating new identifiers in the macro)
- symbolic_block -> symbolicblock (since I did symbolicgoto, symboliclabel too) - should fix Expr-incompatibility as well (default conversion) - add new continue/break/symbolicblock forms to validator - fix scope of new identifier in JL `@label` (hygiene by default means we need to specify the scope layer if we're generating new identifiers in the macro)
- symbolic_block -> symbolicblock (since I did symbolicgoto, symboliclabel too) - should fix Expr-incompatibility as well (default conversion) - add new continue/break/symbolicblock forms to validator - fix scope of new identifier in JL `@label` (hygiene by default means we need to specify the scope layer if we're generating new identifiers in the macro)
|
What's up with this? I want to update the Multibreak package to use these expressions, |
|
It's a syntax versioned feature. |
|
But inactive includes aren't parsed, are they? |
|
Correct, if you want to mix syntax versions in your packages (which is not really recommended), you can do Note that the syntax version change will affect all future includes. Maybe we should hav a version of the macro that changes it for just one include. |
Backports labeled break/continue support from JuliaLang/julia#60481 (commit 8dab3f0623) to support parsing Julia 1.14+ source code. Co-authored-by: Claude <noreply@anthropic.com>
|
Actually I was a little silly not realizing that I didn't need the syntax but only the AST expressions in the code. I did need the syntax in the tests though, so the tips came in handy. One more question, are there any potential problems with having unused |
Will be gone after lowering. |

This is a redo of #60367 taking into account various feedback on that PR. In particular, it seemed like people strongly disliked the
break breaksyntax for two primary reasons:break break break breakInstead, the consensus seemed to be that labeled break should be the only facility available. Thus, this implements a proper labeled break facility that looks as follows:
The idea is to re-use the
@labelmacro for now, but possibly promote this to syntax in a future version if it gains widespread use. Note that parser changes are still required, since thebreaksyntax is currently an error. However, compat.jl could provide@goto break name val, which parses fine.continueis extended with label support as well:However, the feature is not restricted to loops. A particular use case is to replace cleanup blocks written like
by a labeled begin/end block:
This doesn't save much typing work, but it makes this kind of pattern much more structured, e.g. for code-folding in IDEs.
A similar pattern replaces the
for-thenconstruction originally proposed:For convenience, the label may be ommitted, in which case it defaults to
_, i.e. the above can be written as:I've taken the liberty of converting some base code for testing and to give an idea of what the syntax looks like in practice, but didn't go through particularly comprehensively. These changes should be considered extended usage examples.
Largely written by Claude, and I haven't looked at the implementation particularly carefully yet - for now I'm just interested in discussion of the syntax.