Преглед изворни кода

Add C++-like `while` loops (#340)

Add C++-like `while` loops

- Omits variable declarations in condition syntax (`while (auto x = DoSomething())`).
Jon Meow пре 5 година
родитељ
комит
7e81fb9c62
2 измењених фајлова са 254 додато и 0 уклоњено
  1. 1 0
      proposals/README.md
  2. 253 0
      proposals/p0340.md

+ 1 - 0
proposals/README.md

@@ -44,6 +44,7 @@ request:
 -   [0199 - String literals](p0199.md)
 -   [0253 - 2021 Roadmap](p0253.md)
 -   [0285 - if/else](p0285.md)
+-   [0340 - while loops](p0340.md)
 -   [0426 - Governance & evolution revamp](p0426.md)
 
 <!-- endproposals -->

+ 253 - 0
proposals/p0340.md

@@ -0,0 +1,253 @@
+# while loops
+
+<!--
+Part of the Carbon Language project, under the Apache License v2.0 with LLVM
+Exceptions. See /LICENSE for license information.
+SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+-->
+
+[Pull request](https://github.com/carbon-language/carbon-lang/pull/340)
+
+<!-- toc -->
+
+## Table of contents
+
+-   [Problem](#problem)
+-   [Background](#background)
+-   [Proposal](#proposal)
+-   [Details](#details)
+    -   [Executable semantics form](#executable-semantics-form)
+-   [Caveats](#caveats)
+    -   [C++ as baseline](#c-as-baseline)
+    -   [`do`/`while`](#dowhile)
+-   [Rationale based on Carbon's goals](#rationale-based-on-carbons-goals)
+-   [Alternatives considered](#alternatives-considered)
+    -   [Non-C++ syntax](#non-c-syntax)
+    -   [Initializing variables in the `while`](#initializing-variables-in-the-while)
+
+<!-- tocstop -->
+
+## Problem
+
+`while` is noted in the [language overview](/docs/design/README.md#while), but
+is provisional. Control flow is important, and `while` is basic; the form is
+similar in many languages, even if details may change.
+
+## Background
+
+-   C++: A couple example languages following C++'s syntax closely are Java and
+    TypeScript.
+
+    ```cc
+    while (x) {
+      DoSomething();
+    }
+
+    do {
+      DoSomethingElse();
+    } while (y);
+    ```
+
+-   Python: Python does not provide `do`/`while`. However, the `else` syntax for
+    having code execute if the condition is _never_ true may be of interest.
+
+    ```python
+    while x:
+      DoSomething()
+
+    while True:
+      DoSomethingElse()
+      if not y:
+        break
+
+    while z:
+      print("z is true")
+    else:
+      print("z was never true")
+    ```
+
+-   Swift: Swift uses `repeat` instead of `do`.
+
+    ```swift
+    while x {
+      DoSomething()
+    }
+
+    repeat {
+      DoSomethingElse()
+    } while y
+    ```
+
+-   Rust: Rust provides only a basic `while` loop, relying on the condition-less
+    `loop` to achieve `do`/`while`-like behavior.
+
+    ```rust
+    while x {
+      DoSomething();
+    }
+
+    loop {
+      DoSomethingElse();
+      if (!y) { break; }
+    }
+    ```
+
+-   Go: Go has no `while` loops, only `for` loops. However, a `for` can be
+    written similar to a `while`.
+
+    ```go
+    for x {
+      DoSomething()
+    }
+
+    for {
+      DoSomethingElse();
+      if !y { break; }
+    }
+    ```
+
+## Proposal
+
+Carbon should adopt `while` loop syntax consistent with C/C++. In particular, it
+should adopt these three kinds of statements:
+
+-   `while`: declares that we're doing a loop, containing the condition.
+-   `continue`: continues with the next loop iteration, starting with the loop
+    condition.
+-   `break`: breaks out of the loop, without testing the loop condition.
+
+## Details
+
+Loop syntax looks like:
+
+-   `while (` _boolean expression_ `) {` _statements_ `}`
+
+While will evaluate the loop condition before each pass of the loop, only
+continuing if the loop condition is true. When the loop condition evaluates to
+false, the loop completes.
+
+Similar to the
+[`if`/`else` proposal](https://github.com/carbon-language/carbon-lang/pull/285),
+the braces are optional and must be paired (`{ ... }`) if present. When there
+are no braces, only one statement is allowed.
+
+`continue` will continue with the next loop iteration directly, skipping any
+other statements in the loop body. The next loop iteration behaves as normal,
+starting with the condition being tested.
+
+`break` exits the loop immediately, without testing the condition.
+
+All of this is consistent with C/C++ behavior.
+
+### Executable semantics form
+
+```
+%token WHILE
+%token CONTINUE
+%token BREAK
+
+statement:
+  WHILE '(' expression ')' statement
+| CONTINUE ';'
+| BREAK ';'
+| /* pre-existing statements elided */
+;
+```
+
+Note that `continue` and `break` should only be valid in a loop context.
+
+## Caveats
+
+### C++ as baseline
+
+This baseline syntax is based on C++, following the migration sub-goal
+[Familiarity for experienced C++ developers with a gentle learning curve](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code).
+To the extent that this proposal anchors on a particular approach, it aims to
+anchor on C++'s existing syntax, consistent with that sub-goal.
+
+Alternatives will generally reflect breaking consistency with C++ syntax. While
+most proposals may consider alternatives more, this proposal suggests a
+threshold of only accepting alternatives that skew from C++ syntax if they are
+clearly better; the priority in this proposal is to _avoid debate_ and produce a
+trivial proposal. Where an alternative would trigger debate, it should be
+examined by an advocate in a separate proposal.
+
+### `do`/`while`
+
+`do`/`while` is omitted from this proposal because of disagreement about whether
+it should be included in Carbon. It's better to have `do`/`while` considered
+separately as a result, in order to separate review of the non-contentious
+`while`.
+
+## Rationale based on Carbon's goals
+
+Relevant goals are:
+
+-   [3. Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write):
+
+    -   `while` loops are easy to read and very helpful.
+
+-   [7. Interoperability with and migration from existing C++ code](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code):
+
+    -   Keeping syntax close to C++ will make it easier for developers to
+        transition.
+
+## Alternatives considered
+
+Both alternatives from the
+[`if`/`else` proposal](https://github.com/carbon-language/carbon-lang/pull/285)
+apply to `while` as well: we could remove parentheses, require braces, or both.
+The conclusions mirror here in order to avoid a divergence in syntax.
+
+Additional alternatives follow.
+
+### Non-C++ syntax
+
+Various non-C++ features that came up and are not suggested by this proposal
+because they aren't in C++ are:
+
+-   `else` on `while`, as in Python.
+-   A `loop` statement with `while(true)` behavior, as in Rust.
+-   Labeled break and continue statements, as in Java or TypeScript.
+
+These may be added later, but they are not part of the
+[C++ baseline](#c-as-baseline), and have not received much consideration beyond
+that adopting the proposed syntax would not significantly impair adoption of
+such features.
+
+### Initializing variables in the `while`
+
+This proposal does not offer a way to initialize variables in the `while`.
+
+For comparison, C++ does allow declaring a variable in the condition, such as:
+
+```cc
+while (optional<T> next = get_next()) { ... }
+```
+
+In addition,
+[Selections statements with initializer](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0305r1.html)
+could be inferred to suggest a corresponding `while (init; cond)` syntax.
+
+Neither of these is suggested in this proposal because we are likely to consider
+a _different_ route of allowing declaration of a variable in expressions. For
+example, the following would be legal not because `while` would use a
+`condition` semantic that allows variable declarations as a form, but because it
+uses `expression` semantics and `var` would be part of `expression` semantics:
+
+```carbon
+while (var optional<T> next = get_next()) { ... }
+```
+
+In particular, this would also allow more flexible usage addressing more complex
+use-cases that C++ does not, such as:
+
+```carbon
+while ((var status_code c = bar()) != SUCCESS) { ... }`
+```
+
+This breaks slightly from the [C++ baseline](#c-as-baseline) by offering a
+subset of C++ functionality. However, we can choose to add related functionality
+later if `expression` semantics end up not including `var`. Temporarily omitting
+`condition` functionality avoids having to reconcile it later if we pursue the
+`expression` route, and it is not crucial to `while` loop functionality.