Просмотр исходного кода

Updating function and variable docs (#1017)

I was doing this for #851 initially, but I think #438 and #826 hadn't made it in (possibly intentionally due to #851? I don't recall). 

Co-authored-by: Chandler Carruth <chandlerc@gmail.com>
Co-authored-by: Richard Smith <richard@metafoo.co.uk>
Jon Meow 4 лет назад
Родитель
Сommit
a2728f82bb
4 измененных файлов с 212 добавлено и 48 удалено
  1. 8 10
      docs/design/README.md
  2. 143 36
      docs/design/functions.md
  3. 53 0
      docs/design/type_inference.md
  4. 8 2
      docs/design/variables.md

+ 8 - 10
docs/design/README.md

@@ -301,23 +301,21 @@ Some common expressions in Carbon include:
 ### Functions
 
 > References: [Functions](functions.md)
->
-> **TODO:** References need to be evolved.
 
 Functions are the core unit of behavior. For example:
 
 ```carbon
-fn Sum(a: Int, b: Int) -> Int;
+fn Add(a: i64, b: i64) -> i64;
 ```
 
 Breaking this apart:
 
 -   `fn` is the keyword used to indicate a function.
--   Its name is `Sum`.
--   It accepts two `Int` parameters, `a` and `b`.
--   It returns an `Int` result.
+-   Its name is `Add`.
+-   It accepts two `i64` parameters, `a` and `b`.
+-   It returns an `i64` result.
 
-You would call this function like `Sum(1, 2)`.
+You would call this function like `Add(1, 2)`.
 
 ### Blocks and statements
 
@@ -354,8 +352,8 @@ work similarly to function parameters.
 For example:
 
 ```carbon
-fn Foo() {
-  var x: Int = 42;
+fn DoSomething() {
+  var x: i64 = 42;
 }
 ```
 
@@ -363,7 +361,7 @@ Breaking this apart:
 
 -   `var` is the keyword used to indicate a variable.
 -   Its name is `x`.
--   Its type is `Int`.
+-   Its type is `i64`.
 -   It is initialized with the value `42`.
 
 ### Lifetime and move semantics

+ 143 - 36
docs/design/functions.md

@@ -10,54 +10,161 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 
 ## Table of contents
 
--   [TODO](#todo)
--   [Basic functions](#basic-functions)
+-   [Overview](#overview)
+-   [Function definitions](#function-definitions)
+    -   [Return clause](#return-clause)
+    -   [`return` statements](#return-statements)
+-   [Function declarations](#function-declarations)
+-   [Function calls](#function-calls)
+-   [Functions in other features](#functions-in-other-features)
+-   [Alternatives considered](#alternatives-considered)
+-   [References](#references)
 
 <!-- tocstop -->
 
-## TODO
+## Overview
 
-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.
+Functions are the core building block for applications. Carbon's basic function
+syntax is:
 
-## Basic functions
+-   _parameter_: _identifier_ `:` _expression_
+-   _parameter-list_: _[ parameter_ `,` _parameter_ `,` _... ]_
+-   _return-clause_: _[_ `->` _< expression |_ `auto` _> ]_
+-   _signature_: `fn` _identifier_ `(` _parameter-list_ `)` _return-clause_
+-   _function-definition_: _signature_ `{` _statements_ `}`
+-   _function-declaration_: _signature_ `;`
+-   _function-call_: _identifier_ `(` _[ expression_ `,` _expression_ `,` _...
+    ]_ `)`
 
-Programs written in Carbon, much like those written in other languages, are
-primarily divided up into "functions" (or "procedures", "subroutines", or
-"subprograms"). These are the core unit of behavior for the programming
-language. Let's look at a simple example to understand how these work:
+A function with only a signature and no body is a function declaration, or
+forward declaration. When the body is a present, it's a function definition. The
+body introduces nested scopes which may contain local variable declarations.
 
+## Function definitions
+
+A basic function definition may look like:
+
+```carbon
+fn Add(a: i64, b: i64) -> i64 {
+  return a + b;
+}
 ```
-fn Sum(a: Int, b: Int) -> Int;
+
+This declares a function called `Add` which accepts two `i64` parameters, the
+first called `a` and the second called `b`, and returns an `i64` result. It
+returns the result of adding the two arguments.
+
+C++ might declare the same thing:
+
+```cpp
+std::int64_t Add(std::int64_t a, std::int64_t b) {
+  return a + b;
+}
+
+// Or with trailing return type syntax:
+auto Add(std::int64_t a, std::int64_t b) -> std::int64_t {
+  return a + b;
+}
 ```
 
-This declares a function called `Sum` which accepts two `Int` parameters, the
-first called `a` and the second called `b`, and returns an `Int` result. C++
-might declare the same thing:
+### Return clause
+
+The return clause of a function specifies the return type using one of three
+possible syntaxes:
+
+-   `->` followed by an _expression_, such as `i64`, directly states the return
+    type. This expression will be evaluated at compile-time, so must be valid in
+    that context.
+    -   For example, `fn ToString(val: i64) -> String;` has a return type of
+        `String`.
+-   `->` followed by the `auto` keyword indicates that
+    [type inference](type_inference.md) should be used to determine the return
+    type.
+    -   For example, `fn Echo(val: i64) -> auto { return val; }` will have a
+        return type of `i64` through type inference.
+    -   Declarations must have a known return type, so `auto` is not valid.
+    -   The function must have precisely one `return` statement. That `return`
+        statement's expression will then be used for type inference.
+-   Omission indicates that the return type is the empty tuple, `()`.
+    -   For example, `fn Sleep(seconds: i64);` is similar to
+        `fn Sleep(seconds: i64) -> ();`.
+    -   `()` is similar to a `void` return type in C++.
+
+### `return` statements
+
+The [`return` statement](control_flow/return.md) is essential to function
+control flow. It ends the flow of the function and returns execution to the
+caller.
+
+When the [return clause](#return-clause) is omitted, the `return` statement has
+no expression argument, and function control flow implicitly ends after the last
+statement in the function's body as if `return;` were present.
+
+When the return clause is provided, including when it is `-> ()`, the `return`
+statement must have an expression that is convertible to the return type, and a
+`return` statement must be used to end control flow of the function.
+
+## Function declarations
 
+Functions may be declared separate from the definition by providing only a
+signature, with no body. This provides an API which may be called. For example:
+
+```carbon
+// Declaration:
+fn Add(a: i64, b: i64) -> i64;
+
+// Definition:
+fn Add(a: i64, b: i64) -> i64 {
+  return a + b;
+}
 ```
-std::int64_t Sum(std::int64_t a, std::int64_t b);
 
-// Or with trailing return type syntax:
-auto Sum(std::int64_t a, std::int64_t b) -> std::int64_t;
+The corresponding definition may be provided later in the same file or, when the
+declaration is in an
+[`api` file of a library](code_and_name_organization/#libraries), in the `impl`
+file of the same library. The signature of a function declaration must match the
+corresponding definition. This includes the [return clause](#return-clause);
+even though an omitted return type has equivalent behavior to `-> ()`, the
+presence or omission must match.
+
+## Function calls
+
+Function calls use a function's identifier to pass multiple expression arguments
+corresponding to the function signature's parameters. For example:
+
+```carbon
+fn Add(a: i64, b: i64) -> i64 {
+  return a + b;
+}
+
+fn Main() {
+  Add(1, 2);
+}
 ```
 
-Let's look at how some specific parts of this work. The function declaration is
-introduced with a keyword `fn` followed by the name of the function `Sum`. This
-declares that name in the surrounding scope and opens up a new scope for this
-function. We declare the first parameter as `Int a`. The `Int` part is an
-expression (here referring to a constant) that computes the type of the
-parameter. The `:` marks the end of the type expression and introduces the
-identifier for the parameter, `a`. The parameter names are introduced into the
-function's scope and can be referenced immediately after they are introduced.
-The return type is indicated with `-> Int`, where again `Int` is just an
-expression computing the desired type. The return type can be completely omitted
-in the case of functions which do not return a value.
-
-Calling functions involves a new form of expression: `Sum(1, 2)` for example.
-The first part, `Sum`, is an expression referring to the name of the function.
-The second part, `(1, 2)` is a parenthesized list of arguments to the function.
-The juxtaposition of one expression with parentheses forms the core of a call
-expression, similar to a postfix operator.
+Here, `Add(1, 2)` is a function call expression. `Add` refers to the function
+definition's identifier. The parenthesized arguments `1` and `2` are passed to
+the `a` and `b` parameters of `Add`.
+
+## Functions in other features
+
+Other designs build upon basic function syntax to add advanced features:
+
+-   [Generic functions](generics/overview.md#generic-functions) adds support for
+    deduced parameters and generic type parameters.
+-   [Class member functions](classes.md#member-functions) adds support for
+    methods and class functions.
+
+## Alternatives considered
+
+-   [Function keyword](/proposals/p0438.md#function-keyword)
+-   [Only allow `auto` return types if parameters are generic](/proposals/p0826.md#only-allow-auto-return-types-if-parameters-are-generic)
+-   [Provide alternate function syntax for concise return type inference](/proposals/p0826.md#provide-alternate-function-syntax-for-concise-return-type-inference)
+-   [Allow separate declaration and definition](/proposals/p0826.md#allow-separate-declaration-and-definition)
+
+## References
+
+-   Proposal
+    [#438: Add statement syntax for function declarations](https://github.com/carbon-language/carbon-lang/pull/438)
+-   Proposal
+    [#826: Function return type inference](https://github.com/carbon-language/carbon-lang/pull/826)

+ 53 - 0
docs/design/type_inference.md

@@ -0,0 +1,53 @@
+# Type inference
+
+<!--
+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)
+-   [Open questions](#open-questions)
+    -   [Inferring a variable type from literals](#inferring-a-variable-type-from-literals)
+-   [Alternatives considered](#alternatives-considered)
+-   [References](#references)
+
+<!-- tocstop -->
+
+## Overview
+
+[Type inference](https://en.wikipedia.org/wiki/Type_inference) occurs in Carbon
+when the `auto` keyword is used. This may occur in
+[variable declarations](variables.md) or [function declarations](functions.md).
+
+At present, type inference is very simple: given the expression which generates
+the value to be used for type inference, the inferred type is the precise type
+of that expression. For example, the inferred type for `auto` in
+`fn Foo(x: i64) -> auto { return x; }` is `i64`.
+
+Type inference is currently supported for [function return types](functions.md)
+and [declared variable types](variables.md).
+
+## Open questions
+
+### Inferring a variable type from literals
+
+Using the type on the right side for `var y: auto = 1` currently results in a
+constant `IntLiteral(1)` value, whereas most languages would suggest a variable
+integer type, such as `i64`. Carbon might also make it an error. Although type
+inference currently only addresses `auto` for variables and function return
+types, this is something that will be considered as part of type inference in
+general, because it also affects generics, templates, lambdas, and return types.
+
+## Alternatives considered
+
+-   [Use `_` instead of `auto`](/proposals/p0851.md#use-_-instead-of-auto)
+
+## References
+
+-   Proposal
+    [#851: auto keyword for vars](https://github.com/carbon-language/carbon-lang/pull/851)

+ 8 - 2
docs/design/variables.md

@@ -22,7 +22,7 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 
 Carbon's local variable syntax is:
 
-> `var` _identifier_`:` _type_ _[_ `=` _value_ _]_`;`
+-   `var` _identifier_`:` _< expression |_ `auto` _> [_ `=` _value ]_`;`
 
 Blocks introduce nested scopes and can contain local variable declarations that
 work similarly to function parameters.
@@ -31,7 +31,7 @@ For example:
 
 ```
 fn Foo() {
-  var x: Int = 42;
+  var x: i32 = 42;
 }
 ```
 
@@ -40,6 +40,9 @@ type `Int` and is initialized with the value `42`. These variable declarations
 (and function declarations) have a lot more power than what we're covering just
 yet, but this gives you the basic idea.
 
+If `auto` is used in place of the type, [type inference](type_inference.md) is
+used to automatically determine the variable's type.
+
 While there can be global constants, there are no global variables.
 
 ## Notes
@@ -61,6 +64,7 @@ discover that their convenience outweighs any improvements afforded.
 -   [Colon between type and identifier](/proposals/p0339.md#colon-between-type-and-identifier)
 -   [Type elision](/proposals/p0339.md#type-elision)
 -   [Type ordering](/proposals/p0618.md#type-ordering)
+-   [Elide the type instead of using `auto`](/proposals/p0851.md#elide-the-type-instead-of-using-auto)
 
 ## References
 
@@ -68,3 +72,5 @@ discover that their convenience outweighs any improvements afforded.
     [#339: `var` statement](https://github.com/carbon-language/carbon-lang/pull/339)
 -   Proposal
     [#618: `var` ordering](https://github.com/carbon-language/carbon-lang/pull/618)
+-   Proposal
+    [#851: auto keyword for vars](https://github.com/carbon-language/carbon-lang/pull/851)