Skip to content

Commit dd4deb6

Browse files
josh11bwolffgchandlerc
authored
Redo introduction of design overview (#2017)
Previous overview is changed to an introduction that includes a modified first example, and adding a brief tour of Carbon in the form of an explanation of the features demonstrated in that example. Also update to reflect that we expect `Print` to be available in some package imported by default, which we are currently calling `Carbon`. Co-authored-by: Wolff Dobson <[email protected]> Co-authored-by: Chandler Carruth <[email protected]>
1 parent 9572a33 commit dd4deb6

File tree

1 file changed

+223
-38
lines changed

1 file changed

+223
-38
lines changed

docs/design/README.md

Lines changed: 223 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
1313

1414
## Table of contents
1515

16-
- [Overview](#overview)
16+
- [Introduction](#introduction)
1717
- [This document is provisional](#this-document-is-provisional)
18-
- [Hello, Carbon](#hello-carbon)
18+
- [Tour of the basics](#tour-of-the-basics)
1919
- [Code and comments](#code-and-comments)
2020
- [Build modes](#build-modes)
2121
- [Types are values](#types-are-values)
@@ -120,7 +120,7 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
120120

121121
<!-- tocstop -->
122122

123-
## Overview
123+
## Introduction
124124

125125
This documentation describes the design of the Carbon language, and the
126126
rationale for that design. This documentation is an overview of the Carbon
@@ -139,37 +139,201 @@ design have things that have not been decided through the Carbon process. This
139139
preliminary material fills in gaps until aspects of the design can be filled in.
140140
Features that are provisional have been marked as such on a best-effort basis.
141141

142-
## Hello, Carbon
142+
### Tour of the basics
143143

144144
Here is a simple function showing some Carbon code:
145145

146146
```carbon
147-
import Console;
147+
import Math;
148148
149-
// Prints the Fibonacci numbers less than `limit`.
150-
fn Fibonacci(limit: i64) {
151-
var (a: i64, b: i64) = (0, 1);
152-
while (a < limit) {
153-
Console.Print(a, " ");
154-
let next: i64 = a + b;
155-
a = b;
156-
b = next;
149+
// Returns the smallest factor of `n` > 1, and
150+
// whether `n` itself is prime.
151+
fn SmallestFactor(n: i32) -> (i32, bool) {
152+
let limit: i32 = Math.Sqrt(n) as i32;
153+
var i: i32 = 2;
154+
while (i <= limit) {
155+
let remainder: i32 = n % i;
156+
if (remainder == 0) {
157+
Carbon.Print("{0} is a factor of {1}", i, n);
158+
return (i, false);
159+
}
160+
if (i == 2) {
161+
i = 3;
162+
} else {
163+
// Skip even numbers once we get past `2`.
164+
i += 2;
165+
}
157166
}
158-
Console.Print("\n");
167+
return (n, true);
159168
}
160169
```
161170

162171
Carbon is a language that should feel familiar to C++ and C developers. This
163172
example has familiar constructs like [imports](#imports),
164-
[function definitions](#functions), [typed arguments](#binding-patterns), and
165-
[curly braces](#blocks-and-statements).
173+
[comments](#code-and-comments), [function definitions](#functions),
174+
[typed arguments](#binding-patterns), and [expressions](#expressions).
175+
[Statements](#blocks-and-statements) and
176+
[declarations](#declarations-definitions-and-scopes) are terminated with a `;`
177+
or something in curly braces `{`...`}`.
166178

167179
A few other features that are unlike C or C++ may stand out. First,
168180
[declarations](#declarations-definitions-and-scopes) start with introducer
169181
keywords. `fn` introduces a function declaration, and `var` introduces a
170-
[variable declaration](#variable-var-declarations). You can also see a
171-
[_tuple_](#tuples), a composite type written as a comma-separated list inside
172-
parentheses. Unlike, say, Python, these types are strongly-typed as well.
182+
[variable declaration](#variable-var-declarations).
183+
184+
The example starts with an [`import` declaration](#imports). Carbon imports are
185+
more like [C++ modules](https://en.cppreference.com/w/cpp/language/modules) than
186+
[textual inclusion during preprocessing using `#include`](https://en.cppreference.com/w/cpp/preprocessor/include).
187+
The `import` declaration imports a
188+
[library from a package](#files-libraries-packages). It must appear at the top
189+
of a Carbon source file, the first thing after the
190+
[optional `package` declaration](#package-declaration). Libraries can optionally
191+
be split into [api and implementation files](#files-libraries-packages), like
192+
C++'s header and source files but without requiring a source file in any cases.
193+
This declaration from the example:
194+
195+
```carbon
196+
import Math;
197+
```
198+
199+
imports the default library from package `Math`. The names from this library are
200+
accessible as members of `Math`, like `Math.Sqrt`. The `Carbon.Print` function
201+
comes from the `Carbon` package's prelude library which is
202+
[imported by default](#name-lookup-for-common-types). Unlike C++, the namespaces
203+
of different packages are kept separate, so there are no name conflicts.
204+
205+
Carbon [comments](#code-and-comments) must be on a line by themselves starting
206+
with `//`:
207+
208+
```carbon
209+
// Returns the smallest factor of `n` > 1, and
210+
// whether `n` itself is prime.
211+
...
212+
// Skip even numbers once we get past `2`.
213+
```
214+
215+
A [function definition](#functions) consists of:
216+
217+
- the `fn` keyword introducer,
218+
- the function's name,
219+
- a parameter list in round parens `(`...`)`,
220+
- an optional `->` and return type, and
221+
- a body inside curly braces `{`...`}`.
222+
223+
```carbon
224+
fn SmallestFactor(n: i32) -> (i32, bool) {
225+
...
226+
return (i, false);
227+
...
228+
return (n, true);
229+
}
230+
```
231+
232+
The body of the function is an ordered sequence of
233+
[statements](#blocks-and-statements) and
234+
[declarations](#declarations-definitions-and-scopes). Function execution ends
235+
when it reaches a `return` statement or the end of the function body. `return`
236+
statements can also specify an expression whose value is returned.
237+
238+
Here `i32` refers to a signed [integer type](#integer-types), with 32 bits, and
239+
`bool` is the [boolean type](#bool). Carbon also has
240+
[floating-point types](#floating-point-types) like `f32` and `f64`, and
241+
[string types](#string-types).
242+
243+
A [variable declaration](#variable-var-declarations) has three parts:
244+
245+
- the `var` keyword introducer,
246+
- the name followed by a `:` and a type, declared the same way as a parameter
247+
in a function signature, and
248+
- an optional initializer.
249+
250+
```carbon
251+
var i: i32 = 2;
252+
```
253+
254+
You can modify the value of a variable with an
255+
[assignment statement](#assignment-statements):
256+
257+
```carbon
258+
i = 3;
259+
...
260+
i += 2;
261+
```
262+
263+
[Constants are declared](#constant-let-declarations) with the `let` keyword
264+
introducer. The syntax parallels variable declarations except the initializer is
265+
required:
266+
267+
```carbon
268+
let limit: i32 = Math.Sqrt(n) as i32;
269+
...
270+
let remainder: i32 = n % i;
271+
```
272+
273+
The initializer `Math.Sqrt(n) as i32` is an [expression](#expressions). It first
274+
calls the `Math.Sqrt` function with `n` as the argument. Then, the `as` operator
275+
casts the floating-point return value to `i32`. Lossy conversions like that must
276+
be done explicitly.
277+
278+
Other expressions include `n % i`, which applies the binary `%` modulo operator
279+
with `n` and `i` as arguments, and `remainder == 0`, which applies the `==`
280+
comparison operator producing a `bool` result. Expression return values are
281+
ignored when expressions are used as statements, as in this call to the
282+
`Carbon.Print` function:
283+
284+
```carbon
285+
Carbon.Print("{0} is a factor of {1}", i, n);
286+
```
287+
288+
Function calls consist of the name of the function followed by the
289+
comma-separated argument list in round parentheses `(`...`)`.
290+
291+
Control flow statements, including `if`, `while`, `for`, `break`, and
292+
`continue`, change the order that statements are executed, as they do in C++:
293+
294+
```carbon
295+
while (i <= limit) {
296+
...
297+
if (remainder == 0) {
298+
...
299+
}
300+
if (i == 2) {
301+
...
302+
} else {
303+
...
304+
}
305+
}
306+
```
307+
308+
Every code block in curly braces `{`...`}` defines a scope. Names are visible
309+
from their declaration until the end of innermost scope containing it. So
310+
`remainder` in the example is visible until the curly brace `}` that closes the
311+
`while`.
312+
313+
The example function uses a [_tuple_](#tuples), a
314+
[composite type](#composite-types), to return multiple values. Both tuple values
315+
and types are written using a comma-separated list inside parentheses. So
316+
`(i, false)` and `(n, true)` are tuple values, and `(i32, bool)` is their type.
317+
318+
[Struct types](#struct-types) are similar, except their members are referenced
319+
by name instead of position. The example could be changed to use structs instead
320+
as follows:
321+
322+
```carbon
323+
// Return type of `{.factor: i32, .prime: bool}` is a struct
324+
// with an `i32` field named `.factor`, and a `bool` field
325+
// named `.prime`.
326+
fn SmallestFactor(n: i32) -> {.factor: i32, .prime: bool} {
327+
...
328+
if (remainder == 0) {
329+
// Return a struct value.
330+
return {.factor = i, .prime = false};
331+
}
332+
...
333+
// Return a struct value.
334+
return {.factor = n, .prime = true};
335+
}
336+
```
173337

174338
## Code and comments
175339

@@ -190,7 +354,7 @@ required to be the only non-whitespace on the line.
190354
> References:
191355
>
192356
> - [Source files](code_and_name_organization/source_files.md)
193-
> - [lexical conventions](lexical_conventions)
357+
> - [Lexical conventions](lexical_conventions)
194358
> - Proposal
195359
> [#142: Unicode source files](https://github.com/carbon-language/carbon-lang/pull/142)
196360
> - Proposal
@@ -213,10 +377,26 @@ The behavior of the Carbon compiler depends on the _build mode_:
213377

214378
Expressions compute values in Carbon, and these values are always strongly typed
215379
much like in C++. However, an important difference from C++ is that types are
216-
themselves modeled as values; specifically, compile-time constant values. This
217-
means that the grammar for writing a type is the [expression](#expressions)
218-
grammar. Expressions written where a type is expected must be able to be
219-
evaluated at compile-time and must evaluate to a type value.
380+
themselves modeled as values; specifically, compile-time-constant values. This
381+
has a number of consequences:
382+
383+
- Names for types are in the same namespace shared with functions, variables,
384+
namespaces, and so on.
385+
- The grammar for writing a type is the [expression](#expressions) grammar,
386+
not a separate grammar for types. As a result, Carbon doesn't use angle
387+
brackets `<`...`>` in types, since `<` and `>` are used for comparison in
388+
expressions.
389+
- Function call syntax is used to specify parameters to a type, like
390+
`HashMap(String, i64)`.
391+
392+
Some values, such as `()` and `{}`, may even be used as types, but only act like
393+
types when they are in a type position, like after a `:` in a variable
394+
declaration or the return type after a `->` in a function declaration. Any
395+
expression in a type position must be
396+
[a constants or symbolic value](#value-categories-and-value-phases) so the
397+
compiler can resolve whether the value can be used as a type. This also puts
398+
limits on how much operators can do different things for types. This is good for
399+
consistency, but is a significant restriction on Carbon's design.
220400

221401
## Primitive types
222402

@@ -567,7 +747,7 @@ Elements of an array may be accessed using square brackets (`[`...`]`), as in
567747

568748
```carbon
569749
a[i] = 2;
570-
Console.Print(a[0]);
750+
Carbon.Print(a[0]);
571751
```
572752

573753
> **TODO:** Slices
@@ -689,9 +869,11 @@ are two kinds of patterns:
689869
- _Irrefutable_ patterns are guaranteed to match, so long as the code
690870
type-checks.
691871

692-
Irrefutable patterns are used in [function parameters](#functions),
872+
In the [introduction](#tour-of-the-basics), [function parameters](#functions),
693873
[variable `var` declarations](#variable-var-declarations), and
694-
[constant `let` declarations](#constant-let-declarations).
874+
[constant `let` declarations](#constant-let-declarations) use a "name `:` type"
875+
construction. That construction is an example of an irrefutable pattern, and in
876+
fact any irrefutable pattern may be used in those positions.
695877
[`match` statements](#match) can include both refutable patterns and irrefutable
696878
patterns.
697879

@@ -1051,11 +1233,11 @@ For example:
10511233

10521234
```carbon
10531235
if (fruit.IsYellow()) {
1054-
Console.Print("Banana!");
1236+
Carbon.Print("Banana!");
10551237
} else if (fruit.IsOrange()) {
1056-
Console.Print("Orange!");
1238+
Carbon.Print("Orange!");
10571239
} else {
1058-
Console.Print("Vegetable!");
1240+
Carbon.Print("Vegetable!");
10591241
}
10601242
```
10611243

@@ -1084,10 +1266,10 @@ example, this prints `0`, `1`, `2`, then `Done!`:
10841266
```carbon
10851267
var x: i32 = 0;
10861268
while (x < 3) {
1087-
Console.Print(x);
1269+
Carbon.Print(x);
10881270
++x;
10891271
}
1090-
Console.Print("Done!");
1272+
Carbon.Print("Done!");
10911273
```
10921274

10931275
> References:
@@ -1103,7 +1285,7 @@ example, this prints each `String` value in `names`:
11031285

11041286
```carbon
11051287
for (var name: String in names) {
1106-
Console.Print(name);
1288+
Carbon.Print(name);
11071289
}
11081290
```
11091291

@@ -1123,7 +1305,7 @@ processed):
11231305
```carbon
11241306
for (var step: Step in steps) {
11251307
if (step.IsManual()) {
1126-
Console.Print("Reached manual step!");
1308+
Carbon.Print("Reached manual step!");
11271309
break;
11281310
}
11291311
step.Process();
@@ -1152,7 +1334,7 @@ while (!f.EOF()) {
11521334
if (line.IsEmpty()) {
11531335
continue;
11541336
}
1155-
Console.Print(line);
1337+
Carbon.Print(line);
11561338
}
11571339
```
11581340

@@ -1181,7 +1363,7 @@ fn PrintFirstN(n: i32) {
11811363
// executed after a `return`.
11821364
return;
11831365
}
1184-
Console.Print(i);
1366+
Carbon.Print(i);
11851367
}
11861368
}
11871369
```
@@ -2021,7 +2203,7 @@ class C {
20212203
// ✅ Allowed: unambiguous
20222204
C.F();
20232205
// ❌ Error: ambiguous whether `P` means
2024-
// `package.P` or `package.P.F`.
2206+
// `package.P` or `package.C.P`.
20252207
P.H();
20262208
// ✅ Allowed
20272209
package.P.H();
@@ -2266,6 +2448,9 @@ imported automatically into every `api` file. Dedicated type literal syntaxes
22662448
like `i32` and `bool` refer to types defined within this package, based on the
22672449
["all APIs are library APIs" principle](/docs/project/principles/library_apis_only.md).
22682450

2451+
> **TODO:** Prelude provisionally imports the `Carbon` package which includes
2452+
> common facilities, like `Print` and the interfaces for operator overloading.
2453+
22692454
> References:
22702455
>
22712456
> - [Name lookup](name_lookup.md)
@@ -2420,7 +2605,7 @@ class Circle {
24202605
24212606
impl as Printable {
24222607
fn Print[me: Self]() {
2423-
Console.WriteLine("Circle with radius: {0}", me.radius);
2608+
Carbon.Print("Circle with radius: {0}", me.radius);
24242609
}
24252610
}
24262611
}

0 commit comments

Comments
 (0)