Explorar el Código

Start updating control flow design (#544)

Jon Meow hace 4 años
padre
commit
93e7a37493

+ 82 - 53
docs/design/README.md

@@ -26,8 +26,12 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
     -   [Variables](#variables)
     -   [Variables](#variables)
     -   [Lifetime and move semantics](#lifetime-and-move-semantics)
     -   [Lifetime and move semantics](#lifetime-and-move-semantics)
     -   [Control flow](#control-flow)
     -   [Control flow](#control-flow)
-        -   [`if`/`else`](#ifelse)
-        -   [`while`, `break`, and `continue`](#while-break-and-continue)
+        -   [`if` and `else`](#if-and-else)
+        -   [Loops](#loops)
+            -   [`while`](#while)
+            -   [`for`](#for)
+            -   [`break`](#break)
+            -   [`continue`](#continue)
         -   [`return`](#return)
         -   [`return`](#return)
 -   [Types](#types)
 -   [Types](#types)
     -   [Primitive types](#primitive-types)
     -   [Primitive types](#primitive-types)
@@ -352,87 +356,112 @@ Breaking this apart:
 
 
 ### Control flow
 ### Control flow
 
 
-> References: [Control flow](control_flow.md)
->
-> **TODO:** References need to be evolved.
+> References: [Control flow](control_flow/README.md)
 
 
 Blocks of statements are generally executed sequentially. However, statements
 Blocks of statements are generally executed sequentially. However, statements
 are the primary place where this flow of execution can be controlled.
 are the primary place where this flow of execution can be controlled.
 
 
-#### `if`/`else`
+#### `if` and `else`
 
 
-> References: [Control flow](control_flow.md)
->
-> **TODO:** References need to be evolved.
+> References: [Control flow](control_flow/conditionals.md)
 
 
-`if` and `else` are common flow control keywords, which can result in
-conditional execution of statements.
+`if` and `else` provide conditional execution of statements. For example:
 
 
-For example:
+```carbon
+if (fruit.IsYellow()) {
+  Print("Banana!");
+} else if (fruit.IsOrange()) {
+  Print("Orange!");
+} else {
+  Print("Vegetable!");
+}
+```
+
+This code will:
+
+-   Print `Banana!` if `fruit.IsYellow()` is `True`.
+-   Print `Orange!` if `fruit.IsYellow()` is `False` and `fruit.IsOrange()` is
+    `True`.
+-   Print `Vegetable!` if both of the above return `False`.
+
+#### Loops
+
+##### `while`
+
+> References: [Control flow](control_flow/loops.md#while)
+
+`while` statements loop for as long as the passed expression returns `True`. For
+example, this prints `0`, `1`, `2`, then `Done!`:
 
 
 ```carbon
 ```carbon
-fn Foo(Int x) {
-  if (x < 42) {
-    Bar();
-  } else if (x > 77) {
-    Baz();
-  }
+var Int x = 0;
+while (x < 3) {
+  Print(x);
+  ++x;
 }
 }
+Print("Done!");
 ```
 ```
 
 
-Breaking the `Foo` function apart:
+##### `for`
 
 
--   `Bar()` is invoked if `x` is less than `42`.
--   `Baz()` is invoked if `x` is greater than `77`.
--   Nothing happens if `x` is between `42` and `77`.
+> References: [Control flow](control_flow/loops.md#for)
 
 
-#### `while`, `break`, and `continue`
+`for` statements support range-based looping, typically over containers. For
+example, this prints all names in `names`:
 
 
-> References: [Control flow](control_flow.md)
->
-> **TODO:** References need to be evolved.
+```carbon
+for (var String name : names) {
+  Print(name);
+}
+```
 
 
-Loops will be supported with a low-level primitive `while` statement. `break`
-will be a way to exit the `while` directly, while `continue` will skip the rest
-of the current loop iteration.
+`PrintNames()` prints each `String` in the `names` `List` in iteration order.
 
 
-For example:
+##### `break`
+
+> References: [Control flow](control_flow/loops.md#break)
+
+The `break` statement immediately ends a `while` or `for` loop. Execution will
+resume at the end of the loop's scope. For example, this processes steps until a
+manual step is hit (if no manual step is hit, all steps are processed):
 
 
 ```carbon
 ```carbon
-fn Foo() {
-  var Int x = 0;
-  while (x < 42) {
-    if (ShouldStop()) break;
-    if (ShouldSkip(x)) {
-      ++x;
-      continue;
-    }
-    Bar(x);
-    ++x;
+for (var Step step : steps) {
+  if (step.IsManual()) {
+    Print("Reached manual step!");
+    break;
   }
   }
+  step.Process();
 }
 }
 ```
 ```
 
 
-Breaking the `Foo` function apart:
+##### `continue`
 
 
--   The while body is normally executed for all values of `x` in [0, 42).
-    -   The increment of x at the end causes this.
--   If `ShouldStop()` returns true, the `break` causes the `while` to exit
-    early.
--   If `ShouldSkip()` returns true, the `continue` causes the `while` to restart
-    early.
--   Otherwise, `Bar(x)` is called for values of `x` in [0, 42).
+> References: [Control flow](control_flow/loops.md#continue)
+
+The `continue` statement immediately goes to the next loop of a `while` or
+`for`. In a `while`, execution continues with the `while` expression. For
+example, this prints all non-empty lines of a file, using `continue` to skip
+empty lines:
+
+```carbon
+File f = OpenFile(path);
+while (!f.EOF()) {
+  String line = f.ReadLine();
+  if (line.IsEmpty()) {
+    continue;
+  }
+  Print(line);
+}
+```
 
 
 #### `return`
 #### `return`
 
 
-> References: [Control flow](control_flow.md)
->
-> **TODO:** References need to be evolved.
+> References: [Control flow](control_flow/return.md)
 
 
 The `return` statement ends the flow of execution within a function, returning
 The `return` statement ends the flow of execution within a function, returning
 execution to the caller. If the function returns a value to the caller, that
 execution to the caller. If the function returns a value to the caller, that
-value is provided by an expression in the return statement. This allows us to
-complete the definition of our `Sum` function from earlier as:
+value is provided by an expression in the return statement. For example:
 
 
 ```carbon
 ```carbon
 fn Sum(Int a, Int b) -> Int {
 fn Sum(Int a, Int b) -> Int {

+ 0 - 80
docs/design/control_flow.md

@@ -1,80 +0,0 @@
-# Control flow
-
-<!--
-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
--->
-
-<!-- toc -->
-
-## Table of contents
-
--   [TODO](#todo)
--   [Overview](#overview)
--   [Open questions](#open-questions)
-    -   [`if` blocks](#if-blocks)
-    -   [`break` and `continue`](#break-and-continue)
-
-<!-- tocstop -->
-
-## TODO
-
-This is a skeletal design, added to support [the overview](README.md). It should
-not be treated as accepted by the core team; rather, it is a placeholder until
-we have more time to examine this detail. Please feel welcome to rewrite and
-update as appropriate.
-
-At least summarize `if` and `else` to cover basics. Especially important to
-surface the idea of using basic conditionals as both expressions and statements
-to avoid needing conditional operators.
-
-Looping is an especially interesting topic to explore as there are lots of
-challenges posed by the C++ loop structure. Even C++ itself has been seeing
-significant interest and pressure to improve its looping facilities.
-
-## Overview
-
-Blocks of statements are generally executed linearly. However, statements are
-the primary place where this flow of execution can be controlled. Carbon's
-control flow constructs are mostly similar to those in C, C++, and other
-languages.
-
-```
-fn Foo(Int x) {
-  if (x < 42) {
-    Bar();
-  } else if (x > 77) {
-    Baz();
-  }
-}
-```
-
-Loops will at least be supported with a low-level primitive `while` statement,
-with `break` and `continue` statements which work the same as in C++.
-
-Last but not least, for the basics we need to include the `return` statement.
-This statement ends the flow of execution within a function, returning it to the
-caller. If the function returns a value to the caller, that value is provided by
-an expression in the return statement. This allows us to complete the definition
-of our `Sum` function from earlier as:
-
-```
-fn Sum(Int a, Int b) -> Int {
-  return a + b;
-}
-```
-
-## Open questions
-
-### `if` blocks
-
-It is an open question whether a block is required or a single statement may be
-nested in an `if` statement. Similarly, it is an open question whether `else if`
-is a single keyword versus a nested `if` statement, and if it is a single
-construct whether it should be spelled `elif` or something else.
-
-### `break` and `continue`
-
-If and how to support a "labeled break" or "labeled continue" is still a point
-of open discussion.

+ 26 - 0
docs/design/control_flow/README.md

@@ -0,0 +1,26 @@
+# Control flow
+
+<!--
+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
+-->
+
+## Overview
+
+Blocks of statements are generally executed linearly. However, statements are
+the primary place where this flow of execution can be controlled.
+
+Carbon's flow control statements are:
+
+-   [`if` and `else`](conditionals.md) provides conditional execution of
+    statements.
+-   Loops:
+    -   [`while`](loops.md#while) executes the loop body for as long as the loop
+        expression returns `True`.
+    -   [`for`](loops.md#for) iterates over an object, such as elements in an
+        array.
+    -   [`break`](loops.md#break) exits loops.
+    -   [`continue`](loops.md#continue) goes to the next iteration of a loop.
+-   [`return`](return.md) ends the flow of execution within a function,
+    returning it to the caller.

+ 46 - 0
docs/design/control_flow/conditionals.md

@@ -0,0 +1,46 @@
+# Control flow
+
+<!--
+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
+-->
+
+<!-- toc -->
+
+## Table of contents
+
+-   [Overview](#overview)
+-   [Relevant proposals](#relevant-proposals)
+
+<!-- tocstop -->
+
+## Overview
+
+`if` and `else` provide conditional execution of statements. For example:
+
+```carbon
+if (fruit.IsYellow()) {
+  Print("Banana!");
+} else if (fruit.IsOrange()) {
+  Print("Orange!");
+} else {
+  Print("Vegetable!");
+}
+```
+
+This code will:
+
+-   Print `Banana!` if `fruit.IsYellow()` is `True`.
+-   Print `Orange!` if `fruit.IsYellow()` is `False` and `fruit.IsOrange()` is
+    `True`.
+-   Print `Vegetable!` if both of the above return `False`.
+
+> TODO: Flesh out text (currently just overview)
+
+## Relevant proposals
+
+Most discussion of design choices and alternatives may be found in relevant
+proposals.
+
+-   [`if` and `else`](/proposals/p0285.md)

+ 96 - 0
docs/design/control_flow/loops.md

@@ -0,0 +1,96 @@
+# 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
+-->
+
+<!-- toc -->
+
+## Table of contents
+
+-   [`while`](#while)
+-   [`for`](#for)
+-   [`break`](#break)
+-   [`continue`](#continue)
+-   [Relevant proposals](#relevant-proposals)
+
+<!-- tocstop -->
+
+## `while`
+
+`while` statements loop for as long as the passed expression returns `True`. For
+example, this prints `0`, `1`, `2`, then `Done!`:
+
+```carbon
+var Int x = 0;
+while (x < 3) {
+  Print(x);
+  ++x;
+}
+Print("Done!");
+```
+
+> TODO: Flesh out text (currently just overview)
+
+## `for`
+
+`for` statements support range-based looping, typically over containers. For
+example, this prints all names in `names`:
+
+```carbon
+for (var String name : names) {
+  Print(name);
+}
+```
+
+`PrintNames()` prints each `String` in the `names` `List` in iteration order.
+
+> TODO: Flesh out text (currently just overview)
+
+## `break`
+
+The `break` statement immediately ends a `while` or `for` loop. Execution will
+resume at the end of the loop's scope. For example, this processes steps until a
+manual step is hit (if no manual step is hit, all steps are processed):
+
+```carbon
+for (var Step step : steps) {
+  if (step.IsManual()) {
+    Print("Reached manual step!");
+    break;
+  }
+  step.Process();
+}
+```
+
+> TODO: Flesh out text (currently just overview)
+
+## `continue`
+
+The `continue` statement immediately goes to the next loop of a `while` or
+`for`. In a `while`, execution continues with the `while` expression. For
+example, this prints all non-empty lines of a file, using `continue` to skip
+empty lines:
+
+```carbon
+File f = OpenFile(path);
+while (!f.EOF()) {
+  String line = f.ReadLine();
+  if (line.IsEmpty()) {
+    continue;
+  }
+  Print(line);
+}
+```
+
+> TODO: Flesh out text (currently just overview)
+
+## Relevant proposals
+
+Most discussion of design choices and alternatives may be found in relevant
+proposals.
+
+-   [`while`](/proposals/p0340.md)
+-   [`for`](/proposals/p0353.md)

+ 35 - 0
docs/design/control_flow/return.md

@@ -0,0 +1,35 @@
+# `return`
+
+<!--
+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
+-->
+
+<!-- toc -->
+
+## Table of contents
+
+-   [Overview](#overview)
+-   [Relevant proposals](#relevant-proposals)
+
+<!-- tocstop -->
+
+## Overview
+
+The `return` statement ends the flow of execution within a function, returning
+execution to the caller. If the function returns a value to the caller, that
+value is provided by an expression in the return statement. For example:
+
+```carbon
+fn Sum(Int a, Int b) -> Int {
+  return a + b;
+}
+```
+
+> TODO: Flesh out text (currently just overview)
+
+## Relevant proposals
+
+-   [Initial syntax](/proposals/p0415.md)
+-   [`return` with no argument](/proposals/p0538.md)