diff --git a/gitlab-pages/docker-compose.yml b/gitlab-pages/docker-compose.yml index af12b7af7..8f9e490b8 100644 --- a/gitlab-pages/docker-compose.yml +++ b/gitlab-pages/docker-compose.yml @@ -17,7 +17,7 @@ services: # - ./website/versioned_docs:/app/website/versioned_docs - ./website/sidebars.json:/app/website/sidebars.json - ./website/docusaurus.config.js:/app/website/docusaurus.config.js - - ./website/versions.json:/app/website/versions.json + # - ./website/versions.json:/app/website/versions.json # - ./website/core/AlgoliaSearch.js:/app/website/core/AlgoliaSearch.js working_dir: /app/website diff --git a/gitlab-pages/docs/contributors/big-picture/front-end.md b/gitlab-pages/docs/contributors/big-picture/front-end.md index d4bcfb9e7..d23fe884e 100644 --- a/gitlab-pages/docs/contributors/big-picture/front-end.md +++ b/gitlab-pages/docs/contributors/big-picture/front-end.md @@ -10,6 +10,6 @@ Its files are in `parser/parser_name`. ## Concrete Syntax Tree The CST is the aforementioned structured representation of the program. Is is structurally very close to the source code, and is mostly an intermediary there because manipulating string is not practical. Its files are in `parser/parser_name`. -## Simplifier -A Simplifier is a function that takes a CST and outputs the corresponding Common AST. This is the actual bridge between a given syntax and LIGO. +## Sugar_to_core +A Sugar_to_core is a function that takes a CST and outputs the corresponding Common AST. This is the actual bridge between a given syntax and LIGO. Its files are in `simplify/parser_name`. diff --git a/gitlab-pages/docs/contributors/big-picture/middle-end.md b/gitlab-pages/docs/contributors/big-picture/middle-end.md index 6dac7f5ec..f7cd04a8b 100644 --- a/gitlab-pages/docs/contributors/big-picture/middle-end.md +++ b/gitlab-pages/docs/contributors/big-picture/middle-end.md @@ -6,7 +6,7 @@ title: Middle End The Middle-End is the core of LIGO. It is also composed of three parts. ## Common AST The Common AST is the closest thing to what could be called “LIGO lang”. As such, it should be as simple as possible. Collapsing particular cases in more general constructs is encouraged. Documenting it is crucial for people who’ll write new parsers or editor support for Front-end related things. -Its files are in `ast_simplified/`, of interest is the definition of the AST itself in `ast_simplified/types.ml`. +Its files are in `ast_core/`, of interest is the definition of the AST itself in `ast_core/types.ml`. ## Type Checker The Type Checker, among other things, checks that a given AST is valid with regard to type-safety. It also annotates expressions with their types, free-variables and local environments. As time passes, we want to make the type-system stronger, to encode arbitrarily complex properties in an extensible manner. diff --git a/gitlab-pages/docs/contributors/ligo_test_guide.md b/gitlab-pages/docs/contributors/ligo_test_guide.md index eea05d77d..f8be06001 100644 --- a/gitlab-pages/docs/contributors/ligo_test_guide.md +++ b/gitlab-pages/docs/contributors/ligo_test_guide.md @@ -102,7 +102,7 @@ What's going on is similar to the last program: `expect_eq_evaluate` runs a prog For example, once the program stops running the value of `address` is `"tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx"`. The *comparison*, however, is made to a constructed expression. -Remember that we're testing from OCaml, but the program is written and evaluated as LIGO. In order to provide a proper comparison, we convert our expected test values into LIGO expressions and data. Constructors such as `e_list` and `e_address` provide a bridge between LIGO and OCaml. Their definitions can be found in files such as [src/stages/ast_simplified/combinators.ml](https://gitlab.com/ligolang/ligo/blob/dev/src/stages/ast_simplified/combinators.ml), or using [Merlin's definition point finder](https://github.com/ocaml/merlin/wiki). These same functions are used during the simplification stage of LIGO compilation, so becoming familiar with them will help prepare you to work on the [front end](contributors/big-picture/front-end/). +Remember that we're testing from OCaml, but the program is written and evaluated as LIGO. In order to provide a proper comparison, we convert our expected test values into LIGO expressions and data. Constructors such as `e_list` and `e_address` provide a bridge between LIGO and OCaml. Their definitions can be found in files such as [src/stages/ast_core/combinators.ml](https://gitlab.com/ligolang/ligo/blob/dev/src/stages/ast_core/combinators.ml), or using [Merlin's definition point finder](https://github.com/ocaml/merlin/wiki). These same functions are used during the simplification stage of LIGO compilation, so becoming familiar with them will help prepare you to work on the [front end](contributors/big-picture/front-end/). ## How To Write A Test For LIGO diff --git a/gitlab-pages/docs/intro/FAQ.md b/gitlab-pages/docs/intro/FAQ.md new file mode 100644 index 000000000..33501af46 --- /dev/null +++ b/gitlab-pages/docs/intro/FAQ.md @@ -0,0 +1,11 @@ +--- +id: faq +title: FAQ +--- + +# Frequently Asked Questions + +Before you ask... + +## Question One +Answer. diff --git a/gitlab-pages/docs/language-basics/functions.md b/gitlab-pages/docs/language-basics/functions.md index eadc1c31e..f8fc729a6 100644 --- a/gitlab-pages/docs/language-basics/functions.md +++ b/gitlab-pages/docs/language-basics/functions.md @@ -299,3 +299,78 @@ gitlab-pages/docs/language-basics/src/functions/incr_map.religo incr_map + +## Nested functions (also known as closures) +It's possible to place functions inside other functions. These functions +have access to variables in the same scope. + + + +```pascaligo +function closure_example (const i : int) : int is + block { + function closure (const j : int) : int is i + j + } with closure (i) +``` + + + + +```cameligo +let closure_example (i : int) : int = + let closure : int -> int = fun (j : int) -> i + j in + closure i +``` + + + + +```reasonligo +let closure_example = (i : int) : int => { + let closure = (j: int): int => i + j; + closure(i); +}; +``` + + + +## Recursive function + +LIGO functions are not recursive by default, the user need to indicate that the function is recursive. + +At the moment, recursive function are limited to one (possibly tupled) parameter and recursion is +limited to tail recursion (i.e the recursive call should be the last expression of the function) + + +In PascaLigo recursive functions are defined using the `recursive` keyword + +```pascaligo group=d +recursive function sum (const n : int; const acc: int) : int is + if n<1 then acc else sum(n-1,acc+n) + +recursive function fibo (const n: int; const n_1: int; const n_0 :int) : int is + if n<2 then n_1 else fibo(n-1,n_1+n_0,n_1) +``` + + +In CameLigo recursive functions are defined using the `rec` keyword + +```cameligo group=d +let rec sum ((n,acc):int * int) : int = + if (n < 1) then acc else sum (n-1, acc+n) + +let rec fibo ((n,n_1,n_0):int*int*int) : int = + if (n < 2) then n_1 else fibo (n-1, n_1 + n_0, n_1) +``` + + +In ReasonLigo recursive functions are defined using the `rec` keyword + +```reasonligo group=d +let rec sum = ((n, acc) : (int,int)): int => + if (n < 1) {acc;} else {sum ((n-1,acc+n));}; + +let rec fibo = ((n, n_1, n_0) : (int,int,int)): int => + if (n < 2) {n_1;} else {fibo ((n-1,n_1+n_0,n_1));}; +``` + diff --git a/gitlab-pages/docs/language-basics/loops.md b/gitlab-pages/docs/language-basics/loops.md index 8f81c93ae..e6d26adea 100644 --- a/gitlab-pages/docs/language-basics/loops.md +++ b/gitlab-pages/docs/language-basics/loops.md @@ -57,45 +57,21 @@ constant, therefore it makes no sense in CameLIGO to feature loops, which we understand as syntactic constructs where the state of a stopping condition is mutated, as with "while" loops in PascaLIGO. -Instead, CameLIGO implements a *folded operation* by means of a -predefined function named `Loop.fold_while`. It takes an initial value -of a certain type, called an *accumulator*, and repeatedly calls a -given function, called *folded function*, that takes that -accumulator and returns the next value of the accumulator, until a -condition is met and the fold stops with the final value of the -accumulator. The iterated function needs to have a special type: if -the type of the accumulator is `t`, then it must have the type `bool * -t` (not simply `t`). It is the boolean value that denotes whether the -stopping condition has been reached. +Instead, CameLIGO loops are written by means of a tail recursive function Here is how to compute the greatest common divisors of two natural numbers by means of Euclid's algorithm: ```cameligo group=a -let iter (x,y : nat * nat) : bool * (nat * nat) = - if y = 0n then false, (x,y) else true, (y, x mod y) +let rec iter (x,y : nat * nat) : nat = + if y = 0n then x else iter (y, x mod y) let gcd (x,y : nat * nat) : nat = let x,y = if x < y then y,x else x,y in - let x,y = Loop.fold_while iter (x,y) - in x + iter (x,y) ``` -To ease the writing and reading of the iterated functions (here, -`iter`), two predefined functions are provided: `Loop.resume` and -`Loop.stop`: - -```cameligo group=a -let iter (x,y : nat * nat) : bool * (nat * nat) = - if y = 0n then Loop.stop (x,y) else Loop.resume (y, x mod y) - -let gcd (x,y : nat * nat) : nat = - let x,y = if x < y then y,x else x,y in - let x,y = Loop.fold_while iter (x,y) - in x -``` - -> Note that `stop` and `continue` (now `Loop.resume`) are +> Note that `fold_while`, `stop` and `continue` (now `Loop.resume`) are > *deprecated*. You can call the function `gcd` defined above using the LIGO compiler @@ -114,47 +90,22 @@ constant, therefore it makes no sense in ReasonLIGO to feature loops, which we understand as syntactic constructs where the state of a stopping condition is mutated, as with "while" loops in PascaLIGO. -Instead, ReasonLIGO features a *fold operation* as a predefined -function named `Loop.fold_while`. It takes an initial value of a -certain type, called an *accumulator*, and repeatedly calls a given -function, called *iterated function*, that takes that accumulator and -returns the next value of the accumulator, until a condition is met -and the fold stops with the final value of the accumulator. The -iterated function needs to have a special type: if the type of the -accumulator is `t`, then it must have the type `bool * t` (not simply -`t`). It is the boolean value that denotes whether the stopping -condition has been reached. +Instead, ReasonLIGO loops are written by means of tail recursive functions Here is how to compute the greatest common divisors of two natural numbers by means of Euclid's algorithm: ```reasonligo group=a -let iter = ((x,y) : (nat, nat)) : (bool, (nat, nat)) => - if (y == 0n) { (false, (x,y)); } else { (true, (y, x mod y)); }; +let rec iter = ((x,y) : (nat, nat)) : nat => + if (y == 0n) { x; } else { iter ((y, x mod y)); }; let gcd = ((x,y) : (nat, nat)) : nat => { let (x,y) = if (x < y) { (y,x); } else { (x,y); }; - let (x,y) = Loop.fold_while (iter, (x,y)); - x + iter ((x,y)) }; ``` -To ease the writing and reading of the iterated functions (here, -`iter`), two predefined functions are provided: `Loop.resume` and -`Loop.stop`: - -```reasonligo group=b -let iter = ((x,y) : (nat, nat)) : (bool, (nat, nat)) => - if (y == 0n) { Loop.stop ((x,y)); } else { Loop.resume ((y, x mod y)); }; - -let gcd = ((x,y) : (nat, nat)) : nat => { - let (x,y) = if (x < y) { (y,x); } else { (x,y); }; - let (x,y) = Loop.fold_while (iter, (x,y)); - x -}; -``` - -> Note that `stop` and `continue` (now `Loop.resume`) are +> Note that `fold_while`, `stop` and `continue` (now `Loop.resume`) are > *deprecated*. diff --git a/gitlab-pages/docs/reference/big_map.md b/gitlab-pages/docs/reference/big_map.md index 952275c1c..e20bdc48c 100644 --- a/gitlab-pages/docs/reference/big_map.md +++ b/gitlab-pages/docs/reference/big_map.md @@ -1,25 +1,33 @@ --- id: big-map-reference -title: Big Maps — Scalable Maps +title: Big_map +description: A lazily deserialized map that's intended to store large amounts of data. +hide_table_of_contents: true --- import Syntax from '@theme/Syntax'; +import SyntaxTitle from '@theme/SyntaxTitle'; -Ordinary maps are fine for contracts with a finite lifespan or a -bounded number of users. For many contracts however, the intention is -to have a map holding *many* entries, potentially millions of -them. The cost of loading those entries into the environment each time -a user executes the contract would eventually become too expensive -were it not for *big maps*. Big maps are a data structure offered by -Michelson which handles the scaling concerns for us. In LIGO, the -interface for big maps is analogous to the one used for ordinary maps. +A lazily deserialized map that's intended to store large amounts of data. -# Declaring a Map +The gast costs of deserialized maps are higher than standard maps as data is lazily deserialized. + +type big_map ('key, 'value) + + +type ('key, 'value) big_map + + +type big_map ('key, 'value) + -```pascaligo group=big_maps +The type of a big map from values of type `key` to +values of type `value` is `big_map (key, value)`. + +```pascaligo group=big_map type move is int * int type register is big_map (address, move) ``` @@ -27,7 +35,10 @@ type register is big_map (address, move) -```cameligo group=big_maps +The type of a big map from values of type `key` to values +of type `value` is `(key, value) big_map`. + +```cameligo group=big_map type move = int * int type register = (address, move) big_map ``` @@ -35,59 +46,91 @@ type register = (address, move) big_map -```reasonligo group=big_maps +The type of a big map from values of type `key` to +values of type `value` is `big_map (key, value)`. + +```reasonligo group=big_map type move = (int, int); type register = big_map (address, move); ``` + +function empty : big_map ('key, 'value) + + +val empty : ('key, 'value) big_map + + +let empty: big_map ('key, 'value) + - -# Creating an Empty Big Map - - +Create an empty big_map. -```pascaligo group=big_maps -const empty : register = big_map [] +```pascaligo group=big_map +const empty : register = Big_map.empty +``` + +Alternatively, you can also create an empty big_map using: + +```pascaligo group=big_map +const empty_alternative : register = big_map [] ``` -```cameligo group=big_maps +```cameligo group=big_map let empty : register = Big_map.empty ``` -```reasonligo group=big_maps +```reasonligo group=big_map let empty : register = Big_map.empty ``` -# Creating a Non-empty Map - + +function literal : list ('key * 'value) -> big_map ('key, 'value) + + +val literal : ('key * 'value) list -> ('key, 'value) big_map + + +let literal: list(('key, 'value)) => big_map('key, 'value) + +Create a non-empty big_map. -```pascaligo group=big_maps +```pascaligo group=big_map const moves : register = + Big_map.literal (list [ + (("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address), (1,2)); + (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address), (0,3))]); +``` + +Alternative way of creating an empty big_map: + +```pascaligo group=big_map +const moves_alternative : register = big_map [ ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address) -> (1,2); - ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) -> (0,3)] + ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) -> (0,3)]; ``` -```cameligo group=big_maps +```cameligo group=big_map let moves : register = Big_map.literal [ (("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address), (1,2)); @@ -97,7 +140,7 @@ let moves : register = -```reasonligo group=big_maps +```reasonligo group=big_map let moves : register = Big_map.literal ([ ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address, (1,2)), @@ -106,21 +149,40 @@ let moves : register = + +function find_opt : 'key -> big_map ('key, 'value) -> option 'value + + +val find_opt : 'key -> ('key, 'value) big_map -> 'value option + + +let find_opt : ('key, big_map ('key, 'value)) => option ('value) + -# Accessing Values +Retrieve a value from a big map with the given key. + +Because the key may be missing in the big map, the result is an +*optional value*. -```pascaligo group=big_maps +```pascaligo group=big_map const my_balance : option (move) = - moves [("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address)] + Big_map.find_opt (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address), moves) +``` + +Alternatively: + +```pascaligo group=big_map +const my_balance_alternative : option (move) = + moves [("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address)]; ``` -```cameligo group=big_maps +```cameligo group=big_map let my_balance : move option = Big_map.find_opt ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) moves ``` @@ -128,33 +190,62 @@ let my_balance : move option = -```reasonligo group=big_maps +```reasonligo group=big_map let my_balance : option (move) = Big_map.find_opt ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address, moves); ``` + +function update : 'key -> option 'value -> big_map ('key, 'value) -> big_map ('key, 'value) + + +val update: 'key -> 'value option -> ('key, 'value) big_map -> ('key, 'value) big_map + + +let update: ('key, option('value), big_map ('key, 'value)) => big_map ('key, 'value) + - -# Updating Big Maps - +Note: when `None` is used as a value, the value is removed from the big_map. -```pascaligo group=big_maps -function add (var m : register) : register is - block { - m [("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address)] := (4,9) - } with m - -const updated_map : register = add (moves) +```pascaligo group=big_map + const updated_big_map : register = Big_map.update(("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), Some (4,9), moves); ``` +Alternatively: + +```pascaligo group=big_map + +function update (var m : register) : register is + block { + m [("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address)] := (4,9); + } with m + +``` + +If multiple bindings need to be updated, PascaLIGO offers a *patch +instruction* for maps, similar to that for records. + +```pascaligo group=big_map +function assignments (var m : register) : register is + block { + patch m with map [ + ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) -> (4,9); + ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address) -> (1,2) + ] + } with m +``` + +> Note the use of the keyword `map` instead of `big_map` (which is not +> a keyword). + -```cameligo group=big_maps +```cameligo group=big_map let updated_map : register = Big_map.update ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) (Some (4,9)) moves @@ -163,7 +254,7 @@ let updated_map : register = -```reasonligo group=big_maps +```reasonligo group=big_map let updated_map : register = Big_map.update (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), Some ((4,9)), moves); @@ -171,14 +262,64 @@ let updated_map : register = + +function add : 'key -> 'value -> big_map ('key, 'value) -> big_map ('key, 'value) + + +val add : 'key -> 'value -> ('key, 'value) big_map -> ('key, 'value) big_map + + +let add: ('key, 'value, big_map('key, 'value)) => big_map('key, 'value) + + -# Removing Bindings +```pascaligo group=big_map +const added_item : register = Big_map.add (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address), (4, 9), moves) +``` + + + + +```cameligo group=big_map +let add (m : register) : register = + Big_map.add + ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) (4,9) m +``` + + + + +```reasonligo group=big_map +let add = (m: register): register => + Big_map.add + (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address), (4,9), m); +``` + + + +function remove: 'key -> big_map ('key, 'value) -> big_map ('key, 'value) + + +val remove: 'key -> ('key, 'value) big_map -> ('key, 'value) big_map + + +let remove: ('key, big_map ('key, 'value)) => big_map ('key, 'value) + -```pascaligo group=big_maps +```pascaligo group=big_map + const updated_map : register = + Big_map.remove (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), moves) +``` + +Alternatively, the instruction `remove key from map m` removes the key +`key` from the big map `m` (note that the keyword is `map`, not +`big_map`). + +```pascaligo group=big_map function rem (var m : register) : register is block { remove ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address) from map moves @@ -190,17 +331,17 @@ const updated_map : register = rem (moves) -```cameligo group=big_maps +```cameligo group=big_map let updated_map : register = - Map.remove ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address) moves + Big_map.remove ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address) moves ``` -```reasonligo group=big_maps +```reasonligo group=big_map let updated_map : register = - Map.remove (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), moves) + Big_map.remove (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), moves) ``` diff --git a/gitlab-pages/docs/reference/bitwise.md b/gitlab-pages/docs/reference/bitwise.md new file mode 100644 index 000000000..85d6bde86 --- /dev/null +++ b/gitlab-pages/docs/reference/bitwise.md @@ -0,0 +1,69 @@ +--- +id: bitwise-reference +title: Bitwise +description: Operations on bytes +hide_table_of_contents: true +--- + +import Syntax from '@theme/Syntax'; +import SyntaxTitle from '@theme/SyntaxTitle'; + + +function and : nat -> nat -> nat + + +val and : nat -> nat -> nat + + +let and: (nat, nat) -> nat + + +A bitwise `and` operation. + + +function or : nat -> nat -> nat + + +val or : nat -> nat -> nat + + +let or: (nat, nat) -> nat + + +A bitwise `or` operation. + + +function xor : nat -> nat -> nat + + +val xor : nat -> nat -> nat + + +let xor: (nat, nat) -> nat + + +A bitwise `xor` operation. + + +function shift_left : nat -> nat -> nat + + +val shift_left : nat -> nat -> nat + + +let shift_left: (nat, nat) -> nat + + +A bitwise shift left operation. + + +function shift_right : nat -> nat -> nat + + +val shift_right : nat -> nat -> nat + + +let shift_right: (nat, nat) -> nat + + +A bitwise shift right operation. diff --git a/gitlab-pages/docs/reference/bytes.md b/gitlab-pages/docs/reference/bytes.md index dc8dc1aec..68e61d8cd 100644 --- a/gitlab-pages/docs/reference/bytes.md +++ b/gitlab-pages/docs/reference/bytes.md @@ -1,21 +1,43 @@ --- id: bytes-reference -title: Bytes — Manipulate bytes data +title: Bytes +description: Operations on bytes +hide_table_of_contents: true --- import Syntax from '@theme/Syntax'; +import SyntaxTitle from '@theme/SyntaxTitle'; -## Bytes.concat(b1: bytes, b2: bytes) : bytes + +type bytes + + +type bytes + + +type bytes + + + +function concat : bytes -> bytes -> bytes + + +val concat : bytes -> bytes -> bytes + + +let concat: (bytes, bytes) => bytes + Concatenate together two `bytes` arguments and return the result. ```pascaligo -function concat_op (const s : bytes) : bytes is - begin skip end with bytes_concat(s , 0x7070) +function concat_op (const s : bytes) : bytes is Bytes.concat(s , 0x7070) ``` +> Note that `bytes_concat` is *deprecated*. + @@ -33,41 +55,58 @@ let concat_op = (s: bytes): bytes => Bytes.concat(s, 0x7070); -## Bytes.slice(pos1: nat, pos2: nat, data: bytes) : bytes + +function sub : nat -> nat -> bytes -> bytes + + +val sub : nat -> nat -> bytes -> bytes + + +let sub : (nat, nat, bytes) => bytes + Extract the bytes between `pos1` and `pos2`. **Positions are zero indexed and inclusive**. For example if you gave the input "ff7a7aff" to the following: - - ```pascaligo -function slice_op (const s : bytes) : bytes is - begin skip end with bytes_slice(1n , 2n , s) +function slice_op (const s : bytes) : bytes is Bytes.sub(1n , 2n , s) ``` +> Note that `bytes_slice` is *deprecated*. + ```cameligo -let slice_op (s : bytes) : bytes = - Bytes.slice 1n 2n s +let slice_op (s : bytes) : bytes = Bytes.sub 1n 2n s ``` +> Note that `Bytes.slice` is *deprecated*. + ``` -let slice_op = (s: bytes): bytes => Bytes.slice(1n, 2n, s); +let slice_op = (s: bytes): bytes => Bytes.sub(1n, 2n, s); ``` +> Note that `Bytes.slice` is *deprecated*. + - It would return "7a7a" rather than "ff7a" or "ff" or "7a". -## Bytes.pack(data: a') : bytes + +function pack : 'a -> bytes + + +val pack : 'a -> bytes + + +let pack : 'a => bytes + Converts Michelson data structures to a binary format for serialization. @@ -105,10 +144,19 @@ let id_string = (p: string) : option(string) => { -## Bytes.unpack(packed: bytes) : a' + +function unpack : bytes -> option 'a + + +val unpack : bytes -> 'a option + + +let unpack: bytes => option('a) + -Reverses the result of using `unpack` on data, going from Michelson's binary -serialization format to the `option` type annotated on the call. +Reverses the result of using `pack` on data. + +As the conversion might fail an option type is returned. > ⚠️ `PACK` and `UNPACK` are features of Michelson that are intended to be used by people that really know what they're doing. There are several failure cases (such as `UNPACK`ing a lambda from an untrusted source), most of which are beyond the scope of this document. Don't use these functions without doing your homework first. @@ -143,3 +191,12 @@ let id_string = (p: string) : option(string) => { + +function length : bytes -> nat + + +val length : bytes -> nat + + +let length: bytes => nat + diff --git a/gitlab-pages/docs/reference/crypto.md b/gitlab-pages/docs/reference/crypto.md index 49f5a9f02..ba8d146fd 100644 --- a/gitlab-pages/docs/reference/crypto.md +++ b/gitlab-pages/docs/reference/crypto.md @@ -1,11 +1,58 @@ --- id: crypto-reference -title: Crypto — Cryptographic functions +title: Crypto +description: Cryptographic operations +hide_table_of_contents: true --- import Syntax from '@theme/Syntax'; +import SyntaxTitle from '@theme/SyntaxTitle'; -## Crypto.blake2b(data: bytes): bytes + +type key + + +type key + + +type key + + +A public cryptographic key. + + +type key_hash + + +type key_hash + + +type key_hash + + +The hash of a public cryptographic key. + + +type signature + + +type signature + + +type signature + + +A cryptographic signature. + + +function blake2b : bytes -> bytes + + +val blake2b : bytes -> bytes + + +let blake2b: bytes => bytes + Runs the [blake2b hash algorithm](https://en.wikipedia.org/wiki/BLAKE_(hash_function)#BLAKE2) over the given `bytes` data and returns a `bytes` representing the hash. @@ -15,9 +62,11 @@ over the given `bytes` data and returns a `bytes` representing the hash. ```pascaligo -function hasherman_blake (const s: bytes) : bytes is blake2b(s) +function hasherman_blake (const s: bytes) : bytes is Crypto.blake2b(s) ``` +> Note that `blake2b` is *deprecated*. Please use `Crypto.blake2b`. + @@ -25,6 +74,8 @@ function hasherman_blake (const s: bytes) : bytes is blake2b(s) let hasherman_blake (s: bytes) : bytes = Crypto.blake2b s ``` + + @@ -34,8 +85,15 @@ let hasherman_blake = (s: bytes) => Crypto.blake2b(s); - -## Crypto.sha256(data: bytes) : bytes + +function sha256 : bytes -> bytes + + +val sha256 : bytes -> bytes + + +let sha256: bytes => bytes + Runs the [sha256 hash algorithm](https://en.wikipedia.org/wiki/SHA-2) over the given `bytes` data and returns a `bytes` representing the hash. @@ -45,10 +103,11 @@ Runs the [sha256 hash algorithm](https://en.wikipedia.org/wiki/SHA-2) over the g ```pascaligo -function hasherman (const s : bytes) : bytes is - begin skip end with sha_256(s) +function hasherman (const s : bytes) : bytes is Crypto.sha256(s) ``` +> Note that `sha_256` is *deprecated*. Please use `Crypto.sha256`. + @@ -66,8 +125,15 @@ let hasherman = (s: bytes): bytes => Crypto.sha256(s); - -## Crypto.sha512(data: bytes) : bytes + +function sha512 : bytes -> bytes + + +val sha512 : bytes -> bytes + + +let sha512: bytes => bytes + Runs the [sha512 hash algorithm](https://en.wikipedia.org/wiki/SHA-2) over the given `bytes` data and returns a `bytes` representing the hash. @@ -77,9 +143,11 @@ Runs the [sha512 hash algorithm](https://en.wikipedia.org/wiki/SHA-2) over the g ```pascaligo -function hasherman512 (const s: bytes) : bytes is sha_512(s) +function hasherman512 (const s: bytes) : bytes is Crypto.sha512(s) ``` +> Note that `sha_512` is *deprecated*. Please use `Crypto.sha512`. + @@ -96,8 +164,15 @@ let hasherman512 = (s: bytes) => Crypto.sha512(s); - -## Crypto.hash_key(k: key) : key_hash + +function hash_key : key -> key_hash + + +val hash_key : key -> key_hash + + +let hash_key: key => key_hash + Hashes a key for easy comparison and storage. @@ -108,11 +183,13 @@ Hashes a key for easy comparison and storage. ```pascaligo function check_hash_key (const kh1 : key_hash; const k2 : key) : bool * key_hash is block { var ret : bool := False ; - var kh2 : key_hash := crypto_hash_key(k2) ; + var kh2 : key_hash := Crypto.hash_key(k2) ; if kh1 = kh2 then ret := True else skip; } with (ret, kh2) ``` +> Note that `hash_key` is *deprecated*. Please use `Crypto.hash_key`. + @@ -141,8 +218,15 @@ let check_hash_key = ((kh1, k2): (key_hash, key)) : (bool, key_hash) => { - -## Crypto.check(pk: key, signed: signature, data: bytes) : bool + +function check : key -> signature -> bytes -> bool + + +val check : key -> signature -> bytes -> bool + + +let check: (key, signature, bytes) => bool + Check that a message has been signed by a particular key. @@ -157,9 +241,11 @@ function check_signature (const pk: key; const signed: signature; const msg: bytes) : bool - is crypto_check(pk, signed, msg) + is Crypto.check(pk, signed, msg) ``` +> Note that `crypto_check` is *deprecated*. Please use `Crypto.check`. + diff --git a/gitlab-pages/docs/reference/current.md b/gitlab-pages/docs/reference/current.md index 642bbb6fe..56c719630 100644 --- a/gitlab-pages/docs/reference/current.md +++ b/gitlab-pages/docs/reference/current.md @@ -1,11 +1,96 @@ --- id: current-reference -title: Tezos - Things relating to the current execution context +title: Tezos +description: General operations for Tezos +hide_table_of_contents: true --- import Syntax from '@theme/Syntax'; +import SyntaxTitle from '@theme/SyntaxTitle'; -# Tezos.balance + +type timestamp + + +type timestamp + + +type timestamp + + +A date in the real world. + + +type mutez + + +type mutez + + +type mutez + + +A specific type for tokens. + + +type address + + +type address + + +type address + + +An untyped address which can refer to a smart contract or account. + + +type contract('parameter) + + +type 'parameter contract + + +type contract('parameter) + + +A typed contract. + +Use `unit` as `parameter` to indicate an implicit account. + + +type operation + + +type operation + + +type operation + + +An operation emitted by the contract + + +type chain_id + + +type chain_id + + +type chain_id + + +The identifier of a chain, used to indicate test or main chains. + + +function balance : mutez + + +val balance : mutez + + +let balance: mutez + Get the balance for the contract. @@ -18,7 +103,7 @@ function main (const p : unit; const s: tez) : list (operation) * tez is ((nil : list (operation)), Tezos.balance) ``` -> Note that `balance` and `Current.balance` are *deprecated*. +> Note that `balance` and `Current.balance` are *deprecated*. @@ -42,7 +127,15 @@ let main = ((p,s) : (unit, tez)) => -## Tezos.now + +function now : timestamp + + +val now : timestamp + + +let now: timestamp + Returns the current time as a [unix timestamp](https://en.wikipedia.org/wiki/Unix_time). @@ -64,7 +157,7 @@ const some_date: timestamp = ("2000-01-01T10:10:10Z" : timestamp); const one_day_later: timestamp = some_date + one_day; ``` -> Note that `now` is *deprecated*. +> Note that `now` is *deprecated*. Please use `Tezos.now`. @@ -106,7 +199,7 @@ const one_day: int = 86_400; const in_24_hrs: timestamp = today - one_day; ``` -> Note that `now` is *deprecated*. +> Note that `now` is *deprecated*. Please use `Tezos.now`. @@ -145,7 +238,7 @@ for numbers const not_tommorow: bool = (Tezos.now = in_24_hrs) ``` -> Note that `now` is *deprecated*. +> Note that `now` is *deprecated*. Please use `Tezos.now`. @@ -169,7 +262,15 @@ let not_tomorrow: bool = (Tezos.now == in_24_hrs); -## Amount + +function amount : mutez + + +val amount : mutez + + +let amount: mutez + Get the amount of tez provided by the sender to complete this transaction. @@ -207,7 +308,15 @@ let threshold = (p : unit) : int => -## Sender + +function sender : address + + +val sender : address + + +let sender: address + Get the address that initiated the current transaction. @@ -219,7 +328,7 @@ Get the address that initiated the current transaction. function main (const p : unit) : address is Tezos.sender ``` -> Note that `sender` is *deprecated*. +> Note that `sender` is *deprecated*. Please use `Tezos.sender`. @@ -243,7 +352,15 @@ let main = (p : unit) : address => Tezos.sender; -## Address + +function address : contract 'a -> address + + +val address : 'a contract -> address + + +let address: contract('a) => address + Get the address associated with a value of type `contract`. @@ -257,7 +374,7 @@ function main (const p : key_hash) : address is block { } with Tezos.address(c) ``` -> Note that `implicit_account` and `address` are *deprecated*. +> Note that `implicit_account` and `address` are *deprecated*. Please use `Tezos.implicit_account` and `Tezos.address` instead. @@ -287,7 +404,15 @@ let main = (p : key_hash) : address => { -## Self Address + +function self_address : address + + +val self_address : address + + +let self_address: address + Get the address of the currently running contract. @@ -299,7 +424,7 @@ Get the address of the currently running contract. function main (const p : unit) : address is Tezos.self_address ``` -> Note that `self_address` is *deprecated*. +> Note that `self_address` is *deprecated*. Please use `Tezos.self_address`. @@ -320,8 +445,15 @@ let main = (p : unit) : address => Tezos.self_address; > Note that `Current.self_address` is *deprecated*. - -## Self + +function self : string -> contract 'a + + +val self : string -> 'a contract + + +let self: string => contract('a) + Typecast the currently running contract with an entrypoint annotation. If your are using entrypoints: use "%bar" for constructor Bar @@ -353,13 +485,21 @@ let main = (p: unit) : contract(unit) => -## Implicit Account + +function implicit_account : key_hash -> contract 'a + + +val implicit_account : key_hash -> 'a contract + + +let implicit_account: key_hash => contract('a) + Get the default contract associated with an on-chain key-pair. This contract does not execute code, instead it exists to receive tokens on behalf of a key's owner. - +See also: http://tezos.gitlab.io/user/glossary.html#implicit-account @@ -368,7 +508,7 @@ function main (const kh: key_hash) : contract (unit) is Tezos.implicit_account (kh) ``` -> Note that `implicit_account` is *deprecated*. +> Note that `implicit_account` is *deprecated*. Please use `Tezos.implicit_account`. @@ -392,7 +532,15 @@ let main = (kh : key_hash): contract (unit) => -## Source + +function source : address + + +val source : address + + +let source: address + Get the _originator_ (address) of the current transaction. That is, if a chain of transactions led to the current execution get the address @@ -426,7 +574,7 @@ current transaction. function main (const p: unit) : address is Tezos.source ``` -> Note that `source` is *deprecated*. +> Note that `source` is *deprecated*. Please use `Tezos.source`. @@ -449,7 +597,15 @@ let main = (p : unit) : address => Tezos.source; -## Failwith + +function failwith : string -> unit + + +function failwith : string -> unit + + +function failwith : string -> unit + Cause the contract to fail with an error message. @@ -485,3 +641,125 @@ let main = ((p,s) : (int, unit)) => + +function chain_id : chain_id + + +val chain_id : chain_id + + +let chain_id: chain_id + + +Get the identifier of the chain to distinguish between main and test chains. + +This is mainly intended to avoid replay attacks between the chains, and can currently +only be used together with `Bytes.pack` and `Bytes.unpack`. + + + +```pascaligo +type storage is bytes + +function main (const ignore : unit; const storage: storage) : + (list(operation) * storage) is block { + const packed : bytes = Bytes.pack (Tezos.chain_id); + if (storage =/= packed) then { + failwith("wrong chain") + } else + skip; +} with ((nil: list(operation)), packed) +``` + + + + +```cameligo +type storage = bytes + +let main ((ignore, storage): (unit * storage)) = + let packed = Bytes.pack Tezos.chain_id in + if (storage <> packed) then + (failwith "wrong chain" : (operation list * storage)) + else + (([]: operation list), (packed: storage)) +``` + + + + +```reasonligo +type storage = bytes; + +let main = ((ignore, storage): (unit, storage)) => { + let packed = Bytes.pack(Tezos.chain_id); + if (storage != packed) { + (failwith("wrong chain"): (list(operation), storage)); + } else { + ([]: list(operation), packed); + } +}; +``` + + + + +function transaction : 'parameter -> mutez -> contract('parameter) -> operation + + +val transaction : 'parameter -> mutez -> 'parameter contract -> operation + + +let transaction: 'parameter -> mutez -> contract('parameter) -> operation + + +Create a transaction to a contract or account. + +To indicate an account, use `unit` as `parameter`. + + + +function set_delegate : option(key_hash) -> operation + + +val set_delegate : key_hash option -> operation + + +let set_delegate: option(key_hash) => operation + + +Create a delegation. + +See also: http://tezos.gitlab.io/user/glossary.html?highlight=delegate#delegate + + +function get_contract_opt : address -> option(contract('parameter)) + + +val get_contract_opt : address -> 'parameter contract option + + +let get_contract_opt : address => option(contract('parameter)) + + +Get a contract from an address. + +When no contract is found or the contract doesn't match the type, +`None` is returned. + + +function get_entrypoint_opt : string -> address -> option(contract('parameter)) + + +function get_entrypoint_opt : string -> address -> 'parameter contract option + + +function get_entrypoint_opt: (string, address) => option(contract('parameter)) + + +Get a contract from an address and entrypoint. + +Entrypoints are written in the form of: `%entrypoint`. + +When no contract is found or the contract doesn't match the type, +`None` is returned. diff --git a/gitlab-pages/docs/reference/list.md b/gitlab-pages/docs/reference/list.md index cbded72e6..e85e5b543 100644 --- a/gitlab-pages/docs/reference/list.md +++ b/gitlab-pages/docs/reference/list.md @@ -1,96 +1,62 @@ --- id: list-reference -title: Lists — Linear Collections +title: List +description: List operations +hide_table_of_contents: true --- import Syntax from '@theme/Syntax'; +import SyntaxTitle from '@theme/SyntaxTitle'; -Lists are linear collections of elements of the same type. Linear -means that, in order to reach an element in a list, we must visit all -the elements before (sequential access). Elements can be repeated, as -only their order in the collection matters. The first element is -called the *head*, and the sub-list after the head is called the -*tail*. For those familiar with algorithmic data structure, you can -think of a list a *stack*, where the top is written on the left. + +type list ('t) + + +type 't list + + +type list('t) + -# Defining Lists +A sequence of elements of the same type. + +function length : nat + + +val length : nat + + +let length: nat + - +Get the number of elements in a list. -```pascaligo group=lists -const empty_list : list (int) = nil // Or list [] -const my_list : list (int) = list [1; 2; 2] // The head is 1 -``` + +function size : nat + + +val size : nat + + +let size: nat + - - +Get the number of elements in a list. -```cameligo group=lists -let empty_list : int list = [] -let my_list : int list = [1; 2; 2] // The head is 1 -``` - - - - -```reasonligo group=lists -let empty_list : list (int) = []; -let my_list : list (int) = [1, 2, 2]; // The head is 1 -``` - - - - -# Adding to Lists - -Lists can be augmented by adding an element before the head (or, in -terms of stack, by *pushing an element on top*). - - - - - -```pascaligo group=lists -const larger_list : list (int) = 5 # my_list // [5;1;2;2] -``` - - - - -```cameligo group=lists -let larger_list : int list = 5 :: my_list // [5;1;2;2] -``` - - - - -```reasonligo group=lists -let larger_list : list (int) = [5, ...my_list]; // [5,1,2,2] -``` - - - - - -# Functional Iteration over Lists - -A *functional iterator* is a function that traverses a data structure -and calls in turn a given function over the elements of that structure -to compute some value. Another approach is possible in PascaLIGO: -*loops* (see the relevant section). - -There are three kinds of functional iterations over LIGO lists: the -*iterated operation*, the *map operation* (not to be confused with the -*map data structure*) and the *fold operation*. - -## Iterated Operation over Lists - -The first, the *iterated operation*, is an iteration over the list -with a unit return value. It is useful to enforce certain invariants -on the element of a list, or fail. +Synonym for `List.length`. + +function iter : ('a -> unit) -> list('a) -> unit + + +val iter : ('a -> unit) -> 'a list -> unit + + +let iter: (('a => unit), list('a)) => unit + +Iterate over items in a list. @@ -104,6 +70,8 @@ function iter_op (const l : list (int)) : unit is > Note that `list_iter` is *deprecated*. +Alternatively it's also possible to use [loops](../language-basics/loops.md). + @@ -126,17 +94,23 @@ let iter_op = (l : list (int)) : unit => { -## Mapped Operation over Lists - -We may want to change all the elements of a given list by applying to -them a function. This is called a *map operation*, not to be confused -with the map data structure. - + +function map : ('a -> 'b) -> list('a) -> list('b) + + +val map : ('a -> 'b) -> 'a list -> 'b list + + +let map: (('a => 'b), list('a)) => list('b) + +Apply a function to items of a list to create a new list. ```pascaligo group=lists +const larger_list: list(int) = list [1; 2; 3] + function increment (const i : int): int is i + 1 // Creates a new list with all elements incremented by 1 @@ -149,6 +123,8 @@ const plus_one : list (int) = List.map (increment, larger_list) ```cameligo group=lists +let larger_list: int list = [1; 2; 3] + let increment (i : int) : int = i + 1 // Creates a new list with all elements incremented by 1 @@ -159,6 +135,8 @@ let plus_one : int list = List.map increment larger_list ```reasonligo group=lists +let larger_list: list(int) = [1, 2, 3]; + let increment = (i : int) : int => i + 1; // Creates a new list with all elements incremented by 1 @@ -167,22 +145,25 @@ let plus_one : list (int) = List.map (increment, larger_list); + +function fold : (('accumulator -> 'item -> 'accumulator) -> list('item) -> 'accumulator) -> 'accumulator + + +val fold : ('accumulator -> 'item -> 'accumulator) -> 'item list -> 'accumulator -> 'accumulator + + +let fold: ((('accumulator, 'item) => 'accumulator), list('item), 'accumulator) => 'accumulator + - -## Folded Operation over Lists - -A *folded operation* is the most general of iterations. The folded -function takes two arguments: an *accumulator* and the structure -*element* at hand, with which it then produces a new accumulator. This -enables having a partial result that becomes complete when the -traversal of the data structure is over. - - +[Fold over items in a list](../language-basics/sets-lists-tuples#folded-operation-over-lists); ```pascaligo group=lists +const my_list: list(int) = list [1; 2; 3] + function sum (const acc : int; const i : int): int is acc + i + const sum_of_elements : int = List.fold (sum, my_list, 0) ``` @@ -192,7 +173,10 @@ const sum_of_elements : int = List.fold (sum, my_list, 0) ```cameligo group=lists -let sum (acc, i: int * int) : int = acc + i +let my_list : int list = [1; 2; 3] + +let sum (acc, i : int * int) : int = acc + i + let sum_of_elements : int = List.fold sum my_list 0 ``` @@ -200,40 +184,11 @@ let sum_of_elements : int = List.fold sum my_list 0 ```reasonligo group=lists +let my_list : list(int) = [1, 2, 3]; + let sum = ((result, i): (int, int)): int => result + i; + let sum_of_elements : int = List.fold (sum, my_list, 0); ``` - - -# List Length - -Get the number of elements in a list. - - - - - -```pascaligo -function size_of (const l : list (int)) : nat is List.length (l) -``` - -> Note that `size` is *deprecated*. - - - - -```cameligo -let size_of (l : int list) : nat = List.length l -``` - - - - -```reasonligo -let size_of = (l : list (int)) : nat => List.length (l); -``` - - - diff --git a/gitlab-pages/docs/reference/map.md b/gitlab-pages/docs/reference/map.md index b359380eb..bf26f6bcf 100644 --- a/gitlab-pages/docs/reference/map.md +++ b/gitlab-pages/docs/reference/map.md @@ -1,22 +1,28 @@ --- id: map-reference -title: Maps +title: Map +description: Map operations +hide_table_of_contents: true --- import Syntax from '@theme/Syntax'; +import SyntaxTitle from '@theme/SyntaxTitle'; -*Maps* are a data structure which associate values of the same type to -values of the same type. The former are called *key* and the latter -*values*. Together they make up a *binding*. An additional requirement -is that the type of the keys must be *comparable*, in the Michelson -sense. - -# Declaring a Map - - + +type map ('key, 'value) + + +type ('key, 'value) map + + +type map ('key, 'value) + +The type of a map from values of type `key` to +values of type `value` is `map (key, value)`. + ```pascaligo group=maps type move is int * int type register is map (address, move) @@ -25,6 +31,9 @@ type register is map (address, move) +The type of a map from values of type `key` to values +of type `value` is `(key, value) map`. + ```cameligo group=maps type move = int * int type register = (address, move) map @@ -33,6 +42,9 @@ type register = (address, move) map +The type of a map from values of type `key` to +values of type `value` is `map (key, value)`. + ```reasonligo group=maps type move = (int, int); type register = map (address, move); @@ -40,13 +52,26 @@ type register = map (address, move); + +function empty : map ('key, 'value) + + +val empty : ('key, 'value) map + + +let empty: map('key, 'value) + -# Creating an Empty Map - - +Create an empty map. +```pascaligo group=maps +const empty : register = Map.empty +``` + +Or + ```pascaligo group=maps const empty : register = map [] ``` @@ -68,16 +93,34 @@ let empty : register = Map.empty -# Creating a Non-empty Map + +function literal : list ('key * 'value) -> map ('key, 'value) + + +val literal : ('key * 'value) list -> ('key, 'value) map + + +let literal: list(('key, 'value)) => map('key, 'value) + +Create a non-empty map. ```pascaligo group=maps const moves : register = + Map.literal (list [ + (("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address), (1,2)); + (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address), (0,3))]); +``` + +Alternative way of creating an empty map: + +```pascaligo group=maps +const moves_alternative : register = map [ ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address) -> (1,2); - ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) -> (0,3)] + ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) -> (0,3)]; ``` @@ -103,14 +146,32 @@ let moves : register = -# Accessing Map Bindings + +function find_opt : 'key -> map ('key, 'value) -> option 'value + + +val find_opt : 'key -> ('key, 'value) map -> 'value option + + +let find_opt : ('key, map ('key, 'value)) => option ('value) + + +Retrieve a (option) value from a map with the given key. Returns `None` if the +key is missing and the value otherwise. ```pascaligo group=maps const my_balance : option (move) = - moves [("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address)] + Map.find_opt (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address), moves) +``` + +Alternatively: + +```pascaligo group=maps +const my_balance_alternative : option (move) = + moves [("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address)]; ``` @@ -126,67 +187,40 @@ let my_balance : move option = ```reasonligo group=maps let my_balance : option (move) = - Map.find_opt (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address), moves); + Map.find_opt ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address, moves); ``` -Notice how the value we read is an optional value: this is to force -the reader to account for a missing key in the map. This requires -*pattern matching*. - + +function update : 'key -> option 'value -> map ('key, 'value) -> map ('key, 'value) + + +val update: 'key -> 'value option -> ('key, 'value) map -> ('key, 'value) map + + +let update: ('key, option('value), map('key, 'value)) => map ('key, 'value) + +Note: when `None` is used as a value, the key and associated value is removed +from the map. ```pascaligo group=maps -function force_access (const key : address; const moves : register) : move is - case moves[key] of - Some (move) -> move - | None -> (failwith ("No move.") : move) - end + const updated_map : register = Map.update(("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), Some (4,9), moves); ``` - - - -```cameligo group=maps -let force_access (key, moves : address * register) : move = - match Map.find_opt key moves with - Some move -> move - | None -> (failwith "No move." : move) -``` - - - - -```reasonligo group=maps -let force_access = ((key, moves) : (address, register)) : move => { - switch (Map.find_opt (key, moves)) { - | Some (move) => move - | None => failwith ("No move.") : move - } -}; -``` - - - - -# Updating a Map - -Given a map, we may want to add a new binding, remove one, or modify -one by changing the value associated to an already existing key. All -those operations are called *updates*. - - - +Alternatively: ```pascaligo group=maps -function assign (var m : register) : register is + +function update (var m : register) : register is block { - m [("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address)] := (4,9) + m [("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address)] := (4,9); } with m + ``` If multiple bindings need to be updated, PascaLIGO offers a *patch @@ -206,14 +240,40 @@ function assignments (var m : register) : register is ```cameligo group=maps -let assign (m : register) : register = +let updated_map : register = Map.update - ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) (Some (4,9)) m + ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) (Some (4,9)) moves ``` -Notice the optional value `Some (4,9)` instead of `(4,9)`. If we had -use `None` instead, that would have meant that the binding is removed. -As a particular case, we can only add a key and its associated value. + + + +```reasonligo group=maps +let updated_map : register = + Map.update + (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), Some ((4,9)), moves); +``` + + + + + +function add : 'key -> 'value -> map ('key, 'value) -> map ('key, 'value) + + +val add : 'key -> 'value -> ('key, 'value) map -> ('key, 'value) map + + +let add: ('key, 'value, map('key, 'value)) => map('key, 'value) + + + +```pascaligo group=maps +const added_item : register = Map.add (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address), (4, 9), moves) +``` + + + ```cameligo group=maps let add (m : register) : register = @@ -225,18 +285,7 @@ let add (m : register) : register = ```reasonligo group=maps -let assign = (m : register) : register => - Map.update - (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address), Some ((4,9)), m); -``` - -Notice the optional value `Some (4,9)` instead of `(4,9)`. If we had -use `None` instead, that would have meant that the binding is removed. - -As a particular case, we can only add a key and its associated value. - -```reasonligo group=maps -let add = (m : register) : register => +let add = (m: register): register => Map.add (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address), (4,9), m); ``` @@ -244,57 +293,63 @@ let add = (m : register) : register => -To remove a binding from a map, we need its key. - - + +function remove : 'key -> map ('key, 'value) -> map ('key, 'value) + + +val remove : 'key -> ('key, 'value) map -> ('key, 'value) map + + +let remove: (key, map('key, 'value)) => map('key, 'value) + ```pascaligo group=maps -function delete (const key : address; var moves : register) : register is + const updated_map : register = + Map.remove (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), moves) +``` + +Alternatively, the instruction `remove key from map m` removes the key +`key` from the map `m`. + +```pascaligo group=maps +function rem (var m : register) : register is block { - remove key from map moves - } with moves + remove ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address) from map moves + } with m + +const updated_map : register = rem (moves) ``` ```cameligo group=maps -let delete (key, moves : address * register) : register = - Map.remove key moves +let updated_map : register = + Map.remove ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address) moves ``` ```reasonligo group=maps -let delete = ((key, moves) : (address, register)) : register => - Map.remove (key, moves); +let updated_map : register = + Map.remove (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), moves) ``` - -# Functional Iteration over Maps - -A *functional iterator* is a function that traverses a data structure -and calls in turn a given function over the elements of that structure -to compute some value. Another approach is possible in PascaLIGO: -*loops* (see the relevant section). - -There are three kinds of functional iterations over LIGO maps: the -*iterated operation*, the *map operation* (not to be confused with the -*map data structure*) and the *fold operation*. - -## Iterated Operation over Maps - -The first, the *iterated operation*, is an iteration over the map with -no return value: its only use is to produce side-effects. This can be -useful if for example you would like to check that each value inside -of a map is within a certain range, and fail with an error otherwise. - + +function iter : ((key, value) -> unit) -> map (key, value) -> unit + + +val iter : (('key * 'value) -> unit) -> ('key, 'value) map -> unit + + +let iter: ((('key, 'value)) => unit, map('key, 'value)) => unit + @@ -330,14 +385,15 @@ let iter_op = (m : register) : unit => { - -## Map Operations over Maps - -We may want to change all the bindings of a map by applying to them a -function. This is called a *map operation*, not to be confused with -the map data structure. The predefined functional iterator -implementing the map operation over maps is called `Map.map`. - + +function map : (('key, 'value) -> ('mapped_key, 'mapped_item)) -> map ('key, 'value) -> map ('mapped_key, 'mapped_value) + + +val map : (('key * 'value) -> ('mapped_key * 'mapped_item)) -> (key, value) map -> (mapped_key, mapped_value) map + + +let map: ((('key, 'value)) => ('mapped_key, 'mapped_item), map(key, value)) => map(mapped_key, mapped_value) + @@ -374,14 +430,15 @@ let map_op = (m : register) : register => { -## Folded Operations over Maps - -A *folded operation* is the most general of iterations. The folded -function takes two arguments: an *accumulator* and the structure -*element* at hand, with which it then produces a new accumulator. This -enables having a partial result that becomes complete when the -traversal of the data structure is over. - + +function fold : (('accumulator -> ('key, 'value) -> 'accumulator) -> map ('key, 'value) -> 'accumulator) -> 'accumulator + + +val fold : ('accumulator -> ('key * 'value) -> 'accumulator) -> ('key, 'value) map -> 'accumulator -> 'accumulator + + +let fold: ((('accumulator, ('key, 'value)) => 'accumulator), map('key, 'value), 'accumulator) => 'accumulator + @@ -417,3 +474,28 @@ let fold_op = (m : register) : int => { + +function size : map ('key, 'value) -> nat + + +val size : ('key, 'value) map -> nat + + +let size: map('key, 'value) => nat + + +Returns the number of items in the map. + + + +function mem : key -> map (key, value) -> bool + + +val mem : 'key -> ('key, 'value) map => bool + + +let mem : ('key, map('key, 'value)) => bool + + +Checks if a key exists in the map. + diff --git a/gitlab-pages/docs/reference/set.md b/gitlab-pages/docs/reference/set.md index eca62a741..9478a2048 100644 --- a/gitlab-pages/docs/reference/set.md +++ b/gitlab-pages/docs/reference/set.md @@ -1,20 +1,45 @@ --- id: set-reference -title: Sets — Unordered unique collection of a type +title: Set +description: Set operations +hide_table_of_contents: true --- import Syntax from '@theme/Syntax'; +import SyntaxTitle from '@theme/SyntaxTitle'; -Sets are unordered collections of values of the same type, like lists -are ordered collections. Like the mathematical sets and lists, sets -can be empty and, if not, elements of sets in LIGO are *unique*, -whereas they can be repeated in a *list*. +Sets are unordered collections of unique values of the same type. -# Empty Sets + +type set ('value) + + +type 'value set + + +type set('value) + + +function empty : set('value) + + +val empty : 'value set + + +let empty: set('value) + + +Create an empty set. +```pascaligo group=sets +const my_set : set (int) = Set.empty +``` + +Alternative syntax: + ```pascaligo group=sets const my_set : set (int) = set [] ``` @@ -35,12 +60,26 @@ let my_set : set (int) = Set.empty; + +function literal : list('value) -> set('value) + + +val literal : 'value list -> 'value set + + +let literal: list('value) => set('value) + -# Non-empty Sets - +Create a non-empty set. +```pascaligo group=sets +const my_set : set (int) = Set.literal (list [3; 2; 2; 1]) +``` + +Or use the following syntax sugar: + ```pascaligo group=sets const my_set : set (int) = set [3; 2; 2; 1] ``` @@ -50,7 +89,7 @@ const my_set : set (int) = set [3; 2; 2; 1] ```cameligo group=sets let my_set : int set = - Set.add 3 (Set.add 2 (Set.add 2 (Set.add 1 (Set.empty : int set)))) + Set.literal [3; 2; 2; 1] ``` @@ -58,19 +97,33 @@ let my_set : int set = ```reasonligo group=sets let my_set : set (int) = - Set.add (3, Set.add (2, Set.add (2, Set.add (1, Set.empty : set (int))))); + Set.literal ([3, 2, 2, 1]); ``` + +function mem : 'value -> set('value) -> 'bool + + +val mem : 'value -> 'value set -> bool + + +let mem: ('value, set('value)) => bool + -# Set Membership - +Checks if a value exists in the set. ```pascaligo group=sets -const contains_3 : bool = my_set contains 3 +const contains_3 : bool = Set.mem(3, my_set) +``` + +Or: + +```pascaligo group=sets +const contains_3_alt : bool = my_set contains 3 ``` @@ -89,12 +142,17 @@ let contains_3 : bool = Set.mem (3, my_set); + +function cardinal : set('value) -> nat + + +val cardinal : 'value set -> nat + + +let cardinal: set('value) => nat + -# Cardinal of Sets - -The predefined function `Set.size` returns the number of -elements in a given set as follows. - +Number of elements in a set. @@ -102,7 +160,7 @@ elements in a given set as follows. const cardinal : nat = Set.size (my_set) ``` -> Note that `size` is *deprecated*. +> Note that `size` is *deprecated*. Please use `Set.size` @@ -120,72 +178,41 @@ let cardinal : nat = Set.size (my_set); + +function add : 'value -> set('value) -> set('value) + + +val add : 'value -> 'value set -> 'value set + + +let add: ('value, set('value)) => set('value) + -# Updating Sets +Add a value to a set. -There are two ways to update a set, that is to add or remove from it. + +function remove : 'value -> set('value) -> set('value) + + +val remove : 'value -> 'value set -> 'value set + + +let remove: ('value, set('value)) => set('value) + +Remove a value from a set. - + +function iter : ('a -> unit) -> set('a) -> unit + + +val iter : ('a -> unit) -> 'a set -> unit + + +let iter: (('a => unit), set('a)) => unit + -In PascaLIGO, either we create a new set from the given one, or we -modify it in-place. First, let us consider the former way: -```pascaligo group=sets -const larger_set : set (int) = Set.add (4, my_set) -const smaller_set : set (int) = Set.remove (3, my_set) -``` - -> Note that `set_add` and `set_remove` are *deprecated*. - -If we are in a block, we can use an instruction to modify the set -bound to a given variable. This is called a *patch*. It is only -possible to add elements by means of a patch, not remove any: it is -the union of two sets. - -```pascaligo group=sets -function update (var s : set (int)) : set (int) is block { - patch s with set [4; 7] -} with s - -const new_set : set (int) = update (my_set) -``` - - - - -```cameligo group=sets -let larger_set : int set = Set.add 4 my_set -let smaller_set : int set = Set.remove 3 my_set -``` - - - - -```reasonligo group=sets -let larger_set : set (int) = Set.add (4, my_set); -let smaller_set : set (int) = Set.remove (3, my_set); -``` - - - - -# Functional Iteration over Sets - -A *functional iterator* is a function that traverses a data structure -and calls in turn a given function over the elements of that structure -to compute some value. Another approach is possible in PascaLIGO: -*loops* (see the relevant section). - -There are three kinds of functional iterations over LIGO maps: the -*iterated operation*, the *mapped operation* (not to be confused with -the *map data structure*) and the *folded operation*. - -## Iterated Operation - -The first, the *iterated operation*, is an iteration over the map with -no return value: its only use is to produce side-effects. This can be -useful if for example you would like to check that each value inside -of a map is within a certain range, and fail with an error otherwise. +Iterate over values in a set. @@ -221,15 +248,17 @@ let iter_op = (s : set (int)) : unit => { + +function fold : (('accumulator -> 'item -> 'accumulator) -> set ('item) -> 'accumulator) -> 'accumulator + + +val fold : ('accumulator -> 'item -> 'accumulator) -> 'set list -> 'accumulator -> 'accumulator + + +let fold: ((('accumulator, 'item) => 'accumulator), set('item), 'accumulator) => 'accumulator + -## Folded Operation - -A *folded operation* is the most general of iterations. The folded -function takes two arguments: an *accumulator* and the structure -*element* at hand, with which it then produces a new accumulator. This -enables having a partial result that becomes complete when the -traversal of the data structure is over. - +[Fold over values in a set](../language-basics/sets-lists-tuples#folded-operation) @@ -241,17 +270,6 @@ const sum_of_elements : int = Set.fold (sum, my_set, 0) > Note that `set_fold` is *deprecated*. -It is possible to use a *loop* over a set as well. - -```pascaligo group=sets -function loop (const s : set (int)) : int is block { - var sum : int := 0; - for element in set s block { - sum := sum + element - } -} with sum -``` - @@ -269,4 +287,3 @@ let sum_of_elements : int = Set.fold (sum, my_set, 0); ``` - diff --git a/gitlab-pages/docs/reference/string.md b/gitlab-pages/docs/reference/string.md index c75e850a4..b61453ec7 100644 --- a/gitlab-pages/docs/reference/string.md +++ b/gitlab-pages/docs/reference/string.md @@ -1,45 +1,77 @@ --- id: string-reference -title: String — Manipulate string data +title: String +description: Operations for strings. +hide_table_of_contents: true --- import Syntax from '@theme/Syntax'; +import SyntaxTitle from '@theme/SyntaxTitle'; -## String.size(s: string) : nat + +type string + + +type string + + +type string + -Get the size of a string. [Michelson only supports ASCII strings](http://tezos.gitlab.io/whitedoc/michelson.html#constants) +A sequence of characters. + + +function length : string -> nat + + +val length : string -> nat + + +let length: string => nat + + +Get the size of a string. + +[Michelson only supports ASCII strings](http://tezos.gitlab.io/whitedoc/michelson.html#constants) so for now you can assume that each character takes one byte of storage. - - ```pascaligo -function string_size (const s: string) : nat is size(s) +function string_size (const s: string) : nat is String.length(s) ``` +> Note that `size` and `String.size` are *deprecated*. + ```cameligo -let size_op (s: string) : nat = String.size s +let size_op (s: string) : nat = String.length s ``` +> Note that `String.size` is *deprecated*. + ```reasonligo -let size_op = (s: string): nat => String.size(s); +let size_op = (s: string): nat => String.length(s); ``` +> Note that `String.size` is *deprecated*. + - -## String.length(s: string) : nat - -Alias for `String.size`. - -## String.slice(pos1: nat, pos2: nat, s: string) : string + +function sub : nat -> nat -> string -> string + + +val sub : nat -> nat -> string -> string + + +let sub: (nat, nat, string) => string + Get the substring of `s` between `pos1` inclusive and `pos2` inclusive. For example the string "tata" given to the function below would return "at". @@ -48,31 +80,41 @@ the string "tata" given to the function below would return "at". ```pascaligo -function slice_op (const s : string) : string is string_slice(1n , 2n , s) +function slice_op (const s : string) : string is String.sub(1n , 2n , s) ``` +> Note that `string_slice` is *deprecated*. + ```cameligo -let slice_op (s: string) : string = String.slice 1n 2n s +let slice_op (s: string) : string = String.sub 1n 2n s ``` +> Note that `String.slice` is *deprecated*. + ```reasonligo -let slice_op = (s: string): string => String.slice(1n, 2n, s); +let slice_op = (s: string): string => String.sub(1n, 2n, s); ``` +> Note that `String.slice` is *deprecated*. + -## String.sub(pos1: nat, pos2: nat, s: string) : string - -Alias for `String.slice`. - -## String.concat(s1: string, s2: string) : string + +function concat : string -> string -> string + + +val concat : string -> string -> string + + +let concat: (string, string) => string + Concatenate two strings and return the result. @@ -81,21 +123,40 @@ Concatenate two strings and return the result. ```pascaligo -function concat_op (const s : string) : string is s ^ "toto" +function concat_op (const s : string) : string is String.concat(s, "toto") +``` + +Alternatively: + +```pascaligo +function concat_op_alt (const s : string) : string is s ^ "toto" ``` ```cameligo -let concat_syntax (s: string) = s ^ "test_literal" +let concat_syntax (s: string) = String.concat s "test_literal" ``` +Alternatively: + +```cameligo +let concat_syntax_alt (s: string) = s ^ "test_literal" +``` + + ```reasonligo -let concat_syntax = (s: string) => s ++ "test_literal"; +let concat_syntax = (s: string) => String.concat(s, "test_literal"); +``` + +Alternatively: + +```reasonligo +let concat_syntax_alt = (s: string) => s ++ "test_literal"; ``` diff --git a/gitlab-pages/website/docusaurus.config.js b/gitlab-pages/website/docusaurus.config.js index 5fd7c6ddd..9cab1f4ea 100644 --- a/gitlab-pages/website/docusaurus.config.js +++ b/gitlab-pages/website/docusaurus.config.js @@ -99,7 +99,6 @@ const siteConfig = { },*/ // Add custom scripts here that would be placed in