Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
sbillig committed May 18, 2022
1 parent cfc6deb commit b86c21d
Show file tree
Hide file tree
Showing 36 changed files with 309 additions and 250 deletions.
3 changes: 1 addition & 2 deletions docs/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@
* [`break` Statement](spec/statements/break.md)
* [`continue` Statement](spec/statements/continue.md)
* [`assert` Statement](spec/statements/assert.md)
* [`pass` Statement](spec/statements/pass.md)
* [Expressions](spec/expressions/index.md)
* [Call expressions](spec/expressions/call.md)
* [Tuple expressions](spec/expressions/tuple.md)
Expand Down Expand Up @@ -80,4 +79,4 @@
* [Function calls](spec/function_calls.md)

* [Release Notes](release_notes.md)
* [Code of Conduct](code_of_conduct.md)
* [Code of Conduct](code_of_conduct.md)
15 changes: 8 additions & 7 deletions docs/src/quickstart/deploy_contract.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,17 @@ Let's recall that we finished our guest book in the previous chapter with the fo
```python
use std::context::Context

contract GuestBook:
contract GuestBook {
messages: Map<address, String<100>>

pub fn sign(self, ctx: Context, book_msg: String<100>):
self.messages[ctx.msg_sender()] = book_msg
pub fn sign(self, ctx: Context, book_msg: String<100>) {
self.messages[ctx.msg_sender()] = book_msg
}

pub fn get_msg(self, addr: address) -> String<100>:
return self.messages[addr].to_mem()
pub fn get_msg(self, addr: address) -> String<100> {
return self.messages[addr].to_mem()
}
}
```

If you haven't already, run `./fe guest_book.fe --overwrite` to obtain the bytecode that we want to deploy.
Expand Down Expand Up @@ -115,5 +118,3 @@ We <3 Fe
As we can see in the last line of the output the signature for address `0x4E14AaF86CF0759d6Ec8C7433acd66F07D093293` is in fact *We <3 Fe*.

Congratulations! You've deployed real Fe code to a live network 🤖


62 changes: 25 additions & 37 deletions docs/src/quickstart/first_contract.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
## Write your first Fe contract

Now that we have the compiler installed let's write our first contract. A contract contains the code that will be deployed to the Ethereum blockchain and resides at a specific address.
Now that we have the compiler installed let's write our first contract. A contract contains the code that will be deployed to the Ethereum blockchain and resides at a specific address.

The code of the contract dictates how:
- it manipulates its own state
Expand All @@ -15,37 +15,17 @@ To keep things simple we will just write a basic *guestbook* where people can le

Fe code is written in files ending on the `.fe` file extension. Let's create a file `guest_book.fe` and put in the following content.

```python
contract GuestBook:
```

Now, execute `./fe guest_book.fe` to compile the file.

Oops, the compiler is telling us that it didn't expect our code to end here.

```
Unable to compile guest_book.fe.
error: unexpected end of file
┌─ guest_book.fe:1:20
1 │ contract GuestBook:
│ ^
```

Fe follows Pythonic block indentation rules and the compiler expects us to provide a block of indented code after `GuestBook:`.

Let's expand the code by providing a [`map`](../spec/type_system/types/map.md) where we can associate messages with Ethereum addresses. The messages will simply be a [`string`](../spec/type_system/types/string.md) of a maximum length of `100` written as `string100`.
The addresses are represented by the builtin [`address`](../spec/type_system/types/address.md) type.

```
contract GuestBook:
contract GuestBook {
messages: Map<address, String<100>>
}
```

Execute `./fe guest_book.fe` again to recompile the file.
Here we're using a [`map`](../spec/type_system/types/map.md) to associate messages with Ethereum addresses.
The messages will simply be a [`string`](../spec/type_system/types/string.md) of a maximum length of `100` written as `String<100>`.
The addresses are represented by the builtin [`address`](../spec/type_system/types/address.md) type.

This time, the compiler tells us that it compiled our contract and that it has put the artifacts into a subdirectory called `output`.
Execute `./fe guest_book.fe` to compile the file. The compiler tells us that it compiled our contract and that it has put the artifacts into a subdirectory called `output`.

```
Compiled guest_book.fe. Outputs in `output`
Expand Down Expand Up @@ -75,14 +55,16 @@ Let's focus on the functionality of our world changing application and add a met
```python
use std::context::Context

contract GuestBook:
contract GuestBook {
messages: Map<address, String<100>>

pub fn sign(self, ctx: Context, book_msg: String<100>):
pub fn sign(self, ctx: Context, book_msg: String<100>) {
self.messages[ctx.msg_sender()] = book_msg
}
}
```

The code should look familiar to those of us that have written Python before except that in Fe every method that is defined without the [`pub`](../spec/items/visibility_and_privacy.md) keyword becomes private. Since we want people to interact with our contract and call the `sign` method we have to prefix it with `pub`.
In Fe, every method that is defined without the [`pub`](../spec/items/visibility_and_privacy.md) keyword becomes private. Since we want people to interact with our contract and call the `sign` method we have to prefix it with `pub`.

Let's recompile the contract again and see what happens.

Expand Down Expand Up @@ -121,22 +103,25 @@ To make the guest book more useful we will also add a method `get_msg` to read e
```python
use std::context::Context

contract GuestBook:
contract GuestBook {
messages: Map<address, String<100>>

pub fn sign(self, ctx: Context, book_msg: String<100>):
pub fn sign(self, ctx: Context, book_msg: String<100>) {
self.messages[ctx.msg_sender()] = book_msg
}

pub fn get_msg(self, addr: address) -> String<100>:
pub fn get_msg(self, addr: address) -> String<100> {
return self.messages[addr]
}
}
```

However, we will hit another error as we try to recompile the current code.

```
Unable to compile guest_book.fe.
error: value must be copied to memory
┌─ guest_book.fe:8:14
┌─ guest_book.fe:10:14
8 │ return self.messages[addr]
│ ^^^^^^^^^^^^^^^^^^^ this value is in storage
Expand All @@ -154,14 +139,17 @@ The code should compile fine when we change it accordingly.
```python
use std::context::Context

contract GuestBook:
contract GuestBook {
messages: Map<address, String<100>>

pub fn sign(self, ctx: Context, book_msg: String<100>):
pub fn sign(self, ctx: Context, book_msg: String<100>) {
self.messages[ctx.msg_sender()] = book_msg
}

pub fn get_msg(self, addr: address) -> String<100>:
pub fn get_msg(self, addr: address) -> String<100> {
return self.messages[addr].to_mem()
}
}
```

Congratulations! You finished your first little Fe project. 👏
Expand Down
13 changes: 8 additions & 5 deletions docs/src/spec/expressions/attribute.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,27 @@ The syntax for an attribute expression is an expression, then a `.` and finally
Examples:

```python
struct Point:
struct Point {
pub x: u256
pub y: u256
}

contract Foo:
contract Foo {
some_point: Point
some_tuple: (bool, u256)

fn get_point() -> Point:
fn get_point() -> Point {
return Point(x: 100, y: 500)
}

pub fn baz(some_point: Point, some_tuple: (bool, u256)):
pub fn baz(some_point: Point, some_tuple: (bool, u256)) {
# Different examples of attribute expressions
let bool_1: bool = some_tuple.item0
let x1: u256 = some_point.x
let point1: u256 = get_point().x
let point2: u256 = some_point.x

}
}
```

[_Expression_]: ./index.md
Expand Down
9 changes: 5 additions & 4 deletions docs/src/spec/expressions/call.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,16 @@ A *call expression* calls a function. The syntax of a call expression is an [exp
Example:

```python
contract Foo:
contract Foo {

pub fn demo(self):
pub fn demo(self) {
let ann: address = address(0xaa)
let bob: address = address(0xbb)
self.transfer(from: ann, to: bob, 25)
}

pub fn transfer(self, from: address, to: address, _ val: u256):
pass
pub fn transfer(self, from: address, to: address, _ val: u256) {}
}
```

[_Expression_]: ./index.md
Expand Down
8 changes: 5 additions & 3 deletions docs/src/spec/expressions/indexing.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@
Example:

```python
contract Foo:
contract Foo {

balances: Map<address, u256>

pub fn baz(self, values: Array<u256, 10>):
pub fn baz(self, values: Array<u256, 10>) {
# Assign value at slot 5
values[5] = 1000
# Read value at slot 5
Expand All @@ -25,8 +25,10 @@ contract Foo:

# Read balance of address zero
let bal: u256 = self.balances[address(0)]
}
}
```

[_Expression_]: ./index.md
[Array]: ../type_system/types/array.md
[Map]: ../type_system/types/map.md
[Map]: ../type_system/types/map.md
9 changes: 6 additions & 3 deletions docs/src/spec/expressions/list.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,18 @@ An array item can be accessed via an [index expression].
Example:

```python
contract Foo:
contract Foo {

fn get_val3() -> u256:
fn get_val3() -> u256 {
return 3
}

pub fn baz():
pub fn baz() {
let val1: u256 = 2
# A list expression
let foo: Array<u256, 3> = [1, val1, get_val3()]
}
}
```

[_Expression_]: ./index.md
Expand Down
7 changes: 4 additions & 3 deletions docs/src/spec/expressions/name.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@ A *name expression* resolves to a local variable.
Example:

```python
contract Foo:

pub fn baz(foo: u256):
contract Foo {
pub fn baz(foo: u256) {
# name expression resolving to the value of `foo`
foo
}
}
```

[IDENTIFIER]: ../lexical_structure/identifiers.md
13 changes: 6 additions & 7 deletions docs/src/spec/expressions/tuple.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,17 @@ A tuple field can be accessed via an [attribute expression].

Example:

```python
contract Foo:

pub fn bar():
```
contract Foo {
pub fn bar() {
# Creating a tuple via a tuple expression
let some_tuple: (u256, bool) = (1, false)
# Accessing the first tuple field via the `item0` field
baz(input: some_tuple.item0)

pub fn baz(input: u256):
pass
}
pub fn baz(input: u256) {}
}
```

[_Expression_]: ./index.md
Expand Down
1 change: 0 additions & 1 deletion docs/src/spec/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
* [`break` Statement](statements/break.md)
* [`continue` Statement](statements/continue.md)
* [`assert` Statement](statements/assert.md)
* [`pass` Statement](statements/pass.md)
* [Expressions](expressions/index.md)
* [Call expressions](expressions/call.md)
* [Tuple expressions](expressions/tuple.md)
Expand Down
14 changes: 9 additions & 5 deletions docs/src/spec/items/contracts.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,21 +28,25 @@

An example of a `contract`:

```python
```
use std::context::Context
contract GuestBook:
contract GuestBook {
messages: Map<address, String<100>>
event Signed:
event Signed {
book_msg: String<100>
}
pub fn sign(self, ctx: Context, book_msg: String<100>):
pub fn sign(self, ctx: Context, book_msg: String<100>) {
self.messages[ctx.msg_sender()] = book_msg
emit Signed(ctx, book_msg: book_msg)
}
pub fn get_msg(self, addr: address) -> String<100>:
pub fn get_msg(self, addr: address) -> String<100> {
return self.messages[addr].to_mem()
}
}
```

[NEWLINE]: ../lexical_structure/tokens.md#newline
Expand Down
11 changes: 7 additions & 4 deletions docs/src/spec/items/events.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,22 @@ An _event_ is a nominal [event type] defined with the keyword `event`. It is emi

An example of a `event` item and its use:

```python
```
use std::context::Context
contract Foo:
event Transfer:
contract Foo {
event Transfer {
idx sender: address
idx receiver: address
value: u256
}
fn transfer(ctx: Context, to: address, value: u256):
fn transfer(ctx: Context, to: address, value: u256) {
# Heavy logic here
# All done, log the event for listeners
emit Transfer(ctx, sender: ctx.msg_sender(), receiver: to, value)
}
}
```

[NEWLINE]: ../lexical_structure/tokens.md#newline
Expand Down
Loading

0 comments on commit b86c21d

Please sign in to comment.