mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-24 20:20:10 +01:00
Values, variables, pointers, and references (#2006)
Introduce a concrete design for how Carbon values, objects, storage,
variables,
and pointers will work. This includes fleshing out the design for:
- The expression categories used in Carbon to represent values and
objects,
how they interact, and terminology that anchors on their expression
nature.
- An expression category model for readonly, abstract values that can
efficiently support function inputs.
- A customization system for value expression representations,
especially as
seen on function boundaries in the calling convention.
- An expression category model for references instead of a type system
model.
- How patterns match different expression categories.
- How initialization works in conjunction with function returns.
- Specific pointer syntax, semantics, and library customization
mechanisms.
- A `const` type qualifier for use when the value expression category
system
is too abstracted from the underlying objects in storage.
---------
Co-authored-by: Geoff Romer <gromer@google.com>
Co-authored-by: josh11b <josh11b@users.noreply.github.com>
Co-authored-by: Adrien Leravat <Pixep@users.noreply.github.com>
Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
Co-authored-by: Richard Smith <richard@metafoo.co.uk>
This commit is contained in:
co-authored by
Geoff Romer
josh11b
Adrien Leravat
Jon Ross-Perkins
Richard Smith
parent
049fbc1ee4
commit
0d1e6bd84d
+134
-74
@@ -27,7 +27,9 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
- [Floating-point literals](#floating-point-literals)
|
||||
- [String types](#string-types)
|
||||
- [String literals](#string-literals)
|
||||
- [Value categories and value phases](#value-categories-and-value-phases)
|
||||
- [Values, objects, and expressions](#values-objects-and-expressions)
|
||||
- [Expression categories](#expression-categories)
|
||||
- [Value phases](#value-phases)
|
||||
- [Composite types](#composite-types)
|
||||
- [Tuples](#tuples)
|
||||
- [Struct types](#struct-types)
|
||||
@@ -43,6 +45,7 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
- [Constant `let` declarations](#constant-let-declarations)
|
||||
- [Variable `var` declarations](#variable-var-declarations)
|
||||
- [`auto`](#auto)
|
||||
- [Global constants and variables](#global-constants-and-variables)
|
||||
- [Functions](#functions)
|
||||
- [Parameters](#parameters)
|
||||
- [`auto` return type](#auto-return-type)
|
||||
@@ -396,10 +399,10 @@ Some values, such as `()` and `{}`, may even be used as types, but only act like
|
||||
types when they are in a type position, like after a `:` in a variable
|
||||
declaration or the return type after a `->` in a function declaration. Any
|
||||
expression in a type position must be
|
||||
[a constants or symbolic value](#value-categories-and-value-phases) so the
|
||||
compiler can resolve whether the value can be used as a type. This also puts
|
||||
limits on how much operators can do different things for types. This is good for
|
||||
consistency, but is a significant restriction on Carbon's design.
|
||||
[a constant or symbolic value](#value-phases) so the compiler can resolve
|
||||
whether the value can be used as a type. This also puts limits on how much
|
||||
operators can do different things for types. This is good for consistency, but
|
||||
is a significant restriction on Carbon's design.
|
||||
|
||||
## Primitive types
|
||||
|
||||
@@ -637,21 +640,57 @@ are available for representing strings with `\`s and `"`s.
|
||||
> - Proposal
|
||||
> [#199: String literals](https://github.com/carbon-language/carbon-lang/pull/199)
|
||||
|
||||
## Value categories and value phases
|
||||
## Values, objects, and expressions
|
||||
|
||||
Every expression has a
|
||||
[value category](<https://en.wikipedia.org/wiki/Value_(computer_science)#lrvalue>),
|
||||
similar to [C++](https://en.cppreference.com/w/cpp/language/value_category),
|
||||
that is either _l-value_ or _r-value_. Carbon will automatically convert an
|
||||
l-value to an r-value, but not in the other direction.
|
||||
Carbon has both abstract _values_ and concrete _objects_. Carbon _values_ are
|
||||
things like `42`, `true`, and `i32` (a type value). Carbon _objects_ have
|
||||
_storage_ where values can be read and written. Storage also allows taking the
|
||||
address of an object in memory in Carbon.
|
||||
|
||||
L-value expressions refer to values that have storage and a stable address. They
|
||||
may be modified, assuming their type is not [`const`](#const).
|
||||
> References:
|
||||
>
|
||||
> - [Values, variables, and pointers](values.md)
|
||||
> - Proposal
|
||||
> [#2006: Values, variables, pointers, and references](https://github.com/carbon-language/carbon-lang/pull/2006)
|
||||
|
||||
R-value expressions evaluate to values that may not have dedicated storage. This
|
||||
means they cannot be modified and their address generally cannot be taken. The
|
||||
values of r-value expressions are broken down into three kinds, called _value
|
||||
phases_:
|
||||
### Expression categories
|
||||
|
||||
A Carbon expression produces a value, references an object, or initializes an
|
||||
object. Every expression has a
|
||||
[category](<https://en.wikipedia.org/wiki/Value_(computer_science)#lrvalue>),
|
||||
similar to [C++](https://en.cppreference.com/w/cpp/language/value_category):
|
||||
|
||||
- [_Value expressions_](values.md#value-expressions) produce abstract,
|
||||
read-only _values_ that cannot be modified or have their address taken.
|
||||
- [_Reference expressions_](values.md#reference-expressions) refer to
|
||||
_objects_ with _storage_ where a value may be read or written and the
|
||||
object's address can be taken.
|
||||
- [_Initializing expressions_](values.md#initializing-expressions) which
|
||||
require storage to be provided implicitly when evaluating the expression.
|
||||
The expression then initializes an object in that storage. These are used to
|
||||
model function returns, which can construct the returned value directly in
|
||||
the caller's storage.
|
||||
|
||||
Expressions in one category can be converted to any other category when needed.
|
||||
The primitive conversion steps used are:
|
||||
|
||||
- _Value binding_ converts a reference expression into a value expression.
|
||||
- _Direct initialization_ converts a value expression into an initializing
|
||||
expression.
|
||||
- _Copy initialization_ converts a reference expression into an initializing
|
||||
expression.
|
||||
- _Temporary materialization_ converts an initializing expression into a
|
||||
reference expression.
|
||||
|
||||
> References:
|
||||
>
|
||||
> - [Expression categories](values.md#expression-categories)
|
||||
> - Proposal
|
||||
> [#2006: Values, variables, pointers, and references](https://github.com/carbon-language/carbon-lang/pull/2006)
|
||||
|
||||
### Value phases
|
||||
|
||||
Value expressions are also broken down into three _value phases_:
|
||||
|
||||
- A _constant_ has a value known at compile time, and that value is available
|
||||
during type checking, for example to use as the size of an array. These
|
||||
@@ -674,7 +713,7 @@ to a runtime value:
|
||||
```mermaid
|
||||
graph TD;
|
||||
A(constant)-->B(symbolic value)-->C(runtime value);
|
||||
D(l-value)-->C;
|
||||
D(reference expression)-->C;
|
||||
```
|
||||
|
||||
Constants convert to symbolic values and to runtime values. Symbolic values will
|
||||
@@ -682,9 +721,7 @@ generally convert into runtime values if an operation that inspects the value is
|
||||
performed on them. Runtime values will convert into constants or to symbolic
|
||||
values if constant evaluation of the runtime expression succeeds.
|
||||
|
||||
> **Note:** Conversion of runtime values to other phases is provisional, as are
|
||||
> the semantics of r-values. See pending proposal
|
||||
> [#2006: Values, variables, pointers, and references](https://github.com/carbon-language/carbon-lang/pull/2006).
|
||||
> **Note:** Conversion of runtime values to other phases is provisional.
|
||||
|
||||
## Composite types
|
||||
|
||||
@@ -762,30 +799,25 @@ not support
|
||||
[pointer arithmetic](<https://en.wikipedia.org/wiki/Pointer_(computer_programming)>);
|
||||
the only pointer [operations](#expressions) are:
|
||||
|
||||
- Dereference: given a pointer `p`, `*p` gives the value `p` points to as an
|
||||
[l-value](#value-categories-and-value-phases). `p->m` is syntactic sugar for
|
||||
`(*p).m`.
|
||||
- Address-of: given an [l-value](#value-categories-and-value-phases) `x`, `&x`
|
||||
- Dereference: given a pointer `p`, `*p` gives the value `p` points to as a
|
||||
[reference expression](#expression-categories). `p->m` is syntactic sugar
|
||||
for `(*p).m`.
|
||||
- Address-of: given a [reference expression](#expression-categories) `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*)`.
|
||||
|
||||
**TODO:** Perhaps Carbon will have
|
||||
**Future work:** Perhaps Carbon will have
|
||||
[stricter pointer provenance](https://www.ralfj.de/blog/2022/04/11/provenance-exposed.html)
|
||||
or restrictions on casts between pointers and integers.
|
||||
|
||||
> **Note:** While the syntax for pointers has been decided, the semantics of
|
||||
> pointers are provisional, as is the syntax for optionals. See pending proposal
|
||||
> [#2006: Values, variables, pointers, and references](https://github.com/carbon-language/carbon-lang/pull/2006).
|
||||
|
||||
> 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)
|
||||
> - [Pointers](values.md#pointers)
|
||||
> - Proposal
|
||||
> [#2006: Values, variables, pointers, and references](https://github.com/carbon-language/carbon-lang/pull/2006)
|
||||
|
||||
### Arrays and slices
|
||||
|
||||
@@ -846,7 +878,7 @@ Some common expressions in Carbon include:
|
||||
`not e`
|
||||
- [Indexing](#arrays-and-slices): `a[3]`
|
||||
- [Function](#functions) call: `f(4)`
|
||||
- [Pointer](#pointer-types): `*p`, `p->m`, `&x`
|
||||
- [Pointer](expressions/pointer_operators.md): `*p`, `p->m`, `&x`
|
||||
- [Move](#move): `~x`
|
||||
|
||||
- [Conditionals](expressions/if.md): `if c then t else f`
|
||||
@@ -875,6 +907,8 @@ are applied to convert the expression to the target type.
|
||||
> [#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)
|
||||
> - Proposal
|
||||
> [#2006: Values, variables, pointers, and references](https://github.com/carbon-language/carbon-lang/pull/2006)
|
||||
|
||||
## Declarations, Definitions, and Scopes
|
||||
|
||||
@@ -954,14 +988,15 @@ binding any name to it.
|
||||
Binding patterns default to _`let` bindings_. The `var` keyword is used to make
|
||||
it a _`var` binding_.
|
||||
|
||||
- The result of a `let` binding is the name is bound to an
|
||||
[r-value](#value-categories-and-value-phases). This means the value cannot
|
||||
be modified, and its address generally cannot be taken.
|
||||
- A `var` binding has dedicated storage, and so the name is an
|
||||
[l-value](#value-categories-and-value-phases) which can be modified and has
|
||||
a stable address.
|
||||
- A `let` binding binds a name to a value, so the name can be used as a
|
||||
[value expression](#expression-categories). This means the value cannot be
|
||||
modified, and its address generally cannot be taken.
|
||||
- A `var` binding creates an object with dedicated storage, and so the name
|
||||
can be used as a [reference expression](#expression-categories) which can be
|
||||
modified and has a stable address.
|
||||
|
||||
A `let`-binding may be implemented as an alias for the original value (like a
|
||||
A `let`-binding may be [implemented](values.md#value-expressions) as an alias
|
||||
for the original value (like a
|
||||
[`const` reference in C++](<https://en.wikipedia.org/wiki/Reference_(C%2B%2B)>)),
|
||||
or it may be copied from the original value (if it is copyable), or it may be
|
||||
moved from the original value (if it was a temporary). The Carbon
|
||||
@@ -971,9 +1006,8 @@ the program's correctness must not depend on which option the Carbon
|
||||
implementation chooses.
|
||||
|
||||
A [generic binding](#checked-and-template-parameters) uses `:!` instead of a
|
||||
colon (`:`) and can only match
|
||||
[constant or symbolic values](#value-categories-and-value-phases), not run-time
|
||||
values.
|
||||
colon (`:`) and can only match [constant or symbolic values](#value-phases), not
|
||||
run-time values.
|
||||
|
||||
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
|
||||
@@ -1049,14 +1083,17 @@ 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).
|
||||
|
||||
> **Note:** `let` declarations are provisional. See pending proposal
|
||||
> [#2006: Values, variables, pointers, and references](https://github.com/carbon-language/carbon-lang/pull/2006).
|
||||
> References:
|
||||
>
|
||||
> - [Binding patterns and local variables with `let` and `var`](values.md#binding-patterns-and-local-variables-with-let-and-var)
|
||||
> - Proposal
|
||||
> [#2006: Values, variables, pointers, and references](https://github.com/carbon-language/carbon-lang/pull/2006)
|
||||
|
||||
### Variable `var` declarations
|
||||
|
||||
A `var` declaration is similar, except with `var` bindings, so `x` here is an
|
||||
[l-value](#value-categories-and-value-phases) with storage and an address, and
|
||||
so may be modified:
|
||||
A `var` declaration is similar, except with `var` bindings, so `x` here is a
|
||||
[reference expression](#expression-categories) for an object with storage and an
|
||||
address, and so may be modified:
|
||||
|
||||
```carbon
|
||||
var x: i64 = 42;
|
||||
@@ -1069,7 +1106,7 @@ they are used.
|
||||
|
||||
> References:
|
||||
>
|
||||
> - [Variables](variables.md)
|
||||
> - [Binding patterns and local variables with `let` and `var`](values.md#binding-patterns-and-local-variables-with-let-and-var)
|
||||
> - Proposal
|
||||
> [#162: Basic Syntax](https://github.com/carbon-language/carbon-lang/pull/162)
|
||||
> - Proposal
|
||||
@@ -1078,6 +1115,8 @@ they are used.
|
||||
> [#339: Add `var <type> <identifier> [ = <value> ];` 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)
|
||||
> - Proposal
|
||||
> [#2006: Values, variables, pointers, and references](https://github.com/carbon-language/carbon-lang/pull/2006)
|
||||
|
||||
### `auto`
|
||||
|
||||
@@ -1098,6 +1137,21 @@ var z: auto = (y > 1);
|
||||
> - Proposal
|
||||
> [#851: auto keyword for vars](https://github.com/carbon-language/carbon-lang/pull/851)
|
||||
|
||||
### Global constants and variables
|
||||
|
||||
[Constant `let` declarations](#constant-let-declarations) may occur at a global
|
||||
scope as well as local and member scopes. However, there are currently no global
|
||||
variables.
|
||||
|
||||
> **Note**: The semantics of global constant declarations and absence of global
|
||||
> variable declarations is currently provisional.
|
||||
>
|
||||
> We are exploring several different ideas for how to design less bug-prone
|
||||
> patterns to replace the important use cases programmers still have for global
|
||||
> variables. We may be unable to fully address them, at least for migrated code,
|
||||
> and be forced to add some limited form of global variables back. We may also
|
||||
> discover that their convenience outweighs any improvements afforded.
|
||||
|
||||
## Functions
|
||||
|
||||
Functions are the core unit of behavior. For example, this is a
|
||||
@@ -1149,7 +1203,7 @@ declaration. The parameter names in a forward declaration may be omitted using
|
||||
|
||||
The bindings in the parameter list default to
|
||||
[`let` bindings](#binding-patterns), and so the parameter names are treated as
|
||||
[r-values](#value-categories-and-value-phases). This is appropriate for input
|
||||
[value expressions](#expression-categories). This is appropriate for input
|
||||
parameters. This binding will be implemented using a pointer, unless it is legal
|
||||
to copy and copying is cheaper.
|
||||
|
||||
@@ -1167,9 +1221,11 @@ the caller, and dereferencing using `*` in the callee.
|
||||
Outputs of a function should prefer to be returned. Multiple values may be
|
||||
returned using a [tuple](#tuples) or [struct](#struct-types) type.
|
||||
|
||||
> **Note:** The semantics of parameter passing are provisional. See pending
|
||||
> proposal
|
||||
> [#2006: Values, variables, pointers, and references](https://github.com/carbon-language/carbon-lang/pull/2006).
|
||||
> References:
|
||||
>
|
||||
> - [Binding patterns and local variables with `let` and `var`](values.md#binding-patterns-and-local-variables-with-let-and-var)
|
||||
> - Proposal
|
||||
> [#2006: Values, variables, pointers, and references](https://github.com/carbon-language/carbon-lang/pull/2006)
|
||||
|
||||
### `auto` return type
|
||||
|
||||
@@ -1689,8 +1745,8 @@ two methods `Distance` and `Offset`:
|
||||
declaration.
|
||||
- `origin.Offset(`...`)` does modify the value of `origin`. This is signified
|
||||
using `[addr self: Self*]` in the method declaration. Since calling this
|
||||
method requires taking the address of `origin`, it may only be called on
|
||||
[non-`const`](#const) [l-values](#value-categories-and-value-phases).
|
||||
method requires taking the [non-`const`](#const) address of `origin`, it may
|
||||
only be called on [reference expressions](#expression-categories).
|
||||
- Methods may be declared lexically inline like `Distance`, or lexically out
|
||||
of line like `Offset`.
|
||||
|
||||
@@ -1883,20 +1939,19 @@ type, use `UnsafeDelete`.
|
||||
|
||||
#### `const`
|
||||
|
||||
> **Note:** This is provisional, no design for `const` has been through the
|
||||
> proposal process yet.
|
||||
|
||||
For every type `MyClass`, there is the type `const MyClass` such that:
|
||||
|
||||
- The data representation is the same, so a `MyClass*` value may be implicitly
|
||||
converted to a `(const MyClass)*`.
|
||||
- A `const MyClass` [l-value](#value-categories-and-value-phases) may
|
||||
automatically convert to a `MyClass` r-value, the same way that a `MyClass`
|
||||
l-value can.
|
||||
- A `const MyClass` [reference expression](#expression-categories) may
|
||||
automatically convert to a `MyClass` value expression, the same way that a
|
||||
`MyClass` reference expression can.
|
||||
- If member `x` of `MyClass` has type `T`, then member `x` of `const MyClass`
|
||||
has type `const T`.
|
||||
- The API of a `const MyClass` is a subset of `MyClass`, excluding all methods
|
||||
taking `[addr self: Self*]`.
|
||||
- While all of the member names in `MyClass` are also member names in
|
||||
`const MyClass`, the effective API of a `const MyClass` reference expression
|
||||
is a subset of `MyClass`, because only `addr` methods accepting a
|
||||
`const Self*` will be valid.
|
||||
|
||||
Note that `const` binds more tightly than postfix-`*` for forming a pointer
|
||||
type, so `const MyClass*` is equal to `(const MyClass)*`.
|
||||
@@ -1911,8 +1966,8 @@ var origin: Point = {.x = 0, .y = 0};
|
||||
// `const Point*`:
|
||||
let p: const Point* = &origin;
|
||||
|
||||
// ✅ Allowed conversion of `const Point` l-value
|
||||
// to `Point` r-value.
|
||||
// ✅ Allowed conversion of `const Point` reference expression
|
||||
// to `Point` value expression.
|
||||
let five: f32 = p->Distance(3, 4);
|
||||
|
||||
// ❌ Error: mutating method `Offset` excluded
|
||||
@@ -1924,6 +1979,12 @@ p->Offset(3, 4);
|
||||
p->x += 2;
|
||||
```
|
||||
|
||||
> References:
|
||||
>
|
||||
> - [`const`-qualified types](values.md#const-qualified-types)
|
||||
> - Proposal
|
||||
> [#2006: Values, variables, pointers, and references](https://github.com/carbon-language/carbon-lang/pull/2006)
|
||||
|
||||
#### Unformed state
|
||||
|
||||
Types indicate that they support unformed states by
|
||||
@@ -1967,8 +2028,6 @@ value.
|
||||
> **Note:** This is provisional. The move operator was discussed but not
|
||||
> proposed in accepted proposal
|
||||
> [#257: Initialization of memory and variables](https://github.com/carbon-language/carbon-lang/pull/257).
|
||||
> See pending proposal
|
||||
> [#2006: Values, variables, pointers, and references](https://github.com/carbon-language/carbon-lang/pull/2006).
|
||||
|
||||
#### Mixins
|
||||
|
||||
@@ -2664,8 +2723,8 @@ templates. Constraints can then be added incrementally, with the compiler
|
||||
verifying that the semantics stay the same. Once all constraints have been
|
||||
added, removing the word `template` to switch to a checked parameter is safe.
|
||||
|
||||
The [value phase](#value-categories-and-value-phases) of a checked parameter is
|
||||
a symbolic value whereas the value phase of a template parameter is constant.
|
||||
The [value phase](#value-phases) of a checked parameter is a symbolic value
|
||||
whereas the value phase of a template parameter is constant.
|
||||
|
||||
Although checked generics are generally preferred, templates enable translation
|
||||
of code between C++ and Carbon, and address some cases where the type checking
|
||||
@@ -3111,9 +3170,10 @@ The interfaces that correspond to each operator are given by:
|
||||
The
|
||||
[logical operators can not be overloaded](expressions/logical_operators.md#overloading).
|
||||
|
||||
Operators that result in [l-values](#value-categories-and-value-phases), such as
|
||||
dereferencing `*p` and indexing `a[3]`, have interfaces that return the address
|
||||
of the value. Carbon automatically dereferences the pointer to get the l-value.
|
||||
Operators that result in [reference expressions](#expression-categories), such
|
||||
as dereferencing `*p` and indexing `a[3]`, have interfaces that return the
|
||||
address of the value. Carbon automatically dereferences the pointer to form the
|
||||
reference expression.
|
||||
|
||||
Operators that can take multiple arguments, such as function calling operator
|
||||
`f(4)`, have a [variadic](generics/details.md#variadic-arguments) parameter
|
||||
|
||||
@@ -80,8 +80,8 @@ fn MaybeDraw(should_draw: bool) -> () {
|
||||
|
||||
### `returned var`
|
||||
|
||||
[Variables](../variables.md) may be declared with a `returned` statement. Its
|
||||
syntax is:
|
||||
[Local variables](../values.md#binding-patterns-and-local-variables-with-let-and-var)
|
||||
may be declared with a `returned` statement. Its syntax is:
|
||||
|
||||
> `returned` _var statement_
|
||||
|
||||
|
||||
@@ -61,10 +61,27 @@ graph BT
|
||||
unqualifiedName["x"]
|
||||
click unqualifiedName "https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/expressions/README.md#unqualified-names"
|
||||
|
||||
top((" "))
|
||||
|
||||
memberAccess>"x.y<br>
|
||||
x.(...)"]
|
||||
x.(...)<br>
|
||||
x->y<br>
|
||||
x->(...)"]
|
||||
click memberAccess "https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/expressions/member_access.md"
|
||||
|
||||
constType["const T"]
|
||||
click pointer-type "https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/expressions/type_operators.md"
|
||||
|
||||
pointerType>"T*"]
|
||||
click pointer-type "https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/expressions/type_operators.md"
|
||||
|
||||
%% FIXME: Need to switch unary operators from a left/right associativity to
|
||||
%% a "repeated" marker, as we only have one direction for associativity and
|
||||
%% that is wrong in this specific case.
|
||||
pointer>"*x<br>
|
||||
&x<br>"]
|
||||
click pointer "https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/expressions/pointer.md"
|
||||
|
||||
negation["-x"]
|
||||
click negation "https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/expressions/arithmetic.md"
|
||||
|
||||
@@ -124,15 +141,22 @@ graph BT
|
||||
|
||||
expressionEnd["x;"]
|
||||
|
||||
memberAccess --> parens & braces & unqualifiedName
|
||||
negation --> memberAccess
|
||||
complement --> memberAccess
|
||||
top --> parens & braces & unqualifiedName
|
||||
|
||||
constType --> top
|
||||
pointerType --> constType
|
||||
as --> pointerType
|
||||
|
||||
memberAccess --> top
|
||||
pointer --> memberAccess
|
||||
negation --> pointer
|
||||
complement --> pointer
|
||||
unary --> negation & complement
|
||||
%% Use a longer arrow here to put `not` next to `and` and `or`.
|
||||
not -----> memberAccess
|
||||
multiplication & modulo & as & bitwise_and & bitwise_or & bitwise_xor & shift --> unary
|
||||
not -------> memberAccess
|
||||
as & multiplication & modulo & bitwise_and & bitwise_or & bitwise_xor & shift --> unary
|
||||
addition --> multiplication
|
||||
comparison --> modulo & addition & as & bitwise_and & bitwise_or & bitwise_xor & shift
|
||||
comparison --> as & addition & modulo & bitwise_and & bitwise_or & bitwise_xor & shift
|
||||
logicalOperand --> comparison & not
|
||||
and & or --> logicalOperand
|
||||
logicalExpression --> and & or
|
||||
@@ -179,12 +203,14 @@ keyword and is not preceded by a period (`.`).
|
||||
|
||||
### Qualified names and member access
|
||||
|
||||
A _qualified name_ is a word that appears immediately after a period. Qualified
|
||||
names appear in the following contexts:
|
||||
A _qualified name_ is a word that appears immediately after a period or
|
||||
rightward arrow. Qualified names appear in the following contexts:
|
||||
|
||||
- [Designators](/docs/design/classes.md#literals): `.` _word_
|
||||
- [Simple member access expressions](member_access.md): _expression_ `.`
|
||||
_word_
|
||||
- [Simple pointer member access expressions](member_access.md): _expression_
|
||||
`->` _word_
|
||||
|
||||
```
|
||||
var x: auto = {.hello = 1, .world = 2};
|
||||
@@ -194,6 +220,10 @@ var x: auto = {.hello = 1, .world = 2};
|
||||
x.hello = x.world;
|
||||
^^^^^ ^^^^^ qualified name
|
||||
^^^^^^^ ^^^^^^^ member access expression
|
||||
|
||||
x.hello = (&x)->world;
|
||||
^^^^^ qualified name
|
||||
^^^^^^^^^^^ pointer member access expression
|
||||
```
|
||||
|
||||
Qualified names refer to members of an entity determined by the context in which
|
||||
@@ -231,6 +261,7 @@ complex than a single _word_, a compound member access expression can be used,
|
||||
with parentheses around the member name:
|
||||
|
||||
- _expression_ `.` `(` _expression_ `)`
|
||||
- _expression_ `->` `(` _expression_ `)`
|
||||
|
||||
```
|
||||
interface I { fn F[self: Self](); }
|
||||
@@ -241,34 +272,40 @@ impl X as I { fn F[self: Self]() {} }
|
||||
fn Q(x: X) { x.(I.F)(); }
|
||||
```
|
||||
|
||||
Either simple or compound member access can be part of a _pointer_ member access
|
||||
expression when an `->` is used instead of a `.`, where _expression_ `->` _..._
|
||||
is syntactic sugar for `(` `*` _expression_ `)` `.` _..._.
|
||||
|
||||
## Operators
|
||||
|
||||
Most expressions are modeled as operators:
|
||||
|
||||
| Category | Operator | Syntax | Function |
|
||||
| ---------- | ------------------------------- | --------- | --------------------------------------------------------------------- |
|
||||
| Arithmetic | [`-`](arithmetic.md) (unary) | `-x` | The negation of `x`. |
|
||||
| Bitwise | [`^`](bitwise.md) (unary) | `^x` | The bitwise complement of `x`. |
|
||||
| Arithmetic | [`+`](arithmetic.md) | `x + y` | The sum of `x` and `y`. |
|
||||
| Arithmetic | [`-`](arithmetic.md) (binary) | `x - y` | The difference of `x` and `y`. |
|
||||
| Arithmetic | [`*`](arithmetic.md) | `x * y` | The product of `x` and `y`. |
|
||||
| Arithmetic | [`/`](arithmetic.md) | `x / y` | `x` divided by `y`, or the quotient thereof. |
|
||||
| Arithmetic | [`%`](arithmetic.md) | `x % y` | `x` modulo `y`. |
|
||||
| Bitwise | [`&`](bitwise.md) | `x & y` | The bitwise AND of `x` and `y`. |
|
||||
| Bitwise | [`\|`](bitwise.md) | `x \| y` | The bitwise OR of `x` and `y`. |
|
||||
| Bitwise | [`^`](bitwise.md) (binary) | `x ^ y` | The bitwise XOR of `x` and `y`. |
|
||||
| Bitwise | [`<<`](bitwise.md) | `x << y` | `x` bit-shifted left `y` places. |
|
||||
| Bitwise | [`>>`](bitwise.md) | `x >> y` | `x` bit-shifted right `y` places. |
|
||||
| Conversion | [`as`](as_expressions.md) | `x as T` | Converts the value `x` to the type `T`. |
|
||||
| Comparison | [`==`](comparison_operators.md) | `x == y` | Equality: `true` if `x` is equal to `y`. |
|
||||
| Comparison | [`!=`](comparison_operators.md) | `x != y` | Inequality: `true` if `x` is not equal to `y`. |
|
||||
| Comparison | [`<`](comparison_operators.md) | `x < y` | Less than: `true` if `x` is less than `y`. |
|
||||
| Comparison | [`<=`](comparison_operators.md) | `x <= y` | Less than or equal: `true` if `x` is less than or equal to `y`. |
|
||||
| Comparison | [`>`](comparison_operators.md) | `x > y` | Greater than: `true` if `x` is greater than to `y`. |
|
||||
| Comparison | [`>=`](comparison_operators.md) | `x >= y` | Greater than or equal: `true` if `x` is greater than or equal to `y`. |
|
||||
| Logical | [`and`](logical_operators.md) | `x and y` | A short-circuiting logical AND: `true` if both operands are `true`. |
|
||||
| Logical | [`or`](logical_operators.md) | `x or y` | A short-circuiting logical OR: `true` if either operand is `true`. |
|
||||
| Logical | [`not`](logical_operators.md) | `not x` | Logical NOT: `true` if the operand is `false`. |
|
||||
| Category | Operator | Syntax | Function |
|
||||
| ---------- | ----------------------------------- | --------- | --------------------------------------------------------------------- |
|
||||
| Pointer | [`*`](pointer_operators.md) (unary) | `*x` | Pointer dereference: the object pointed to by `x`. |
|
||||
| Pointer | [`&`](pointer_operators.md) (unary) | `&x` | Address-of: a pointer to the object `x`. |
|
||||
| Arithmetic | [`-`](arithmetic.md) (unary) | `-x` | The negation of `x`. |
|
||||
| Bitwise | [`^`](bitwise.md) (unary) | `^x` | The bitwise complement of `x`. |
|
||||
| Arithmetic | [`+`](arithmetic.md) | `x + y` | The sum of `x` and `y`. |
|
||||
| Arithmetic | [`-`](arithmetic.md) (binary) | `x - y` | The difference of `x` and `y`. |
|
||||
| Arithmetic | [`*`](arithmetic.md) | `x * y` | The product of `x` and `y`. |
|
||||
| Arithmetic | [`/`](arithmetic.md) | `x / y` | `x` divided by `y`, or the quotient thereof. |
|
||||
| Arithmetic | [`%`](arithmetic.md) | `x % y` | `x` modulo `y`. |
|
||||
| Bitwise | [`&`](bitwise.md) | `x & y` | The bitwise AND of `x` and `y`. |
|
||||
| Bitwise | [`\|`](bitwise.md) | `x \| y` | The bitwise OR of `x` and `y`. |
|
||||
| Bitwise | [`^`](bitwise.md) (binary) | `x ^ y` | The bitwise XOR of `x` and `y`. |
|
||||
| Bitwise | [`<<`](bitwise.md) | `x << y` | `x` bit-shifted left `y` places. |
|
||||
| Bitwise | [`>>`](bitwise.md) | `x >> y` | `x` bit-shifted right `y` places. |
|
||||
| Conversion | [`as`](as_expressions.md) | `x as T` | Converts the value `x` to the type `T`. |
|
||||
| Comparison | [`==`](comparison_operators.md) | `x == y` | Equality: `true` if `x` is equal to `y`. |
|
||||
| Comparison | [`!=`](comparison_operators.md) | `x != y` | Inequality: `true` if `x` is not equal to `y`. |
|
||||
| Comparison | [`<`](comparison_operators.md) | `x < y` | Less than: `true` if `x` is less than `y`. |
|
||||
| Comparison | [`<=`](comparison_operators.md) | `x <= y` | Less than or equal: `true` if `x` is less than or equal to `y`. |
|
||||
| Comparison | [`>`](comparison_operators.md) | `x > y` | Greater than: `true` if `x` is greater than to `y`. |
|
||||
| Comparison | [`>=`](comparison_operators.md) | `x >= y` | Greater than or equal: `true` if `x` is greater than or equal to `y`. |
|
||||
| Logical | [`and`](logical_operators.md) | `x and y` | A short-circuiting logical AND: `true` if both operands are `true`. |
|
||||
| Logical | [`or`](logical_operators.md) | `x or y` | A short-circuiting logical OR: `true` if either operand is `true`. |
|
||||
| Logical | [`not`](logical_operators.md) | `not x` | Logical NOT: `true` if the operand is `false`. |
|
||||
|
||||
The binary arithmetic and bitwise operators also have
|
||||
[compound assignment](/docs/design/assignment.md) forms. These are statements
|
||||
|
||||
@@ -23,14 +23,17 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
## Overview
|
||||
|
||||
Carbon supports indexing using the conventional `a[i]` subscript syntax. When
|
||||
`a` is an l-value, the result of subscripting is always an l-value, but when `a`
|
||||
is an r-value, the result can be an l-value or an r-value, depending on which
|
||||
`a` is a
|
||||
[durable reference expression](/docs/design/values.md#durable-reference-expressions),
|
||||
the result of subscripting is also a durable reference expression, but when `a`
|
||||
is a [value expression](/docs/design/values.md#value-expressions), the result
|
||||
can be a durable reference expression or a value expression, depending on which
|
||||
interface the type implements:
|
||||
|
||||
- If subscripting an r-value produces an r-value result, as with an array, the
|
||||
type should implement `IndexWith`.
|
||||
- If subscripting an r-value produces an l-value result, as with C++'s
|
||||
`std::span`, the type should implement `IndirectIndexWith`.
|
||||
- If subscripting a value expression produces a value expression, as with an
|
||||
array, the type should implement `IndexWith`.
|
||||
- If subscripting a value expression produces a durable reference expression,
|
||||
as with C++'s `std::span`, the type should implement `IndirectIndexWith`.
|
||||
|
||||
`IndirectIndexWith` is a subtype of `IndexWith`, and subscript expressions are
|
||||
rewritten to method calls on `IndirectIndexWith` if the type is known to
|
||||
@@ -39,6 +42,19 @@ implement that interface, or to method calls on `IndexWith` otherwise.
|
||||
`IndirectIndexWith` provides a final blanket `impl` of `IndexWith`, so a type
|
||||
can implement at most one of those two interfaces.
|
||||
|
||||
The `Addr` methods of these interfaces, which are used to form durable reference
|
||||
expressions on indexing, must return a pointer and work similarly to the
|
||||
[pointer dereference customization interface](/docs/design/values.md#dereferencing-customization).
|
||||
The returned pointer is then dereferenced by the language to form the reference
|
||||
expression referring to the pointed-to object. These methods must return a raw
|
||||
pointer, and do not automatically chain with customized dereference interfaces.
|
||||
|
||||
**Open question:** It's not clear that the lack of chaining is necessary, and it
|
||||
might be more expressive for the pointer type returned by the `Addr` methods to
|
||||
be an associated type with a default to allow types to produce custom
|
||||
pointer-like types on their indexing boundary and have them still be
|
||||
automatically dereferenced.
|
||||
|
||||
## Details
|
||||
|
||||
A subscript expression has the form "_lhs_ `[` _index_ `]`". As in C++, this
|
||||
@@ -61,13 +77,15 @@ interface IndirectIndexWith(SubscriptType:! type) {
|
||||
```
|
||||
|
||||
A subscript expression where _lhs_ has type `T` and _index_ has type `I` is
|
||||
rewritten based on the value category of _lhs_ and whether `T` is known to
|
||||
rewritten based on the expression category of _lhs_ and whether `T` is known to
|
||||
implement `IndirectIndexWith(I)`:
|
||||
|
||||
- If `T` implements `IndirectIndexWith(I)`, the expression is rewritten to
|
||||
"`*((` _lhs_ `).(IndirectIndexWith(I).Addr)(` _index_ `))`".
|
||||
- Otherwise, if _lhs_ is an l-value, the expression is rewritten to "`*((`
|
||||
_lhs_ `).(IndexWith(I).Addr)(` _index_ `))`".
|
||||
- Otherwise, if _lhs_ is a
|
||||
[_durable reference expression_](/docs/design/values.md#durable-reference-expressions),
|
||||
the expression is rewritten to "`*((` _lhs_ `).(IndexWith(I).Addr)(` _index_
|
||||
`))`".
|
||||
- Otherwise, the expression is rewritten to "`(` _lhs_ `).(IndexWith(I).At)(`
|
||||
_index_ `)`".
|
||||
|
||||
@@ -136,3 +154,5 @@ Carbon API.
|
||||
|
||||
- Proposal
|
||||
[#2274: Subscript syntax and semantics](https://github.com/carbon-language/carbon-lang/pull/2274)
|
||||
- Proposal
|
||||
[#2006: Values, variables, and pointers](https://github.com/carbon-language/carbon-lang/pull/2006)
|
||||
|
||||
@@ -29,9 +29,12 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
## Overview
|
||||
|
||||
A _qualified name_ is a [word](../lexical_conventions/words.md) that is preceded
|
||||
by a period. The name is found within a contextually determined entity:
|
||||
by a period or a rightward arrow. The name is found within a contextually
|
||||
determined entity:
|
||||
|
||||
- In a member access expression, this is the entity preceding the period.
|
||||
- In a pointer member access expression, this is the entity pointed to by the
|
||||
pointer preceding the rightward arrow.
|
||||
- For a designator in a struct literal, the name is introduced as a member of
|
||||
the struct type.
|
||||
|
||||
@@ -43,10 +46,12 @@ A member access expression is either a _simple_ member access expression of the
|
||||
form:
|
||||
|
||||
- _member-access-expression_ ::= _expression_ `.` _word_
|
||||
- _member-access-expression_ ::= _expression_ `->` _word_
|
||||
|
||||
or a _compound_ member access of the form:
|
||||
|
||||
- _member-access-expression_ ::= _expression_ `.` `(` _expression_ `)`
|
||||
- _member-access-expression_ ::= _expression_ `->` `(` _expression_ `)`
|
||||
|
||||
Compound member accesses allow specifying a qualified member name.
|
||||
|
||||
@@ -66,14 +71,26 @@ class Cog {
|
||||
fn GrowSomeCogs() {
|
||||
var cog1: Cog = Cog.Make(1);
|
||||
var cog2: Cog = cog1.Make(2);
|
||||
var cog_pointer: Cog* = &cog2;
|
||||
let cog1_size: i32 = cog1.size;
|
||||
cog1.Grow(1.5);
|
||||
cog2.(Cog.Grow)(cog1_size as f64);
|
||||
cog1.(Widget.Grow)(1.1);
|
||||
cog2.(Widgets.Cog.(Widgets.Widget.Grow))(1.9);
|
||||
cog_pointer->Grow(0.75);
|
||||
cog_pointer->(Widget.Grow)(1.2);
|
||||
}
|
||||
```
|
||||
|
||||
Pointer member access expressions are those using a `->` instead of a `.` and
|
||||
their semantics are exactly what would result from first dereferencing the
|
||||
expression preceding the `->` and then forming a member access expression using
|
||||
a `.`. For example, a simple pointer member access expression _expression_ `->`
|
||||
_word_ becomes `(` `*` _expression_ `)` `.` _word_. More details on this syntax
|
||||
and semantics can be found in the [pointers](/docs/design/values.md#pointers)
|
||||
design. The rest of this document describes the semantics using `.` alone for
|
||||
simplicity.
|
||||
|
||||
A member access expression is processed using the following steps:
|
||||
|
||||
- First, the word or parenthesized expression to the right of the `.` is
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
# Pointer operators
|
||||
|
||||
<!--
|
||||
Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
||||
Exceptions. See /LICENSE for license information.
|
||||
SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
-->
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
## Table of contents
|
||||
|
||||
- [Overview](#overview)
|
||||
- [Details](#details)
|
||||
- [Precedence](#precedence)
|
||||
- [Alternatives considered](#alternatives-considered)
|
||||
- [References](#references)
|
||||
|
||||
<!-- tocstop -->
|
||||
|
||||
## Overview
|
||||
|
||||
Carbon provides the following operators related to pointers:
|
||||
|
||||
- `&` as a prefix unary operator takes the address of an object, forming a
|
||||
pointer to it.
|
||||
- `*` as a prefix unary operator dereferences a pointer.
|
||||
|
||||
Note that [member access expressions](member_access.md) include an `->` form
|
||||
that implicitly performs a dereference in the same way as the `*` operator.
|
||||
|
||||
## Details
|
||||
|
||||
The semantic details of pointer operators are collected in the main
|
||||
[pointers](/docs/design/values.md#pointers) design. The syntax and precedence
|
||||
details are covered here.
|
||||
|
||||
The syntax tries to remain as similar as possible to C++ pointer types as they
|
||||
are commonly written in code and are expected to be extremely common and a key
|
||||
anchor of syntactic similarity between the languages.
|
||||
|
||||
### Precedence
|
||||
|
||||
These operators have high precedence. Only [member access](member_access.md)
|
||||
expressions can be used as an unparenthesized operand to them.
|
||||
|
||||
The two prefix operators `&` and `*` are generally above the other unary and
|
||||
binary operators and can appear inside them as unparenthesized operands. For the
|
||||
full details, see the [precedence graph](README.md#precedence).
|
||||
|
||||
## Alternatives considered
|
||||
|
||||
- [Alternative pointer syntaxes](/proposals/p2006.md#alternative-pointer-syntaxes)
|
||||
|
||||
## References
|
||||
|
||||
- [Proposal #2006: Values, variables, and pointers](/proposals/p2006.md)
|
||||
@@ -0,0 +1,67 @@
|
||||
# Type operators
|
||||
|
||||
<!--
|
||||
Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
||||
Exceptions. See /LICENSE for license information.
|
||||
SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
-->
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
## Table of contents
|
||||
|
||||
- [Overview](#overview)
|
||||
- [Details](#details)
|
||||
- [Precedence](#precedence)
|
||||
- [Alternatives considered](#alternatives-considered)
|
||||
- [References](#references)
|
||||
|
||||
<!-- tocstop -->
|
||||
|
||||
## Overview
|
||||
|
||||
Carbon provides the following operators to transform types:
|
||||
|
||||
- `const` as a prefix unary operator produces a `const`-qualified type.
|
||||
- `*` as a postfix unary operator produces a pointer _type_ to some other
|
||||
type.
|
||||
|
||||
The pointer type operator is also covered as one of the
|
||||
[pointer operators](pointer_operators.md).
|
||||
|
||||
## Details
|
||||
|
||||
The semantic details of both `const`-qualified types and pointer types are
|
||||
provided as part of the [values](/docs/design/values.md) design:
|
||||
|
||||
- [`const`-qualified types](/docs/design/values.md#const-qualified-types)
|
||||
- [Pointers](/docs/design/values.md#pointers)
|
||||
|
||||
The syntax of these operators tries to mimic the most common appearance of
|
||||
`const` types and pointer types in C++.
|
||||
|
||||
### Precedence
|
||||
|
||||
Because these are type operators, they don't have many precedence relationship
|
||||
with non-type operators.
|
||||
|
||||
- `const` binds more tightly than `*` and can appear unparenthesized in an
|
||||
operand, despite being both a unary operator and having whitespace
|
||||
separating it.
|
||||
- This allows the syntax of a pointer to a `const i32` to be `const i32*`,
|
||||
which is intended to be familiar to C++ developers.
|
||||
- Forming a `const` pointer type requires parentheses: `const (i32*)`.
|
||||
- All type operators bind more tightly than `as` so they can be used in its
|
||||
type operand.
|
||||
- This also allows a desirable transitive precedence with `if`:
|
||||
`if condition then T* else U*`.
|
||||
|
||||
## Alternatives considered
|
||||
|
||||
- [Alternative pointer syntaxes](/proposals/p2006.md#alternative-pointer-syntaxes)
|
||||
- [Alternative syntaxes for locals](/proposals/p2006.md#alternative-syntaxes-for-locals)
|
||||
- [Make `const` a postfix rather than prefix operator](/proposals/p2006.md#make-const-a-postfix-rather-than-prefix-operator)
|
||||
|
||||
## References
|
||||
|
||||
- [Proposal #2006: Values, variables, and pointers](/proposals/p2006.md)
|
||||
@@ -287,7 +287,7 @@ _Binding patterns_ associate a name with a type and a value. This is used to
|
||||
declare function parameters, in `let` and `var` declarations, as well as to
|
||||
declare [generic parameters](#generic-means-compile-time-parameterized). There
|
||||
are three kinds of binding patterns, corresponding to
|
||||
[the three value phases](/docs/design/README.md#value-categories-and-value-phases):
|
||||
[the three value phases](/docs/design/README.md#value-phases):
|
||||
|
||||
- A _runtime binding pattern_ binds to a dynamic value at runtime, and is
|
||||
written using a `:`, as in `x: i32`.
|
||||
|
||||
@@ -22,7 +22,8 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
[Type inference](https://en.wikipedia.org/wiki/Type_inference) occurs in Carbon
|
||||
when the `auto` keyword is used. This may occur in
|
||||
[variable declarations](variables.md) or [function declarations](functions.md).
|
||||
[variable declarations](values.md#binding-patterns-and-local-variables-with-let-and-var)
|
||||
or [function declarations](functions.md).
|
||||
|
||||
At present, type inference is very simple: given the expression which generates
|
||||
the value to be used for type inference, the inferred type is the precise type
|
||||
@@ -30,7 +31,8 @@ of that expression. For example, the inferred type for `auto` in
|
||||
`fn Foo(x: i64) -> auto { return x; }` is `i64`.
|
||||
|
||||
Type inference is currently supported for [function return types](functions.md)
|
||||
and [declared variable types](variables.md).
|
||||
and
|
||||
[declared variable types](values.md#binding-patterns-and-local-variables-with-let-and-var).
|
||||
|
||||
## Open questions
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,76 +0,0 @@
|
||||
# Variables
|
||||
|
||||
<!--
|
||||
Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
||||
Exceptions. See /LICENSE for license information.
|
||||
SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
-->
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
## Table of contents
|
||||
|
||||
- [Overview](#overview)
|
||||
- [Notes](#notes)
|
||||
- [Global variables](#global-variables)
|
||||
- [Alternatives considered](#alternatives-considered)
|
||||
- [References](#references)
|
||||
|
||||
<!-- tocstop -->
|
||||
|
||||
## Overview
|
||||
|
||||
Carbon's local variable syntax is:
|
||||
|
||||
- `var` _identifier_`:` _< expression |_ `auto` _> [_ `=` _value ]_`;`
|
||||
|
||||
Blocks introduce nested scopes and can contain local variable declarations that
|
||||
work similarly to function parameters.
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
fn Foo() {
|
||||
var x: i32 = 42;
|
||||
}
|
||||
```
|
||||
|
||||
This introduces a local variable named `x` into the block's scope. It has the
|
||||
type `Int` and is initialized with the value `42`. These variable declarations
|
||||
(and function declarations) have a lot more power than what we're covering just
|
||||
yet, but this gives you the basic idea.
|
||||
|
||||
If `auto` is used in place of the type, [type inference](type_inference.md) is
|
||||
used to automatically determine the variable's type.
|
||||
|
||||
While there can be global constants, there are no global variables.
|
||||
|
||||
## Notes
|
||||
|
||||
> TODO: Constant syntax is an ongoing discussion.
|
||||
|
||||
### Global variables
|
||||
|
||||
We are exploring several different ideas for how to design less bug-prone
|
||||
patterns to replace the important use cases programmers still have for global
|
||||
variables. We may be unable to fully address them, at least for migrated code,
|
||||
and be forced to add some limited form of global variables back. We may also
|
||||
discover that their convenience outweighs any improvements afforded.
|
||||
|
||||
## Alternatives considered
|
||||
|
||||
- [No `var` introducer keyword](/proposals/p0339.md#no-var-introducer-keyword)
|
||||
- [Name of the `var` statement introducer](/proposals/p0339.md#name-of-the-var-statement-introducer)
|
||||
- [Colon between type and identifier](/proposals/p0339.md#colon-between-type-and-identifier)
|
||||
- [Type elision](/proposals/p0339.md#type-elision)
|
||||
- [Type ordering](/proposals/p0618.md#type-ordering)
|
||||
- [Elide the type instead of using `auto`](/proposals/p0851.md#elide-the-type-instead-of-using-auto)
|
||||
|
||||
## References
|
||||
|
||||
- Proposal
|
||||
[#339: `var` statement](https://github.com/carbon-language/carbon-lang/pull/339)
|
||||
- Proposal
|
||||
[#618: `var` ordering](https://github.com/carbon-language/carbon-lang/pull/618)
|
||||
- Proposal
|
||||
[#851: auto keyword for vars](https://github.com/carbon-language/carbon-lang/pull/851)
|
||||
+1020
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user