Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 17 additions & 18 deletions docs/design/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1767,16 +1767,16 @@ class Point {
return Math.Sqrt(dx * dx + dy * dy);
}
// Mutating method declaration
fn Offset[addr self: Self*](dx: i32, dy: i32);
fn Offset[ref self: Self](dx: i32, dy: i32);

var x: i32;
var y: i32;
}

// Out-of-line definition of method declared inline
fn Point.Offset[addr self: Self*](dx: i32, dy: i32) {
self->x += dx;
self->y += dy;
fn Point.Offset[ref self: Self](dx: i32, dy: i32) {
self.x += dx;
self.y += dy;
}

var origin: Point = {.x = 0, .y = 0};
Expand All @@ -1796,10 +1796,9 @@ two methods `Distance` and `Offset`:
- `Distance` computes and returns the distance to another point, without
modifying the `Point`. This is signified using `[self: Self]` in the method
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 [non-`const`](#const) address of `origin`, it may
only be called on [reference expressions](#expression-categories).
- `origin.Offset(`...`)` _does_ modify the value of `origin`. This is
signified using `[ref self: Self]` in the method declaration. 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`.

Expand Down Expand Up @@ -1955,7 +1954,7 @@ names resolvable by the compiler, and don't act like forward declarations.

A destructor for a class is custom code executed when the lifetime of a value of
that type ends. They are defined with `fn destroy` followed by either
`[self: Self]` or `[addr self: Self*]` (as is done with [methods](#methods)) and
`[self: Self]` or `[ref self: Self]` (as is done with [methods](#methods)) and
the block of code in the class definition, as in:

```carbon
Expand All @@ -1969,7 +1968,7 @@ or:
```carbon
class MyClass {
// Can modify `self` in the body.
fn destroy[addr self: Self*]() { ... }
fn destroy[ref self: Self]() { ... }
}
```

Expand Down Expand Up @@ -2004,8 +2003,8 @@ For every type `MyClass`, there is the type `const MyClass` such that:
has type `const T`.
- 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.
is a subset of `MyClass`, because only `ref` 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)*`.
Expand Down Expand Up @@ -2996,8 +2995,8 @@ associated constant to represent the type of elements stored in the stack.
```
interface StackInterface {
let ElementType:! Movable;
fn Push[addr self: Self*](value: ElementType);
fn Pop[addr self: Self*]() -> ElementType;
fn Push[ref self: Self](value: ElementType);
fn Pop[ref self: Self]() -> ElementType;
fn IsEmpty[self: Self]() -> bool;
}
```
Expand All @@ -3008,14 +3007,14 @@ for the `ElementType` member of the interface using a `where` clause:
```carbon
class IntStack {
extend impl as StackInterface where .ElementType = i32 {
fn Push[addr self: Self*](value: i32);
fn Push[ref self: Self](value: i32);
// ...
}
}

class FruitStack {
extend impl as StackInterface where .ElementType = Fruit {
fn Push[addr self: Self*](value: Fruit);
fn Push[ref self: Self](value: Fruit);
// ...
}
}
Expand Down Expand Up @@ -3043,8 +3042,8 @@ values of any type `T`:

```carbon
class Stack(T:! type) {
fn Push[addr self: Self*](value: T);
fn Pop[addr self: Self*]() -> T;
fn Push[ref self: Self](value: T);
fn Pop[ref self: Self]() -> T;

var storage: Array(T);
}
Expand Down
33 changes: 16 additions & 17 deletions docs/design/assignment.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,8 @@ standard library.
## Syntax

The operands of these operators can be any [expression](expressions/README.md).
However, the first operand must be modifiable because it is passed to an
`[addr self: Self*]` parameter, which disallows most expression forms other
than:
However, the first operand must be modifiable because it is passed to a
`[ref self: Self]` parameter, which disallows most expression forms other than:

- The name of a `var` binding.
- A dereference of a pointer.
Expand Down Expand Up @@ -175,7 +174,7 @@ provided for built-in types as necessary to give the semantics described above.
```
// Simple `=`.
interface AssignWith(U:! type) {
fn Op[addr self: Self*](other: U);
fn Op[ref self: Self](other: U);
}
constraint Assign { extend AssignWith(Self); }
```
Expand All @@ -189,48 +188,48 @@ Given `var x: T` and `y: U`:
```
// Compound `+=`.
interface AddAssignWith(U:! type) {
fn Op[addr self: Self*](other: U);
fn Op[ref self: Self](other: U);
}
constraint AddAssign { extend AddAssignWith(Self); }
```

```
// Compound `-=`.
interface SubAssignWith(U:! type) {
fn Op[addr self: Self*](other: U);
fn Op[ref self: Self](other: U);
}
constraint SubAssign { extend SubAssignWith(Self); }
```

```
// Compound `*=`.
interface MulAssignWith(U:! type) {
fn Op[addr self: Self*](other: U);
fn Op[ref self: Self](other: U);
}
constraint MulAssign { extend MulAssignWith(Self); }
```

```
// Compound `/=`.
interface DivAssignWith(U:! type) {
fn Op[addr self: Self*](other: U);
fn Op[ref self: Self](other: U);
}
constraint DivAssign { extend DivAssignWith(Self); }
```

```
// Compound `%=`.
interface ModAssignWith(U:! type) {
fn Op[addr self: Self*](other: U);
fn Op[ref self: Self](other: U);
}
constraint ModAssign { extend ModAssignWith(Self); }
```

```
// Increment `++`.
interface Inc { fn Op[addr self: Self*](); }
interface Inc { fn Op[ref self: Self](); }
// Decrement `++`.
interface Dec { fn Op[addr self: Self*](); }
interface Dec { fn Op[ref self: Self](); }
```

Given `var x: T` and `y: U`:
Expand All @@ -248,39 +247,39 @@ Given `var x: T` and `y: U`:
```
// Compound `&=`.
interface BitAndAssignWith(U:! type) {
fn Op[addr self: Self*](other: U);
fn Op[ref self: Self](other: U);
}
constraint BitAndAssign { extend BitAndAssignWith(Self); }
```

```
// Compound `|=`.
interface BitOrAssignWith(U:! type) {
fn Op[addr self: Self*](other: U);
fn Op[ref self: Self](other: U);
}
constraint BitOrAssign { extend BitOrAssignWith(Self); }
```

```
// Compound `^=`.
interface BitXorAssignWith(U:! type) {
fn Op[addr self: Self*](other: U);
fn Op[ref self: Self](other: U);
}
constraint BitXorAssign { extend BitXorAssignWith(Self); }
```

```
// Compound `<<=`.
interface LeftShiftAssignWith(U:! type) {
fn Op[addr self: Self*](other: U);
fn Op[ref self: Self](other: U);
}
constraint LeftShiftAssign { extend LeftShiftAssignWith(Self); }
```

```
// Compound `>>=`.
interface RightShiftAssignWith(U:! type) {
fn Op[addr self: Self*](other: U);
fn Op[ref self: Self](other: U);
}
constraint RightShiftAssign { extend RightShiftAssignWith(Self); }
```
Expand Down Expand Up @@ -310,7 +309,7 @@ This defaulting is accomplished by a parameterized implementation of
```
impl forall [U:! type, T:! OpWith(U) where .Self impls AssignWith(.Self.Result)]
T as OpAssignWith(U) {
fn Op[addr self: Self*](other: U) {
fn Op[ref self: Self](other: U) {
// Here, `$` is the operator described by `OpWith`.
*self = *self $ other;
}
Expand Down
33 changes: 16 additions & 17 deletions docs/design/classes.md
Original file line number Diff line number Diff line change
Expand Up @@ -903,14 +903,14 @@ class Circle {
fn Diameter[self: Self]() -> f32 {
return self.radius * 2;
}
fn Expand[addr self: Self*](distance: f32);
fn Expand[ref self: Self](distance: f32);

var center: Point;
var radius: f32;
}

fn Circle.Expand[addr self: Self*](distance: f32) {
self->radius += distance;
fn Circle.Expand[ref self: Self](distance: f32) {
self.radius += distance;
}

var c: Circle = {.center = Point.Origin(), .radius = 1.5 };
Expand All @@ -925,12 +925,11 @@ Assert(Math.Abs(c.Diameter() - 4.0) < 0.001);
the `Circle` instance. This is signified using `[self: Self]` in the method
declaration.
- `c.Expand(`...`)` does modify the value of `c`. This is signified using
`[addr self: Self*]` in the method declaration.
`[ref self: Self]` in the method declaration.

The pattern '`addr self:` _type_' means "first take the address of the argument,
which must be an
[l-value](<https://en.wikipedia.org/wiki/Value_(computer_science)#lrvalue>), and
then match pattern '`self:` _type_' against it".
The pattern '`ref self:` _type_' means "the argument must be a
[reference expression](/docs/design/values.md#reference-expressions), and must
match the pattern '`self:` _type_'".

If the method declaration also includes
[deduced compile-time parameters](/docs/design/generics/overview.md#deduced-parameters),
Expand Down Expand Up @@ -1585,7 +1584,7 @@ or:
```carbon
class MyClass {
// Can modify `self` in the body.
fn destroy[addr self: Self*]() { ... }
fn destroy[ref self: Self]() { ... }
}
```

Expand All @@ -1608,9 +1607,9 @@ Destructors may be declared in class scope and then defined out-of-line:

```carbon
class MyClass {
fn destroy[addr self: Self*]();
fn destroy[ref self: Self]();
}
fn MyClass.destroy[addr self: Self*]() { ... }
fn MyClass.destroy[ref self: Self]() { ... }
```

It is illegal to delete an instance of a derived class through a pointer to one
Expand All @@ -1622,12 +1621,12 @@ must be `override`:

```carbon
base class MyBaseClass {
virtual fn destroy[addr self: Self*]() { ... }
virtual fn destroy[ref self: Self]() { ... }
}

class MyDerivedClass {
extend base: MyBaseClass;
override fn destroy[addr self: Self*]() { ... }
override fn destroy[ref self: Self]() { ... }
}
```

Expand Down Expand Up @@ -1677,8 +1676,8 @@ call the `UnsafeDelete` method instead. Note that you may not call
```
interface Allocator {
// ...
fn Delete[T:! Deletable, addr self: Self*](p: T*);
fn UnsafeDelete[T:! Destructible, addr self: Self*](p: T*);
fn Delete[T:! Deletable, ref self: Self](p: T*);
fn UnsafeDelete[T:! Destructible, ref self: Self](p: T*);
}
```

Expand Down Expand Up @@ -1835,10 +1834,10 @@ base class MyBaseClass {

class MyDerivedClass {
extend base: MyBaseClass;
fn UsesProtected[addr self: Self*]() {
fn UsesProtected[ref self: Self]() {
// Can access protected members in derived class
var x: i32 = HelperClassFunction(3);
self->data = self->HelperMethod(x);
self.data = self.HelperMethod(x);
}
}
```
Expand Down
12 changes: 4 additions & 8 deletions docs/design/expressions/member_access.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ For example:
namespace Widgets;

interface Widgets.Widget {
fn Grow[addr self: Self*](factor: f64);
fn Grow[ref self: Self](factor: f64);
}

class Widgets.Cog {
Expand Down Expand Up @@ -765,19 +765,15 @@ If instance binding is performed:

- For a method, the result is a _bound method_, which is a value `F` such that
a function call `F(args)` behaves the same as a call to `M(args)` with the
`self` parameter initialized by a corresponding recipient argument:

- If the method declares its `self` parameter with `addr`, the recipient
argument is `&x`.
- Otherwise, the recipient argument is `x`.
`self` parameter initialized by `x`.

```carbon
class Blob {
fn Mutate[addr self: Self*](n: i32);
fn Mutate[ref self: Self](n: i32);
}
fn F(p: Blob*) {
// ✅ OK, forms bound method `((*p).M)` and calls it.
// This calls `Blob.Mutate` with `self` initialized by `&(*p)`
// This calls `Blob.Mutate` with `self` initialized by `*p`
// and `n` initialized by `5`.
(*p).Mutate(5);

Expand Down
4 changes: 2 additions & 2 deletions docs/design/generics/appendix-witness.md
Original file line number Diff line number Diff line change
Expand Up @@ -241,12 +241,12 @@ witness table.

```
interface Iterator {
fn Advance[addr self: Self*]();
fn Advance[ref self: Self]();
}

interface Container {
let IteratorType:! Iterator;
fn Begin[addr self: Self*]() -> IteratorType;
fn Begin[ref self: Self]() -> IteratorType;
}
```

Expand Down
Loading