diff --git a/docs/design/README.md b/docs/design/README.md index cb3dfccc2f35b..b38207cb51a87 100644 --- a/docs/design/README.md +++ b/docs/design/README.md @@ -11,21 +11,38 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception ## Table of contents - [Overview](#overview) -- [Context and disclaimer](#context-and-disclaimer) - - [Example code](#example-code) -- [Basic syntax](#basic-syntax) - - [Code and comments](#code-and-comments) - - [Packages, libraries, and namespaces](#packages-libraries-and-namespaces) - - [Names and scopes](#names-and-scopes) - - [Naming conventions](#naming-conventions) - - [Aliases](#aliases) - - [Name lookup](#name-lookup) - - [Name lookup for common types](#name-lookup-for-common-types) - - [Expressions](#expressions) - - [Functions](#functions) + - [This document is provisional](#this-document-is-provisional) +- [Hello, Carbon](#hello-carbon) +- [Code and comments](#code-and-comments) +- [Build modes](#build-modes) +- [Types are values](#types-are-values) +- [Primitive types](#primitive-types) + - [`bool`](#bool) + - [Integer types](#integer-types) + - [Integer literals](#integer-literals) + - [Floating-point types](#floating-point-types) + - [Floating-point literals](#floating-point-literals) + - [String types](#string-types) + - [String literals](#string-literals) +- [Composite types](#composite-types) + - [Tuples](#tuples) + - [Struct types](#struct-types) + - [Pointer types](#pointer-types) + - [Arrays and slices](#arrays-and-slices) +- [Expressions](#expressions) +- [Declarations, Definitions, and Scopes](#declarations-definitions-and-scopes) +- [Patterns](#patterns) + - [Binding patterns](#binding-patterns) + - [Destructuring patterns](#destructuring-patterns) + - [Refutable patterns](#refutable-patterns) +- [Name-binding declarations](#name-binding-declarations) + - [Constant `let` declarations](#constant-let-declarations) + - [Variable `var` declarations](#variable-var-declarations) + - [`auto`](#auto) +- [Functions](#functions) + - [`auto` return type](#auto-return-type) - [Blocks and statements](#blocks-and-statements) - - [Variables](#variables) - - [Lifetime and move semantics](#lifetime-and-move-semantics) + - [Assignment statements](#assignment-statements) - [Control flow](#control-flow) - [`if` and `else`](#if-and-else) - [Loops](#loops) @@ -34,608 +51,1217 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - [`break`](#break) - [`continue`](#continue) - [`return`](#return) -- [Types](#types) - - [Primitive types](#primitive-types) - - [Composite types](#composite-types) - - [Tuples](#tuples) - - [Variants](#variants) - - [Pointers and references](#pointers-and-references) - - [Arrays and slices](#arrays-and-slices) - - [User-defined types](#user-defined-types) - - [Classes](#classes) - - [Assignment, copying](#assignment-copying) - - [Member access](#member-access) - - [Methods](#methods) - - [Allocation, construction, and destruction](#allocation-construction-and-destruction) - - [Moving](#moving) - - [Comparison](#comparison) - - [Implicit and explicit conversion](#implicit-and-explicit-conversion) - - [Inline type composition](#inline-type-composition) - - [Unions](#unions) -- [Pattern matching](#pattern-matching) - - [`match` control flow](#match-control-flow) - - [Pattern matching in local variables](#pattern-matching-in-local-variables) - - [Pattern matching as function overload resolution](#pattern-matching-as-function-overload-resolution) -- [Type abstractions](#type-abstractions) - - [Interfaces](#interfaces) - - [Generics](#generics) - - [Templates](#templates) - - [Types with template parameters](#types-with-template-parameters) + - [`returned var`](#returned-var) + - [`match`](#match) +- [User-defined types](#user-defined-types) + - [Classes](#classes) + - [Assignment](#assignment) + - [Class functions and factory functions](#class-functions-and-factory-functions) + - [Methods](#methods) + - [Inheritance](#inheritance) + - [Access control](#access-control) + - [Destructors](#destructors) + - [Choice types](#choice-types) +- [Names](#names) + - [Packages, libraries, namespaces](#packages-libraries-namespaces) + - [Legal names](#legal-names) + - [Naming conventions](#naming-conventions) + - [Aliases](#aliases) + - [Name lookup](#name-lookup) + - [Name lookup for common types](#name-lookup-for-common-types) + - [Name visibility](#name-visibility) +- [Generics](#generics) + - [Interfaces and implementations](#interfaces-and-implementations) + - [Checked and template parameters](#checked-and-template-parameters) + - [Templates](#templates) + - [Generic functions](#generic-functions) - [Functions with template parameters](#functions-with-template-parameters) - - [Overloading](#overloading) -- [Metaprogramming](#metaprogramming) -- [Execution abstractions](#execution-abstractions) - - [Abstract machine and execution model](#abstract-machine-and-execution-model) - - [Lambdas](#lambdas) - - [Co-routines](#co-routines) + - [Generic types](#generic-types) + - [Types with template parameters](#types-with-template-parameters) + - [Generic choice types](#generic-choice-types) + - [Operator overloading](#operator-overloading) + - [Common type](#common-type) - [Bidirectional interoperability with C/C++](#bidirectional-interoperability-with-cc) +- [Unfinished tales](#unfinished-tales) + - [Pattern matching as function overload resolution](#pattern-matching-as-function-overload-resolution) + - [Lifetime and move semantics](#lifetime-and-move-semantics) + - [Metaprogramming](#metaprogramming) + - [Execution abstractions](#execution-abstractions) + - [Abstract machine and execution model](#abstract-machine-and-execution-model) + - [Lambdas](#lambdas) + - [Co-routines](#co-routines) ## Overview This documentation describes the design of the Carbon language, and the -rationale for that design. - -## Context and disclaimer - -Eventually, this document hopes to provide a high-level overview of the design -of the Carbon language. It should summarize the key points across the different -aspects of the language design and link to more detailed and comprehensive -design documents to expand on specific aspects of the design. That means it -isn't and doesn't intend to be complete or stand on its own. Notably, it doesn't -attempt to provide detailed and comprehensive justification for design -decisions. Those should instead be provided by the dedicated and focused designs -linked to from here. However, it should provide an overarching view of the -design and a good basis for diving into specific details. +rationale for that design. This documentation is an overview of the Carbon +project in its current state, written for the builders of Carbon and for those +interested in learning more about Carbon. -However, these are extremely early days for Carbon. Currently, this document -tries to capture two things: +This document is _not_ a complete programming manual, and, nor does it provide +detailed and comprehensive justification for design decisions. These +descriptions are found in linked dedicated designs. -1. Initial musings about what _might_ make sense as a basis for Carbon. These - are largely informed by idle discussions between C++ and Clang developers - over the years, and should not be given any particular weight. -2. A summary and snapshot of in-progress efforts to flesh out and motivate - specific designs for parts of the language. +### This document is provisional -The utility of capturing these at this early stage is primarily to give everyone -a reasonably consistent set of terminology and context as we begin fleshing out -concrete (and well justified) designs for each part of the language. In some -cases, it captures ideas that may be interesting to explore, but isn't meant to -overly anchor on them. Any ideas here need to be fully explored and justified -with a detailed analysis. The context of #1 (directly evolving C++, experience -building Clang, and experience working on C++ codebases including Clang and LLVM -themselves) is also important. It is both an important signal but also a bias. +This document includes much that is provisional or placeholder. This means that +the syntax used, language rules, standard library, and other aspects of the +design have things that have not been decided through the Carbon process. This +preliminary material fills in gaps until aspects of the design can be filled in. -### Example code +## Hello, Carbon -Some syntax used in example code is provisional or placeholder, and may change -later. +Here is a simple function showing some Carbon code: -## Basic syntax +```carbon +import Console; + +// Prints the Fibonacci numbers less than `limit`. +fn Fibonacci(limit: i64) { + var (a: i64, b: i64) = (0, 1); + while (a < limit) { + Console.Print(a, " "); + let next: i64 = a + b; + a = b; + b = next; + } + Console.Print("\n"); +} +``` -### Code and comments +Carbon is a language that should feel familiar to C++ and C developers. This +example has familiar constructs like imports, function definitions, typed +arguments, and curly braces. -> References: [Source files](code_and_name_organization/source_files.md) and -> [lexical conventions](lexical_conventions) -> -> **TODO:** References need to be evolved. +A few other features that are unlike C or C++ may stand out. First, declarations +start with introducer keywords. `fn` introduces a function declaration, and +`var` introduces a variable declaration. You can also see a _tuple_, a composite +type written as a comma-separated list inside parentheses. Unlike, say, Python, +these types are strongly-typed as well. -- All source code is UTF-8 encoded text. For simplicity, no other encoding is - supported. -- Line comments look like `// ...`. However, they are required to be the only - non-whitespace on the line for readability. -- Block comments look like `//\{ ... //\}`, with each marker on its own line. - Nested block comments are supported using named regions. For example: - - ```carbon - live code - //\{ - commented code - //\{ nested block - commented code in nested block - //\} nested block - //\} - live code - ``` - -- Decimal, hexadecimal, and binary integer literals and decimal and - hexadecimal floating-point literals are supported, with `_` as a digit - separator. For example, `42`, `0b1011_1101` and `0x1.EEFp+5`. Numeric - literals are case-sensitive: `0x`, `0b`, `e+`, and `p+` must be lowercase, - whereas hexadecimal digits must be uppercase. A digit is required on both - sides of a period. - -### Packages, libraries, and namespaces - -> References: [Code and name organization](code_and_name_organization) +## Code and comments -- **Files** are grouped into libraries, which are in turn grouped into - packages. -- **Libraries** are the granularity of code reuse through imports. -- **Packages** are the unit of distribution. +All source code is UTF-8 encoded text. Comments, identifiers, and strings are +allowed to have non-ASCII characters. -Name paths in Carbon always start with the package name. Additional namespaces -may be specified as desired. +```carbon +var résultat: String = "Succès"; +``` -For example, this code declares a class `Geometry.Shapes.Flat.Circle` in a -library `Geometry/OneSide`: +Comments start with two slashes `//` and go to the end of the line. They are +required to be the only non-whitespace on the line. ```carbon -package Geometry library("OneSide") namespace Shapes; - -namespace Flat; -class Flat.Circle { ... } +// Compute an approximation of π ``` -This type can be used from another package: +> References: +> +> - [Source files](code_and_name_organization/source_files.md) +> - [lexical conventions](lexical_conventions) +> - Proposal +> [#142: Unicode source files](https://github.com/carbon-language/carbon-lang/pull/142) +> - Proposal +> [#198: Comments](https://github.com/carbon-language/carbon-lang/pull/198) -```carbon -package ExampleUser; +## Build modes -import Geometry library("OneSide"); +The behavior of the Carbon compiler depends on the _build mode_: -fn Foo(Geometry.Shapes.Flat.Circle circle) { ... } -``` +- In a _development build_, the priority is diagnosing problems and fast build + time. +- In a _performance build_, the priority is fastest execution time and lowest + memory usage. +- In a _hardened build_, the first priority is safety and second is + performance. -### Names and scopes +> References: [Safety strategy](/docs/project/principles/safety_strategy.md) -> References: [Lexical conventions](lexical_conventions) -> -> **TODO:** References need to be evolved. +## Types are values -Various constructs introduce a named entity in Carbon. These can be functions, -types, variables, or other kinds of entities that we'll cover. A name in Carbon -is formed from a word, which is a sequence of letters, numbers, and underscores, -and which starts with a letter. We intend to follow Unicode's Annex 31 in -selecting valid identifier characters, but a concrete set of valid characters -has not been selected yet. +Expressions compute values in Carbon, and these values are always strongly typed +much like in C++. However, an important difference from C++ is that types are +themselves modeled as values; specifically, compile-time constant values. This +means that the grammar for writing a type is the [expression](#expressions) +grammar. Expressions written where a type is expected must be able to be +evaluated at compile-time and must evaluate to a type value. -#### Naming conventions +## Primitive types -> References: [Naming conventions](naming_conventions.md) +Primitive types fall into the following categories: -Our naming conventions are: +- the boolean type `bool`, +- signed and unsigned integer types, +- IEEE-754 floating-point types, and +- string types. -- For idiomatic Carbon code: - - `UpperCamelCase` will be used when the named entity cannot have a - dynamically varying value. For example, functions, namespaces, or - compile-time constant values. - - `lower_snake_case` will be used when the named entity's value won't be - known until runtime, such as for variables. -- For Carbon-provided features: - - Keywords and type literals will use `lower_snake_case`. - - Other code will use the conventions for idiomatic Carbon code. +These are made available through the [prelude](#name-lookup-for-common-types). + +> References: [Primitive types](primitive_types.md) -#### Aliases +### `bool` + +The type `bool` is a boolean type with two possible values: `true` and `false`. +[Comparison expressions](#expressions) produce `bool` values. The condition +arguments in [control-flow statements](#control-flow), like [`if`](#if-and-else) +and [`while`](#while), and +[`if`-`then`-`else` conditional expressions](#expressions) take `bool` values. + +### Integer types + +The signed-integer type with bit width `N` may be written `Carbon.Int(N)`. For +convenience and brevity, the common power-of-two sizes may be written with an +`i` followed by the size: `i8`, `i16`, `i32`, `i64`, `i128`, or `i256`. +Signed-integer +[overflow](expressions/arithmetic.md#overflow-and-other-error-conditions) is a +programming error: + +- In a development build, overflow will be caught immediately when it happens + at runtime. +- In a performance build, the optimizer can assume that such conditions don't + occur. As a consequence, if they do, the behavior of the program is not + defined. +- In a hardened build, overflow does not result in undefined behavior. + Instead, either the program will be aborted, or the arithmetic will evaluate + to a mathematically incorrect result, such as a two's complement result or + zero. + +The unsigned-integer types are: `u8`, `u16`, `u32`, `u64`, `u128`, `u256`, and +`Carbon.UInt(N)`. Unsigned integer types wrap around on overflow, we strongly +advise that they are not used except when those semantics are desired. These +types are intended for bit manipulation or modular arithmetic as often found in +[hashing](https://en.wikipedia.org/wiki/Hash_function), +[cryptography](https://en.wikipedia.org/wiki/Cryptography), and +[PRNG](https://en.wikipedia.org/wiki/Pseudorandom_number_generator) use cases. +Values which can never be negative, like sizes, but for which wrapping does not +make sense +[should use signed integer types](/proposals/p1083.md#dont-let-unsigned-arithmetic-wrap). -> References: [Aliases](aliases.md) +> References: > -> **TODO:** References need to be evolved. +> - Question-for-leads issue +> [#543: pick names for fixed-size integer types](https://github.com/carbon-language/carbon-lang/issues/543) +> - Proposal +> [#820: Implicit conversions](https://github.com/carbon-language/carbon-lang/pull/820) +> - Proposal +> [#1083: Arithmetic expressions](https://github.com/carbon-language/carbon-lang/pull/1083) -Carbon provides a facility to declare a new name as an alias for a value. This -is a fully general facility because everything is a value in Carbon, including -types. +#### Integer literals -For example: +Integers may be written in decimal, hexadecimal, or binary: -```carbon -alias MyInt = Int; -``` +- `12345` (decimal) +- `0x1FE` (hexadecimal) +- `0b1010` (binary) -This creates an alias called `MyInt` for whatever `Int` resolves to. Code -textually after this can refer to `MyInt`, and it will transparently refer to -`Int`. +Underscores `_` may be used as digit separators, but for decimal and hexadecimal +literals, they can only appear in conventional locations. Numeric literals are +case-sensitive: `0x`, `0b` must be lowercase, whereas hexadecimal digits must be +uppercase. Integer literals never contain a `.`. -#### Name lookup +Unlike in C++, literals do not have a suffix to indicate their type. Instead, +numeric literals have a type derived from their value, and can be +[implicitly converted](expressions/implicit_conversions.md) to any type that can +represent that value. -> References: [name lookup](name_lookup.md) +> References: > -> **TODO:** References need to be evolved. +> - [Integer literals](lexical_conventions/numeric_literals.md#integer-literals) +> - Proposal +> [#143: Numeric literals](https://github.com/carbon-language/carbon-lang/pull/143) +> - Proposal +> [#144: Numeric literal semantics](https://github.com/carbon-language/carbon-lang/pull/144) +> - Proposal +> [#820: Implicit conversions](https://github.com/carbon-language/carbon-lang/pull/820) -Unqualified name lookup will always find a file-local result, including aliases. +### Floating-point types -##### Name lookup for common types +Floating-point types in Carbon have IEEE 754 semantics, use the round-to-nearest +rounding mode, and do not set any floating-point exception state. They are named +with an `f` and the number of bits: `f16`, `f32`, `f64`, and `f128`. +[`BFloat16`](primitive_types.md#bfloat16) is also provided. -> References: [Name lookup](name_lookup.md) +> References: > -> **TODO:** References need to be evolved. +> - Question-for-leads issue +> [#543: pick names for fixed-size integer types](https://github.com/carbon-language/carbon-lang/issues/543) +> - Proposal +> [#820: Implicit conversions](https://github.com/carbon-language/carbon-lang/pull/820) +> - Proposal +> [#1083: Arithmetic expressions](https://github.com/carbon-language/carbon-lang/pull/1083) -Common types that we expect to be used universally will be provided for every -file, including `Int` and `Bool`. These will likely be defined in a special -"prelude" package. +#### Floating-point literals -### Expressions +Floating-point types along with [user-defined types](#user-defined-types) may +initialized from _real-number literals_. Decimal and hexadecimal real-number +literals are supported: -> References: [Lexical conventions](lexical_conventions) and -> [expressions](expressions/) -> -> **TODO:** References need to be evolved. +- `123.456` (digits on both sides of the `.`) +- `123.456e789` (optional `+` or `-` after the `e`) +- `0x1.Ap123` (optional `+` or `-` after the `p`) -Expressions describe some computed value. The simplest example would be a -literal number like `42`: an expression that computes the integer value 42. +Real-number literals always have a period (`.`) and a digit on each side of the +period. When a real-number literal is interpreted as a value of a floating-point +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. -Some common expressions in Carbon include: +> References: +> +> - [Real-number literals](lexical_conventions/numeric_literals.md#real-number-literals) +> - Proposal +> [#143: Numeric literals](https://github.com/carbon-language/carbon-lang/pull/143) +> - Proposal +> [#144: Numeric literal semantics](https://github.com/carbon-language/carbon-lang/pull/144) +> - Proposal +> [#820: Implicit conversions](https://github.com/carbon-language/carbon-lang/pull/820) +> - Proposal +> [#866: Allow ties in floating literals](https://github.com/carbon-language/carbon-lang/pull/866) -- Literals: `42`, `3.1419`, `"Hello World!"` -- Operators: +### String types - - Increment and decrement: `++i`, `--j` - - These do not return any result. - - Unary negation: `-x` - - Arithmetic: `1 + 2`, `3 - 4`, `2 * 5`, `6 / 3` - - Bitwise: `2 & 3`, `2 | 4`, `3 ^ 1`, `~7` - - Bit shift: `1 << 3`, `8 >> 1` - - Comparison: `2 == 2`, `3 != 4`, `5 < 6`, `7 > 6`, `8 <= 8`, `8 >= 8` - - Logical: `a and b`, `c or d` +There are two string types: -- Parenthesized expressions: `(7 + 8) * (3 - 1)` +- `String` - a byte sequence treated as containing UTF-8 encoded text. +- `StringView` - a read-only reference to a byte sequence treated as + containing UTF-8 encoded text. -### Functions +#### String literals -> References: [Functions](functions.md) +String literals may be written on a single line using a double quotation mark +(`"`) at the beginning and end of the string, as in `"example"`. -Functions are the core unit of behavior. For example: +Multi-line string literals, called _block string literals_, begin and end with +three double quotation marks (`"""`), and may have a file type indicator after +the first `"""`. ```carbon -fn Add(a: i64, b: i64) -> i64; +// Block string literal: +var block: String = """ + The winds grow high; so do your stomachs, lords. + How irksome is this music to my heart! + When such strings jar, what hope of harmony? + I pray, my lords, let me compound this strife. + -- History of Henry VI, Part II, Act II, Scene 1, W. Shakespeare + """; ``` -Breaking this apart: - -- `fn` is the keyword used to indicate a function. -- Its name is `Add`. -- It accepts two `i64` parameters, `a` and `b`. -- It returns an `i64` result. - -You would call this function like `Add(1, 2)`. +The indentation of a block string literal's terminating line is removed from all +preceding lines. -### Blocks and statements +Strings may contain +[escape sequences](lexical_conventions/string_literals.md#escape-sequences) +introduced with a backslash (`\`). +[Raw string literals](lexical_conventions/string_literals.md#raw-string-literals) +are available for representing strings with `\`s and `"`s. -> References: [Blocks and statements](blocks_and_statements.md) +> References: > -> **TODO:** References need to be evolved. +> - [String literals](lexical_conventions/string_literals.md) +> - Proposal +> [#199: String literals](https://github.com/carbon-language/carbon-lang/pull/199) -The body or definition of a function is provided by a block of code containing -statements. The body of a function is also a new, nested scope inside the -function's scope, meaning that parameter names are available. +## Composite types -Statements within a block are terminated by a semicolon. Each statement can, -among other things, be an expression. +### Tuples -For example, here is a function definition using a block of statements, one of -which is nested: +A tuple is a fixed-size collection of values that can have different types, +where each value is identified by its position in the tuple. An example use of +tuples is to return multiple values from a function: ```carbon -fn Foo() { - Bar(); - { - Baz(); - } +fn DoubleBoth(x: i32, y: i32) -> (i32, i32) { + return (2 * x, 2 * y); } ``` -### Variables +Breaking this example apart: -> References: [Variables](variables.md) +- The return type is a tuple of two `i32` types. +- The expression uses tuple syntax to build a tuple of two `i32` values. -Blocks introduce nested scopes and can contain local variable declarations that -work similarly to function parameters. +Both of these are expressions using the tuple syntax +`(, )`. The only difference is the type of the tuple +expression: one is a tuple of types, the other a tuple of values. In other +words, a tuple type is a tuple _of_ types. -For example: +The components of a tuple are accessed positionally, so element access uses +subscript syntax, but the index must be a compile-time constant: ```carbon -fn DoSomething() { - var x: i64 = 42; +fn DoubleTuple(x: (i32, i32)) -> (i32, i32) { + return (2 * x[0], 2 * x[1]); } ``` -Breaking this apart: +Tuple types are +[structural](https://en.wikipedia.org/wiki/Structural_type_system). -- `var` is the keyword used to indicate a variable. -- Its name is `x`. -- Its type is `i64`. -- It is initialized with the value `42`. +> References: [Tuples](tuples.md) -### Lifetime and move semantics +### Struct types -> References: TODO -> -> **TODO:** References need to be evolved. +Carbon also has +[structural types](https://en.wikipedia.org/wiki/Structural_type_system) whose +members are identified by name instead of position. These are called _structural +data classes_, also known as a _struct types_ or _structs_. -### Control flow +Both struct types and values are written inside curly braces (`{`...`}`). In +both cases, they have a comma-separated list of members that start with a period +(`.`) followed by the field name. -> References: [Control flow](control_flow/README.md) +- In a struct type, the field name is followed by a colon (`:`) and the type, + as in: `{.name: String, .count: i32}`. +- In a struct value, called a _structural data class literal_ or a _struct + literal_, the field name is followed by an equal sign (`=`) and the value, + as in `{.key = "Joe", .count = 3}`. -Blocks of statements are generally executed sequentially. However, statements -are the primary place where this flow of execution can be controlled. +> References: +> +> - [Struct types](classes.md#struct-types) +> - Proposal +> [#561: Basic classes: use cases, struct literals, struct types, and future work](https://github.com/carbon-language/carbon-lang/pull/561) +> - Proposal +> [#981: Implicit conversions for aggregates](https://github.com/carbon-language/carbon-lang/pull/981) +> - Proposal +> [#710: Default comparison for data classes](https://github.com/carbon-language/carbon-lang/issues/710) + +### Pointer types + +The type of pointers-to-values-of-type-`T` is written `T*`. Carbon pointers do +not support +[pointer arithmetic](); +the only pointer [operations](#expressions) are: + +- Dereference: given a pointer `p`, `*p` gives the value `p` points to as an + [l-value](). + `p->m` is syntactic sugar for `(*p).m`. +- Address-of: given an + [l-value]() + `x`, `&x` returns a pointer to `x`. + +There are no [null pointers](https://en.wikipedia.org/wiki/Null_pointer) in +Carbon. To represent a pointer that may not refer to a valid object, use the +type `Optional(T*)`. + +Pointers are the main Carbon mechanism for allowing a function to modify a +variable of the caller. -#### `if` and `else` +> References: +> +> - Question-for-leads issue +> [#520: should we use whitespace-sensitive operator fixity?](https://github.com/carbon-language/carbon-lang/issues/520) +> - Question-for-leads issue +> [#523: what syntax should we use for pointer types?](https://github.com/carbon-language/carbon-lang/issues/523) -> References: [Control flow](control_flow/conditionals.md) +### Arrays and slices -`if` and `else` provide conditional execution of statements. For example: +The type of an array of holding 4 `i32` values is written `[i32; 4]`. There is +an [implicit conversion](expressions/implicit_conversions.md) from tuples to +arrays of the same length as long as every component of the tuple may be +implicitly converted to the destination element type. In cases where the size of +the array may be deduced, it may be omitted, as in: ```carbon -if (fruit.IsYellow()) { - Print("Banana!"); -} else if (fruit.IsOrange()) { - Print("Orange!"); -} else { - Print("Vegetable!"); -} +var i: i32 = 1; +// `[i32;]` equivalent to `[i32; 3]` here. +var a: [i32;] = (i, i, i); ``` -This code will: +Elements of an array may be accessed using square brackets (`[`...`]`), as in +`a[i]`: -- 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`. +```carbon +a[i] = 2; +Console.Print(a[0]); +``` -#### Loops +> **TODO:** Slices -##### `while` +## Expressions -> References: [Control flow](control_flow/loops.md#while) +Expressions describe some computed value. The simplest example would be a +literal number like `42`: an expression that computes the integer value 42. -`while` statements loop for as long as the passed expression returns `True`. For -example, this prints `0`, `1`, `2`, then `Done!`: +Some common expressions in Carbon include: -```carbon -var x: Int = 0; -while (x < 3) { - Print(x); - ++x; -} -Print("Done!"); -``` +- Literals: -##### `for` + - [boolean](#bool): `true`, `false` + - [integer](#integer-literals): `42`, `-7` + - [real-number](#floating-point-literals): `3.1419`, `6.022e+23` + - [string](#string-literals): `"Hello World!"` + - [tuple](#tuples): `(1, 2, 3)` + - [struct](#struct-types): `{.word = "the", .count = 56}` -> References: [Control flow](control_flow/loops.md#for) +- [Names](#names) and [member access](expressions/member_access.md) -`for` statements support range-based looping, typically over containers. For -example, this prints all names in `names`: +- [Operators](expressions#operators): -```carbon -for (var name: String in names) { - Print(name); -} -``` + - [Arithmetic](expressions/arithmetic.md): `-x`, `1 + 2`, `3 - 4`, + `2 * 5`, `6 / 3`, `5 % 3` + - [Bitwise](expressions/bitwise.md): `2 & 3`, `2 | 4`, `3 ^ 1`, `^7` + - [Bit shift](expressions/bitwise.md): `1 << 3`, `8 >> 1` + - [Comparison](expressions/comparison_operators.md): `2 == 2`, `3 != 4`, + `5 < 6`, `7 > 6`, `8 <= 8`, `8 >= 8` + - [Conversion](expressions/as_expressions.md): `2 as i32` + - [Logical](expressions/logical_operators.md): `a and b`, `c or d`, + `not e` + - [Indexing](#arrays-and-slices): `a[3]` + - [Function](#functions) call: `f(4)` + - [Pointer](#pointer-types): `*p`, `p->m`, `&x` -`PrintNames()` prints each `String` in the `names` `List` in iteration order. +- [Conditionals](expressions/if.md): `if c then t else f` +- Parentheses: `(7 + 8) * (3 - 1)` -##### `break` +When an expression appears in a context in which an expression of a specific +type is expected, [implicit conversions](expressions/implicit_conversions.md) +are applied to convert the expression to the target type. -> References: [Control flow](control_flow/loops.md#break) +> References: +> +> - [Expressions](expressions/) +> - Proposal +> [#162: Basic Syntax](https://github.com/carbon-language/carbon-lang/pull/162) +> - Proposal +> [#555: Operator precedence](https://github.com/carbon-language/carbon-lang/pull/555) +> - Proposal +> [#601: Operator tokens](https://github.com/carbon-language/carbon-lang/pull/601) +> - Proposal +> [#680: And, or, not](https://github.com/carbon-language/carbon-lang/pull/680) +> - Proposal +> [#702: Comparison operators](https://github.com/carbon-language/carbon-lang/pull/702) +> - Proposal +> [#845: as expressions](https://github.com/carbon-language/carbon-lang/pull/845) +> - Proposal +> [#911: Conditional expressions](https://github.com/carbon-language/carbon-lang/pull/911) +> - Proposal +> [#1083: Arithmetic expressions](https://github.com/carbon-language/carbon-lang/pull/1083) + +## Declarations, Definitions, and Scopes + +_Declarations_ introduce a new [name](#names) and say what that name represents. +For some kinds of entities, like [functions](#functions), there are two kinds of +declarations: _forward declarations_ and _definitions_. In this case, there +should be exactly one definition for the name, but there can be additional +forward declarations that introduce the name before it is defined. Forward +declarations allow cyclic references, and can be used to declare a name in an +[api file](#packages-libraries-namespaces) that is defined in an +[impl file](#packages-libraries-namespaces). A name that has been declared but +not defined is called _incomplete_, and in some cases there are limitations on +what can be done with an incomplete name. + +A name is valid until the end of the innermost enclosing +[_scope_](). Except for +the outermost scope, scopes are enclosed in curly braces (`{`...`}`). + +## Patterns + +A _pattern_ says how to receive some data that is being matched against. There +are two kinds of patterns: + +- _Refutable_ patterns can fail to match based on the runtime value being + matched. +- _Irrefutable_ patterns are guaranteed to match, so long as the code + type-checks. + +Irrefutable patterns are used in [function parameters](#functions), +[variable `var` declarations](#variable-var-declarations), and +[constant `let` declarations](#constant-let-declarations). +[`match` statements](#match) can include both refutable patterns and irrefutable +patterns. -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): +> References: +> +> - [Pattern matching](pattern_matching.md) +> - Proposal +> [#162: Basic Syntax](https://github.com/carbon-language/carbon-lang/pull/162) -```carbon -for (var step: Step in steps) { - if (step.IsManual()) { - Print("Reached manual step!"); - break; - } - step.Process(); -} -``` +### Binding patterns -##### `continue` +The most common irrefutable pattern is a _binding pattern_, consisting of a new +name, a colon (`:`), and a type. It binds the matched value of that type to that +name. It can only match values that may be +[implicitly converted](expressions/implicit_conversions.md) to that type. A +underscore (`_`) may be used instead of the name to match a value but without +binding any name to it. -> References: [Control flow](control_flow/loops.md#continue) +Binding patterns default to _`let` bindings_ except inside a context where the +`var` keyword is used to make it a _`var` binding_: -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: +- The result of a `let` binding is the name is bound to an + [non-l-value](). + This means the value can not be modified, and its address cannot be taken. +- A `var` binding has dedicated storage, and so the name is an + [l-value]() + which can be modified and has a stable address. -```carbon -var f: File = OpenFile(path); -while (!f.EOF()) { - var line: String = f.ReadLine(); - if (line.IsEmpty()) { - continue; - } - Print(line); -} -``` +A [generic binding](#checked-and-template-parameters) uses `:!` instead of a +colon (`:`) and can only match compile-time values. -#### `return` +The keyword `auto` may be used in place of the type in a binding pattern, as +long as the type can be deduced from the type of a value in the same +declaration. -> References: [Control flow](control_flow/return.md) +### Destructuring patterns -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: +There are also irrefutable _destructuring patterns_, such as _tuple +destructuring_. A tuple destructuring pattern looks like a tuple of patterns. It +may only be used to match tuple values whose components match the component +patterns of the tuple. An example use is: ```carbon -fn Sum(a: Int, b: Int) -> Int { - return a + b; +// `Bar()` returns a tuple consisting of an +// `i32` value and 2-tuple of `f32` values. +fn Bar() -> (i32, (f32, f32)); + +fn Foo() -> i64 { + // Pattern in `var` declaration: + var (p: i64, _: auto) = Bar(); + return p; } ``` -## Types +The pattern used in the `var` declaration destructures the tuple value returned +by `Bar()`. The first component pattern, `p: i64`, corresponds to the first +component of the value returned by `Bar()`, which has type `i32`. This is +allowed since there is an implicit conversion from `i32` to `i64`. The result of +this conversion is assigned to the name `p`. The second component pattern, +`_: auto`, matches the second component of the value returned by `Bar()`, which +has type `(f32, f32)`. + +### Refutable patterns + +Additional kinds of patterns are allowed in [`match` statements](#match), that +may or may not match based on the runtime value of the `match` expression: + +- An _expression pattern_ is an expression, such as `42`, whose value must be + equal to match. +- A _choice pattern_ matches one case from a choice type, as described in + [the choice types section](#choice-types). +- A _dynamic cast pattern_ is tests the dynamic type, as described in + [inheritance](#inheritance). -> References: [Primitive types](primitive_types.md), [tuples](tuples.md), and -> [classes](classes.md) +See [`match`](#match) for examples of refutable patterns. + +> References: > -> **TODO:** References need to be evolved. +> - [Pattern matching](pattern_matching.md) +> - Question-for-leads issue +> [#1283: how should pattern matching and implicit conversion interact?](https://github.com/carbon-language/carbon-lang/issues/1283) -Carbon's core types are broken down into three categories: +## Name-binding declarations -- Primitive types -- Composite types -- User-defined types +There are two kinds of name-binding declarations: -The first two are intrinsic and directly built in the language. The last aspect -of types allows for defining new types. +- constant declarations, introduced with `let`, and +- variable declarations, introduced with `var`. -Expressions compute values in Carbon, and these values are always strongly typed -much like in C++. However, an important difference from C++ is that types are -themselves modeled as values; specifically, compile-time constant values. -However, in simple cases this doesn't make much difference. +There are no forward declarations of these; all name-binding declarations are +[definitions](#declarations-definitions-and-scopes). -### Primitive types +### Constant `let` declarations -> References: [Primitive types](primitive_types.md) -> -> **TODO:** References need to be evolved. +A `let` declaration matches an [irrefutable pattern](#patterns) to a value. In +this example, the name `x` is bound to the value `42` with type `i64`: -These types are fundamental to the language as they aren't either formed from or -modifying other types. They also have semantics that are defined from first -principles rather than in terms of other operations. These will be made -available through the [prelude package](#name-lookup-for-common-types). +```carbon +let x: i64 = 42; +``` -Primitive types fall into the following categories: +Here `x: i64` is the pattern, which is followed by an equal sign (`=`) and the +value to match, `42`. The names from [binding patterns](#binding-patterns) are +introduced into the enclosing [scope](#declarations-definitions-and-scopes). -- `Bool` - a boolean type with two possible values: `True` and `False`. -- `Int` and `UInt` - signed and unsigned 64-bit integer types. - - Standard sizes are available, both signed and unsigned, including - `Int8`, `Int16`, `Int32`, `Int128`, and `Int256`. - - Overflow in either direction is an error. -- `Float64` - a floating point type with semantics based on IEEE-754. - - Standard sizes are available, including `Float16`, `Float32`, and - `Float128`. - - [`BFloat16`](primitive_types.md#bfloat16) is also provided. -- `String` - a byte sequence treated as containing UTF-8 encoded text. - - `StringView` - a read-only reference to a byte sequence treated as - containing UTF-8 encoded text. +### Variable `var` declarations -### Composite types +A `var` declaration is similar, except with `var` bindings, so `x` here is an +[l-value]() with +storage and an address, and so may be modified: -#### Tuples +```carbon +var x: i64 = 42; +x = 7; +``` -> References: [Tuples](tuples.md) +Variables with a type that has +[an unformed state](https://github.com/carbon-language/carbon-lang/pull/257) do +not need to be initialized in the variable declaration, but do need to be +assigned before they are used. + +> References: > -> **TODO:** References need to be evolved. +> - [Variables](variables.md) +> - Proposal +> [#162: Basic Syntax](https://github.com/carbon-language/carbon-lang/pull/162) +> - Proposal +> [#257: Initialization of memory and variables](https://github.com/carbon-language/carbon-lang/pull/257) +> - Proposal +> [#339: Add `var [ = ];` syntax for variables](https://github.com/carbon-language/carbon-lang/pull/339) +> - Proposal +> [#618: var ordering](https://github.com/carbon-language/carbon-lang/pull/618) + +### `auto` + +If `auto` is used as the type in a `var` or `let` declaration, the type is the +static type of the initializer expression, which is required. + +``` +var x: i64 = 2; +// The type of `y` is inferred to be `i64`. +let y: auto = x + 3; +// The type of `z` is inferred to be `bool`. +var z: auto = (y > 1); +``` + +> References: +> +> - [Type inference](type_inference.md) +> - Proposal +> [#851: auto keyword for vars](https://github.com/carbon-language/carbon-lang/pull/851) -The primary composite type involves simple aggregation of other types as a -tuple. In formal type theory, tuples are product types. +## Functions -An example use of tuples is: +Functions are the core unit of behavior. For example, this is a +[forward declaration](#declarations-definitions-and-scopes) of a function that +adds two 64-bit integers: ```carbon -fn DoubleBoth(x: Int, y: Int) -> (Int, Int) { - return (2 * x, 2 * y); -} +fn Add(a: i64, b: i64) -> i64; ``` -Breaking this example apart: +Breaking this apart: -- The return type is a tuple of two `Int` types. -- The expression uses tuple syntax to build a tuple of two `Int` values. +- `fn` is the keyword used to introduce a function. +- Its name is `Add`. This is the name added to the enclosing + [scope](#declarations-definitions-and-scopes). +- The parameter list in parentheses (`(`...`)`) is a comma-separated list of + [irrefutable patterns](#patterns). +- It returns an `i64` result. Functions that return nothing omit the `->` and + return type. -Both of these are expressions using the tuple syntax -`(, )`. The only difference is the type of the tuple -expression: one is a tuple of types, the other a tuple of values. +You would call this function like `Add(1, 2)`. -Element access uses subscript syntax: +A function definition is a function declaration that has a body +[block](#blocks-and-statements) instead of a semicolon: ```carbon -fn DoubleTuple(x: (Int, Int)) -> (Int, Int) { - return (2 * x[0], 2 * x[1]); +fn Add(a: i64, b: i64) -> i64 { + return a + b; } ``` -Tuples also support multiple indices and slicing to restructure tuple elements: +The names of the parameters are in scope until the end of the definition or +declaration. -```carbon -// This reverses the tuple using multiple indices. -fn Reverse(x: (Int, Int, Int)) -> (Int, Int, Int) { - return x[2, 1, 0]; -} +The bindings in the parameter list default to +[`let` bindings](#binding-patterns), and so the parameter names are treated as +[r-values](). If +the `var` keyword is added before the binding, then the arguments will be copied +to new storage, and so can be mutated in the function body. The copy ensures +that any mutations will not be visible to the caller. + +> References: +> +> - [Functions](functions.md) +> - Proposal +> [#162: Basic Syntax](https://github.com/carbon-language/carbon-lang/pull/162) +> - Proposal +> [#438: Add statement syntax for function declarations](https://github.com/carbon-language/carbon-lang/pull/438) +> - Question-for-leads issue +> [#476: Optional argument names (unused arguments)](https://github.com/carbon-language/carbon-lang/issues/476) + +### `auto` return type -// This slices the tuple by extracting elements [0, 2). -fn RemoveLast(x: (Int, Int, Int)) -> (Int, Int) { - return x[0 .. 2]; +If `auto` is used in place of the return type, the return type of the function +is inferred from the function body. It is set to [common type](#common-type) of +the static type of arguments to the [`return` statements](#return) in the +function. This is not allowed in a forward declaration. + +``` +// Return type is inferred to be `bool`, the type of `a > 0`. +fn Positive(a: i64) -> auto { + return a > 0; } ``` -#### Variants +> References: +> +> - [Type inference](type_inference.md) +> - [Function return clause](functions.md#return-clause) +> - Proposal +> [#826: Function return type inference](https://github.com/carbon-language/carbon-lang/pull/826) -> **TODO:** Needs a feature design and a high level summary provided inline. +### Blocks and statements -#### Pointers and references +A _block_ is a sequence of _statements_. A block defines a +[scope](#declarations-definitions-and-scopes) and, like other scopes, is +enclosed in curly braces (`{`...`}`). Each statement is terminated by a +semicolon or block. [Expressions](#expressions) and +[`var`](#variable-var-declarations) and [`let`](#constant-let-declarations) are +valid statements. -> **TODO:** Needs a feature design and a high level summary provided inline. +Statements within a block are normally executed in the order the appear in the +source code, except when modified by control-flow statements. -#### Arrays and slices +The body of a function is defined by a block, and some +[control-flow statements](#control-flow) have their own blocks of code. These +are nested within the enclosing scope. For example, here is a function +definition with a block of statements defining the body of the function, and a +nested block as part of a `while` statement: -> **TODO:** Needs a feature design and a high level summary provided inline. +```carbon +fn Foo() { + Bar(); + while (Baz()) { + Quux(); + } +} +``` -### User-defined types +> References: +> +> - [Blocks and statements](blocks_and_statements.md) +> - Proposal +> [#162: Basic Syntax](https://github.com/carbon-language/carbon-lang/pull/162) -#### Classes +### Assignment statements -> References: [Classes](classes.md) +Assignment statements mutate the value of the +[l-value]() +described on the left-hand side of the assignment. -Classes are a way for users to define their own data strutures or record types. +- Assignment: `x = y;`. `x` is assigned the value of `y`. +- Increment and decrement: `++i;`, `--j;`. `i` is set to `i + 1`, `j` is set + to `j - 1`. +- Compound assignment: `x += y;`, `x -= y;`, `x *= y;`, `x /= y;`, `x &= y;`, + `x |= y;`, `x ^= y;`, `x <<= y;`, `x >>= y;`. `x @= y;` is equivalent to + `x = x @ y;` for each operator `@`. -For example: +Unlike C++, these assignments are statements, not expressions, and don't return +a value. -```carbon -class Widget { - var x: Int; - var y: Int; - var z: Int; +### Control flow - var payload: String; +Blocks of statements are generally executed sequentially. Control-flow +statements give additional control over the flow of execution and which +statements are executed. + +Some control-flow statements include [blocks](#blocks-and-statements). Those +blocks will always be within curly braces `{`...`}`. + +```carbon +// Curly braces { ... } are required. +if (condition) { + ExecutedWhenTrue(); +} else { + ExecutedWhenFalse(); } ``` -Breaking apart `Widget`: +This is unlike C++, which allows control-flow constructs to omit curly braces +around a single statement. -- `Widget` has three `Int` members: `x`, `y`, and `z`. -- `Widget` has one `String` member: `payload`. -- Given an instance `dial`, a member can be referenced with `dial.paylod`. +> References: +> +> - [Control flow](control_flow/README.md) +> - Proposal +> [#162: Basic Syntax](https://github.com/carbon-language/carbon-lang/pull/162) +> - Proposal +> [#623: Require braces](https://github.com/carbon-language/carbon-lang/pull/623) -##### Assignment, copying +#### `if` and `else` -You may use a _structural data class literal_, also known as a _struct literal_, -to assign or initialize a variable with a class type. +`if` and `else` provide conditional execution of statements. An `if` statement +consists of: -```carbon -var sprocket: Widget = {.x = 3, .y = 4, .z = 5, .payload = "Sproing"}; -sprocket = {.x = 2, .y = 1, .z = 0, .payload = "Bounce"}; -``` +- An `if` introducer followed by a condition in parentheses. If the condition + evaluates to `true`, the block following the condition is executed, + otherwise it is skipped. +- This may be followed by zero or more `else if` clauses, whose conditions are + evaluated if all prior conditions evaluate to `false`, with a block that is + executed if that evaluation is to `true`. +- A final optional `else` clause, with a block that is executed if all + conditions evaluate to `false`. -You may also copy one struct into another of the same type. +For example: ```carbon -var thingy: Widget = sprocket; -sprocket = thingy; +if (fruit.IsYellow()) { + Console.Print("Banana!"); +} else if (fruit.IsOrange()) { + Console.Print("Orange!"); +} else { + Console.Print("Vegetable!"); +} ``` -##### Member access +This code will: -The data members of a variable with a class type may be accessed using dot `.` -notation: +- 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`. -```carbon -Assert(sprocket.x == thingy.x); -``` +> References: +> +> - [Control flow](control_flow/conditionals.md) +> - Proposal +> [#285: if/else](https://github.com/carbon-language/carbon-lang/pull/285) + +#### Loops -##### Methods +> References: [Loops](control_flow/loops.md) -Class type definitions can include methods: +##### `while` + +`while` statements loop for as long as the passed expression returns `true`. For +example, this prints `0`, `1`, `2`, then `Done!`: ```carbon -class Point { - fn Distance[me: Self](x2: i32, y2: i32) -> f32 { - var dx: i32 = x2 - me.x; +var x: i32 = 0; +while (x < 3) { + Console.Print(x); + ++x; +} +Console.Print("Done!"); +``` + +> References: +> +> - [`while` loops](control_flow/loops.md#while) +> - Proposal +> [#340: Add C++-like `while` loops](https://github.com/carbon-language/carbon-lang/pull/340) + +##### `for` + +`for` statements support range-based looping, typically over containers. For +example, this prints all names in `names`: + +```carbon +for (var name: String in names) { + Console.Print(name); +} +``` + +This prints each `String` value in `names`. + +> References: +> +> - [`for` loops](control_flow/loops.md#for) +> - Proposal +> [#353: Add C++-like `for` loops](https://github.com/carbon-language/carbon-lang/pull/353) + +##### `break` + +The `break` statement immediately ends a `while` or `for` loop. Execution will +continue starting from 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 in steps) { + if (step.IsManual()) { + Console.Print("Reached manual step!"); + break; + } + step.Process(); +} +``` + +> References: [`break`](control_flow/loops.md#break) + +##### `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 +var f: File = OpenFile(path); +while (!f.EOF()) { + var line: String = f.ReadLine(); + if (line.IsEmpty()) { + continue; + } + Console.Print(line); +} +``` + +> References: [`continue`](control_flow/loops.md#continue) + +#### `return` + +The `return` statement ends the flow of execution within a function, returning +execution to the caller. + +```carbon +// Prints the integers 1 .. `n` and then +// returns to the caller. +fn PrintFirstN(n: i32) { + var i: i32 = 0; + while (true) { + i += 1; + if (i > n) { + // None of the rest of the function is + // executed after a `return`. + return; + } + Console.Print(i); + } +} +``` + +If the function returns a value to the caller, that value is provided by an +expression in the return statement. For example: + +```carbon +fn Sign(i: i32) -> i32 { + if (i > 0) { + return 1; + } + if (i < 0) { + return -1; + } + return 0; +} + +Assert(Sign(-3) == -1); +``` + +> References: +> +> - [`return`](control_flow/return.md) +> - [`return` statements](functions.md#return-statements) +> - Proposal +> [#415: return](https://github.com/carbon-language/carbon-lang/pull/415) +> - Proposal +> [#538: return with no argument](https://github.com/carbon-language/carbon-lang/pull/538) + +##### `returned var` + +To avoid a copy when returning a variable, add a `returned` prefix to the +variable's declaration and use `return var` instead of returning an expression, +as in: + +```carbon +fn MakeCircle(radius: i32) -> Circle { + returned var c: Circle; + c.radius = radius; + // `return c` would be invalid because `returned` is in use. + return var; +} +``` + +This is instead of +[the "named return value optimization" of C++](https://en.wikipedia.org/wiki/Copy_elision#Return_value_optimization). + +> References: +> +> - [`returned var`](control_flow/return.md#returned-var) +> - Proposal +> [#257: Initialization of memory and variables](https://github.com/carbon-language/carbon-lang/pull/257) + +#### `match` + +`match` is a control flow similar to `switch` of C/C++ and mirrors similar +constructs in other languages, such as Swift. The `match` keyword is followed by +an expression in parentheses, whose value is matched against the `case` +declarations, each of which contains a [refutable pattern](#refutable-patterns), +in order. The refutable pattern may optionally be followed by an `if` +expression, which may use the names from bindings in the pattern. + +The code for the first matching `case` is executed. An optional `default` block +may be placed after the `case` declarations, it will be executed if none of the +`case` declarations match. + +An example `match` is: + +```carbon +fn Bar() -> (i32, (f32, f32)); + +fn Foo() -> f32 { + match (Bar()) { + case (42, (x: f32, y: f32)) => { + return x - y; + } + case (p: i32, (x: f32, _: f32)) if (p < 13) => { + return p * x; + } + case (p: i32, _: auto) if (p > 3) => { + return p * Pi; + } + default => { + return Pi; + } + } +} +``` + +> References: +> +> - [Pattern matching](pattern_matching.md) +> - Question-for-leads issue +> [#1283: how should pattern matching and implicit conversion interact?](https://github.com/carbon-language/carbon-lang/issues/1283) + +## User-defined types + +> **TODO:** Maybe rename to "nominal types"? + +### Classes + +_Nominal classes_, or just +[_classes_](), are a +way for users to define their own +[data strutures](https://en.wikipedia.org/wiki/Data_structure) or +[record types](). + +This is an example of a class +[definition](#declarations-definitions-and-scopes): + +```carbon +class Widget { + var x: i32; + var y: i32; + var payload: String; +} +``` + +Breaking this apart: + +- This defines a class named `Widget`. `Widget` is the name added to the + enclosing [scope](#declarations-definitions-and-scopes). +- The name `Widget` is followed by curly braces (`{`...`}`) containing the + class _body_, making this a + [definition](#declarations-definitions-and-scopes). A + [forward declaration](#declarations-definitions-and-scopes) would instead + have a semicolon(`;`). +- Those braces delimit the class' + [scope](#declarations-definitions-and-scopes). +- Fields, or + [instances variables](https://en.wikipedia.org/wiki/Instance_variable), are + defined using [`var` declarations](#variable-var-declarations). `Widget` has + two `i32` fields (`x` and `y`), and one `String` field (`payload`). + +The order of the field declarations determines the fields' memory-layout order. + +Classes may have other kinds of members beyond fields declared in its scope: + +- [Class functions](#class-functions-and-factory-functions) +- [Methods](#methods) +- [`alias`](#aliases) +- [`let`](#constant-let-declarations) to define class constants. **TODO:** + Another syntax to define constants associated with the class like + `class let` or `static let`? +- `class`, to define a + [_member class_ or _nested class_](https://en.wikipedia.org/wiki/Inner_class) + +Within the scope of a class, the unqualified name `Self` can be used to refer to +the class itself. + +Members of a class are [accessed](expressions/member_access.md) using the dot +(`.`) notation, so given an instance `dial` of type `Widget`, `dial.payload` +refers to its `payload` field. + +Both [structural data classes](#struct-types) and nominal classes are considered +_class types_, but they are commonly referred to as "structs" and "classes" +respectively when that is not confusing. Like structs, classes refer to their +members by name. Unlike structs, classes are +[nominal types](https://en.wikipedia.org/wiki/Nominal_type_system#Nominal_typing). + +> References: +> +> - [Classes](classes.md#nominal-class-types) +> - Proposal +> [#722: Nominal classes and methods](https://github.com/carbon-language/carbon-lang/pull/722) +> - Proposal +> [#989: Member access expressions](https://github.com/carbon-language/carbon-lang/pull/989) + +#### Assignment + +There is an [implicit conversions](expressions/implicit_conversions.md) defined +between a [struct literal](#struct-types) and a class type with the same fields, +in any scope that has [access](#access-control) to all of the class' fields. +This may be used to assign or initialize a variable with a class type, as in: + +```carbon +var sprocket: Widget = {.x = 3, .y = 4, .payload = "Sproing"}; +sprocket = {.x = 2, .y = 1, .payload = "Bounce"}; +``` + +> References: +> +> - [Classes: Construction](classes.md#construction) +> - Proposal +> [#981: Implicit conversions for aggregates](https://github.com/carbon-language/carbon-lang/pull/981) + +#### Class functions and factory functions + +Classes may also contain _class functions_. These are functions that are +accessed as members of the type, like +[static member functions in C++](), +as opposed to [methods](#methods) that are members of instances. They are +commonly used to define a function that creates instances. Carbon does not have +separate +[constructors]() +like C++ does. + +```carbon +class Point { + // Class function that instantiates `Point`. + // `Self` in class scope means the class currently being defined. + fn Origin() -> Self { + return {.x = 0, .y = 0}; + } + var x: i32; + var y: i32; +} +``` + +Note that if the definition of a function is provided inside the class scope, +the body is treated as if it was defined immediately after the outermost class +definition. This means that members such as the fields will be considered +defined even if their definitions are later in the source than the class +function. + +The [`returned var` feature](#returned-var) can be used if the address of the +instance being created is needed in a factory function, as in: + +```carbon +class Registered { + fn Create() -> Self { + returned var result: Self = {...}; + StoreMyPointerSomewhere(&result); + return var; + } +} +``` + +This approach can also be used for types that can't be copied or moved. + +#### Methods + +Class type definitions can include methods: + +```carbon +class Point { + // Method defined inline + fn Distance[me: Self](x2: i32, y2: i32) -> f32 { + var dx: i32 = x2 - me.x; var dy: i32 = y2 - me.y; return Math.Sqrt(dx * dx - dy * dy); } + // Mutating method fn Offset[addr me: Self*](dx: i32, dy: i32); var x: i32; var y: i32; } +// Out-of-line definition of method declared inline. fn Point.Offset[addr me: Self*](dx: i32, dy: i32) { me->x += dx; me->y += dy; @@ -650,7 +1276,7 @@ Assert(origin.Distance(3, 4) == 0.0); This defines a `Point` class type with two integer data members `x` and `y` and two methods `Distance` and `Offset`: -- Methods are defined as functions with a `me` parameter inside square +- Methods are defined as class functions with a `me` parameter inside square brackets `[`...`]` before the regular explicit parameter list in parens `(`...`)`. - Methods are called using using the member syntax, `origin.Distance(`...`)` @@ -663,180 +1289,410 @@ two methods `Distance` and `Offset`: - Methods may be declared lexically inline like `Distance`, or lexically out of line like `Offset`. -##### Allocation, construction, and destruction +> References: +> +> - [Methods](classes.md#methods) +> - Proposal +> [#722: Nominal classes and methods](https://github.com/carbon-language/carbon-lang/pull/722) -> **TODO:** Needs a feature design and a high level summary provided inline. +#### Inheritance -##### Moving +Classes by default are +[_final_](), +which means they may not be extended. A class may be declared as allowing +extension using either the `base class` or `abstract class` introducer instead +of `class`. An `abstract class` is a base class that may not itself be +instantiated. -> **TODO:** Needs a feature design and a high level summary provided inline. +```carbon +base class MyBaseClass { ... } +``` -##### Comparison +Either kind of base class maybe _extended_ to get a _derived class_. Derived +classes are final unless they are themselved declared `base` or `abstract`. +Classes may only extend a single class. Carbon only supports single inheritance, +and will use mixins instead of multiple inheritance. -> **TODO:** Needs a feature design and a high level summary provided inline. +```carbon +base class MiddleDerived extends MyBaseClass { ... } +class FinalDerived extends MiddleDerived { ... } +// ❌ Forbidden: class Illegal extends FinalDerived { ... } +``` -##### Implicit and explicit conversion +A base class may define +[virtual methods](https://en.wikipedia.org/wiki/Virtual_function). These are +methods whose implementation may be overridden in a derived class. By default +methods are _non-virtual_, the declaration of a virtual methods must be prefixed +by one of these three keywords: + +- A method marked `virtual` has a definition in this class but not in any + base. +- A method marked `abstract` does not have have a definition in this class, + but must have a definition in any non-`abstract` derived class. +- A method marked `impl` has a definition in this class, overriding any + definition in a base class. + +A pointer to a derived class may be cast to a pointer to one of its base +classes. Calling a virtual method through a pointer to a base class will use the +overridden definition provided in the derived class. Base classes with `virtual` +methods may use +[run-time type information](https://en.wikipedia.org/wiki/Run-time_type_information) +in a match statement to dynamically test whether the dynamic type of a value is +some derived class, as in: -> **TODO:** Needs a feature design and a high level summary provided inline. +```carbon +var base_ptr: MyBaseType* = ...; +match (base_ptr) { + case dyn p: MiddleDerived* => { ... } +} +``` -##### Inline type composition +For purposes of construction, a derived class acts like its first field is +called `base` with the type of its immediate base class. -> **TODO:** Needs a feature design and a high level summary provided inline. +```carbon +class MyDerivedType extends MyBaseType { + fn Create() -> MyDerivedType { + return {.base = MyBaseType.Create(), .derived_field = 7}; + } + var derived_field: i32; +} +``` -#### Unions +Abstract classes can't be instantiated, so instead they should define class +functions returning `partial Self`. Those functions should be marked +[`protected`](#access-control) so they may only be used by derived classes. -> **TODO:** Needs a detailed design and a high level summary provided inline. +```carbon +abstract class AbstractClass { + protected fn Create() -> partial Self { + return {.field_1 = 3, .field_2 = 9}; + } + // ... + var field_1: i32; + var field_2: i32; +} +// ❌ Error: can't instantiate abstract class +var abc: AbstractClass = ...; + +class DerivedFromAbstract extends AbstractClass { + fn Create() -> Self { + // AbstractClass.Create() returns a + // `partial AbstractClass` that can be used as + // the `.base` member when constructing a value + // of a derived class. + return {.base = AbstractClass.Create(), + .derived_field = 42 }; + } -## Pattern matching + var derived_field: i32; +} +``` -> References: [Pattern matching](pattern_matching.md) +> References: > -> **TODO:** References need to be evolved. +> - [Inheritance](classes.md#inheritance) +> - Proposal +> [#777: Inheritance](https://github.com/carbon-language/carbon-lang/pull/777) +> - Proposal +> [#820: Implicit conversions](https://github.com/carbon-language/carbon-lang/pull/820) -The most prominent mechanism to manipulate and work with types in Carbon is -pattern matching. This may seem like a deviation from C++, but in fact this is -largely about building a clear, coherent model for a fundamental part of C++: -overload resolution. +#### Access control -### `match` control flow +Class members are by default publicly accessible. The `private` keyword prefix +can be added to the member's declaration to restrict it to members of the class +or any friends. A `private virtual` or `private abstract` method may be +implemented in derived classes, even though it may not be called. -> References: [Pattern matching](pattern_matching.md) +Friends may be declared using a `friend` declaration inside the class naming an +existing function or type. Unlike C++, `friend` declarations may only refer to +names resolvable by the compiler, and don't act like forward declarations. + +`protected` is like `private`, but also gives access to derived classes. + +> References: > -> **TODO:** References need to be evolved. +> - [Access control for class members](classes.md#access-control) +> - Question-for-leads issue +> [#665: `private` vs `public` _syntax_ strategy, as well as other visibility tools like `external`/`api`/etc.](https://github.com/carbon-language/carbon-lang/issues/665) +> - Question-for-leads issue +> [#971: Private interfaces in public API files](https://github.com/carbon-language/carbon-lang/issues/971) -`match` is a control flow similar to `switch` of C/C++ and mirrors similar -constructs in other languages, such as Swift. +#### Destructors -An example `match` is: +A destructor for a class is custom code executed when the lifetime of a value of +that type ends. They are defined with the `destructor` keyword followed by +either `[me: Self]` or `[addr me: Self*]` (as is done with [methods](#methods)) +and the block of code in the class definition, as in: ```carbon -fn Bar() -> (Int, (Float, Float)); +class MyClass { + destructor [me: Self] { ... } +} +``` -fn Foo() -> Float { - match (Bar()...) { - case (42, (x: Float, y: Float)) => { - return x - y; - } - case (p: Int, (x: Float, _: Float)) if (p < 13) => { - return p * x; - } - case (p: Int, _: auto) if (p > 3) => { - return p * Pi; - } - default => { - return Pi; +or: + +```carbon +class MyClass { + // Can modify `me` in the body. + destructor [addr me: Self*] { ... } +} +``` + +The destructor for a class is run before the destructors of its data members. +The data members are destroyed in reverse order of declaration. Derived classes +are destroyed before their base classes. + +A destructor in a abstract or base class may be declared `virtual` like with +[methods](#inheritance). Destructors in classes derived from one with a virtual +destructor must be declared with the `impl` keyword prefix. It is illegal to +delete an instance of a derived class through a pointer to a base class unless +the base class is declared `virtual` or `impl`. To delete a pointer to a +non-abstract base class when it is known not to point to a value with a derived +type, use `UnsafeDelete`. + +> References: +> +> - [Destructors](classes.md#destructors) +> - Proposal +> [#1154: Destructors](https://github.com/carbon-language/carbon-lang/pull/1154) + +### Choice types + +A _choice type_ is a [tagged union](https://en.wikipedia.org/wiki/Tagged_union), +that can store different types of data in a storage space that can hold the +largest. A choice type has a name, and a list of cases separated by commas +(`,`). Each case has a name and an optional parameter list. + +```carbon +choice IntResult { + Success(value: i32), + Failure(error: String), + Cancelled +} +``` + +The value of a choice type is one of the cases, plus the values of the +parameters to that case, if any. A value can be constructed by naming the case +and providing values for the parameters, if any: + +```carbon +fn ParseAsInt(s: String) -> IntResult { + var r: i32 = 0; + for (c: i32 in s) { + if (not IsDigit(c)) { + // Equivalent to `IntResult.Failure(...)` + return .Failure("Invalid character"); } + // ... } + return .Success(r); } ``` -Breaking apart this `match`: +Choice type values may be consumed using a [`match` statement](#match): -- It accepts a value that will be inspected; in this case, the result of the - call to `Bar()`. - - It then will find the _first_ `case` that matches this value, and - execute that block. - - If none match, then it executes the default block. -- Each `case` pattern contains a value pattern, such as `(Int p, auto _)`, - followed by an optional boolean predicate introduced by the `if` keyword. - - The value pattern must first match, and then the predicate must also - evaluate to true for the overall `case` pattern to match. - - Using `auto` for a type will always match. +```carbon +match (ParseAsInt(s)) { + case .Success(value: i32) => { + return value; + } + case .Failure(error: String) => { + Display(error); + } + case .Cancelled => { + Terminate(); + } +} +``` -Value patterns may be composed of the following: +They can also represent an +[enumerated type](https://en.wikipedia.org/wiki/Enumerated_type), if no +additional data is associated with the choices, as in: -- An expression, such as `42`, whose value must be equal to match. -- An identifier to bind the value, followed by a `:` and followed by a type, - such as `Int`. - - The special identifier `_` may be used to discard the value once - matched. -- A destructuring pattern containing a sequence of value patterns, such as - `(x: Float, y: Float)`, 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. +```carbon +choice LikeABoolean { False, True } +``` -### Pattern matching in local variables +> References: +> +> - Proposal +> [#157: Design direction for sum types](https://github.com/carbon-language/carbon-lang/pull/157) +> - Proposal +> [#162: Basic Syntax](https://github.com/carbon-language/carbon-lang/pull/162) -> References: [Pattern matching](pattern_matching.md) +## Names + +### Packages, libraries, namespaces + +> References: > -> **TODO:** References need to be evolved. +> - [Code and name organization](code_and_name_organization) +> - Proposal +> [#107: Code and name organization](https://github.com/carbon-language/carbon-lang/pull/107) +> - Proposal +> [#752: api file default public](https://github.com/carbon-language/carbon-lang/pull/752) +> - Question-for-leads issue +> [#1136: what is the top-level scope in a source file, and what names are found there?](https://github.com/carbon-language/carbon-lang/issues/1136) -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, so a boolean predicate cannot be used directly. +- **Files** are grouped into libraries, which are in turn grouped into + packages. +- **Libraries** are the granularity of code reuse through imports. +- **Packages** are the unit of distribution. + +Name paths in Carbon always start with the package name. Additional namespaces +may be specified as desired. -An example use is: +For example, this code declares a class `Geometry.Shapes.Flat.Circle` in a +library `Geometry/OneSide`: ```carbon -fn Bar() -> (Int, (Float, Float)); -fn Foo() -> Int { - var (p: Int, _: auto) = Bar(); - return p; -} +package Geometry library("OneSide") namespace Shapes; + +namespace Flat; +class Flat.Circle { ... } ``` -To break this apart: +This type can be used from another package: -- The `Int` returned by `Bar()` matches and is bound to `p`, then returned. -- The `(Float, Float)` returned by `Bar()` matches and is discarded by - `_: auto`. +```carbon +package ExampleUser; -### Pattern matching as function overload resolution +import Geometry library("OneSide"); -> References: [Pattern matching](pattern_matching.md) +fn Foo(Geometry.Shapes.Flat.Circle circle) { ... } +``` + +### Legal names + +> References: [Lexical conventions](lexical_conventions) > -> **TODO:** References need to be evolved. Needs a detailed design and a high -> level summary provided inline. +> **TODO:** References need to be evolved. -## Type abstractions +Various constructs introduce a named entity in Carbon. These can be functions, +types, variables, or other kinds of entities. A name in Carbon is formed from a +word, which is a sequence of letters, numbers, and underscores, and which starts +with a letter. We intend to follow Unicode's Annex 31 in selecting valid +identifier characters, but a concrete set of valid characters has not been +selected yet. -### Interfaces +### Naming conventions -> **TODO:** Needs a feature design and a high level summary provided inline. +> References: +> +> - [Naming conventions](naming_conventions.md) +> - Proposal +> [#861: Naming conventions](https://github.com/carbon-language/carbon-lang/pull/861) -### Generics +Our naming conventions are: -> **TODO:** Needs a feature design and a high level summary provided inline. +- For idiomatic Carbon code: + - `UpperCamelCase` will be used when the named entity cannot have a + dynamically varying value. For example, functions, namespaces, or + compile-time constant values. + - `lower_snake_case` will be used when the named entity's value won't be + known until runtime, such as for variables. +- For Carbon-provided features: + - Keywords and type literals will use `lower_snake_case`. + - Other code will use the conventions for idiomatic Carbon code. -### Templates +### Aliases -> References: [Templates](templates.md) +> References: > +> - [Aliases](aliases.md) +> - Question-for-leads issue +> [#749: Alias syntax](https://github.com/carbon-language/carbon-lang/issues/749) + > **TODO:** References need to be evolved. -Carbon templates follow the same fundamental paradigm as C++ templates: they are -instantiated when called, resulting in late type checking, duck typing, and lazy -binding. Although generics are generally preferred, templates enable translation -of code between C++ and Carbon, and address some cases where the type checking -rigor of generics are problematic. +Carbon provides a facility to declare a new name as an alias for a value. This +is a fully general facility because everything is a value in Carbon, including +types. -#### Types with template parameters +For example: -> References: [Templates](templates.md) +```carbon +alias MyInt = i32; +``` + +This creates an alias called `MyInt` for whatever `i32` resolves to. Code +textually after this can refer to `MyInt`, and it will transparently refer to +`i32`. + +### Name lookup + +> References: +> +> - [Name lookup](name_lookup.md) +> - Proposal +> [#989: Member access expressions](https://github.com/carbon-language/carbon-lang/pull/989) > > **TODO:** References need to be evolved. -User-defined types may have template parameters. The resulting type-function may -be used to instantiate the parameterized definition with the provided arguments -in order to produce a complete type. For example: +Unqualified name lookup will always find a file-local result, including aliases, +or names that are defined as part of the prelude. -```carbon -class Stack(template T:! Type) { - var storage: Array(T); +#### Name lookup for common types - fn Push(value: T); - fn Pop() -> T; -} -``` +FIXME: should this be renamed to "The prelude"? -Breaking apart the template use in `Stack`: +> References: [Name lookup](name_lookup.md) +> +> - Question-for-leads issue +> [#750: Naming conventions for Carbon-provided features](https://github.com/carbon-language/carbon-lang/issues/750) +> - Question-for-leads issue +> [#1058: How should interfaces for core functionality be named?](https://github.com/carbon-language/carbon-lang/issues/1058) +> +> **TODO:** References need to be evolved. -- `Stack` is a paremeterized type accepting a type `T`. -- `T` may be used within the definition of `Stack` anywhere a normal type - would be used, and will only be type checked on instantiation. -- `var ... Array(T)` instantiates a parameterized type `Array` when `Stack` is - instantiated. +Common types that we expect to be used universally will be provided for every +file, including `i32` and `Bool`. These will likely be defined in a special +"prelude" package. + +### Name visibility + +> References: +> +> - FIXME: Name visibility and access control at file scope +> - Question-for-leads issue +> [#665: `private` vs `public` _syntax_ strategy, as well as other visibility tools like `external`/`api`/etc.](https://github.com/carbon-language/carbon-lang/issues/665) +> - Proposal +> [#752: api file default public](https://github.com/carbon-language/carbon-lang/pull/752) + +> **TODO:** + +## Generics + +> **TODO:** + +### Interfaces and implementations + +> **TODO:** + +### Checked and template parameters + +> References: Proposal +> [#989: Member access expressions](https://github.com/carbon-language/carbon-lang/pull/989) + +> **TODO:** + +#### Templates + +> References: [Templates](templates.md) +> +> **TODO:** References need to be evolved. + +Carbon templates follow the same fundamental paradigm as C++ templates: they are +instantiated when called, resulting in late type checking, duck typing, and lazy +binding. Although generics are generally preferred, templates enable translation +of code between C++ and Carbon, and address some cases where the type checking +rigor of generics are problematic. + +### Generic functions + +> **TODO:** #### Functions with template parameters @@ -857,10 +1713,10 @@ fn Convert[template T:! Type](source: T, template U:! Type) -> U { return converted; } -fn Foo(i: Int) -> Float { - // Instantiates with the `T` implicit argument set to `Int` and the `U` - // explicit argument set to `Float`, then calls with the runtime value `i`. - return Convert(i, Float); +fn Foo(i: i32) -> f32 { + // Instantiates with the `T` implicit argument set to `i32` and the `U` + // explicit argument set to `f32`, then calls with the runtime value `i`. + return Convert(i, f32); } ``` @@ -872,23 +1728,110 @@ that type unavailable to the declaration of _that_ runtime parameter, it still is a _template_ parameter and available to use as a type in the remaining parts of the function declaration. -#### Overloading +### Generic types + +> **TODO:** + +#### Types with template parameters > References: [Templates](templates.md) > > **TODO:** References need to be evolved. -An important feature of templates in C++ is the ability to customize how they -end up specialized for specific arguments. Because template parameters (whether -as type parameters or function parameters) are pattern matched, we expect to -leverage pattern matching techniques to provide "better match" definitions that -are selected analogously to specializations in C++ templates. When expressed -through pattern matching, this may enable things beyond just template parameter -specialization, but that is an area that we want to explore cautiously. +User-defined types may have template parameters. The resulting type-function may +be used to instantiate the parameterized definition with the provided arguments +in order to produce a complete type. For example: -> **TODO:** lots more work to flesh this out needs to be done... +```carbon +class Stack(template T:! Type) { + var storage: Array(T); -## Metaprogramming + fn Push(value: T); + fn Pop() -> T; +} +``` + +Breaking apart the template use in `Stack`: + +- `Stack` is a paremeterized type accepting a type `T`. +- `T` may be used within the definition of `Stack` anywhere a normal type + would be used, and will only be type checked on instantiation. +- `var ... Array(T)` instantiates a parameterized type `Array` when `Stack` is + instantiated. + +#### Generic choice types + +```carbon +choice Result(T:! Type, Error:! Type) { + Success(value: T), + Failure(error: Error), + Cancelled +} +``` + +### Operator overloading + +> References: +> +> - [Operator overloading](generics/details.md#operator-overloading) +> - Proposal +> [#702: Comparison operators](https://github.com/carbon-language/carbon-lang/pull/702) +> - Proposal +> [#820: Implicit conversions](https://github.com/carbon-language/carbon-lang/pull/820) +> - Proposal +> [#845: as expressions](https://github.com/carbon-language/carbon-lang/pull/845) +> - Question-for-leads issue +> [#1058: How should interfaces for core functionality be named?](https://github.com/carbon-language/carbon-lang/issues/1058) +> - Proposal +> [#1083: Arithmetic expressions](https://github.com/carbon-language/carbon-lang/pull/1083) +> - Proposal +> [#1191: Bitwise operators](https://github.com/carbon-language/carbon-lang/pull/1191) +> - Proposal +> [#1178: Rework operator interfaces](https://github.com/carbon-language/carbon-lang/pull/1178) + +> **TODO:** + +> - [Implicit conversions](expressions/implicit_conversions.md#extensibility) +> - [`as` expressions](expressions/as_expressions.md#extensibility) +> - [Comparison operators](expressions/comparison_operators.md#extensibility) +> - [Arithmetic expressions](expressions/arithmetic.md#extensibility) +> - [Bitwise and shift operators](expressions/bitwise.md#extensibility) + +#### Common type + +> References: +> +> - [`if` expressions](expressions/if.md#finding-a-common-type) +> - Proposal +> [#911: Conditional expressions](https://github.com/carbon-language/carbon-lang/pull/911) + +> **TODO:** + +## Bidirectional interoperability with C/C++ + +> References: +> +> - [Bidirectional interoperability with C/C++](interoperability/README.md) +> - Proposal +> [#175: C++ interoperability goals](https://github.com/carbon-language/carbon-lang/pull/175) +> +> **TODO:** References need to be evolved. Needs a detailed design and a high +> level summary provided inline. + +## Unfinished tales + +### Pattern matching as function overload resolution + +> References: [Pattern matching](pattern_matching.md) +> +> **TODO:** References need to be evolved. Needs a detailed design and a high +> level summary provided inline. + +### Lifetime and move semantics + +> **TODO:** + +### Metaprogramming > References: [Metaprogramming](metaprogramming.md) > @@ -899,27 +1842,19 @@ Carbon provides metaprogramming facilities that look similar to regular Carbon code. These are structured, and do not offer arbitrary inclusion or preprocessing of source text such as C/C++ does. -## Execution abstractions +### Execution abstractions Carbon provides some higher-order abstractions of program execution, as well as the critical underpinnings of such abstractions. -### Abstract machine and execution model - -> **TODO:** Needs a feature design and a high level summary provided inline. +#### Abstract machine and execution model -### Lambdas +> **TODO:** -> **TODO:** Needs a feature design and a high level summary provided inline. +#### Lambdas -### Co-routines +> **TODO:** -> **TODO:** Needs a feature design and a high level summary provided inline. +#### Co-routines -## Bidirectional interoperability with C/C++ - -> References: -> [Bidirectional interoperability with C/C++](interoperability/README.md) -> -> **TODO:** References need to be evolved. Needs a detailed design and a high -> level summary provided inline. +> **TODO:** diff --git a/docs/design/control_flow/return.md b/docs/design/control_flow/return.md index 84456600d8347..ac92fc94fbb2d 100644 --- a/docs/design/control_flow/return.md +++ b/docs/design/control_flow/return.md @@ -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; diff --git a/docs/design/lexical_conventions/numeric_literals.md b/docs/design/lexical_conventions/numeric_literals.md index 2065a44f76833..b4f1a33a6d30b 100644 --- a/docs/design/lexical_conventions/numeric_literals.md +++ b/docs/design/lexical_conventions/numeric_literals.md @@ -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±_N_. 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-_b_, 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` diff --git a/docs/design/pattern_matching.md b/docs/design/pattern_matching.md index 834c39445009c..86d85eb76cb72 100644 --- a/docs/design/pattern_matching.md +++ b/docs/design/pattern_matching.md @@ -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; } ```