Skip to content

Commit

Permalink
links fixes, func COLORED :)
Browse files Browse the repository at this point in the history
  • Loading branch information
SwiftAdviser committed Aug 24, 2022
1 parent 8d70767 commit a4e013a
Show file tree
Hide file tree
Showing 13 changed files with 221 additions and 206 deletions.
2 changes: 1 addition & 1 deletion docs/develop/func/builtins.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,6 @@ Variable can be dumped to debug log by `~dump` function.
- `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?id=null-values).
- `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
4 changes: 2 additions & 2 deletions docs/develop/func/comments.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
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 -}
-}
Expand Down
50 changes: 26 additions & 24 deletions docs/develop/func/functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,20 @@ Any function declaration or definition starts with a common pattern, and then on
- 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;
}
Expand All @@ -27,18 +27,18 @@ Any function declaration or definition starts with a common pattern, and then on
## 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?id=identifiers) and also it can start with `.` or `~` symbols. The meaning of those symbols is [explained](func/statements?id=methods-calls) in statements section.
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](func/statements?id=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.md?id=method_id).
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
Expand All @@ -50,7 +50,7 @@ Every program must have a function with id 0, that is `main` or `recv_internal`

### 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''();
Expand All @@ -59,7 +59,7 @@ int 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);
}
Expand All @@ -70,22 +70,22 @@ is a valid definition of function `pyth` of type `(int, int) -> (int, int, int)`
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?id=tensor-types) argument. To see the difference, please refer to [function application](/develop/func/statements?id=function-application). Nevertheless, the components of the argument tensor are conventionally called function arguments.
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?id=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`.
Expand All @@ -95,7 +95,7 @@ There are three types of specifiers: `impure`, `inline`/`inline_ref` and `method
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.
Expand All @@ -108,7 +108,7 @@ Code of a function with `inline_ref` specifier is put into a separated cell and
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);
Expand All @@ -118,13 +118,13 @@ 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?id=identifiers). Usually they are named by capital letters though.
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];
Expand All @@ -134,45 +134,47 @@ is a function that takes a tuple of length exactly 2, but with values of any (si

`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?id=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.
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.

[//]: # (The list of assembler commands can be found here: [TVM instructions]&#40;/smart-contracts/tvm-instructions/instructions.md&#41;.)
:::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";
```
14 changes: 7 additions & 7 deletions docs/develop/func/global_variables.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
FunC program is essentially a list of function declarations/definitions and global variable declarations. This section covers the second topic.

Global variable can be declared with `global` keyword followed by variable type and variable name. For example,
```
```cpp
global ((int, int) -> int) op;

int check_assoc(int a, int b, int c) {
Expand All @@ -19,7 +19,7 @@ is a simple program that writes to a global functional variable `op` the additio
Internally global variables are stored in the c7 control register of TVM.
Type of a global variable can be omitted. If so, it will be inferred by the usage of the variable. For example, we can rewrite the program as:
```
```cpp
global op;
int check_assoc(int a, int b, int c) {
Expand All @@ -33,17 +33,17 @@ int main() {
```

It is possible to declare several variables after the same `global` keyword. The following codes are equivalent:
```
```cpp
global int A;
global cell B;
global C;
```
```
```cpp
global int A, cell B, C;
```

It is not allowed to declare some local variable with the same name as an already declared global variable. For example, this code wouldn't compile:
```
```cpp
global cell C;

int main() {
Expand All @@ -52,12 +52,12 @@ int main() {
}
```
Note that this code is correct:
```
```cpp
global int C;

int main() {
int C = 3;
return C;
}
```
but here `int C = 3;` is equivalent to `C = 3;`, i.e. that is an assignment to global variable `C`, not a declaration of local variable `C` (you can find some explanation of this effect in [statements](/develop/func/statements.md?id=variable-declaration)).
but here `int C = 3;` is equivalent to `C = 3;`, i.e. that is an assignment to global variable `C`, not a declaration of local variable `C` (you can find some explanation of this effect in [statements](/develop/func/statements#variable-declaration)).
4 changes: 2 additions & 2 deletions docs/develop/func/statements.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ The first call will modify x, the second and the third won't.
In summary, when a function with name `foo` is called as non-modifying or modifying method (i.e. with `.foo` or `~foo` syntax), FunC compiler use the definition of `.foo` or `~foo` correspondingly if such definition is presented, and if not, it uses the definition of `foo`.

### Operators
Note that currently all of unary and binary operators are integer operators. Logical operators are represented as bitwise integer operators (cf. [absene of boolean type](/develop/func/types?id=absence-of-boolean-type)).
Note that currently all of unary and binary operators are integer operators. Logical operators are represented as bitwise integer operators (cf. [absene of boolean type](/develop/func/types#absence-of-boolean-type)).
#### Unary operators
There are two unary operators:
- `~` is bitwise not (priority 75).
Expand Down Expand Up @@ -248,7 +248,7 @@ while (x < 100) {
}
;; x = 256
```
Note that the truth value of condition `x < 100` is of type `int` (cf. [absene of boolean type](/develop/func/types?id=absence-of-boolean-type)).
Note that the truth value of condition `x < 100` is of type `int` (cf. [absene of boolean type](/develop/func/types#absence-of-boolean-type)).

### Until loop
Has the following syntax:
Expand Down
Loading

0 comments on commit a4e013a

Please sign in to comment.