Design overview update part 1 (#1274)

Reorganizes the sections, and makes a pass filling in and updating the first sections including: types, functions, user-defined types. The following sections are left for part 2, including names, generics, and interop.

Also some smaller updates to, not revisiting the text: `pattern_matching.md`, `control_flow/return.md`, and `lexical_conventions/numeric_literals.md`

Co-authored-by: Geoff Romer <gromer@google.com>
Co-authored-by: Chandler Carruth <chandlerc@gmail.com>
This commit is contained in:
josh11b
2022-06-09 12:58:22 -07:00
committed by GitHub
co-authored by Geoff Romer Chandler Carruth
parent 9007b3952d
commit b17e69aefd
4 changed files with 1695 additions and 760 deletions
+1658 -723
View File
File diff suppressed because it is too large Load Diff
+5 -5
View File
@@ -30,14 +30,14 @@ 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(a: Int, b: Int) -> Int {
fn Sum(a: i32, b: i32) -> i32 {
return a + b;
}
```
When a return type is specified, a function must _always_ `return` before
control flow can reach the end of the function body. In other words,
`fn DoNothing() -> Int {}` would be invalid because execution will reach the end
`fn DoNothing() -> i32 {}` would be invalid because execution will reach the end
of the function body without returning a value.
### Returning empty tuples
@@ -93,7 +93,7 @@ Returning expressions is not allowed while a `returned var` is in scope. For
example:
```carbon
fn MakeCircle(radius: Int) -> Circle {
fn MakeCircle(radius: i32) -> Circle {
returned var c: Circle;
c.radius = radius;
// `return c` would be invalid because `returned` is in use.
@@ -106,7 +106,7 @@ If control flow exits the scope of a `returned` variable in any way other than
`return` may again be used with expressions. For example:
```carbon
fn MakePointInArea(Area area, Int preferred_x, Int preferred_y) -> Point {
fn MakePointInArea(area: Area, preferred_x: i32, preferred_y: i32) -> Point {
if (preferred_x >= 0 && preferred_y >= 0) {
returned var p: Point = { .x = preferred_x, .y = preferred_y };
if (area.Contains(p)) {
@@ -148,7 +148,7 @@ declared by the caller. For example, here the `returned var vector` in
copy:
```carbon
fn CreateVector(x: Int, y: Int) -> Vector {
fn CreateVector(x: i32, y: i32) -> Vector {
returned var vector: Vector;
vector.x = x;
vector.y = y;
@@ -13,7 +13,7 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- [Overview](#overview)
- [Details](#details)
- [Integer literals](#integer-literals)
- [Real number literals](#real-number-literals)
- [Real-number literals](#real-number-literals)
- [Digit separators](#digit-separators)
- [Divergence from other languages](#divergence-from-other-languages)
- [Alternatives considered](#alternatives-considered)
@@ -29,13 +29,13 @@ The following syntaxes are supported:
- `12345` (decimal)
- `0x1FE` (hexadecimal)
- `0b1010` (binary)
- Real number literals
- Real-number literals
- `123.456` (digits on both sides of the `.`)
- `123.456e789` (optional `+` or `-` after the `e`)
- `0x1.2p123` (optional `+` or `-` after the `p`)
- Digit separators (`_`) may be used, but only in conventional locations
Note that real number literals always contain a `.` with digits on both sides,
Note that real-number literals always contain a `.` with digits on both sides,
and integer literals never contain a `.`.
Literals are case-sensitive. Unlike in C++, literals do not have a suffix to
@@ -65,7 +65,7 @@ the literal is `0`, the `0` begins a base specifier, or the next character is a
decimal point (see below). No support is provided for octal literals, and any C
or C++ octal literal (other than `0`) is invalid in Carbon.
### Real number literals
### Real-number literals
Real numbers are written as a decimal or hexadecimal integer followed by a
period (`.`) followed by a sequence of one or more decimal or hexadecimal
@@ -81,23 +81,23 @@ is `p`, and the effect is to multiply the given value by
2<sup>&plusmn;_N_</sup>. The exponent suffix is optional for both decimal and
hexadecimal real numbers.
Note that a decimal integer followed by `e` is not a real number literal. For
Note that a decimal integer followed by `e` is not a real-number literal. For
example, `3e10` is not a valid literal.
When a real number literal is interpreted as a value of a real number type, its
When a real-number literal is interpreted as a value of a real-number type, its
value is the representable real number closest to the value of the literal. In
the case of a tie, the nearest value whose mantissa is even is selected.
The decimal real number syntax allows for any decimal fraction to be expressed
-- that is, any number of the form _a_ x 10<sup>-_b_</sup>, where _a_ is an
integer and _b_ is a non-negative integer. Because the decimal fractions are
dense in the reals and the set of values of the real number type is assumed to
be discrete, every value of the real number type can be expressed as a real
dense in the reals and the set of values of the real-number type is assumed to
be discrete, every value of the real-number type can be expressed as a real
number literal. However, for certain applications, directly expressing the
intended real number representation may be more convenient than producing a
intended real-number representation may be more convenient than producing a
decimal equivalent that is known to convert to the intended value. Hexadecimal
real number literals are provided in order to permit values of binary floating
or fixed point real number types to be expressed directly.
real-number literals are provided in order to permit values of binary floating
or fixed point real-number types to be expressed directly.
### Digit separators
@@ -108,7 +108,7 @@ respective condition:
starting from the right. For example, `2_147_483_648`.
- For hexadecimal integers, the digit separators shall occur every four digits
starting from the right. For example, `0x7FFF_FFFF`.
- For real number literals, digit separators can appear in the decimal and
- For real-number literals, digit separators can appear in the decimal and
hexadecimal integer portions (prior to the period and after the optional `e`
or mandatory `p`) as described in the previous bullets. For example,
`2_147.483648e12_345` or `0x1_00CA.FEF00Dp+24`
+20 -20
View File
@@ -44,16 +44,16 @@ widely used in existing languages (Swift and Rust among others) and is currently
under active investigation for C++. Carbon's `match` can be used as follows:
```
fn Bar() -> (Int, (Float, Float));
fn Foo() -> Float {
fn Bar() -> (i32, (f32, f32));
fn Foo() -> f32 {
match (Bar()) {
case (42, (Float x, Float y)) => {
case (42, (x: f32, y: f32)) => {
return x - y;
}
case (Int p, (Float x, Float _)) if (p < 13) => {
case (p: i32, (x: f32, _: f32)) if (p < 13) => {
return p * x;
}
case (Int p, auto _) if (p > 3) => {
case (p: i32, _: auto) if (p > 3) => {
return p * Pi;
}
default => {
@@ -70,35 +70,35 @@ value, and execute that block. If none match, then it executes the default
block.
Each `case` contains a pattern. The first part is a value pattern
(`(Int p, auto _)` for example) followed by an optional boolean predicate
introduced by the `if` keyword. The value pattern has to match, and then the
predicate has to evaluate to true for the overall pattern to match. Value
patterns can be composed of the following:
(`(p: i32, _: auto)` for example) optionally followed by an `if` and boolean
predicate. The value pattern has to match, and then the predicate has to
evaluate to `true` for the overall pattern to match. Value patterns can be
composed of the following:
- An expression (`42` for example), whose value must be equal to match.
- An optional type (`Int` for example), followed by a `:` and either an
identifier to bind to the value or the special identifier `_` to discard the
value once matched.
- A destructuring pattern containing a sequence of value patterns
(`(Float x, Float y)`) which match against tuples and tuple like values by
- An identifier to bind the value to, followed by a colon (`:`) and a type
(`i32` for example). An underscore (`_`) may be used instead of the
identifier to discard the value once matched.
- A tuple destructuring pattern containing a tuple of value patterns
(`(x: f32, y: f32)`) which match against tuples and tuple-like values by
recursively matching on their elements.
- An unwrapping pattern containing a nested value pattern which matches
against a variant or variant-like value by unwrapping it.
In order to match a value, whatever is specified in the pattern must match.
Using `auto` for a type will always match, making `auto _` the wildcard pattern.
Using `auto` for a type will always match, making `_: auto` the wildcard
pattern.
### Pattern matching in local variables
Value patterns may be used when declaring local variables to conveniently
destructure them and do other type manipulations. However, the patterns must
match at compile time which is why the boolean predicate cannot be used
directly.
match at compile time, so they can't use an `if` clause.
```
fn Bar() -> (Int, (Float, Float));
fn Foo() -> Int {
var (Int p, auto _) = Bar();
fn Bar() -> (i32, (f32, f32));
fn Foo() -> i32 {
var (p: i32, _: auto) = Bar();
return p;
}
```