소스 검색

Start updating control flow design (#544)

Jon Meow 4 년 전
부모
커밋
93e7a37493

+ 82 - 53
docs/design/README.md

@@ -26,8 +26,12 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
     -   [Variables](#variables)
     -   [Lifetime and move semantics](#lifetime-and-move-semantics)
     -   [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)
 -   [Types](#types)
     -   [Primitive types](#primitive-types)
@@ -352,87 +356,112 @@ Breaking this apart:
 
 ### 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
 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
-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
-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`
 
-> 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
 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
 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)