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

Loops grammar #139

Merged
merged 3 commits into from
Dec 1, 2017
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 56 additions & 4 deletions src/expressions/loop-expr.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,25 @@
# Loops

> **<sup>Syntax</sup>**
> _LoopExpression_ :
> &nbsp;&nbsp; [_LoopLabel_]<sup>?</sup> (
> &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; [_InfiniteLoopExpression_]
> &nbsp;&nbsp; &nbsp;&nbsp; | [_PredicateLoopExpression_]
> &nbsp;&nbsp; &nbsp;&nbsp; | [_PredicatePatternLoopExpression_]
> &nbsp;&nbsp; &nbsp;&nbsp; | [_IteratorLoopExpression_]
> &nbsp;&nbsp; )

[_LoopLabel_]: #loop-labels
[_InfiniteLoopExpression_]: #infinite-loops
[_PredicateLoopExpression_]: #predicate-loops
[_PredicatePatternLoopExpression_]: #predicate-pattern-loops
[_IteratorLoopExpression_]: #iterator-loops

Rust supports four loop expressions:

* A [`loop` expression](#infinite-loops) denotes an infinite loop.
* A [`while` expression](#predicate-loops) loops until a predicate is false.
* A [`while let` expression](#while-let-loops) tests a refutable pattern.
* A [`while let` expression](#predicate-pattern-loops) tests a refutable pattern.
* A [`for` expression](#iterator-loops) extracts values from an iterator,
looping until the iterator is empty.

Expand All @@ -14,6 +29,10 @@ Only `loop` supports [evaluation to non-trivial values](#break-and-loop-values).

## Infinite loops

> **<sup>Syntax</sup>**
> _InfiniteLoopExpression_ :
> &nbsp;&nbsp; `loop` [_BlockExpression_]

A `loop` expression repeats execution of its body continuously:
`loop { println!("I live."); }`.

Expand All @@ -26,6 +45,10 @@ expression(s).

## Predicate loops

> **<sup>Syntax</sup>**
> _PredicateLoopExpression_ :
> &nbsp;&nbsp; `while` [_Expression_]<sub>except struct expression</sub> [_BlockExpression_]

A `while` loop begins by evaluating the boolean loop conditional expression. If
the loop conditional expression evaluates to `true`, the loop body block
executes, then control returns to the loop conditional expression. If the loop
Expand All @@ -42,12 +65,17 @@ while i < 10 {
}
```

## `while let` loops
## Predicate pattern loops

> **<sup>Syntax</sup>**
> [_PredicatePatternLoopExpression_] :
> &nbsp;&nbsp; `while` `let` _Pattern_ `=` [_Expression_]<sub>except struct expression</sub>
> [_BlockExpression_]

A `while let` loop is semantically similar to a `while` loop but in place of a
condition expression it expects the keyword `let` followed by a refutable
pattern, an `=` and an expression. If the value of the expression on the right
hand side of the `=` matches the pattern, the loop body block executes then
pattern, an `=`, an expression and a block expression. If the value of the expression on
the right hand side of the `=` matches the pattern, the loop body block executes then
control returns to the pattern matching statement. Otherwise, the while
expression completes.

Expand All @@ -61,6 +89,11 @@ while let Some(y) = x.pop() {

## Iterator loops

> **<sup>Syntax</sup>**
> _IteratorLoopExpression_ :
> &nbsp;&nbsp; `for` _Pattern_ `in` [_Expression_]<sub>except struct expression</sub>
Copy link
Contributor

Choose a reason for hiding this comment

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

Like if, we probably want to link to struct expressions here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Still deciding how I'll do this (the "no struct expression" thing) to make it clear. But yeah, I agree a link to it will be needed.

> [_BlockExpression_]

A `for` expression is a syntactic construct for looping over elements provided
by an implementation of `std::iter::IntoIterator`. If the iterator yields a
value, that value is given the specified name and the body of the loop is
Expand Down Expand Up @@ -89,6 +122,10 @@ assert_eq!(sum, 55);

## Loop labels

> **<sup>Syntax</sup>**
> _LoopLabel_ :
> &nbsp;&nbsp; [LIFETIME_OR_LABEL] `:`

A loop expression may optionally have a _label_. The label is written as
a lifetime preceding the loop expression, as in `'foo: loop { break 'foo; }`,
`'bar: while false {}`, `'humbug: for _ in 0..0 {}`.
Expand All @@ -99,6 +136,10 @@ expressions](#continue-expressions).

## `break` expressions

> **<sup>Syntax</sup>**
> _BreakExpression_ :
> &nbsp;&nbsp; `break` [LIFETIME_OR_LABEL]<sup>?</sup> [_Expression_]<sup>?</sup>

When `break` is encountered, execution of the associated loop body is
immediately terminated, for example:

Expand Down Expand Up @@ -131,6 +172,10 @@ the forms `break`, `break 'label` or ([see below](#break-and-loop-values))

## `continue` expressions

> **<sup>Syntax</sup>**
> _ContinueExpression_ :
> &nbsp;&nbsp; `continue` [LIFETIME_OR_LABEL]<sup>?</sup>

When `continue` is encountered, the current iteration of the associated loop
body is immediately terminated, returning control to the loop *head*. In
the case of a `while` loop, the head is the conditional expression controlling
Expand Down Expand Up @@ -165,3 +210,10 @@ In the case a `loop` has an associated `break`, it is not considered diverging,
and the `loop` must have a type compatible with each `break` expression.
`break` without an expression is considered identical to `break` with
expression `()`.

[IDENTIFIER]: identifiers.html

[_Expression_]: expressions.html
[_BlockExpression_]: expressions/block-expr.html

[LIFETIME_OR_LABEL]: tokens.html#symbols