Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Labeled break and continue #2216

Closed
brson opened this Issue · 31 comments
@brson
Owner

Henri needs a labeled break and continue equivalent in order to generate an HTML parser for servo. For C++ they use gotos and macros. We could possibly devise something with macros, though it may not be efficient.

@graydon

The only difficulty is grammatical: collides when at the beginning of a block. Open brace ident colon is the prefix of a record literal. Any other good looking options?

@boggle

Would pre-declaring of labels help to sort this out, i.e. label foo and a production that dispatches pre-declared labels as potential jump targets and non-declared ones as record fields?

@graydon

might, but seems unfortunate. maybe some kind of sub production on the loop headers? while foo: bar() {...} should work, i think. label immediately following loop keyword. tolerable?

@boggle

I find that hard to read when scanning for labels but with a small lookahead 'foo: while' should be distinguishable due to while being a keyword.

@bstrie
Collaborator

Right now {foo: while true { break; }} is a valid record where the value of foo is ().

@bstrie
Collaborator

Perhaps the most sane solution is simply to introduce a new label keyword. In that way at least it doesn't require too much cleverness, and it requires people to be explicit where they want to use labeled break and continue (which hopefully will not be too often).

@nikomatsakis

One thing: I don't know what Henri needs precisely, but at least in Java it is possible to label an arbitrary block and break out of it:

some_block: {
    ...
    if (some_cond)
        // Jumps to (1)
        break some_block;
    ...
}
... // (1)

Whatever syntax we do may need to be applicable to blocks as well.

This was referenced
@brson
Owner

I think we should try to resolve this for 0.3

@brson
Owner

I took a peek at the parser source and I suspect that it only uses labels on for loops, mostly ones that look like for(;;).

@brson
Owner
#[label = "foo"]
loop {
}

We don't even have to commit to a syntax.

@brson
Owner
#[label = "foo"]
loop {
    #[label = "foo"]
    break;
}
@boggle

Nice, I like this!

@graydon

Attributes could work but feels odd to me given that it is control flow. What about assembly style labels? .label: { ... } ?

@bstrie
Collaborator

If concerns over the syntax for labeling loops is blocking this, there's a way to defer that argument while still having this feature:

loop {
    // whatever
    loop {
        // whatever
        loop {
            if whatever {
                break 0;  // breaks to the parent loop
            }
            else {
                break 1;  // breaks to the grandparent loop
            }
        }
    }
}

Ugly, but at least it wouldn't preclude people from making use of labeled break/continue due to syntax concerns.

@brson
Owner

This is likely to be a rarely used feature so it doesn't need a perfect syntax. It may not be worth, for example, reserving the prefix dot for labels, introducing a new syntax for naming things. Splicing the name in as a subproduction of the loop header as graydon suggested is a reasonably unobtrusive way to introduce a feature we're not sure about.

Here's another idea - loop is the only way to create a labeled loop and it looks like this:

loop {
loop: foo {
loop: bar while something {
loop: baz for xs.each |x| {

This should be easier to scan since all the labels are in the same position.

@JosephLenton

A random suggestion, but why not allow multiple breaks in a stamenet?

loop {
    loop {
        loop {
            break break break;
        }
    }
}

If one break breaks one loop, then two breaks should break two loops, and three would break three loops, and so on.

@Vincent-Belliard

I think that Rust doesn't use dot as an unary prefixed operator. A syntax could be:

loop.foo {}
while.foo a > 0 {}
for.foo each(~[2, 4, 8, 5, 16]) |n| {}

The dot could also be replaced by a colon.

@pcwalton pcwalton was assigned
@jesse99

Was this done in bdb206f? If so it should be documented.

@brson
Owner

The syntax has been added as loop foo: { }, with no syntax for while and for. This is hopefully the minimum we can do to support the use cases for which it matters. It still doesn't work though.

@burg

IME, labeled break/continue is really really helpful when writing an inline flow/text wrapping algorithm.

@catamorphism catamorphism was assigned
@catamorphism

Reassigning to myself.

@nikomatsakis

Deferring to 0.5

@brson
Owner
@hsivonen

One thing: I don't know what Henri needs precisely, but at least in Java it is possible to label an arbitrary block and break out of it

Whoa. I was unaware!

The parser code currently just breaks/continues conditionless for loops. However, so of those never loop and are, in fact, just block to break out of, but I didn’t know that was allowed in Java.

@ibukanov

Regarding that Java feature where the break can jump out of any labeled block. Effectively it provides a forward-only goto that cannot enter new blocks. So what about just adding a real goto to Rust that has the similar forward-only jump restrictions? Then one would not need a labeled continue and explicit label statement no longer looks bad like in:

loop {
loop {
loop {
goto out;
}
}
}
label out;

@brson
Owner

@ibukanov nice idea! It does add two entire keywords for a corner case, though.

@ibukanov
@JosephLenton

Then use 'break break break' instead. No new keywords, just a little extra grammar.

Even with the controlled goto's we have now, they are not that readable.

@catamorphism

This is going to be my priority for 0.5 (and shouldn't take the entire time in between now and the next release!)

@catamorphism catamorphism referenced this issue from a commit
Commit has since been removed from the repository and is no longer available.
@catamorphism catamorphism referenced this issue from a commit in catamorphism/rust
@catamorphism catamorphism Preliminary support for labeled break/continue for `loop`s
This patch adds preliminary middle-end support (liveness and trans)
for breaks and `loop`s to `loop` constructs that have labels.

while and for loops can't have labels yet.

Progress on #2216
57624a3
@catamorphism

Preliminary version pending review by @pcwalton .

@catamorphism catamorphism referenced this issue from a commit
@catamorphism catamorphism Preliminary support for labeled break/continue for `loop`s
This patch adds preliminary middle-end support (liveness and trans)
for breaks and `loop`s to `loop` constructs that have labels.

while and for loops can't have labels yet.

Progress on #2216
dd66e75
@catamorphism

This is working except for a named break inside a for loop. I guess I'll just make a separate bug for that.

@jayanderson jayanderson referenced this issue from a commit
Commit has since been removed from the repository and is no longer available.
@catamorphism catamorphism was unassigned by brson
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.