Skip to content

Commit

Permalink
added versioning
Browse files Browse the repository at this point in the history
  • Loading branch information
SwiftAdviser committed Sep 2, 2022
1 parent d746928 commit 7f7c2c1
Show file tree
Hide file tree
Showing 83 changed files with 8,681 additions and 0 deletions.
30 changes: 30 additions & 0 deletions docs/contribute/hacktoberfest.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Hack-TON-berfest

Hacktoberfest is a month-long global celebration of open source software run by DigitalOcean in partnership with Intel, AppWrite, and DeepSource, with a strong focus on encouraging contributions to open source projects.


<div style={{textAlign:'center', margin: '30px 0'}}>
<img alt="tlb structure" src="/img/docs/hacktoberfest.webp" width="50%"/>
</div>


Here are main concepts of this event:

* **Hacktoberfest is open to everyone**.
* Four quality pull requests must be submitted to public GitHub/GitLab repositories.
* You can sign up anytime between October 1 and October 31.


## What the hype?

In the TON ecosystem we have own leaderboards and more participants we will have the more prizes pool will be!

Prizes include:
* **Limited edition T-short** with TON branding
* **TON Hacktoberfest NFT** for every participant!
* **Prize in TON** for the most important contributions

## FAQ

Please, visit the main event page to see the FAQ answers:
* https://hacktoberfest.digitalocean.com/faq
Binary file added static/img/docs/hacktoberfest.webp
Binary file not shown.
65 changes: 65 additions & 0 deletions versioned_docs/version-1.0.0/contribute/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# How to Contribute

## Identify an area to Contribute to

There are several ways to identify an area where you can contribute to the Wiki:

- The easiest is to reach out to one of the [Docs maintainers](/contribute/maintainers)
saying "I want to help contribute to the TON Docs". They’ll work with you to find
an area for you to contribute.
- If you have a specific contribution in mind but are unsure about it, confirm whether
the contribution is appropriate by contacting one of the [Docs maintainers](/contribute/maintainers) directly.
- See questions that often asked in TON Developers Chats.
- Feel free to read the issues in the GitHub repository.

## TL;DR

- If you need to add or change anything in TON Docs raise a PR
against the `main` branch.
- The documentation team will review the PR or reach out accordingly.
- Repository: https://github.com/SwiftAdviser/ton-docs

## Development

### Online one-click setup for contributing

You can use Gitpod (a free, online, VS Code-like IDE) for contributing. With a single click, it will launch a workspace and automatically:

* clone the docusaurus repo.
* install the dependencies.
* run `yarn start`
* So that you can start contributing straight away.

[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/SwiftAdviser/ton-docs)

:::tip

If you are adding a new document, it is recommended to just have a basic summary/introduction and a link to your github or documentation for more details.

:::

### Code Conventions

- **Most important**: Look around. Match the style you see used in the rest of the project. This includes formatting, naming files, naming things in code, naming things in documentation, etc.
- "Attractive"
- **For documentation**: Do not wrap lines at 80 characters - configure your editor to soft-wrap when editing documentation.

Don't worry too much about styles in general—the maintainers will help you fix them as they review your code.



### Pull Requests

So you have decided to contribute code back to upstream by opening a pull request. You've invested a good chunk of time, and we appreciate it. We will do our best to work with you and get the PR looked at.

Please make sure the following is done when submitting a pull request:

1. **Keep your PR small**. Small pull requests (~300 lines of diff) are much easier to review and more likely to get merged. Make sure the PR does only one thing, otherwise please split it.
2. **Use descriptive titles**. It is recommended to follow commit message style.
3. **Test your changes**. Describe your test plan in your pull request description.

All pull requests should be opened against the `main` branch.

## What Happens Next?

The TON Docs team will be monitoring for pull requests. Do help us by keeping pull requests consistent by following the guidelines above.
22 changes: 22 additions & 0 deletions versioned_docs/version-1.0.0/contribute/maintainers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Maintainers


## Active Team

Current members of the TON Docs team are listed in alphabetical order below.

### SwiftAdviser

* Telegram: [@SwiftAdviser](https://t.me/SwiftAdviser)
* GitHub: [SwiftAdviser](https://github.com/SwiftAdviser)


## Acknowledgements

TON Docs was originally created by [tolya-yanot](https://github.com/tolya-yanot) and [EmelyanenkoK](https://github.com/EmelyanenkoK).

We’d like to recognize a few people who have made significant contributions to TON Docs in the past and have helped maintain and develop them:

- [tolya-yanot](https://example.com)
- [EmelyanenkoK](https://example.com)
- [Tal Kol](https://example.com)
2 changes: 2 additions & 0 deletions versioned_docs/version-1.0.0/develop/func/FAQ.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# FAQ
Ask your questions in [github issues](https://github.com/ton-blockchain/docs) and they will appear here.
22 changes: 22 additions & 0 deletions versioned_docs/version-1.0.0/develop/func/builtins.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Built-ins
This section describes some language constructions which are less fundamental that ones described in previous sections. They could be defined in [stdlib.fc](/develop/func/stdlib.md), but it would leave less room for FunC optimizer.

## Throwing exceptions
Exceptions can be thrown by conditional primitives `throw_if` and `throw_unless` and by unconditional `throw`. The first argument is the error code, the second is the condition (`throw` has only one argument).

Currently FunC doesn't support catching exceptions, unless an exception handler is set with low-level TVM primitives. The primary purpose of described primitives is reverting transactions which don't satisfy some mandatory conditions (like `require` and `revert` in Solidity programming language).

## Booleans
- `true` is alias for `-1`
- `false` is alias for `0`

## Dump variable
Variable can be dumped to debug log by `~dump` function.

## Integer operations
- `muldiv` is multiple-then-divide operation. Intermediate result is stored in 513-bit integer, so it won't overflow if the actual result fits into 257-bit integer.

## Other primitives
- `null?` checks whether the argument is `null`. By the value `null` of TVM type `Null` FunC represents absence of a value of some atomic type, see [null values](/develop/func/types#null-values).
- `touch` and `~touch` move a variable to the top of the stack
- `at` gets the value of component of a tuple on specified position
14 changes: 14 additions & 0 deletions versioned_docs/version-1.0.0/develop/func/comments.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Comments
FunC has single-line comments, which start with `;;` (double `;`).

For example:
```cpp
int x = 1; ;; assign 1 to x
```

It also has multi-line comments, which start with `{-` and end with `-}`. Note that unlike in many other languages, FunC multi-line comments can be nested. For example:
```cpp
{- This is a multi-line comment
{- this is a comment in the comment -}
-}
```
46 changes: 46 additions & 0 deletions versioned_docs/version-1.0.0/develop/func/compiler_directives.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Compiler directives
Those are keywords that start with `#` and instruct compiler to do some actions, checks or adjust parameters.

Those directives can be used only at the outermost level (not inside any function definition).

## #include
The `#include` directive allows to include another FunC source code file that will be parsed at the place of include.

Syntax is `#include "filename.fc";`. Files are automatically checked against re-inclusion and attempting to include
a file more than once would be silently ignored by default, with warning if verbosity level is no lower than 2.

If an error happens during parsing of included file additionally a stack of inclusions is printed with locations
of each include in chain.

## #pragma
The `#pragma` directive is the method for providing additional information to the compiler, beyond what is conveyed
in the language itself.

### #pragma version
Version pragma is used to enforce specific version of FunC compiler when compiling the file.

Version is specified in semver format, that is `a.b.c`, where `a` is major version, `b` is minor, and `c` is patch.

There are several comparison operators available for the developer:
* `a.b.c` or `=a.b.c` - requires exactly the `a.b.c` version of the compiler,
* `>a.b.c` - requires compiler version to be higher than `a.b.c`,
* `>=a.b.c` - requires compiler version to be higher or equal to `a.b.c`,
* `<a.b.c` - requires compiler version to be lower than `a.b.c`,
* `<=a.b.c` - requires compiler version to be lower or equal to `a.b.c`,
* `^a.b.c` - requires the major and minor compiler version to be equal to `a.b` and patch be no lower than `c` part,
* `^a.b` - requires the major compiler version to be equal to `a` part and minor be no lower than `b` part,
* `^a` - requires the major compiler version to be no lower than `a` part.

For other comparison operators (`=`, `>`, `>=`, `<`, `<=`) short format assumes zeros in omitted parts, that is:
* `>a.b` is same as `>a.b.0` (and therefore does NOT match `a.b.0` version),
* `<=a` is same as `<=a.0.0` (and therefore does NOT match `a.0.1` version),
* `^a.b.0` is **NOT** the same as `^a.b`.

For example, `^a.1.2` matches `a.1.3` but not `a.2.3` or `a.1.0`, however, `^a.1` matches them all.

This directive may be used multiple times, the compiler version must satisfy all the provided conditions.

### #pragma not-version
The syntax of this pragma is same as the version pragma, but it fails if the condition is satisfied.

It can be used for blacklisting a specific version known to have problems, for example.
180 changes: 180 additions & 0 deletions versioned_docs/version-1.0.0/develop/func/functions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
# Functions
FunC program is essentially a list of function declarations/definitions and global variable declarations. This section covers the first topic.

Any function declaration or definition starts with a common pattern, and then one of the three things follows:
- single `;`, which means that the function is declared, but not defined yet. It may be defined later in the same file, or in some other file, which is passed before the current one to the FunC compiler.

For example,
```cpp
int add(int x, int y);
```
is a simple declaration of a function named `add` of type `(int, int) -> int`.
- assembler function body definition. It is the way to define functions by low-level TVM primitives for later use in FunC program.
For example,
```cpp
int add(int x, int y) asm "ADD";
```
is an assembler definition of the same function `add` of type `(int, int) -> int`, which will translate to the TVM opcode `ADD`.

- ordinary block statement function body definition. It is the usual way to define functions.
For example,
```cpp
int add(int x, int y) {
return x + y;
}
```
is an ordinary definition of the `add` function.
## Function declaration
As said before, any function declaration or definition starts with a common pattern. The pattern is following:
```cpp
[<forall declarator>] <return_type> <function_name>(<comma_separated_function_args>) <specifiers>
```
where `[ ... ]` correspond to an optional entry.

### Function name
Function name can be any [identifier](/develop/func/literals_identifiers#identifiers) and also it can start with `.` or `~` symbols. The meaning of those symbols is [explained](/develop/func/statements#methods-calls) in statements section.

For example, `udict_add_builder?`, `dict_set` and `~dict_set` are valid and different function names (they are defined in [stdlib.fc](/develop/func/stdlib.md)).

#### Special function names
FunC (actually Fift assembler) has several reserved function names with predefined [ids](/develop/func/functions#method_id).
- `main` and `recv_internal` have id = 0
- `recv_external` has id = -1
- `run_ticktock` has id = -2

Every program must have a function with id 0, that is `main` or `recv_internal` function.

`recv_internal` is called when smart contract receives an inbound internal message, `recv_external` is for inbound external messages and `run_ticktock` is called in ticktock transactions of special smart contracts.


### Return type
Return type can be any atomic or composite type, as [types](/develop/func/types.md) section describes. For example,
```cpp
int foo();
(int, int) foo'();
[int, int] foo''();
(int -> int) foo'''();
() foo''''();
```
are valid functions declarations.
Type inference is also allowed. For example,
```cpp
_ pyth(int m, int n) {
return (m * m - n * n, 2 * m * n, m * m + n * n);
}
```
is a valid definition of function `pyth` of type `(int, int) -> (int, int, int)`, which computes Pythagorean triples.
### Function arguments
Function arguments are separated by commas. Valid declarations of an argument are following:
- Ordinary declaration: type + name. For example, `int x` is a declaration of argument of type `int` and name `x` in function declaration `() foo(int x);`.
- Unused argument declaration: only type. For example,
```cpp
int first(int x, int) {
return x;
}
```
is a valid function definition of type `(int, int) -> int`.
- Argument with inferred type declaration: only name.
For example,
```cpp
int inc(x) {
return x + 1;
}
```
is a valid function definition of type `int -> int`. The `int` type of `x` is inferred by type-checker.
Note that although a function may look like a function of several arguments, it's actually a function of one [tensor-type](/develop/func/types#tensor-types) argument. To see the difference, please refer to [function application](/develop/func/statements#function-application). Nevertheless, the components of the argument tensor are conventionally called function arguments.
### Specifiers
There are three types of specifiers: `impure`, `inline`/`inline_ref` and `method_id`. One, several or none of them can be put in function declaration, but currently they must be presented in the right order: for example, it is not allowed to put `impure` after `inline`.
#### Impure specifier
`impure` specifier means that the function can have some side effects which can't be ignored. For example, we should put `impure` specifier if the function can modify contract storage, send messages or throw an exception when some data is invalid and the function is intended to validate this data.
If `impure` is not specified and the result of the function call is not used, then FunC compiler may and will delete this function call.
For example, in [stdlib.fc](/develop/func/stdlib.md) function
```cpp
int random() impure asm "RANDU256";
```
is defined. `impure` is used because `RANDU256` changes the internal state of the random number generator.

#### Inline specifier
If function has `inline` specifier, its code is actually substituted in every place where the function is called. Needless to say that recursive calls of inlined function are impossible.
#### Inline_ref specifier
Code of a function with `inline_ref` specifier is put into a separated cell and every time when the function is called a `CALLREF` command is executed by TVM. So it's similar to `inline`, but because a cell can be reused in several places without duplicating it, it is almost always more efficient in code size to use `inline_ref` specifier instead of `inline` unless the function is called exactly once. Recursive calls of `inline_ref`'ed functions are still impossible, because there is no cyclic references in TVM cells.
#### method_id
Every function in TVM program has an internal integer id by which it can be called. Ordinary functions are usually numbered by subsequent integers starting from 1, but get-methods of the contract are numbered by crc16 hashes of their name. `method_id(<some_number>)` specifier allows to set id of a function to specified value, and `method_id` uses the default value `(crc16(<function_name>) & 0xffff) | 0x10000`. If a function has `method_id` specifier, then it can be called in lite-client or ton-explorer as a get-method by its name.

For example,
```cpp
(int, int) get_n_k() method_id {
(_, int n, int k, _, _, _, _) = unpack_state();
return (n, k);
}
```
is a get-method of multisig contract.

### Polymorphism with forall
Before any function declaration or definition there can be `forall` type variables declarator. It has the following syntax:
```cpp
forall <comma_separated_type_variables_names> ->
```
where type variable name can be any [identifier](/develop/func/literals_identifiers#identifiers). Usually they are named by capital letters though.

For example,
```cpp
forall X, Y -> [Y, X] pair_swap([X, Y] pair) {
[X p1, Y p2] = pair;
return [p2, p1];
}
```
is a function that takes a tuple of length exactly 2, but with values of any (single stack entry) types in components, and swaps them with each other.

`pair_swap([2, 3])` will produce `[3, 2]` and `pair_swap([1, [2, 3, 4]])` will produce `[[2, 3, 4], 1]`.

In this example `X` and `Y` are [type variables](/develop/func/types#polymorphism-with-type-variables). When the function is called, type variables are substituted with actual types and the code of the function is executed. Note that although the function is polymorphic, the actual assembler code for it is the same for every type substitution. It is achieved essentially by polymorphism of stack manipulation primitives. Currently other forms of polymorphism (like ad-hoc polymorphism with type classes) are not supported.

Also it is worth noticing that the type width of `X` and `Y` is supposed to be equal to 1, that is, the values of `X` or `Y` must occupy single stack entry. So you actually can't call the function `pair_swap` on a tuple of type `[(int, int), int]`, because type `(int, int)` has width 2, i.e. it occupies 2 stack entries.

## Assembler function body definition
As mentioned above, function can be defined by assembler code. The syntax is an `asm` keyword followed by one or several assembler commands, represented as strings.
For example, one can define
```cpp
int inc_then_negate(int x) asm "INC" "NEGATE";
```
– function that increment an integer and then negates it. Calls of this function will be translated to 2 assembler commands `INC` and `NEGATE`. Alternative way to define the function is
```cpp
int inc_then_negate'(int x) asm "INC NEGATE";
```
`INC NEGATE` will be considered by FunC as one assembler command, but it is OK, because Fift assembler knows that it is 2 separate commands.

:::info
The list of assembler commands can be found here: [TVM instructions](/learn/tvm-instructions/instructions).
:::

### Rearranging stack entries
In some cases we want to pass arguments to assembler function is not exactly the same order as assembler command requires or/and take the result in different stack entries order than the command returns. We could manually rearrange the stack by adding corresponding stack primitives, but FunC can do it automatically.

For example, suppose that assembler command `STUXQ` takes integer, builder and integer and returns builder along with integer flag, indicating success or failure of the operation.
We may define a function
```cpp
(builder, int) store_uint_quite(int x, builder b, int len) asm "STUXQ";
```
However, suppose we want to rearrange arguments. Then we can define
```cpp
(builder, int) store_uint_quite(builder b, int x, int len) asm(x b len) "STUXQ";
```
So you can indicate the required order of arguments after `asm` keyword.

Also we can rearrange return values like this:
```cpp
(int, builder) store_uint_quite(int x, builder b, int len) asm( -> 1 0) "STUXQ";
```
The numbers correspond to indexes of returns values (0 is the deepest stack entry among returned values).

Combining this techniques is also possible:
```cpp
(int, builder) store_uint_quite(builder b, int x, int len) asm(x b len -> 1 0) "STUXQ";
```
Loading

0 comments on commit 7f7c2c1

Please sign in to comment.