Skip to content

Commit

Permalink
Additional documentation for the Sway book. (FuelLabs#478)
Browse files Browse the repository at this point in the history
* Add custom types documentation and update roadmap.

* Add information on the turbofish; format markdown

* Updating sway types & rename colored coins. (FuelLabs#481)

* Update Address and ContractID types

* Rename colored coins

* Cleanup markdown

* Move Address and ContractId types to new book section

* Update SUMMARY.md

* Remove colored-coins

* Fixup

* Update docs/src/advanced/generic_types.md

Co-authored-by: John Adler <adlerjohn@users.noreply.github.com>

* Update docs/src/advanced/generic_types.md

Co-authored-by: John Adler <adlerjohn@users.noreply.github.com>

* More doc updates (FuelLabs#501)

* fmt

* New language server.

* Add basics page index.

* Index updates.

* Update index.

* Update readme.

* Update install docs.

* Clean up Forc project intro.

* Skeleton for why sway.

* Fix location of Cargo.toml. (FuelLabs#502)

* WIP storage docs

* docs on reference types and purity: wip

Co-authored-by: Nick Furfaro <nfurfaro33@gmail.com>
Co-authored-by: John Adler <adlerjohn@users.noreply.github.com>
  • Loading branch information
3 people authored Dec 28, 2021
1 parent 6933c95 commit b42d016
Show file tree
Hide file tree
Showing 28 changed files with 522 additions and 58 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@ Sway is a language developed for the Fuel blockchain. It is heavily inspired by

## Documentation

For user documentation, see the Sway Book: <https://fuellabs.github.io/sway/latest/>.
For user documentation, including installing release builds, see the Sway Book: <https://fuellabs.github.io/sway/latest/>.

## Building from Source

This section is for developing the Sway compiler and toolchain. For developing contracts and using Sway, see the above documentation section.

### Dependencies

Sway is built in Rust. To begin, install the Rust toolchain following instructions at <https://www.rust-lang.org/tools/install>. Then configure your Rust toolchain to use Rust `stable`:
Expand All @@ -29,7 +31,7 @@ export PATH="${HOME}/.cargo/bin:${PATH}"

To ensure access to all dependent repositories, [create](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent) and [add](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/adding-a-new-ssh-key-to-your-github-account) SSH keys to your GitHub account.

### Building Sway
### Building Forc

Clone the repository and build the Sway toolchain:

Expand All @@ -51,6 +53,4 @@ To run `forc` from any directory, install `forc` to your local Cargo bin directo

```sh
cargo install --locked --path forc
# Also install sway-server if using the IDE plugin
cargo install --locked --path sway-server
```
19 changes: 13 additions & 6 deletions docs/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,35 @@
- [Installation](./getting-started/installation.md)
- [The Sway Toolchain](./getting-started/sway-toolchain.md)
- [A Forc Project](./getting-started/forc_project.md)
- [Why Sway?](./getting-started/why_sway.md)
- [Examples](./examples/index.md)
- [Subcurrency](./examples/subcurrency.md)
- [FizzBuzz](./examples/fizzbuzz.md)
- [Wallet Smart Contract](./examples/wallet_smart_contract.md)
- [New Concepts](./new-concepts/index.md)
- [Identifiers](./new-concepts/identifiers.md)
- [Colored Coins](./new-concepts/colored-coins.md)
- [UTXOs](./new-concepts/utxos.md)
- [Basics](./basics/index.md)
- [Project Structure](./basics/project_structure.md)
- [Variables](./basics/variables.md)
- [Data Types](./basics/types.md)
- [Built-in Types](./basics/built_in_types.md)
- [Custom Types](./basics/custom_types.md)
- [Blockchain Types](./basics/blockchain_types.md)
- [Functions](./basics/functions.md)
- [Reference Types](./basics/reference_types.md)
- [Sway on the Chain](./sway-on-chain/index.md)
- [Smart Contracts](./sway-on-chain/smart_contracts.md)
- [Scripts](./sway-on-chain/scripts.md)
- [Predicates](./sway-on-chain/predicates.md)
- [Smart Contract Development](./smart-contract-development/index.md)
- [Contract Storage](./smart-contract-development/storage.md)
- [Function Purity](./smart-contract-development/purity.md)
- [Advanced Concepts](./advanced/index.md)
- [Generic Types](./advanced/generic_types.md)
- [Traits](./advanced/traits.md)
- [Trait Constraints](./advanced/trait_constraints.md)
- [Assembly](./advanced/assembly.md)
- [Conventions](./style/index.md)
- [Capitalization](./style/capitalization.md)
- [Strategy and Roadmap](./strategy/strategy_and_roadmap.md)
- [New Concepts](./new-concepts/index.md)
- [Identifiers](./new-concepts/identifiers.md)
- [Native Assets](./new-concepts/native-assets.md)
- [UTXOs](./new-concepts/utxos.md)
- [Language Strategy and Roadmap](./strategy/strategy_and_roadmap.md)
40 changes: 34 additions & 6 deletions docs/src/advanced/generic_types.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# Generic Types
_N.B.: Generic types in Sway are a work in progress, and are currently only partially implemented._

## Basics
## Basics

In Sway, generic types follow a very similar pattern to those in Rust. Let's look as some example syntax,
starting with a generic function:
Expand All @@ -15,15 +14,15 @@ fn noop<T>(argument: T) -> T {
Here, the `noop()` function trivially returns exactly what was given to it. `T` is a _type parameter_, and it saying
that this function exists for all types T. More formally, this function could be typed as:

```
```math
noop :: ∀T. T -> T
```

Generic types are a way to refer to types _in general_, meaning without specifying a single type. Clearly, our `noop` function
would work with any type in the language, so we don't need to specify `noop(argument: u8) -> u8`, `noop(argument: u16) -> u16`, etc.


## Code Generation

One question that arises when dealing with generic types is: how does the assembly handle this? There are a few approaches to handling
generic types at the lowest level. Sway uses a technique called [monomorphization](https://en.wikipedia.org/wiki/Monomorphization). This
means that the generic function is compiled to a non-generic version for every type it is called on. In this way, generic functions are
Expand All @@ -43,7 +42,8 @@ fn successor<T>(argument: T)
```

Run `forc build`, and you will get:
```

```sway
.. |
9 | where T: Add
10 | {
Expand Down Expand Up @@ -75,10 +75,11 @@ fn successor<T>(argument: T)
argument + ~T::incrementor()
}
```
_(There's a little bit of new syntax here. When directly referring to a type to execute a method from it, a tilde (`~`) is used, This may change in the future.)_

_(There's a little bit of new syntax here. When directly referring to a type to execute a method from it, a tilde (`~`) is used. This may change in the future.)_

## Generic Structs and Enums

Just like functions, structs and enums can be generic. Let's take a look at the standard library version of `Option<T>`:

```sway
Expand All @@ -98,10 +99,37 @@ enum Result<T, E> {
```

Both generic enums and generic structs can be trait constrained, as well. Consider this struct:

```sway
struct Foo<T>
where T: Add
{
field_one: T
}
```

## Type Arguments

Similar to Rust, Sway has what is colloquially known as the [turbofish](https://github.com/rust-lang/rust/blob/e98309298d927307c5184f4869604bd068d26183/src/test/ui/parser/bastion-of-the-turbofish.rs). The turbofish looks like this: `::<>` (see the little fish with bubbles behind it?). The turbofish is used to annotate types in a generic context. Say you have the following function:

```sway
fn foo<T, E>(t: T) -> Result<T, E> {
Result::Ok(t)
}
```

In this code example, which is admittedly asinine, you can't possibly know what type `E` is. You'd need to provide the type manually, with a turbofish:

```sway
fn foo<T, E>(t: T) -> Result<T, E> {
Result::<T, MyErrorType>::Ok(t)
}
```

It is also common to see the turbofish used on the function itself:

```sway
fn main() {
foo::<Bar, Baz>()
}
```
5 changes: 4 additions & 1 deletion docs/src/advanced/index.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Advanced Concepts

Advanced concepts.

- [Generic Types](./generic_types.md)
- [Traits](./generic_types.md)
- [Traits](./traits.md)
- [Trait Constraints](./trait_constraints.md)
- [Assembly](./assembly.md)
2 changes: 2 additions & 0 deletions docs/src/advanced/trait_constraints.md
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
# Trait Constraints

Trait constraints on generics are currently a work in progress.
39 changes: 39 additions & 0 deletions docs/src/basics/blockchain_types.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Blockchain Types

Sway has a selection of types provided via the standard library (`lib-std`) which both add a degree of type-safety, as well as make the intention of the developer more clear.

## Address type

The `Address` type is a type-safe wrapper around the primitive `b256` type. Unlike Ethereum, an address **never** refers to a deployed smart contract (see the `ContractId` type below). An `Address` can be either the hash of a public key (An Externally Owned Address if you're coming from Ethereum) or the hash of a [predicate](../sway-on-chain/predicates.md).

```sway
pub struct Address {
value: b256,
}
```

Casting between the `b256` & `Address` types must be done explicitly:

```sway
let my_number: b256 = 0x000000000000000000000000000000000000000000000000000000000000002A;
let my_address: Address = ~Address::from(my_number);
let forty_two: b256 = my_address.into();
```

## ContractId type

The `ContractId` type is a type-safe wrapper around the primitive `b256` type. A contract's id is a unique, deterministic identifier analogous to a contract's address on Ethereum.

```sway
pub struct ContractId {
value: b256,
}
```

Casting between the `b256` & `ContractId` types must be done explicitly:

```sway
let my_number: b256 = 0x000000000000000000000000000000000000000000000000000000000000002A;
let my_contract_id: ContractId = ~ContractId::from(my_number);
let forty_two: b256 = my_contract_id.into();
```
65 changes: 61 additions & 4 deletions docs/src/basics/types.md → docs/src/basics/built_in_types.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Types
# Built-in Types

Every value in Sway is of a certain type. Although, deep down, all values are just ones and zeroes in silicon, Sway needs to know what those ones and zeroes actually mean. This is accomplished with _types_.

Expand Down Expand Up @@ -58,7 +58,64 @@ let my_string: str[4] = "fuel";

Because the string literal `"fuel"` is four letters, the type is `str[4]`, denoting a static length of 4 characters. Strings default to UTF-8 in Sway.

## Address type
## Compound Types

In Sway, the Address type is a type-safe wrapper around the primitive b256 type.
(as of now, not yet implemented)
_Compound types_ are types which group multiple values into one type. In Sway, we have arrays and tuples.

## Tuple Types

_note: tuples are a work in progress and are tracked by [this PR](https://github.com/FuelLabs/sway/pull/399)_
A tuple is a general-purpose static-length aggregation of types. In more plain terms, a tuple is a single type which consists of an aggregate of zero or more types. The internal types that make up a tuple, and the tuple's cardinality, define the tuple's type. Let's take a look at some examples.

```sway
let x: (u64, u64) = (0, 0);
```

This is a tuple, denoted by parenthesized, comma-separated values. Note that the type annotation, `(u64, u64)`, is similar in syntax to the expression which instantiates that type, `(0, 0)`.

```sway
let x: (u64, bool) = (42, true);
assert(x.1)
```

In this example, we have created a new tuple type, `(u64, bool)`, which is a composite of a `u64` and a `bool`. To access a value within a tuple, we use _tuple indexing_: `x.1` stands for the first (zero-indexed, so the `bool`) value of the tuple. Likewise, `x.0` would be the zeroeth, `u64` value of the tuple. Tuple values can also be accessed via destructuring:

```sway
struct Foo {}
let x: (u64, Foo, bool) = (42, Foo {}, true);
let (number, foo, boolean) = x;
```

## Arrays

An array is similar to a tuple, but an array's values must all be of the same type. An array is written as a comma-separated list inside square brackets:

```sway
let x = [1, 2, 3, 4, 5];
```

Arrays are allocated on the stack since their size is known. An array's size is _always_ static, i.e. it cannot change. An array of five elements cannot become an array of six elements.

Arrays can be iterated over, unlike tuples. A common use case for arrays is checking set membership. If you are given a name, and you'd like to figure out if that name is included in your list of classmates, you can use an array:

```sway
let name = /* some user input */;
let classmates = ["Bob", "Jan", "Ron"];
assert(classmates.contains(name));
```

An array's type is written as the type the array contains followed by the numer of elements, semicolon-separated and within square brackets.

```sway
let x: [u64; 5] = [0, 1, 2, 3, 4];
```

To access an element in an array, use _array indexing syntax_:

```sway
let x: [bool; 2] = [true, false];
assert(x[0]);
```

Note that arrays are zero-indexed, just like tuples.
Loading

0 comments on commit b42d016

Please sign in to comment.