Explorar el Código

Add a note about iterative coding style (#6528)

Adding the note about recursion because it occasionally comes up, and
I'm thinking it'd be helpful to document why we prefer iterative
algorithms.

Also moves a few long style points to headers so that they're easier to
link (I wasn't sure it makes sense to do to all of "syntax and
formatting", but either way what's remaining is shorter if that _is_
linked for reference).

---------

Co-authored-by: Dana Jansens <danakj@orodu.net>
Jon Ross-Perkins hace 4 meses
padre
commit
fb58a41b11
Se han modificado 1 ficheros con 89 adiciones y 74 borrados
  1. 89 74
      docs/project/cpp_style_guide.md

+ 89 - 74
docs/project/cpp_style_guide.md

@@ -16,10 +16,14 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
     -   [General naming rules](#general-naming-rules)
     -   [File names](#file-names)
     -   [Syntax and formatting](#syntax-and-formatting)
+        -   [Line comments](#line-comments)
+        -   [Initialization](#initialization)
+        -   [Passing addresses](#passing-addresses)
     -   [Naming variable types and the use of `auto`](#naming-variable-types-and-the-use-of-auto)
     -   [Copyable and movable types](#copyable-and-movable-types)
     -   [Static and global variables](#static-and-global-variables)
     -   [Foundational libraries and data types](#foundational-libraries-and-data-types)
+    -   [Iterative algorithms](#iterative-algorithms)
 -   [Suggested `.clang-format` contents](#suggested-clang-format-contents)
 
 <!-- tocstop -->
@@ -98,31 +102,6 @@ these.
 -   Only declare one variable at a time (declaring multiple variables requires
     confusing repetition of part of the type).
 -   Write `const` before the type when at the outer level: `const int N = 42;`.
--   Only use line comments (with `//`, not `/* ... */`), on a line by
-    themselves, except for
-    [argument name comments](https://clang.llvm.org/extra/clang-tidy/checks/bugprone/argument-comment.html),
-    [closing namespace comments](https://google.github.io/styleguide/cppguide.html#Namespaces),
-    and similar structural comments. In particular, don't append comments about
-    a line of code to the end of its line:
-
-    ```
-    int bad = 42;  // Don't comment here.
-
-    // Instead comment here.
-    int good = 42;
-
-    // Closing namespace comments are structural, and both okay and expected.
-    }  // namespace MyNamespace
-    ```
-
-    This dogfoods our planned commenting syntax for Carbon. It also provides a
-    single, consistent placement rule. It also provides more resilience against
-    automated refactorings. Those changes often make code longer, which forces
-    ever more difficult formatting decisions, and can easily spread one line
-    across multiple lines, leaving it impossible to know where to place the
-    comment. Comments on their own line preceding such code, while still
-    imprecise, are at least less confusing over the course of such refactorings.
-
 -   Use the `using`-based type alias syntax instead of `typedef`.
 -   Don't use `using` to support unqualified lookup on `std` types; for example,
     `using std::vector;`. This also applies to other short namespaces,
@@ -132,51 +111,8 @@ these.
     -   An exception is made for functions like `std::swap` that are
         intentionally called using ADL. This pattern should be written as
         `{ using std::swap; swap(thing1, thing2); }`.
--   For initialization:
-    -   Use assignment syntax (`=`) when initializing directly with the intended
-        value (or with a braced initializer directly specifying that value).
-    -   Prefer braced initialization for aggregate initialization, such as
-        structs, pairs, and initializer lists.
-        -   Use designated initializers (`{.a = 1}`) when possible for structs,
-            but not for pairs or tuples. Prefer to only include the typename
-            when required to compile (`WizType{.a = 1}`). This is analogous to
-            how structs and tuples would be written in Carbon code.
-        -   Avoid braced initialization for types that define a constructor,
-            except as an initializer list
-            (`llvm::SmallVector<int> v = {0, 1};`), `std::pair`, or
-            `std::tuple`. Never use it with `auto` (`auto a = {0, 1}`).
-    -   Prefer parenthesized initialization (`FooType foo(10);`) in most other
-        cases.
-    -   Braced initialization without `=` (`BarType bar{10}`) should be treated
-        as a fallback, preferred only when other constructor syntax doesn't
-        compile.
-    -   Some additional commentary is in
-        [Abseil's tip #88](https://abseil.io/tips/88#best-practices-for-initialization),
-        although these guidelines differ slightly.
 -   Always mark constructors `explicit` unless there's a specific reason to
     support implicit or `{}` initialization.
--   When passing an object's address as an argument, use a reference unless one
-    of the following cases applies:
-
-    -   If the parameter is optional, use a pointer and document that it may be
-        null.
-    -   If it is captured and must outlive the call expression itself, use a
-        pointer and document that it must not be null (unless it is also
-        optional).
-
-        -   When storing an object's address as a non-owned member, prefer
-            storing a pointer. For example:
-
-            ```cpp
-            class Bar {
-             public:
-              // `foo` must not be null.
-              explicit Bar(Foo* foo) : foo_(foo) {}
-             private:
-              Foo* foo_;
-            };
-            ```
-
 -   Always use braces for conditional, `switch`, and loop statements, even when
     the body is a single statement.
     -   Within a `switch` statement, use braces after a `case` label when
@@ -198,6 +134,79 @@ these.
     `protected`. This is motivated by the
     `misc-non-private-member-variables-in-classes` tidy check.
 
+#### Line comments
+
+Only use line comments (with `//`, not `/* ... */`), on a line by themselves,
+except for
+[argument name comments](https://clang.llvm.org/extra/clang-tidy/checks/bugprone/argument-comment.html),
+[closing namespace comments](https://google.github.io/styleguide/cppguide.html#Namespaces),
+and similar structural comments. In particular, don't append comments about a
+line of code to the end of its line:
+
+```
+int bad = 42;  // Don't comment here.
+
+// Instead comment here.
+int good = 42;
+
+// Closing namespace comments are structural, and both okay and expected.
+}  // namespace MyNamespace
+```
+
+This dogfoods our planned commenting syntax for Carbon. It also provides a
+single, consistent placement rule. It also provides more resilience against
+automated refactorings. Those changes often make code longer, which forces ever
+more difficult formatting decisions, and can easily spread one line across
+multiple lines, leaving it impossible to know where to place the comment.
+Comments on their own line preceding such code, while still imprecise, are at
+least less confusing over the course of such refactorings.
+
+#### Initialization
+
+Initialization syntax has guidelines based on what compiles. See also
+[Abseil's tip #88](https://abseil.io/tips/88#best-practices-for-initialization),
+although these guidelines differ slightly.
+
+-   Use assignment syntax (`=`) when initializing directly with the intended
+    value (or with a braced initializer directly specifying that value).
+-   Prefer braced initialization for aggregate initialization, such as structs,
+    pairs, and initializer lists.
+    -   Use designated initializers (`{.a = 1}`) when possible for structs, but
+        not for pairs or tuples. Prefer to only include the typename when
+        required to compile (`WizType{.a = 1}`). This is analogous to how
+        structs and tuples would be written in Carbon code.
+    -   Avoid braced initialization for types that define a constructor, except
+        as an initializer list (`llvm::SmallVector<int> v = {0, 1};`),
+        `std::pair`, or `std::tuple`. Never use it with `auto`
+        (`auto a = {0, 1}`).
+-   Prefer parenthesized initialization (`FooType foo(10);`) in most other
+    cases.
+-   Braced initialization without `=` (`BarType bar{10}`) should be treated as a
+    fallback, preferred only when other constructor syntax doesn't compile.
+
+#### Passing addresses
+
+When passing an object's address as an argument, use a reference unless one of
+the following cases applies:
+
+-   If the parameter is optional, use a pointer and document that it may be
+    null.
+-   If it is captured and must outlive the call expression itself, use a pointer
+    and document that it must not be null (unless it is also optional).
+
+    -   When storing an object's address as a non-owned member, prefer storing a
+        pointer. For example:
+
+        ```cpp
+        class Bar {
+          public:
+            // `foo` must not be null.
+            explicit Bar(Foo* foo) : foo_(foo) {}
+          private:
+            Foo* foo_;
+        };
+        ```
+
 ### Naming variable types and the use of `auto`
 
 We generally use `auto` for most local variables when a type can be inferred,
@@ -235,12 +244,6 @@ class entity, we might call these `class_id`, `class_inst_id`, and
         patterns that tend to occur while building compilers.
     -   They also minimize the vocabulary type friction when using actual LLVM
         and Clang APIs.
--   In explorer, prefer standard C++ facilities, but use LLVM facilities when
-    there is no standard equivalent.
-    -   This approach is aimed to make the explorer codebase more approachable
-        to new contributors.
-    -   In explorer, performance is not a high priority, and friction with LLVM
-        and Clang APIs is much less of a concern.
 -   Do not add other third-party library dependencies to any code that might
     conceivably be used as part of the compiler or runtime.
     -   Compilers and runtime libraries have unique constraints on their
@@ -248,6 +251,18 @@ class entity, we might call these `class_id`, `class_inst_id`, and
         layers to be under the LLVM license that the Carbon project as a whole
         uses (as well as LLVM itself).
 
+### Iterative algorithms
+
+We choose iterative over recursive algorithms, and use clang-tidy to help
+enforce this. We expect Carbon to be used in codebases which stress test the
+compiler, for example due to complex interactions of APIs or simply due to
+repetitive code structures from code generators.
+
+Other solutions that make recursion work better have been considered, but we
+prefer iteration for its performance and robustness. For example, Clang launches
+threads when it gets close to a stack limit; that has performance overhead and
+relies on developers correctly identifying recursion which may have limits.
+
 ## Suggested `.clang-format` contents
 
 See this repository's [`.clang-format` file](/.clang-format).