I upgraded the parsers to accept Map.map etc. I rewrote the doc except "reference" to promote and deprecate built-ins.

This commit is contained in:
Christian Rinderknecht 2020-02-25 18:07:53 +01:00
parent 656807b22e
commit 31a39bffbc
45 changed files with 1534 additions and 1229 deletions

View File

@ -194,8 +194,8 @@ how those built-ins can be utilized.
### Accepting or Declining Tokens in a Smart Contract ### Accepting or Declining Tokens in a Smart Contract
This example shows how `amount` and `failwith` can be used to decline This example shows how `Tezos.amount` and `failwith` can be used to
any transaction that sends more tez than `0mutez`, that is, no decline any transaction that sends more tez than `0tez`, that is, no
incoming tokens are accepted. incoming tokens are accepted.
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
@ -206,11 +206,13 @@ type storage is unit
type return is list (operation) * storage type return is list (operation) * storage
function deny (const action : parameter; const store : storage) : return is function deny (const action : parameter; const store : storage) : return is
if amount > 0mutez then if Tezos.amount > 0tez then
(failwith ("This contract does not accept tokens.") : return) (failwith ("This contract does not accept tokens.") : return)
else ((nil : list (operation)), store) else ((nil : list (operation)), store)
``` ```
> Note that `amount` is *deprecated*.
<!--CameLIGO--> <!--CameLIGO-->
```cameligo group=c ```cameligo group=c
type parameter = unit type parameter = unit
@ -218,11 +220,13 @@ type storage = unit
type return = operation list * storage type return = operation list * storage
let deny (action, store : parameter * storage) : return = let deny (action, store : parameter * storage) : return =
if amount > 0mutez then if Tezos.amount > 0tez then
(failwith "This contract does not accept tokens.": return) (failwith "This contract does not accept tokens." : return)
else (([] : operation list), store) else (([] : operation list), store)
``` ```
> Note that `amount` is *deprecated*.
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo group=c ```reasonligo group=c
type parameter = unit; type parameter = unit;
@ -230,17 +234,20 @@ type storage = unit;
type return = (list (operation), storage); type return = (list (operation), storage);
let deny = ((action, store): (parameter, storage)) : return => { let deny = ((action, store): (parameter, storage)) : return => {
if (amount > 0mutez) { if (Tezos.amount > 0tez) {
(failwith("This contract does not accept tokens."): return); } (failwith("This contract does not accept tokens."): return); }
else { (([] : list (operation)), store); }; else { (([] : list (operation)), store); };
}; };
``` ```
> Note that `amount` is *deprecated*.
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
### Access Control ### Access Control
This example shows how `sender` or `source` can be used to deny access to an entrypoint. This example shows how `Tezos.source` can be used to deny access to an
entrypoint.
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO--> <!--PascaLIGO-->
@ -248,28 +255,35 @@ This example shows how `sender` or `source` can be used to deny access to an ent
const owner : address = ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address); const owner : address = ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address);
function main (const action : parameter; const store : storage) : return is function main (const action : parameter; const store : storage) : return is
if source =/= owner then (failwith ("Access denied.") : return) if Tezos.source =/= owner then (failwith ("Access denied.") : return)
else ((nil : list(operation)), store) else ((nil : list (operation)), store)
``` ```
> Note that `source` is *deprecated*.
<!--CameLIGO--> <!--CameLIGO-->
```cameligo group=c ```cameligo group=c
let owner : address = ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address) let owner : address = ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address)
let main (action, store: parameter * storage) : return = let main (action, store: parameter * storage) : return =
if source <> owner then (failwith "Access denied." : return) if Tezos.source <> owner then (failwith "Access denied." : return)
else (([] : operation list), store) else (([] : operation list), store)
``` ```
> Note that `source` is *deprecated*.
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo group=c ```reasonligo group=c
let owner : address = ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address); let owner : address = ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address);
let main = ((action, store): (parameter, storage)) : storage => { let main = ((action, store) : (parameter, storage)) : storage => {
if (source != owner) { (failwith ("Access denied.") : return); } if (Tezos.source != owner) { (failwith ("Access denied.") : return); }
else { (([] : list (operation)), store); }; else { (([] : list (operation)), store); };
}; };
``` ```
> Note that `source` is *deprecated*.
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
### Inter-Contract Invocations ### Inter-Contract Invocations
@ -327,11 +341,15 @@ const dest : address = ("KT19wgxcuXG9VH4Af5Tpm1vqEKdaMFpznXT3" : address)
function proxy (const action : parameter; const store : storage): return is function proxy (const action : parameter; const store : storage): return is
block { block {
const counter : contract (parameter) = get_contract (dest); const counter : contract (parameter) =
case (Tezos.get_contract_opt (dest) : option (contract (parameter))) of
Some (contract) -> contract
| None -> (failwith ("Contract not found.") : contract (parameter))
end;
(* Reuse the parameter in the subsequent (* Reuse the parameter in the subsequent
transaction or use another one, `mock_param`. *) transaction or use another one, `mock_param`. *)
const mock_param : parameter = Increment (5n); const mock_param : parameter = Increment (5n);
const op : operation = transaction (action, 0mutez, counter); const op : operation = Tezos.transaction (action, 0tez, counter);
const ops : list (operation) = list [op] const ops : list (operation) = list [op]
} with (ops, store) } with (ops, store)
``` ```
@ -363,14 +381,20 @@ type return = operation list * storage
let dest : address = ("KT19wgxcuXG9VH4Af5Tpm1vqEKdaMFpznXT3" : address) let dest : address = ("KT19wgxcuXG9VH4Af5Tpm1vqEKdaMFpznXT3" : address)
let proxy (action, store : parameter * storage) : return = let proxy (action, store : parameter * storage) : return =
let counter : parameter contract = Operation.get_contract dest in let counter : parameter contract =
match (Tezos.get_contract_opt (dest) : parameter contract option) with
Some contract -> contract
| None -> (failwith "Contract not found." : parameter contract) in
(* Reuse the parameter in the subsequent (* Reuse the parameter in the subsequent
transaction or use another one, `mock_param`. *) transaction or use another one, `mock_param`. *)
let mock_param : parameter = Increment (5n) in let mock_param : parameter = Increment (5n) in
let op : operation = Operation.transaction action 0mutez counter let op : operation = Tezos.transaction action 0tez counter
in [op], store in [op], store
``` ```
> Note that `Operation.get_contract` and `Operation.transaction` are
> *deprecated*.
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo skip ```reasonligo skip
// counter.religo // counter.religo
@ -398,13 +422,20 @@ type return = (list (operation), storage);
let dest : address = ("KT19wgxcuXG9VH4Af5Tpm1vqEKdaMFpznXT3" : address); let dest : address = ("KT19wgxcuXG9VH4Af5Tpm1vqEKdaMFpznXT3" : address);
let proxy = ((action, store): (parameter, storage)) : return => { let proxy = ((action, store): (parameter, storage)) : return => {
let counter : contract (parameter) = Operation.get_contract (dest); let counter : contract (parameter) =
switch (Tezos.get_contract_opt (dest) : option (contract (parameter))) {
| Some (contract) => contract;
| None => (failwith ("Contract not found.") : contract (parameter));
};
(* Reuse the parameter in the subsequent (* Reuse the parameter in the subsequent
transaction or use another one, `mock_param`. *) transaction or use another one, `mock_param`. *)
let mock_param : parameter = Increment (5n); let mock_param : parameter = Increment (5n);
let op : operation = Operation.transaction (action, 0mutez, counter); let op : operation = Tezos.transaction (action, 0tez, counter);
([op], store) ([op], store)
}; };
``` ```
> Note that `Operation.get_contract` and `Operation.transaction` are
> *deprecated*.
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->

View File

@ -42,59 +42,78 @@ storage value being returned) which in our case is still `Unit`.
Our counter contract will store a single `int` as it's storage, and Our counter contract will store a single `int` as it's storage, and
will accept an `action` variant in order to re-route our single `main` will accept an `action` variant in order to re-route our single `main`
function to two entrypoints for `addition` and `subtraction`. function to two entrypoints for `add` (addition) and `sub`
(subtraction).
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--Pascaligo--> <!--Pascaligo-->
``` ```
type action is type parameter is
Increment of int Increment of int
| Decrement of int | Decrement of int
function main (const p : action ; const s : int) : (list(operation) * int) is type storage is int
type return is list (operation) * storage
function add (const n : int; const store : storage) : storage is store + n
function sub (const n : int; const store : storage) : storage is store - n
function main (const action : parameter; const store : storage) : return is
((nil : list(operation)), ((nil : list(operation)),
(case p of case action of
| Increment (n) -> s + n Increment (n) -> add (n, store)
| Decrement (n) -> s - n | Decrement (n) -> sub (n, store)
end)) end)
``` ```
<!--CameLIGO--> <!--CameLIGO-->
```cameligo ```cameligo
type action = type parameter =
| Increment of int Increment of int
| Decrement of int | Decrement of int
let main (p, s: action * int) : operation list * int = type storage = int
let result =
match p with type return = (operation) list * storage
| Increment n -> s + n
| Decrement n -> s - n let add (n, store : int * storage) : storage = store + n
in let sub (n, store : int * storage) : storage = store - n
(([]: operation list), result)
let main (action, store : parameter * storage) : operation list * storage =
(([]: operation list),
(match action with
Increment n -> add (n, store)
| Decrement n -> sub (n, store)))
``` ```
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo ```reasonligo
type action = type parameter =
| Increment(int) Increment (int)
| Decrement(int); | Decrement (int)
;
let main = (p_s: (action, int)) : (list(operation), int) => { type storage = int;
let p, s = p_s;
let result = type return = (list (operation), storage);
switch (p) {
| Increment(n) => s + n let add = ((n, store) : (int, storage)) : storage => store + n;
| Decrement(n) => s - n let sub = ((n, store) : (int, storage)) : storage => store - n;
};
(([]: list(operation)), result); let main = ((action, store) : (parameter, storage)) : return =>
}; (([]: list (operation)),
(switch (action) {
| Increment (n) => add ((n, store))
| Decrement (n) => sub ((n, store))
}));
``` ```
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
To dry-run the counter contract, we will use the `main` entrypoint, provide a variant parameter of `Increment(5)` and an initial storage value of `5`. To dry-run the counter contract, we will provide the `main` function
with a variant parameter of value `Increment (5)` and an initial
storage value of `5`.
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--Pascaligo--> <!--Pascaligo-->
@ -131,39 +150,30 @@ Command above will output the following Michelson code:
{ parameter (or (int %decrement) (int %increment)) ; { parameter (or (int %decrement) (int %increment)) ;
storage int ; storage int ;
code { DUP ; code { DUP ;
CAR ;
DIP { DUP } ;
SWAP ;
CDR ; CDR ;
DIP { DUP } ; DIP { DUP } ;
SWAP ; SWAP ;
CAR ;
IF_LEFT IF_LEFT
{ DUP ; { DUP ;
DIP 2 { DUP } ; DIP { DIP { DUP } ; SWAP } ;
DIG 2 ; PAIR ;
DIP { DUP } ; DUP ;
CDR ;
DIP { DUP ; CAR } ;
SUB ; SUB ;
SWAP ; DIP { DROP 2 } }
DROP ;
SWAP ;
DROP }
{ DUP ; { DUP ;
DIP 2 { DUP } ; DIP { DIP { DUP } ; SWAP } ;
DIG 2 ; PAIR ;
DIP { DUP } ; DUP ;
CDR ;
DIP { DUP ; CAR } ;
ADD ; ADD ;
SWAP ; DIP { DROP 2 } } ;
DROP ;
SWAP ;
DROP } ;
NIL operation ; NIL operation ;
PAIR ; PAIR ;
SWAP ; DIP { DROP 2 } } }
DROP ;
SWAP ;
DROP ;
SWAP ;
DROP } }
``` ```
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
@ -180,12 +190,15 @@ ligo compile-storage src/counter.ligo main 5
``` ```
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
In our case the LIGO storage value maps 1:1 to its Michelson
In our case the LIGO storage value maps 1:1 to its Michelson representation, however this will not be the case once the parameter is of a more complex data type, like a record. representation, however this will not be the case once the parameter
is of a more complex data type, like a record.
## Invoking a LIGO contract ## Invoking a LIGO contract
Same rules apply for parameters, as apply for translating LIGO storage values to Michelson. We will need to use `compile-parameter` to compile our `action` variant into Michelson, here's how: Same rules apply for parameters, as apply for translating LIGO storage
values to Michelson. We will need to use `compile-parameter` to
compile our `action` variant into Michelson, here's how:
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--Pascaligo--> <!--Pascaligo-->
@ -195,6 +208,5 @@ ligo compile-parameter src/counter.ligo main 'Increment(5)'
``` ```
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
Now we can use `(Right 5)` which is a Michelson value, to invoke our Now we can use `(Right 5)` which is a Michelson value, to invoke our
contract - e.g. via `tezos-client` contract - e.g., via `tezos-client`

View File

@ -0,0 +1,17 @@
type parameter is
Increment of int
| Decrement of int
type storage is int
type return is list (operation) * storage
function add (const n : int; const store : storage) : storage is store + n
function sub (const n : int; const store : storage) : storage is store - n
function main (const action : parameter; const store : storage) : return is
((nil : list(operation)),
case action of
Increment (n) -> add (n, store)
| Decrement (n) -> sub (n, store)
end)

View File

@ -0,0 +1,9 @@
function multiply (const a : int; const b : int) : int is
block {
const result : int = a * b
} with result
function add (const a : int; const b : int) : int is a + b
function main (const p : unit; const s : unit) : list (operation) * unit is
((nil : list (operation)), s)

View File

@ -0,0 +1,17 @@
type parameter is
Increment of int
| Decrement of int
type storage is int
type return is list (operation) * storage
function add (const n : int; const store : storage) : storage is store + n
function sub (const n : int; const store : storage) : storage is store - n
function main (const action : parameter; const store : storage) : return is
((nil : list(operation)),
case action of
Increment (n) -> add (n, store)
| Decrement (n) -> sub (n, store)
end)

View File

@ -0,0 +1,5 @@
const four : int = 4
const name : string = "John Doe"
function main (const p : unit; const s : unit) : list (operation) * unit is
((nil : list (operation)), s)

View File

@ -18,23 +18,29 @@ current timestamp value.
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO--> <!--PascaLIGO-->
```pascaligo group=a ```pascaligo group=a
const today : timestamp = now const today : timestamp = Tezos.now
``` ```
> Note that `now` is *deprecated*.
<!--CameLIGO--> <!--CameLIGO-->
```cameligo group=a ```cameligo group=a
let today : timestamp = Current.time let today : timestamp = Tezos.now
``` ```
> Note that `Current.time` is *deprecated*.
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo group=a ```reasonligo group=a
let today : timestamp = Current.time; let today : timestamp = Tezos.now;
``` ```
> Note that `Current.time` is *deprecated*.
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
> When running code, the LIGO CLI option > When running code, the LIGO CLI option `--predecessor-timestamp`
> `--predecessor-timestamp` allows you to control what `now` returns. > allows you to control what `Tezos.now` returns.
### Timestamp Arithmetics ### Timestamp Arithmetics
@ -46,31 +52,37 @@ constraints on your smart contracts. Consider the following scenarios.
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO--> <!--PascaLIGO-->
```pascaligo group=b ```pascaligo group=b
const today : timestamp = now const today : timestamp = Tezos.now
const one_day : int = 86400 const one_day : int = 86400
const in_24_hrs : timestamp = today + one_day const in_24_hrs : timestamp = today + one_day
const some_date : timestamp = ("2000-01-01T10:10:10Z" : timestamp) const some_date : timestamp = ("2000-01-01T10:10:10Z" : timestamp)
const one_day_later : timestamp = some_date + one_day const one_day_later : timestamp = some_date + one_day
``` ```
> Note that `now` is *deprecated*.
<!--CameLIGO--> <!--CameLIGO-->
```cameligo group=b ```cameligo group=b
let today : timestamp = Current.time let today : timestamp = Tezos.now
let one_day : int = 86400 let one_day : int = 86400
let in_24_hrs : timestamp = today + one_day let in_24_hrs : timestamp = today + one_day
let some_date : timestamp = ("2000-01-01t10:10:10Z" : timestamp) let some_date : timestamp = ("2000-01-01t10:10:10Z" : timestamp)
let one_day_later : timestamp = some_date + one_day let one_day_later : timestamp = some_date + one_day
``` ```
> Note that `Current.time` is *deprecated*.
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo group=b ```reasonligo group=b
let today : timestamp = Current.time; let today : timestamp = Tezos.now;
let one_day : int = 86400; let one_day : int = 86400;
let in_24_hrs : timestamp = today + one_day; let in_24_hrs : timestamp = today + one_day;
let some_date : timestamp = ("2000-01-01t10:10:10Z" : timestamp); let some_date : timestamp = ("2000-01-01t10:10:10Z" : timestamp);
let one_day_later : timestamp = some_date + one_day; let one_day_later : timestamp = some_date + one_day;
``` ```
> Note that `Current.time` is *deprecated*.
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
#### 24 hours Ago #### 24 hours Ago
@ -78,25 +90,32 @@ let one_day_later : timestamp = some_date + one_day;
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO--> <!--PascaLIGO-->
```pascaligo group=c ```pascaligo group=c
const today : timestamp = now const today : timestamp = Tezos.now
const one_day : int = 86400 const one_day : int = 86400
const in_24_hrs : timestamp = today - one_day const in_24_hrs : timestamp = today - one_day
``` ```
> Note that `now` is *deprecated*.
<!--CameLIGO--> <!--CameLIGO-->
```cameligo group=c ```cameligo group=c
let today : timestamp = Current.time let today : timestamp = Tezos.now
let one_day : int = 86400 let one_day : int = 86400
let in_24_hrs : timestamp = today - one_day let in_24_hrs : timestamp = today - one_day
``` ```
> Note that `Current.time` is *deprecated*.
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo group=c ```reasonligo group=c
let today : timestamp = Current.time; let today : timestamp = Tezos.now;
let one_day : int = 86400; let one_day : int = 86400;
let in_24_hrs : timestamp = today - one_day; let in_24_hrs : timestamp = today - one_day;
``` ```
> Note that `Current.time` is *deprecated*.
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
### Comparing Timestamps ### Comparing Timestamps
@ -107,19 +126,26 @@ applying to numbers.
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO--> <!--PascaLIGO-->
```pascaligo group=c ```pascaligo group=c
const not_tommorow : bool = (now = in_24_hrs) const not_tommorow : bool = (Tezos.now = in_24_hrs)
``` ```
> Note that `now` is *deprecated*.
<!--CameLIGO--> <!--CameLIGO-->
```cameligo group=c ```cameligo group=c
let not_tomorrow : bool = (Current.time = in_24_hrs) let not_tomorrow : bool = (Tezos.now = in_24_hrs)
``` ```
> Note that `Current.time` is *deprecated*.
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo group=c ```reasonligo group=c
let not_tomorrow : bool = (Current.time == in_24_hrs); let not_tomorrow : bool = (Tezos.now == in_24_hrs);
``` ```
> Note that `Current.time` is *deprecated*.
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
## Addresses ## Addresses

View File

@ -4,7 +4,7 @@ title: Cheat Sheet
--- ---
<div class="cheatsheet"> <div class="cheatsheet">
<!-- <!--
Note that this table is not compiled before production and currently needs to be managed manually. Note that this table is not compiled before production and currently needs to be managed manually.
--> -->
@ -30,7 +30,7 @@ Note that this table is not compiled before production and currently needs to be
|Includes|```#include "library.ligo"```| |Includes|```#include "library.ligo"```|
|Functions (short form)|<pre><code>function add (const a : int ; const b : int) : int is<br/>&nbsp;&nbsp;block { skip } with a + b</code></pre>| |Functions (short form)|<pre><code>function add (const a : int ; const b : int) : int is<br/>&nbsp;&nbsp;block { skip } with a + b</code></pre>|
|Functions (long form)|<pre><code>function add (const a : int ; const b : int) : int is<br/>&nbsp;&nbsp;block { <br/>&nbsp;&nbsp;&nbsp;&nbsp;const result: int = a + b;<br/>&nbsp;&nbsp;} with result</code></pre>| |Functions (long form)|<pre><code>function add (const a : int ; const b : int) : int is<br/>&nbsp;&nbsp;block { <br/>&nbsp;&nbsp;&nbsp;&nbsp;const result: int = a + b;<br/>&nbsp;&nbsp;} with result</code></pre>|
| If Statement | <pre><code>if age < 16 <br/>then fail("Too young to drive."); <br/>else const new_id: int = prev_id + 1;</code></pre>| | If Statement | <pre><code>if age < 16 <br/>then fail("Too young to drive."); <br/>else const new_id: int = prev_id + 1;</code></pre>|
|Options|<pre><code>type middleName is option(string);<br/>const middleName : middleName = Some("Foo");<br/>const middleName : middleName = None;</code></pre>| |Options|<pre><code>type middleName is option(string);<br/>const middleName : middleName = Some("Foo");<br/>const middleName : middleName = None;</code></pre>|
|Assignment| ```const age: int = 5;```| |Assignment| ```const age: int = 5;```|
|Assignment on an existing variable <br/></br>*⚠️ This feature is not supported at the top-level scope, you can use it e.g. within functions. Works for Records and Maps as well.*| ```age := 18;```, ```p.age := 21``` | |Assignment on an existing variable <br/></br>*⚠️ This feature is not supported at the top-level scope, you can use it e.g. within functions. Works for Records and Maps as well.*| ```age := 18;```, ```p.age := 21``` |
@ -71,8 +71,8 @@ Note that this table is not compiled before production and currently needs to be
|Variant *(pattern)* matching|<pre><code>let a: action = Increment 5<br/>match a with<br/>&#124; Increment n -> n + 1<br/>&#124; Decrement n -> n - 1<br/></code></pre>| |Variant *(pattern)* matching|<pre><code>let a: action = Increment 5<br/>match a with<br/>&#124; Increment n -> n + 1<br/>&#124; Decrement n -> n - 1<br/></code></pre>|
|Records|<pre><code>type person = {<br/>&nbsp;&nbsp;age: int ;<br/>&nbsp;&nbsp;name: string ;<br/>}<br/><br/>let john : person = {<br/>&nbsp;&nbsp;age = 18;<br/>&nbsp;&nbsp;name = "John Doe";<br/>}<br/><br/>let name: string = john.name</code></pre>| |Records|<pre><code>type person = {<br/>&nbsp;&nbsp;age: int ;<br/>&nbsp;&nbsp;name: string ;<br/>}<br/><br/>let john : person = {<br/>&nbsp;&nbsp;age = 18;<br/>&nbsp;&nbsp;name = "John Doe";<br/>}<br/><br/>let name: string = john.name</code></pre>|
|Maps|<pre><code>type prices = (nat, tez) map<br/><br/>let prices : prices = Map.literal [<br/>&nbsp;&nbsp;(10n, 60mutez);<br/>&nbsp;&nbsp;(50n, 30mutez);<br/>&nbsp;&nbsp;(100n, 10mutez)<br/>]<br/><br/>let price: tez option = Map.find_opt 50n prices<br/><br/>let prices: prices = Map.update 200n (Some 5mutez) prices</code></pre>| |Maps|<pre><code>type prices = (nat, tez) map<br/><br/>let prices : prices = Map.literal [<br/>&nbsp;&nbsp;(10n, 60mutez);<br/>&nbsp;&nbsp;(50n, 30mutez);<br/>&nbsp;&nbsp;(100n, 10mutez)<br/>]<br/><br/>let price: tez option = Map.find_opt 50n prices<br/><br/>let prices: prices = Map.update 200n (Some 5mutez) prices</code></pre>|
|Contracts & Accounts|<pre><code>let destination_address : address = "tz1..."<br/>let contract : unit contract = <br/> Operation.get_contract destination_address</code></pre>| |Contracts & Accounts|<pre><code>let destination_address : address = "tz1..."<br/>let contract : unit contract = <br/> Tezos.get_contract destination_address</code></pre>|
|Transactions|<pre><code>let payment : operation = <br/> Operation.transaction unit amount receiver</code></pre>| |Transactions|<pre><code>let payment : operation = <br/> Tezos.transaction unit amount receiver</code></pre>|
|Exception/Failure|`failwith("Your descriptive error message for the user goes here.")`| |Exception/Failure|`failwith("Your descriptive error message for the user goes here.")`|
<!--ReasonLIGO--> <!--ReasonLIGO-->
@ -103,8 +103,8 @@ Note that this table is not compiled before production and currently needs to be
|Variant *(pattern)* matching|<pre><code>let a: action = Increment(5);<br/>switch(a) {<br/>&#124; Increment(n) => n + 1<br/>&#124; Decrement(n) => n - 1;<br/> } <br/></code></pre>| |Variant *(pattern)* matching|<pre><code>let a: action = Increment(5);<br/>switch(a) {<br/>&#124; Increment(n) => n + 1<br/>&#124; Decrement(n) => n - 1;<br/> } <br/></code></pre>|
|Records|<pre><code>type person = {<br/>&nbsp;&nbsp;age: int,<br/>&nbsp;&nbsp;name: string<br/>}<br/><br/>let john : person = {<br/>&nbsp;&nbsp;age: 18,<br/>&nbsp;&nbsp;name: "John Doe"<br/>};<br/><br/>let name: string = john.name;</code></pre>| |Records|<pre><code>type person = {<br/>&nbsp;&nbsp;age: int,<br/>&nbsp;&nbsp;name: string<br/>}<br/><br/>let john : person = {<br/>&nbsp;&nbsp;age: 18,<br/>&nbsp;&nbsp;name: "John Doe"<br/>};<br/><br/>let name: string = john.name;</code></pre>|
|Maps|<pre><code>type prices = map(nat, tez);<br/><br/>let prices : prices = Map.literal([<br/>&nbsp;&nbsp;(10n, 60mutez),<br/>&nbsp;&nbsp;(50n, 30mutez),<br/>&nbsp;&nbsp;(100n, 10mutez)<br/>]);<br/><br/>let price: option(tez) = Map.find_opt(50n, prices);<br/><br/>let prices: prices = Map.update(200n, Some (5mutez), prices);</code></pre>| |Maps|<pre><code>type prices = map(nat, tez);<br/><br/>let prices : prices = Map.literal([<br/>&nbsp;&nbsp;(10n, 60mutez),<br/>&nbsp;&nbsp;(50n, 30mutez),<br/>&nbsp;&nbsp;(100n, 10mutez)<br/>]);<br/><br/>let price: option(tez) = Map.find_opt(50n, prices);<br/><br/>let prices: prices = Map.update(200n, Some (5mutez), prices);</code></pre>|
|Contracts & Accounts|<pre><code>let destination_address : address = "tz1...";<br/>let contract : contract(unit) = <br/> Operation.get_contract(destination_address);</code></pre>| |Contracts & Accounts|<pre><code>let destination_address : address = "tz1...";<br/>let contract : contract(unit) = <br/> Tezos.get_contract(destination_address);</code></pre>|
|Transactions|<pre><code>let payment : operation = <br/> Operation.transaction (unit, amount, receiver);</code></pre>| |Transactions|<pre><code>let payment : operation = <br/> Tezos.transaction (unit, amount, receiver);</code></pre>|
|Exception/Failure|`failwith("Your descriptive error message for the user goes here.");`| |Exception/Failure|`failwith("Your descriptive error message for the user goes here.");`|

View File

@ -11,8 +11,8 @@ value:
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO--> <!--PascaLIGO-->
```pascaligo group=a ```pascaligo group=a
const a : bool = True // Notice the capital letter const a : bool = True // Also: true
const b : bool = False // Same. const b : bool = False // Also: false
``` ```
<!--CameLIGO--> <!--CameLIGO-->
```cameligo group=a ```cameligo group=a
@ -137,7 +137,7 @@ state.
type magnitude is Small | Large // See variant types. type magnitude is Small | Large // See variant types.
function compare (const n : nat) : magnitude is function compare (const n : nat) : magnitude is
if n < 10n then Small (Unit) else Large (Unit) // Unit is needed for now. if n < 10n then Small else Large
``` ```
You can run the `compare` function defined above using the LIGO compiler You can run the `compare` function defined above using the LIGO compiler
@ -145,7 +145,7 @@ like this:
```shell ```shell
ligo run-function ligo run-function
gitlab-pages/docs/language-basics/boolean-if-else/cond.ligo compare 21n' gitlab-pages/docs/language-basics/boolean-if-else/cond.ligo compare 21n'
# Outputs: Large (Unit) # Outputs: Large(Unit)
``` ```
When the branches of the conditional are not a single expression, as When the branches of the conditional are not a single expression, as
@ -161,7 +161,7 @@ else skip;
``` ```
As an exception to the rule, the blocks in a conditional branch do not As an exception to the rule, the blocks in a conditional branch do not
need to be introduced by the keywor `block`, so, we could have written need to be introduced by the keyword `block`, so we could have written
instead: instead:
```pascaligo skip ```pascaligo skip
if x < y then { if x < y then {
@ -187,9 +187,15 @@ gitlab-pages/docs/language-basics/boolean-if-else/cond.mligo compare 21n'
# Outputs: Large # Outputs: Large
``` ```
> Notice that, as in OCaml, in CameLIGO, if a conditional has a branch
> `else ()`, that branch can be omitted. The resulting so-called
> *dangling else* problem is parsed by associating any `else` to the
> closest previous `then`.
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo group=e ```reasonligo group=e
type magnitude = | Small | Large; // See variant types. type magnitude = Small | Large; // See variant types.
let compare = (n : nat) : magnitude => let compare = (n : nat) : magnitude =>
if (n < 10n) { Small; } else { Large; }; if (n < 10n) { Small; } else { Large; };

View File

@ -4,7 +4,15 @@ title: Functions
--- ---
LIGO functions are the basic building block of contracts. For example, LIGO functions are the basic building block of contracts. For example,
entrypoints are functions. entrypoints are functions and each smart contract needs a main
function that dispatches control to the entrypoints (it is not already
the default entrypoint).
The semantics of function calls in LIGO is that of a *copy of the
arguments but also of the environment*. In the case of PascaLIGO, this
means that any mutation (assignment) on variables outside the scope of
the function will be lost when the function returns, just as the
mutations inside the functions will be.
## Declaring Functions ## Declaring Functions
@ -230,10 +238,14 @@ function to all its elements.
<!--PascaLIGO--> <!--PascaLIGO-->
```pascaligo group=c ```pascaligo group=c
function incr_map (const l : list (int)) : list (int) is function incr_map (const l : list (int)) : list (int) is
list_map (function (const i : int) : int is i + 1, l) List.map (function (const i : int) : int is i + 1, l)
``` ```
You can call the function `incr_map` defined above using the LIGO compiler
like so: > Note that `list_map` is *deprecated*.
You can call the function `incr_map` defined above using the LIGO
compiler like so:
```shell ```shell
ligo run-function ligo run-function
gitlab-pages/docs/language-basics/src/functions/incr_map.ligo incr_map gitlab-pages/docs/language-basics/src/functions/incr_map.ligo incr_map

View File

@ -79,17 +79,21 @@ let gcd (x,y : nat * nat) : nat =
``` ```
To ease the writing and reading of the iterated functions (here, To ease the writing and reading of the iterated functions (here,
`iter`), two predefined functions are provided: `continue` and `stop`: `iter`), two predefined functions are provided: `Loop.continue` and
`Loop.stop`:
```cameligo group=a ```cameligo group=a
let iter (x,y : nat * nat) : bool * (nat * nat) = let iter (x,y : nat * nat) : bool * (nat * nat) =
if y = 0n then stop (x,y) else continue (y, x mod y) if y = 0n then Loop.stop (x,y) else Loop.continue (y, x mod y)
let gcd (x,y : nat * nat) : nat = let gcd (x,y : nat * nat) : nat =
let x,y = if x < y then y,x else x,y in let x,y = if x < y then y,x else x,y in
let x,y = Loop.fold_while iter (x,y) let x,y = Loop.fold_while iter (x,y)
in x in x
``` ```
> Note that `stop` and `continue` are *deprecated*.
You can call the function `gcd` defined above using the LIGO compiler You can call the function `gcd` defined above using the LIGO compiler
like so: like so:
```shell ```shell
@ -131,11 +135,12 @@ let gcd = ((x,y) : (nat, nat)) : nat => {
``` ```
To ease the writing and reading of the iterated functions (here, To ease the writing and reading of the iterated functions (here,
`iter`), two predefined functions are provided: `continue` and `stop`: `iter`), two predefined functions are provided: `Loop.continue` and
`Loop.stop`:
```reasonligo group=b ```reasonligo group=b
let iter = ((x,y) : (nat, nat)) : (bool, (nat, nat)) => let iter = ((x,y) : (nat, nat)) : (bool, (nat, nat)) =>
if (y == 0n) { stop ((x,y)); } else { continue ((y, x mod y)); }; if (y == 0n) { Loop.stop ((x,y)); } else { Loop.continue ((y, x mod y)); };
let gcd = ((x,y) : (nat, nat)) : nat => { let gcd = ((x,y) : (nat, nat)) : nat => {
let (x,y) = if (x < y) { (y,x); } else { (x,y); }; let (x,y) = if (x < y) { (y,x); } else { (x,y); };
@ -143,6 +148,9 @@ let gcd = ((x,y) : (nat, nat)) : nat => {
x x
}; };
``` ```
> Note that `stop` and `continue` are *deprecated*.
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
## Bounded Loops ## Bounded Loops

View File

@ -19,7 +19,7 @@ Let us first consider and example of record type declaration.
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO--> <!--PascaLIGO-->
```pascaligo group=a ```pascaligo group=records1
type user is type user is
record [ record [
id : nat; id : nat;
@ -29,7 +29,7 @@ type user is
``` ```
<!--CameLIGO--> <!--CameLIGO-->
```cameligo group=a ```cameligo group=records1
type user = { type user = {
id : nat; id : nat;
is_admin : bool; is_admin : bool;
@ -38,7 +38,7 @@ type user = {
``` ```
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo group=a ```reasonligo group=records1
type user = { type user = {
id : nat, id : nat,
is_admin : bool, is_admin : bool,
@ -51,7 +51,7 @@ And here is how a record value is defined:
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO--> <!--PascaLIGO-->
```pascaligo group=a ```pascaligo group=records1
const alice : user = const alice : user =
record [ record [
id = 1n; id = 1n;
@ -61,7 +61,7 @@ const alice : user =
``` ```
<!--CameLIGO--> <!--CameLIGO-->
```cameligo group=a ```cameligo group=records1
let alice : user = { let alice : user = {
id = 1n; id = 1n;
is_admin = true; is_admin = true;
@ -70,7 +70,7 @@ let alice : user = {
``` ```
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo group=a ```reasonligo group=records1
let alice : user = { let alice : user = {
id : 1n, id : 1n,
is_admin : true, is_admin : true,
@ -86,17 +86,17 @@ operator, like so:
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO--> <!--PascaLIGO-->
```pascaligo group=a ```pascaligo group=records1
const alice_admin : bool = alice.is_admin const alice_admin : bool = alice.is_admin
``` ```
<!--CameLIGO--> <!--CameLIGO-->
```cameligo group=a ```cameligo group=records1
let alice_admin : bool = alice.is_admin let alice_admin : bool = alice.is_admin
``` ```
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo group=a ```reasonligo group=records1
let alice_admin : bool = alice.is_admin; let alice_admin : bool = alice.is_admin;
``` ```
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
@ -123,7 +123,7 @@ In PascaLIGO, the shape of that expression is `<record variable> with
<record value>`. The record variable is the record to update and the <record value>`. The record variable is the record to update and the
record value is the update itself. record value is the update itself.
```pascaligo group=b ```pascaligo group=records2
type point is record [x : int; y : int; z : int] type point is record [x : int; y : int; z : int]
type vector is record [dx : int; dy : int] type vector is record [dx : int; dy : int]
@ -151,7 +151,7 @@ the blockless function.
The syntax for the functional updates of record in CameLIGO follows The syntax for the functional updates of record in CameLIGO follows
that of OCaml: that of OCaml:
```cameligo group=b ```cameligo group=records2
type point = {x : int; y : int; z : int} type point = {x : int; y : int; z : int}
type vector = {dx : int; dy : int} type vector = {dx : int; dy : int}
@ -179,7 +179,7 @@ xy_translate "({x=2;y=3;z=1}, {dx=3;dy=4})"
The syntax for the functional updates of record in ReasonLIGO follows The syntax for the functional updates of record in ReasonLIGO follows
that of ReasonML: that of ReasonML:
```reasonligo group=b ```reasonligo group=records2
type point = {x : int, y : int, z : int}; type point = {x : int, y : int, z : int};
type vector = {dx : int, dy : int}; type vector = {dx : int, dy : int};
@ -216,7 +216,7 @@ name "patch").
Let us consider defining a function that translates three-dimensional Let us consider defining a function that translates three-dimensional
points on a plane. points on a plane.
```pascaligo group=c ```pascaligo group=records3
type point is record [x : int; y : int; z : int] type point is record [x : int; y : int; z : int]
type vector is record [dx : int; dy : int] type vector is record [dx : int; dy : int]
@ -242,7 +242,7 @@ Of course, we can actually translate the point with only one `patch`,
as the previous example was meant to show that, after the first patch, as the previous example was meant to show that, after the first patch,
the value of `p` indeed changed. So, a shorter version would be the value of `p` indeed changed. So, a shorter version would be
```pascaligo group=d ```pascaligo group=records4
type point is record [x : int; y : int; z : int] type point is record [x : int; y : int; z : int]
type vector is record [dx : int; dy : int] type vector is record [dx : int; dy : int]
@ -267,7 +267,7 @@ Record patches can actually be simulated with functional updates. All
we have to do is *declare a new record value with the same name as the we have to do is *declare a new record value with the same name as the
one we want to update* and use a functional update, like so: one we want to update* and use a functional update, like so:
```pascaligo group=e ```pascaligo group=records5
type point is record [x : int; y : int; z : int] type point is record [x : int; y : int; z : int]
type vector is record [dx : int; dy : int] type vector is record [dx : int; dy : int]
@ -298,71 +298,98 @@ values of the same type. The former are called *key* and the latter
is that the type of the keys must be *comparable*, in the Michelson is that the type of the keys must be *comparable*, in the Michelson
sense. sense.
### Declaring a Map
Here is how a custom map from addresses to a pair of integers is Here is how a custom map from addresses to a pair of integers is
defined. defined.
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO--> <!--PascaLIGO-->
```pascaligo group=f ```pascaligo group=maps
type move is int * int type move is int * int
type register is map (address, move) type register is map (address, move)
``` ```
<!--CameLIGO--> <!--CameLIGO-->
```cameligo group=f ```cameligo group=maps
type move = int * int type move = int * int
type register = (address, move) map type register = (address, move) map
``` ```
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo group=f ```reasonligo group=maps
type move = (int, int); type move = (int, int);
type register = map (address, move); type register = map (address, move);
``` ```
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
And here is how a map value is defined: ### Creating an Empty Map
Here is how to create an empty map.
<!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO-->
```pascaligo group=maps
const empty : register = map []
```
<!--CameLIGO-->
```cameligo group=maps
let empty : register = Map.empty
```
<!--ReasonLIGO-->
```reasonligo group=maps
let empty : register = Map.empty
```
<!--END_DOCUSAURUS_CODE_TABS-->
### Creating a Non-empty Map
And here is how to create a non-empty map value:
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO--> <!--PascaLIGO-->
```pascaligo group=f ```pascaligo group=maps
const moves : register = const moves : register =
map [ map [
("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address) -> (1,2); ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address) -> (1,2);
("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) -> (0,3)] ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) -> (0,3)]
``` ```
> Notice the `->` between the key and its value and `;` to separate Notice the `->` between the key and its value and `;` to separate
> individual map entries. The annotated value `("<string value>" : individual map entries. The annotated value `("<string value>" :
> address)` means that we cast a string into an address. Also, `map` address)` means that we cast a string into an address. Also, `map` is
> is a keyword. a keyword.
<!--CameLIGO--> <!--CameLIGO-->
```cameligo group=f ```cameligo group=maps
let moves : register = let moves : register =
Map.literal [ Map.literal [
(("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address), (1,2)); (("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address), (1,2));
(("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address), (0,3))] (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address), (0,3))]
``` ```
> The `Map.literal` predefined function builds a map from a list of The `Map.literal` predefined function builds a map from a list of
> key-value pair tuples, `(<key>, <value>)`. Note also the `;` to key-value pair tuples, `(<key>, <value>)`. Note also the `;` to
> separate individual map entries. `("<string value>": address)` separate individual map entries. `("<string value>": address)` means
> means that we type-cast a string into an address. that we type-cast a string into an address. -->
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo group=f ```reasonligo group=maps
let moves : register = let moves : register =
Map.literal ([ Map.literal ([
("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address, (1,2)), ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address, (1,2)),
("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address, (0,3))]); ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address, (0,3))]);
``` ```
> The `Map.literal` predefined function builds a map from a list of The `Map.literal` predefined function builds a map from a list of
> key-value pair tuples, `(<key>, <value>)`. Note also the `;` to key-value pair tuples, `(<key>, <value>)`. Note also the `;` to
> separate individual map entries. `("<string value>": address)` separate individual map entries. `("<string value>": address)` means
> means that we type-cast a string into an address. that we type-cast a string into an address. -->
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
@ -375,19 +402,19 @@ In PascaLIGO, we can use the postfix `[]` operator to read the `move`
value associated to a given key (`address` here) in the register. Here value associated to a given key (`address` here) in the register. Here
is an example: is an example:
```pascaligo group=f ```pascaligo group=maps
const my_balance : option (move) = const my_balance : option (move) =
moves [("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address)] moves [("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address)]
``` ```
<!--CameLIGO--> <!--CameLIGO-->
```cameligo group=f ```cameligo group=maps
let my_balance : move option = let my_balance : move option =
Map.find_opt ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) moves Map.find_opt ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) moves
``` ```
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo group=f ```reasonligo group=maps
let my_balance : option (move) = let my_balance : option (move) =
Map.find_opt (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address), moves); Map.find_opt (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address), moves);
``` ```
@ -400,7 +427,7 @@ the reader to account for a missing key in the map. This requires
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO--> <!--PascaLIGO-->
```pascaligo group=f ```pascaligo group=maps
function force_access (const key : address; const moves : register) : move is function force_access (const key : address; const moves : register) : move is
case moves[key] of case moves[key] of
Some (move) -> move Some (move) -> move
@ -409,7 +436,7 @@ function force_access (const key : address; const moves : register) : move is
``` ```
<!--CameLIGO--> <!--CameLIGO-->
```cameligo group=f ```cameligo group=maps
let force_access (key, moves : address * register) : move = let force_access (key, moves : address * register) : move =
match Map.find_opt key moves with match Map.find_opt key moves with
Some move -> move Some move -> move
@ -417,7 +444,7 @@ let force_access (key, moves : address * register) : move =
``` ```
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo group=f ```reasonligo group=maps
let force_access = ((key, moves) : (address, register)) : move => { let force_access = ((key, moves) : (address, register)) : move => {
switch (Map.find_opt (key, moves)) { switch (Map.find_opt (key, moves)) {
| Some (move) => move | Some (move) => move
@ -443,7 +470,7 @@ The values of a PascaLIGO map can be updated using the usual
assignment syntax `<map variable>[<key>] := <new value>`. Let us assignment syntax `<map variable>[<key>] := <new value>`. Let us
consider an example. consider an example.
```pascaligo group=f ```pascaligo group=maps
function assign (var m : register) : register is function assign (var m : register) : register is
block { block {
m [("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address)] := (4,9) m [("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address)] := (4,9)
@ -453,7 +480,7 @@ function assign (var m : register) : register is
If multiple bindings need to be updated, PascaLIGO offers a *patch If multiple bindings need to be updated, PascaLIGO offers a *patch
instruction* for maps, similar to that for records. instruction* for maps, similar to that for records.
```pascaligo group=f ```pascaligo group=maps
function assignments (var m : register) : register is function assignments (var m : register) : register is
block { block {
patch m with map [ patch m with map [
@ -463,35 +490,51 @@ function assignments (var m : register) : register is
} with m } with m
``` ```
See further for the removal of bindings.
<!--CameLIGO--> <!--CameLIGO-->
We can update a binding in a map in CameLIGO by means of the We can update a binding in a map in CameLIGO by means of the
`Map.update` built-in function: `Map.update` built-in function:
```cameligo group=f ```cameligo group=maps
let assign (m : register) : register = let assign (m : register) : register =
Map.update Map.update
("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) (Some (4,9)) m ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) (Some (4,9)) m
``` ```
> Notice the optional value `Some (4,9)` instead of `(4,9)`. If we had 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 use `None` instead, that would have meant that the binding is removed.
> removed.
As a particular case, we can only add a key and its associated value.
```cameligo group=maps
let add (m : register) : register =
Map.add
("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) (4,9) m
```
<!--ReasonLIGO--> <!--ReasonLIGO-->
We can update a binding in a map in ReasonLIGO by means of the We can update a binding in a map in ReasonLIGO by means of the
`Map.update` built-in function: `Map.update` built-in function:
```reasonligo group=f ```reasonligo group=maps
let assign = (m : register) : register => let assign = (m : register) : register =>
Map.update Map.update
(("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address), Some ((4,9)), m); (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address), Some ((4,9)), m);
``` ```
> Notice the optional value `Some (4,9)` instead of `(4,9)`. If we had 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 use `None` instead, that would have meant that the binding is removed.
> removed.
As a particular case, we can only add a key and its associated value.
```reasonligo group=maps
let add = (m : register) : register =>
Map.add
(("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address), (4,9), m);
```
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
@ -503,7 +546,7 @@ To remove a binding from a map, we need its key.
In PascaLIGO, there is a special instruction to remove a binding from In PascaLIGO, there is a special instruction to remove a binding from
a map. a map.
```pascaligo group=f ```pascaligo group=maps
function delete (const key : address; var moves : register) : register is function delete (const key : address; var moves : register) : register is
block { block {
remove key from map moves remove key from map moves
@ -514,7 +557,7 @@ function delete (const key : address; var moves : register) : register is
In CameLIGO, we use the predefined function `Map.remove` as follows: In CameLIGO, we use the predefined function `Map.remove` as follows:
```cameligo group=f ```cameligo group=maps
let delete (key, moves : address * register) : register = let delete (key, moves : address * register) : register =
Map.remove key moves Map.remove key moves
``` ```
@ -523,7 +566,7 @@ let delete (key, moves : address * register) : register =
In ReasonLIGO, we use the predefined function `Map.remove` as follows: In ReasonLIGO, we use the predefined function `Map.remove` as follows:
```reasonligo group=f ```reasonligo group=maps
let delete = ((key, moves) : (address, register)) : register => let delete = ((key, moves) : (address, register)) : register =>
Map.remove (key, moves); Map.remove (key, moves);
``` ```
@ -549,34 +592,28 @@ 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 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. of a map is within a certain range, and fail with an error otherwise.
The predefined functional iterator implementing the iterated operation
over maps is called `Map.iter`. In the following example, the register
of moves is iterated to check that the start of each move is above
`3`.
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO--> <!--PascaLIGO-->
In PascaLIGO, the predefined functional iterator implementing the ```pascaligo group=maps
iterated operation over maps is called `map_iter`. In the following
example, the register of moves is iterated to check that the start of
each move is above `3`.
```pascaligo group=f
function iter_op (const m : register) : unit is function iter_op (const m : register) : unit is
block { block {
function iterated (const i : address; const j : move) : unit is function iterated (const i : address; const j : move) : unit is
if j.1 > 3 then Unit else (failwith ("Below range.") : unit) if j.1 > 3 then Unit else (failwith ("Below range.") : unit)
} with map_iter (iterated, m) } with Map.iter (iterated, m)
``` ```
> The iterated function must be pure, that is, it cannot mutate > Note that `map_iter` is *deprecated*.
> variables.
<!--CameLIGO--> <!--CameLIGO-->
In CameLIGO, the predefinded functional iterator implementing the ```cameligo group=maps
iterated operation over maps is called `Map.iter`. In the following
example, the register of moves is iterated to check that the start of
each move is above `3`.
```cameligo group=f
let iter_op (m : register) : unit = let iter_op (m : register) : unit =
let predicate = fun (i,j : address * move) -> assert (j.0 > 3) let predicate = fun (i,j : address * move) -> assert (j.0 > 3)
in Map.iter predicate m in Map.iter predicate m
@ -584,12 +621,7 @@ let iter_op (m : register) : unit =
<!--ReasonLIGO--> <!--ReasonLIGO-->
In ReasonLIGO, the predefined functional iterator implementing the ```reasonligo group=maps
iterated operation over maps is called `Map.iter`. In the following
example, the register of moves is iterated to check that the start of
each move is above `3`.
```reasonligo group=f
let iter_op = (m : register) : unit => { let iter_op = (m : register) : unit => {
let predicate = ((i,j) : (address, move)) => assert (j[0] > 3); let predicate = ((i,j) : (address, move)) => assert (j[0] > 3);
Map.iter (predicate, m); Map.iter (predicate, m);
@ -601,32 +633,28 @@ let iter_op = (m : register) : unit => {
We may want to change all the bindings of a map by applying to them a 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 function. This is called a *map operation*, not to be confused with
the map data structure. the map data structure. The predefined functional iterator
implementing the map operation over maps is called `Map.map`. In the
following example, we add `1` to the ordinate of the moves in the
register.
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO--> <!--PascaLIGO-->
In PascaLIGO, the predefined functional iterator implementing the map ```pascaligo group=maps
operation over maps is called `map_map` and is used as follows:
```pascaligo group=f
function map_op (const m : register) : register is function map_op (const m : register) : register is
block { block {
function increment (const i : address; const j : move) : move is function increment (const i : address; const j : move) : move is
(j.0, j.1 + 1); (j.0, j.1 + 1)
} with map_map (increment, m) } with Map.map (increment, m)
``` ```
> The mapped function must be pure, that is, it cannot mutate > Note that `map_map` is *deprecated*.
> variables.
<!--CameLIGO--> <!--CameLIGO-->
In CameLIGO, the predefined functional iterator implementing the map ```cameligo group=maps
operation over maps is called `Map.map` and is used as follows:
```cameligo group=f
let map_op (m : register) : register = let map_op (m : register) : register =
let increment = fun (i,j : address * move) -> j.0, j.1 + 1 let increment = fun (i,j : address * move) -> j.0, j.1 + 1
in Map.map increment m in Map.map increment m
@ -634,10 +662,7 @@ let map_op (m : register) : register =
<!--ReasonLIGO--> <!--ReasonLIGO-->
In ReasonLIGO, the predefined functional iteratir implementing the map ```reasonligo group=maps
operation over maps is called `Map.map` and is used as follows:
```reasonligo group=f
let map_op = (m : register) : register => { let map_op = (m : register) : register => {
let increment = ((i,j): (address, move)) => (j[0], j[1] + 1); let increment = ((i,j): (address, move)) => (j[0], j[1] + 1);
Map.map (increment, m); Map.map (increment, m);
@ -653,31 +678,26 @@ function takes two arguments: an *accumulator* and the structure
enables having a partial result that becomes complete when the enables having a partial result that becomes complete when the
traversal of the data structure is over. traversal of the data structure is over.
The predefined functional iterator implementing the folded operation
over maps is called `Map.fold` and is used as follows.
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO--> <!--PascaLIGO-->
In PascaLIGO, the predefined functional iterator implementing the ```pascaligo group=maps
folded operation over maps is called `map_fold` and is used as function fold_op (const m : register) : int is
follows: block {
function folded (const i : int; const j : address * move) : int is
```pascaligo group=f i + j.1.1
function fold_op (const m : register) : int is block { } with Map.fold (folded, m, 5)
function folded (const j : int; const cur : address * move) : int is
j + cur.1.1
} with map_fold (folded, m, 5)
``` ```
> The folded function must be pure, that is, it cannot mutate > Note that `map_fold` is *deprecated*.
> variables.
<!--CameLIGO--> <!--CameLIGO-->
In CameLIGO, the predefined functional iterator implementing the ```cameligo group=maps
folded operation over maps is called `Map.fold` and is used as
follows:
```cameligo group=f
let fold_op (m : register) : register = let fold_op (m : register) : register =
let folded = fun (i,j : int * (address * move)) -> i + j.1.1 let folded = fun (i,j : int * (address * move)) -> i + j.1.1
in Map.fold folded m 5 in Map.fold folded m 5
@ -685,11 +705,7 @@ let fold_op (m : register) : register =
<!--ReasonLIGO--> <!--ReasonLIGO-->
In ReasonLIGO, the predefined functional iterator implementing the ```reasonligo group=maps
folded operation over maps is called `Map.fold` and is used as
follows:
```reasonligo group=f
let fold_op = (m : register) : register => { let fold_op = (m : register) : register => {
let folded = ((i,j): (int, (address, move))) => i + j[1][1]; let folded = ((i,j): (int, (address, move))) => i + j[1][1];
Map.fold (folded, m, 5); Map.fold (folded, m, 5);
@ -709,75 +725,102 @@ 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 Michelson which handles the scaling concerns for us. In LIGO, the
interface for big maps is analogous to the one used for ordinary maps. interface for big maps is analogous to the one used for ordinary maps.
### Declaring a Map
Here is how we define a big map: Here is how we define a big map:
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO--> <!--PascaLIGO-->
```pascaligo group=g ```pascaligo group=big_maps
type move is int * int type move is int * int
type register is big_map (address, move) type register is big_map (address, move)
``` ```
<!--CameLIGO--> <!--CameLIGO-->
```cameligo group=g ```cameligo group=big_maps
type move = int * int type move = int * int
type register = (address, move) big_map type register = (address, move) big_map
``` ```
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo group=g ```reasonligo group=big_maps
type move = (int, int); type move = (int, int);
type register = big_map (address, move); type register = big_map (address, move);
``` ```
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
And here is how a map value is created: ### Creating an Empty Big Map
Here is how to create an empty big map.
<!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO-->
```pascaligo group=big_maps
const empty : register = big_map []
```
<!--CameLIGO-->
```cameligo group=big_maps
let empty : register = Big_map.empty
```
<!--ReasonLIGO-->
```reasonligo group=big_maps
let empty : register = Big_map.empty
```
<!--END_DOCUSAURUS_CODE_TABS-->
### Creating a Non-empty Map
And here is how to create a non-empty map value:
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO--> <!--PascaLIGO-->
```pascaligo group=g ```pascaligo group=big_maps
const moves : register = const moves : register =
big_map [ big_map [
("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address) -> (1,2); ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address) -> (1,2);
("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) -> (0,3)] ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) -> (0,3)]
``` ```
> Notice the right arrow `->` between the key and its value and the Notice the right arrow `->` between the key and its value and the -->
> semicolon separating individual map entries. The value annotation semicolon separating individual map entries. The value annotation -->
> `("<string value>" : address)` means that we cast a string into an `("<string value>" : address)` means that we cast a string into an -->
> address. address. -->
<!--CameLIGO--> <!--CameLIGO-->
```cameligo group=g ```cameligo group=big_maps
let moves : register = let moves : register =
Big_map.literal [ Big_map.literal [
(("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address), (1,2)); (("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address), (1,2));
(("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address), (0,3))] (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address), (0,3))]
``` ```
> The predefind function `Big_map.literal` constructs a big map from a The predefind function `Big_map.literal` constructs a big map from a
> list of key-value pairs `(<key>, <value>)`. Note also the semicolon list of key-value pairs `(<key>, <value>)`. Note also the semicolon
> separating individual map entries. The annotated value `("<string separating individual map entries. The annotated value `("<string>
> value>" : address)` means that we cast a string into an address. value>" : address)` means that we cast a string into an address.
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo group=g ```reasonligo group=big_maps
let moves : register = let moves : register =
Big_map.literal ([ Big_map.literal ([
("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address, (1,2)), ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address, (1,2)),
("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address, (0,3))]); ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address, (0,3))]);
``` ```
> The predefind function `Big_map.literal` constructs a big map from a The predefind function `Big_map.literal` constructs a big map from a
> list of key-value pairs `(<key>, <value>)`. Note also the semicolon list of key-value pairs `(<key>, <value>)`. Note also the semicolon
> separating individual map entries. The annotated value `("<string separating individual map entries. The annotated value `("<string>
> value>" : address)` means that we cast a string into an address. value>" : address)` means that we cast a string into an address.
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
@ -793,21 +836,21 @@ the value we read is an optional value (in our case, of type `option
<!--PascaLIGO--> <!--PascaLIGO-->
```pascaligo group=g ```pascaligo group=big_maps
const my_balance : option (move) = const my_balance : option (move) =
moves [("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address)] moves [("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address)]
``` ```
<!--CameLIGO--> <!--CameLIGO-->
```cameligo group=g ```cameligo group=big_maps
let my_balance : move option = let my_balance : move option =
Big_map.find_opt ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) moves Big_map.find_opt ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) moves
``` ```
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo group=g ```reasonligo group=big_maps
let my_balance : option (move) = let my_balance : option (move) =
Big_map.find_opt ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address, moves); Big_map.find_opt ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address, moves);
``` ```
@ -822,7 +865,7 @@ let my_balance : option (move) =
The values of a PascaLIGO big map can be updated using the The values of a PascaLIGO big map can be updated using the
assignment syntax for ordinary maps assignment syntax for ordinary maps
```pascaligo group=g ```pascaligo group=big_maps
function add (var m : register) : register is function add (var m : register) : register is
block { block {
m [("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address)] := (4,9) m [("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address)] := (4,9)
@ -836,7 +879,7 @@ const updated_map : register = add (moves)
We can update a big map in CameLIGO using the `Big_map.update` We can update a big map in CameLIGO using the `Big_map.update`
built-in: built-in:
```cameligo group=g ```cameligo group=big_maps
let updated_map : register = let updated_map : register =
Big_map.update Big_map.update
("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) (Some (4,9)) moves ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) (Some (4,9)) moves
@ -847,10 +890,10 @@ let updated_map : register =
We can update a big map in ReasonLIGO using the `Big_map.update` We can update a big map in ReasonLIGO using the `Big_map.update`
built-in: built-in:
```reasonligo group=g ```reasonligo group=big_maps
let updated_map : register = let updated_map : register =
Big_map.update Big_map.update
(("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), Some((4,9)), moves); (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), Some ((4,9)), moves);
``` ```
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
@ -867,7 +910,7 @@ syntax.
PascaLIGO features a special syntactic construct to remove bindings PascaLIGO features a special syntactic construct to remove bindings
from maps, of the form `remove <key> from map <map>`. For example, from maps, of the form `remove <key> from map <map>`. For example,
```pascaligo group=g ```pascaligo group=big_maps
function rem (var m : register) : register is function rem (var m : register) : register is
block { block {
remove ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address) from map moves remove ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address) from map moves
@ -881,7 +924,7 @@ const updated_map : register = rem (moves)
In CameLIGO, the predefined function which removes a binding in a map In CameLIGO, the predefined function which removes a binding in a map
is called `Map.remove` and is used as follows: is called `Map.remove` and is used as follows:
```cameligo group=g ```cameligo group=big_maps
let updated_map : register = let updated_map : register =
Map.remove ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address) moves Map.remove ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address) moves
``` ```
@ -891,7 +934,7 @@ let updated_map : register =
In ReasonLIGO, the predefined function which removes a binding in a map In ReasonLIGO, the predefined function which removes a binding in a map
is called `Map.remove` and is used as follows: is called `Map.remove` and is used as follows:
```reasonligo group=g ```reasonligo group=big_maps
let updated_map : register = let updated_map : register =
Map.remove (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), moves) Map.remove (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), moves)
``` ```

View File

@ -3,13 +3,14 @@ id: operators
title: Operators title: Operators
--- ---
## Available operators ## Available Operators
> This list is non-exhaustive. More operators will be added in upcoming LIGO releases. > This list is non-exhaustive. More operators will be added in
> upcoming LIGO releases.
|Michelson |Pascaligo |Description | |Michelson |Pascaligo |Description |
|--- |--- |--- | |--- |--- |--- |
| `SENDER` | `sender` | Address that initiated the current transaction | `SENDER` | `Tezos.sender` | Address that initiated the current transaction
| `SOURCE` | `source` | Address that initiated the transaction, which triggered the current transaction. (useful e.g. when there's a transaction sent by another contract) | `SOURCE` | `Tezos.source` | Address that initiated the transaction, which triggered the current transaction. (useful e.g. when there's a transaction sent by another contract)
| `AMOUNT` | `amount` | Amount of tez sent by the transaction that invoked the contract | `AMOUNT` | `Tezos.amount` | Amount of tez sent by the transaction that invoked the contract
| `NOW` | `now` | Timestamp of the block whose validation triggered execution of the contract, i.e. current time when the contract is run. | `NOW` | `Tezos.now` | Timestamp of the block whose validation triggered execution of the contract, i.e. current time when the contract is run.

View File

@ -176,11 +176,6 @@ There are three kinds of functional iterations over LIGO lists: the
*iterated operation*, the *map operation* (not to be confused with the *iterated operation*, the *map operation* (not to be confused with the
*map data structure*) and the *fold operation*. *map data structure*) and the *fold operation*.
> 💡 Lists can be iterated, folded or mapped to different values. You
> can find additional examples
> [here](https://gitlab.com/ligolang/ligo/tree/dev/src/test/contracts)
> and other built-in operators
> [here](https://gitlab.com/ligolang/ligo/blob/dev/src/passes/operators/operators.ml#L59)
#### Iterated Operation over Lists #### Iterated Operation over Lists
@ -188,37 +183,28 @@ The first, the *iterated operation*, is an iteration over the list
with a unit return value. It is useful to enforce certain invariants with a unit return value. It is useful to enforce certain invariants
on the element of a list, or fail. For example you might want to check on the element of a list, or fail. For example you might want to check
that each value inside of a list is within a certain range, and fail that each value inside of a list is within a certain range, and fail
otherwise. otherwise. The predefined functional iterator implementing the
iterated operation over lists is called `List.iter`.
In the following example, a list is iterated to check that all its
elements (integers) are strictly greater than `3`.
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO--> <!--PascaLIGO-->
In PascaLIGO, the predefined functional iterator implementing the
iterated operation over lists is called `list_iter`.
In the following example, a list is iterated to check that all its
elements (integers) are greater than `3`:
```pascaligo group=lists ```pascaligo group=lists
function iter_op (const l : list (int)) : unit is function iter_op (const l : list (int)) : unit is
block { block {
function iterated (const i : int) : unit is function iterated (const i : int) : unit is
if i > 2 then Unit else (failwith ("Below range.") : unit) if i > 3 then Unit else (failwith ("Below range.") : unit)
} with list_iter (iterated, l) } with List.iter (iterated, l)
``` ```
> The iterated function must be pure, that is, it cannot mutate > Note that `list_iter` is *deprecated*.
> variables.
<!--CameLIGO--> <!--CameLIGO-->
In CameLIGO, the predefined functional iterator implementing the
iterated operation over lists is called `List.iter`.
In the following example, a list is iterated to check that all its
elements (integers) are greater than `3`:
```cameligo group=lists ```cameligo group=lists
let iter_op (l : int list) : unit = let iter_op (l : int list) : unit =
let predicate = fun (i : int) -> assert (i > 3) let predicate = fun (i : int) -> assert (i > 3)
@ -227,12 +213,6 @@ let iter_op (l : int list) : unit =
<!--ReasonLIGO--> <!--ReasonLIGO-->
In ReasonLIGO, the predefined functional iterator implementing the
iterated operation over lists is called `List.iter`.
In the following example, a list is iterated to check that all its
elements (integers) are greater than `3`:
```reasonligo group=lists ```reasonligo group=lists
let iter_op = (l : list (int)) : unit => { let iter_op = (l : list (int)) : unit => {
let predicate = (i : int) => assert (i > 3); let predicate = (i : int) => assert (i > 3);
@ -247,32 +227,25 @@ let iter_op = (l : list (int)) : unit => {
We may want to change all the elements of a given list by applying to 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 them a function. This is called a *map operation*, not to be confused
with the map data structure. with the map data structure. The predefined functional iterator
implementing the mapped operation over lists is called `List.map` and
is used as follows.
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO--> <!--PascaLIGO-->
In PascaLIGO, the predefined functional iterator implementing the
mapped operation over lists is called `list_map` and is used as
follows:
```pascaligo group=lists ```pascaligo group=lists
function increment (const i : int): int is i + 1 function increment (const i : int): int is i + 1
// Creates a new list with all elements incremented by 1 // Creates a new list with all elements incremented by 1
const plus_one : list (int) = list_map (increment, larger_list) const plus_one : list (int) = List.map (increment, larger_list)
``` ```
> The mapped function must be pure, that is, it cannot mutate > Note that `list_map` is *deprecated*.
> variables.
<!--CameLIGO--> <!--CameLIGO-->
In CameLIGO, the predefined functional iterator implementing the
mapped operation over lists is called `List.map` and is used as
follows:
```cameligo group=lists ```cameligo group=lists
let increment (i : int) : int = i + 1 let increment (i : int) : int = i + 1
@ -282,10 +255,6 @@ let plus_one : int list = List.map increment larger_list
<!--ReasonLIGO--> <!--ReasonLIGO-->
In ReasonLIGO, the predefined functional iterator implementing the
mapped operation over lists is called `List.map` and is used as
follows:
```reasonligo group=lists ```reasonligo group=lists
let increment = (i : int) : int => i + 1; let increment = (i : int) : int => i + 1;
@ -301,29 +270,23 @@ A *folded operation* is the most general of iterations. The folded
function takes two arguments: an *accumulator* and the structure function takes two arguments: an *accumulator* and the structure
*element* at hand, with which it then produces a new accumulator. This *element* at hand, with which it then produces a new accumulator. This
enables having a partial result that becomes complete when the enables having a partial result that becomes complete when the
traversal of the data structure is over. traversal of the data structure is over. The predefined functional
iterator implementing the folded operation over lists is called
`List.fold` and is used as follows.
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO--> <!--PascaLIGO-->
In PascaLIGO, the predefined functional iterator implementing the
folded operation over lists is called `list_fold` and is used as
follows:
```pascaligo group=lists ```pascaligo group=lists
function sum (const acc : int; const i : int): int is acc + i function sum (const acc : int; const i : int): int is acc + i
const sum_of_elements : int = list_fold (sum, my_list, 0) const sum_of_elements : int = List.fold (sum, my_list, 0)
``` ```
> The folded function must be pure, that is, it cannot mutate > Note that `list_fold` is *deprecated*.
> variables.
<!--CameLIGO--> <!--CameLIGO-->
In CameLIGO, the predefined functional iterator implementing the folded
operation over lists is called `List.fold` and is used as follows:
```cameligo group=lists ```cameligo group=lists
let sum (acc, i: int * int) : int = acc + i let sum (acc, i: int * int) : int = acc + i
let sum_of_elements : int = List.fold sum my_list 0 let sum_of_elements : int = List.fold sum my_list 0
@ -331,10 +294,6 @@ let sum_of_elements : int = List.fold sum my_list 0
<!--ReasonLIGO--> <!--ReasonLIGO-->
In ReasonLIGO, the predefined functional iterator implementing the
folded operation over lists is called `List.fold` and is used as
follows:
```reasonligo group=lists ```reasonligo group=lists
let sum = ((result, i): (int, int)): int => result + i; let sum = ((result, i): (int, int)): int => result + i;
let sum_of_elements : int = List.fold (sum, my_list, 0); let sum_of_elements : int = List.fold (sum, my_list, 0);
@ -472,36 +431,31 @@ in a set as follows:
```reasonligo group=sets ```reasonligo group=sets
let contains_3 : bool = Set.mem (3, my_set); let contains_3 : bool = Set.mem (3, my_set);
``` ```
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
### Cardinal of Sets ### Cardinal of Sets
The predefined function `Set.size` returns the number of
elements in a given set as follows.
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO--> <!--PascaLIGO-->
In PascaLIGO, the predefined function `size` returns the number of
elements in a given set as follows:
```pascaligo group=sets ```pascaligo group=sets
const set_size : nat = size (my_set) const cardinal : nat = Set.size (my_set)
``` ```
<!--CameLIGO--> <!--CameLIGO-->
In CameLIGO, the predefined function `Set.size` returns the number of
elements in a given set as follows:
```cameligo group=sets ```cameligo group=sets
let set_size : nat = Set.size my_set let cardinal : nat = Set.size my_set
``` ```
<!--ReasonLIGO--> <!--ReasonLIGO-->
In ReasonLIGO, the predefined function `Set.size` returns the number
of elements in a given set as follows:
```reasonligo group=sets ```reasonligo group=sets
let set_size : nat = Set.size (my_set); let cardinal : nat = Set.size (my_set);
``` ```
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
@ -509,20 +463,23 @@ let set_size : nat = Set.size (my_set);
### Updating Sets ### Updating Sets
There are two ways to update a set, that is to add or remove from
it.
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO--> <!--PascaLIGO-->
In PascaLIGO, there are two ways to update a set, that is to add or In PascaLIGO, either we create a new set from the given one, or we
remove from it. Either we create a new set from the given one, or we
modify it in-place. First, let us consider the former way: modify it in-place. First, let us consider the former way:
```pascaligo group=sets ```pascaligo group=sets
const larger_set : set (int) = set_add (4, my_set) const larger_set : set (int) = Set.add (4, my_set)
const smaller_set : set (int) = Set.remove (3, 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 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 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 possible to add elements by means of a patch, not remove any: it is
@ -544,23 +501,23 @@ const new_set : set (int) = update (my_set)
<!--CameLIGO--> <!--CameLIGO-->
In CameLIGO, we update a given set by creating another one, with or In CameLIGO, we can use the predefined functions `Set.add` and
`Set.remove`. We update a given set by creating another one, with or
without some elements. without some elements.
```cameligo group=sets ```cameligo group=sets
let larger_set : int set = Set.add 4 my_set let larger_set : int set = Set.add 4 my_set
let smaller_set : int set = Set.remove 3 my_set let smaller_set : int set = Set.remove 3 my_set
``` ```
<!--ReasonLIGO--> <!--ReasonLIGO-->
In ReasonLIGO, we update a given set by creating another one, with or In ReasonLIGO, we can use the predefined functions `Set.add` and
`Set.remove`. We update a given set by creating another one, with or
without some elements. without some elements.
```reasonligo group=sets ```reasonligo group=sets
let larger_set : set (int) = Set.add (4, my_set); let larger_set : set (int) = Set.add (4, my_set);
let smaller_set : set (int) = Set.remove (3, my_set); let smaller_set : set (int) = Set.remove (3, my_set);
``` ```
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
@ -584,35 +541,27 @@ 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 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. of a map is within a certain range, and fail with an error otherwise.
The predefined functional iterator implementing the iterated operation
over sets is called `Set.iter`. In the following example, a set is
iterated to check that all its elements (integers) are greater than
`3`.
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO--> <!--PascaLIGO-->
In PascaLIGO, the predefined functional iterator implementing the
iterated operation over sets is called `set_iter`.
In the following example, a set is iterated to check that all its
elements (integers) are greater than `3`:
```pascaligo group=sets ```pascaligo group=sets
function iter_op (const s : set (int)) : unit is function iter_op (const s : set (int)) : unit is
block { block {
function iterated (const i : int) : unit is function iterated (const i : int) : unit is
if i > 2 then Unit else (failwith ("Below range.") : unit) if i > 2 then Unit else (failwith ("Below range.") : unit)
} with set_iter (iterated, s) } with Set.iter (iterated, s)
``` ```
> The iterated function must be pure, that is, it cannot mutate > Note that `set_iter` is *deprecated*.
> variables.
<!--CameLIGO--> <!--CameLIGO-->
In CameLIGO, the predefined functional iterator implementing the
iterated operation over sets is called `Set.iter`.
In the following example, a set is iterated to check that all its
elements (integers) are greater than `3`:
```cameligo group=sets ```cameligo group=sets
let iter_op (s : int set) : unit = let iter_op (s : int set) : unit =
let predicate = fun (i : int) -> assert (i > 3) let predicate = fun (i : int) -> assert (i > 3)
@ -621,12 +570,6 @@ let iter_op (s : int set) : unit =
<!--ReasonLIGO--> <!--ReasonLIGO-->
In ReasonLIGO, the predefined functional iterator implementing the
iterated operation over sets is called `Set.iter`.
In the following example, a set is iterated to check that all its
elements (integers) are greater than `3`:
```reasonligo group=sets ```reasonligo group=sets
let iter_op = (s : set (int)) : unit => { let iter_op = (s : set (int)) : unit => {
let predicate = (i : int) => assert (i > 3); let predicate = (i : int) => assert (i > 3);
@ -637,51 +580,51 @@ let iter_op = (s : set (int)) : unit => {
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
#### Mapped Operation (NOT IMPLEMENTED YET) <!-- #### Mapped Operation (NOT IMPLEMENTED YET) -->
We may want to change all the elements of a given set by applying to <!-- We may want to change all the elements of a given set by applying to -->
them a function. This is called a *mapped operation*, not to be <!-- them a function. This is called a *mapped operation*, not to be -->
confused with the map data structure. <!-- confused with the map data structure. -->
<!--DOCUSAURUS_CODE_TABS--> <!-- <\!--DOCUSAURUS_CODE_TABS-\-> -->
<!--PascaLIGO--> <!-- <\!--PascaLIGO-\-> -->
In PascaLIGO, the predefined functional iterator implementing the <!-- In PascaLIGO, the predefined functional iterator implementing the -->
mapped operation over sets is called `set_map` and is used as follows: <!-- mapped operation over sets is called `Set.map` and is used as follows: -->
```pascaligo skip <!-- ```pascaligo skip -->
function increment (const i : int): int is i + 1 <!-- function increment (const i : int): int is i + 1 -->
// Creates a new set with all elements incremented by 1 <!-- // Creates a new set with all elements incremented by 1 -->
const plus_one : set (int) = set_map (increment, larger_set) <!-- const plus_one : set (int) = Set.map (increment, larger_set) -->
``` <!-- ``` -->
<!--CameLIGO--> <!-- <\!--CameLIGO-\-> -->
In CameLIGO, the predefined functional iterator implementing the <!-- In CameLIGO, the predefined functional iterator implementing the -->
mapped operation over sets is called `Set.map` and is used as follows: <!-- mapped operation over sets is called `Set.map` and is used as follows: -->
```cameligo skip <!-- ```cameligo skip -->
let increment (i : int) : int = i + 1 <!-- let increment (i : int) : int = i + 1 -->
// Creates a new set with all elements incremented by 1 <!-- // Creates a new set with all elements incremented by 1 -->
let plus_one : int set = Set.map increment larger_set <!-- let plus_one : int set = Set.map increment larger_set -->
``` <!-- ``` -->
<!--ReasonLIGO--> <!-- <\!--ReasonLIGO-\-> -->
In ReasonLIGO, the predefined functional iterator implementing the <!-- In ReasonLIGO, the predefined functional iterator implementing the -->
mapped operation over sets is called `Set.map` and is used as follows: <!-- mapped operation over sets is called `Set.map` and is used as follows: -->
```reasonligo skip <!-- ```reasonligo skip -->
let increment = (i : int) : int => i + 1; <!-- let increment = (i : int) : int => i + 1; -->
// Creates a new set with all elements incremented by 1 <!-- // Creates a new set with all elements incremented by 1 -->
let plus_one : set (int) = Set.map (increment, larger_set); <!-- let plus_one : set (int) = Set.map (increment, larger_set); -->
``` <!-- ``` -->
<!--END_DOCUSAURUS_CODE_TABS--> <!-- <\!--END_DOCUSAURUS_CODE_TABS-\-> -->
#### Folded Operation #### Folded Operation
@ -689,24 +632,20 @@ A *folded operation* is the most general of iterations. The folded
function takes two arguments: an *accumulator* and the structure function takes two arguments: an *accumulator* and the structure
*element* at hand, with which it then produces a new accumulator. This *element* at hand, with which it then produces a new accumulator. This
enables having a partial result that becomes complete when the enables having a partial result that becomes complete when the
traversal of the data structure is over. traversal of the data structure is over. The predefined fold over sets
is called `Set.fold`.
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO--> <!--PascaLIGO-->
In PascaLIGO, the predefined functional iterator implementing the
folded operation over sets is called `set_fold` and is used as
follows:
```pascaligo group=sets ```pascaligo group=sets
function sum (const acc : int; const i : int): int is acc + i function sum (const acc : int; const i : int): int is acc + i
const sum_of_elements : int = set_fold (sum, my_set, 0) const sum_of_elements : int = Set.fold (sum, my_set, 0)
``` ```
> The folded function must be pure, that is, it cannot mutate > Note that `set_fold` is *deprecated*.
> variables.
It is possible to use a *loop* over a set as well. It is possible to use a *loop* over a set as well.
@ -721,8 +660,6 @@ function loop (const s : set (int)) : int is block {
<!--CameLIGO--> <!--CameLIGO-->
In CameLIGO, the predefined fold over sets is called `Set.fold`.
```cameligo group=sets ```cameligo group=sets
let sum (acc, i : int * int) : int = acc + i let sum (acc, i : int * int) : int = acc + i
@ -731,8 +668,6 @@ let sum_of_elements : int = Set.fold sum my_set 0
<!--ReasonLIGO--> <!--ReasonLIGO-->
In ReasonLIGO, the predefined fold over sets is called `Set.fold`.
```reasonligo group=sets ```reasonligo group=sets
let sum = ((acc, i) : (int, int)) : int => acc + i; let sum = ((acc, i) : (int, int)) : int => acc + i;

View File

@ -1,4 +1,4 @@
type magnitude is Small | Large // See variant types type magnitude is Small | Large // See variant types
function compare (const n : nat) : magnitude is function compare (const n : nat) : magnitude is
if n < 10n then Small (Unit) else Large (Unit) if n < 10n then Small else Large

View File

@ -2,4 +2,4 @@ function increment (const b : int) : int is
(function (const a : int) : int is a + 1) (b) (function (const a : int) : int is a + 1) (b)
function incr_map (const l : list (int)) : list (int) is function incr_map (const l : list (int)) : list (int) is
list_map (function (const i : int) : int is i + 1, l) List.map (function (const i : int) : int is i + 1, l)

View File

@ -4,9 +4,8 @@ const larger_list : int_list = 5 # my_list
function increment (const i : int): int is i + 1 function increment (const i : int): int is i + 1
// Creates a new list with all elements incremented by 1 const plus_one : list (int) = List.map (increment, larger_list);
const plus_one : list (int) = list_map (increment, larger_list);
function sum (const acc : int; const i : int): int is acc + i function sum (const acc : int; const i : int): int is acc + i
const sum_of_elements : int = list_fold (sum, my_list, 0) const sum_of_elements : int = List.fold (sum, my_list, 0)

View File

@ -6,9 +6,9 @@ const contains_3 : bool = my_set contains 3
const set_size : nat = size (my_set) const set_size : nat = size (my_set)
const larger_set : int_set = set_add (4, my_set) const larger_set : int_set = Set.add (4, my_set)
const smaller_set : int_set = set_remove (3, my_set) const smaller_set : int_set = Set.remove (3, my_set)
function update (var s : set (int)) : set (int) is block { function update (var s : set (int)) : set (int) is block {
patch s with set [4; 7] patch s with set [4; 7]
@ -18,7 +18,7 @@ const new_set : set (int) = update (my_set)
function sum (const acc : int; const i : int): int is acc + i function sum (const acc : int; const i : int): int is acc + i
const sum_of_elements : int = set_fold (sum, my_set, 0) const sum_of_elements : int = Set.fold (sum, my_set, 0)
function loop (const s : set (int)) : int is block { function loop (const s : set (int)) : int is block {
var sum : int := 0; var sum : int := 0;

View File

@ -2,6 +2,6 @@ type coin is Head | Tail
function flip (const c : coin) : coin is function flip (const c : coin) : coin is
case c of case c of
Head -> Tail (Unit) // Unit needed because of a bug Head -> Tail
| Tail -> Head (Unit) // Unit needed because of a bug | Tail -> Head
end end

View File

@ -59,21 +59,27 @@ Strings can be sliced using a built-in function:
<!--PascaLIGO--> <!--PascaLIGO-->
```pascaligo group=b ```pascaligo group=b
const name : string = "Alice" const name : string = "Alice"
const slice : string = string_slice (0n, 1n, name) const slice : string = String.slice (0n, 1n, name)
``` ```
> Note that `string_slide` is *deprecated*.
<!--CameLIGO--> <!--CameLIGO-->
```cameligo group=b ```cameligo group=b
let name : string = "Alice" let name : string = "Alice"
let slice : string = String.slice 0n 1n name let slice : string = String.slice 0n 1n name
``` ```
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo group=b ```reasonligo group=b
let name : string = "Alice"; let name : string = "Alice";
let slice : string = String.slice (0n, 1n, name); let slice : string = String.slice (0n, 1n, name);
``` ```
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
> ⚠️ Notice that the offset and length of the slice are natural numbers. > ⚠️ Notice that the offset and length of the slice are natural
> numbers.
## Length of Strings ## Length of Strings
@ -83,8 +89,11 @@ The length of a string can be found using a built-in function:
<!--PascaLIGO--> <!--PascaLIGO-->
```pascaligo group=c ```pascaligo group=c
const name : string = "Alice" const name : string = "Alice"
const length : nat = size (name) // length = 5 const length : nat = String.length (name) // length = 5
``` ```
> Note that `size` is *deprecated*.
<!--CameLIGO--> <!--CameLIGO-->
```cameligo group=c ```cameligo group=c
let name : string = "Alice" let name : string = "Alice"

View File

@ -26,9 +26,11 @@ functionality can be accessed from within LIGO.
```pascaligo group=a ```pascaligo group=a
function id_string (const p : string) : option (string) is block { function id_string (const p : string) : option (string) is block {
const packed : bytes = bytes_pack (p) const packed : bytes = bytes_pack (p)
} with (bytes_unpack (packed) : option (string)) } with (Bytes.unpack (packed) : option (string))
``` ```
> Note that `bytes_unpack` is *deprecated*.
<!--CameLIGO--> <!--CameLIGO-->
```cameligo group=a ```cameligo group=a
let id_string (p : string) : string option = let id_string (p : string) : string option =
@ -103,9 +105,11 @@ function check_signature
(const pk : key; (const pk : key;
const signed : signature; const signed : signature;
const msg : bytes) : bool const msg : bytes) : bool
is crypto_check (pk, signed, msg) is Crypto.check (pk, signed, msg)
``` ```
> Note that `crypto_check` is *deprecated*.
<!--CameLIGO--> <!--CameLIGO-->
```cameligo group=c ```cameligo group=c
let check_signature (pk, signed, msg : key * signature * bytes) : bool = let check_signature (pk, signed, msg : key * signature * bytes) : bool =
@ -124,27 +128,29 @@ let check_signature =
## Contract's Own Address ## Contract's Own Address
Often you want to get the address of the contract being executed. You Often you want to get the address of the contract being executed. You
can do it with `self_address`. can do it with `Tezos.self_address`.
> ⚠️ Due to limitations in Michelson, `self_address` in a contract is > Note that `self_address` is *deprecated*.
> only allowed at the top-level. Using it in an embedded function will
> cause an error. > ⚠️ Due to limitations in Michelson, `Tezos.self_address` in a
> contract is only allowed at the top-level. Using it in an embedded
> function will cause an error.
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO--> <!--PascaLIGO-->
```pascaligo group=d ```pascaligo group=d
const current_addr : address = self_address const current_addr : address = Tezos.self_address
``` ```
<!--CameLIGO--> <!--CameLIGO-->
```cameligo group=d ```cameligo group=d
let current_addr : address = Current.self_address let current_addr : address = Tezos.self_address
``` ```
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo group=d ```reasonligo group=d
let current_addr : address = Current.self_address; let current_addr : address = Tezos.self_address;
``` ```
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->

View File

@ -229,7 +229,7 @@ type return = operation list * storage
let back (param, store : unit * storage) : return = let back (param, store : unit * storage) : return =
let no_op : operation list = [] in let no_op : operation list = [] in
if Current.time > store.deadline then if Tezos.now > store.deadline then
(failwith "Deadline passed." : return) // Annotation (failwith "Deadline passed." : return) // Annotation
else else
match Map.find_opt sender store.backers with match Map.find_opt sender store.backers with
@ -255,7 +255,7 @@ type return = (list (operation), storage);
let back = ((param, store) : (unit, storage)) : return => { let back = ((param, store) : (unit, storage)) : return => {
let no_op : list (operation) = []; let no_op : list (operation) = [];
if (Current.time > store.deadline) { if (Tezos.now > store.deadline) {
(failwith ("Deadline passed.") : return); // Annotation (failwith ("Deadline passed.") : return); // Annotation
} }
else { else {

View File

@ -56,8 +56,8 @@ else):
<!--PascaLIGO--> <!--PascaLIGO-->
```pascaligo group=b ```pascaligo group=b
type coin is Head | Tail type coin is Head | Tail
const head : coin = Head (Unit) // Unit needed for now. const head : coin = Head
const tail : coin = Tail (Unit) // Unit needed for now. const tail : coin = Tail
``` ```
<!--CameLIGO--> <!--CameLIGO-->
@ -69,14 +69,16 @@ let tail : coin = Tail
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo group=b ```reasonligo group=b
type coin = | Head | Tail; type coin = Head | Tail;
let head : coin = Head; let head : coin = Head;
let tail : coin = Tail; let tail : coin = Tail;
``` ```
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
The names `Head` and `Tail` in the definition of the type `coin` are The names `Head` and `Tail` in the definition of the type `coin` are
called *data constructors*, or *variants*. called *data constructors*, or *variants*. In this particular, they
carry no information beyond their names, so they are called *constant
constructors*.
In general, it is interesting for variants to carry some information, In general, it is interesting for variants to carry some information,
and thus go beyond enumerated types. In the following, we show how to and thus go beyond enumerated types. In the following, we show how to
@ -94,7 +96,7 @@ type user is
| Guest | Guest
const u : user = Admin (1000n) const u : user = Admin (1000n)
const g : user = Guest (Unit) // Unit needed because of a bug const g : user = Guest
``` ```
<!--CameLIGO--> <!--CameLIGO-->
@ -125,6 +127,9 @@ let g : user = Guest;
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
In LIGO, a constant constructor is equivalent to the same constructor
taking an argument of type `unit`, so, for example, `Guest` is the
same value as `Guest (unit)`.
## Optional values ## Optional values
@ -172,8 +177,8 @@ type coin is Head | Tail
function flip (const c : coin) : coin is function flip (const c : coin) : coin is
case c of case c of
Head -> Tail (Unit) // Unit needed because of a bug Head -> Tail
| Tail -> Head (Unit) // Unit needed because of a bug | Tail -> Head
end end
``` ```
@ -181,7 +186,7 @@ You can call the function `flip` by using the LIGO compiler like so:
```shell ```shell
ligo run-function ligo run-function
gitlab-pages/docs/language-basics/src/unit-option-pattern-matching/flip.ligo gitlab-pages/docs/language-basics/src/unit-option-pattern-matching/flip.ligo
flip "(Head (Unit))" flip "Head"
# Outputs: Tail(Unit) # Outputs: Tail(Unit)
``` ```

View File

@ -60,7 +60,10 @@ a *global scope*, but they can be declared and used within functions,
or as function parameters. or as function parameters.
> ⚠️ Please be wary that mutation only works within the function scope > ⚠️ Please be wary that mutation only works within the function scope
> itself, values outside of the function scope will not be affected. > itself, values outside of the function scope will not be
> affected. In other words, when a function is called, its arguments
> are copied, *as well as the environment*. Any side-effect to that
> environment is therefore lost when the function returns.
```pascaligo group=b ```pascaligo group=b

View File

@ -1,128 +1,128 @@
--- ---
id: big-map-reference id: big-map-reference
title: Big Map — Scalable hashmap primitive title: Big Map — Scalable Maps
--- ---
## Defining A Big Map Type ## Defining A Big Map Type
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--Pascaligo--> <!--Pascaligo-->
```pascaligo ```pascaligo group=big_map
type move is (int * int) type move is int * int
type moveset is big_map (address, move) type register is big_map (address, move)
type foo is big_map (int, int)
``` ```
<!--CameLIGO--> <!--CameLIGO-->
```cameligo ```cameligo group=big_map
type move = int * int type move = int * int
type moveset = (address, move) big_map type register = (address, move) big_map
type foo = (int, int) big_map
``` ```
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo ```reasonligo group=big_map
type move = (int, int); type move = (int, int);
type moveset = big_map(address, move); type register = big_map (address, move);
type foo = big_map(int, int);
``` ```
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
## Creating A Map ## Creating an Empty Big Map
Create an empty big map.
<!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO-->
```pascaligo group=big_map
const empty : register = big_map []
```
<!--CameLIGO-->
```cameligo group=big_map
let empty : register = Big_map.empty
```
<!--ReasonLIGO-->
```reasonligo group=big_map
let empty : register = Big_map.empty
```
<!--END_DOCUSAURUS_CODE_TABS-->
## Populating A Big Map
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--Pascaligo--> <!--Pascaligo-->
```pascaligo ```pascaligo group=big_map
const moves: moveset = const moves: register =
big_map big_map [
("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address) -> (1,2); ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address) -> (1,2);
("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address) -> (0,3); ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) -> (0,3)]
end
``` ```
<!--CameLIGO--> <!--CameLIGO-->
```cameligo ```cameligo group=big_map
let moves: moveset = let moves: register =
Big_map.literal [ Big_map.literal [
(("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address), (1,2)); (("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address), (1,2));
(("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), (0,3)); (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address), (0,3))]
]
``` ```
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo ```reasonligo group=big_map
let moves: moveset = let moves: register =
Big_map.literal ([ Big_map.literal ([
("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address, (1,2)), ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address, (1,2)),
("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address, (0,3)), ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address, (0,3))]);
]);
``` ```
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
## Big_map.find_opt(k: a', m: (a',b') big_map) : b' option ## Retrieving a Value in a Big Map
Retrieve the value associated with a particular key. This version returns an option Retrieve the value associated with a particular key. This version
which can either shift logic in response to a missing value or throw an error. returns an option which can either shift logic in response to a
missing value or throw an error.
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--Pascaligo--> <!--Pascaligo-->
```pascaligo ```pascaligo group=big_map
const my_balance : option(move) = const my_balance : option (move) =
moves [("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address)] moves [("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address)]
``` ```
<!--CameLIGO--> <!--CameLIGO-->
```cameligo The function is `Big_map.find_opt` whose type is `'key ->
('key,'value) big_map) -> 'value option`. Recall that the function
`Big_map.find_opt` must always be fully applied to its arguments. Here
is an example:
```cameligo group=big_map
let my_balance : move option = let my_balance : move option =
Big_map.find_opt ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address) moves Big_map.find_opt ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) moves
``` ```
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo The function is `Big_map.find_opt` whose type is `('key, ('key,
let my_balance : option(move) = 'value) big_map) : 'value option`. Here is an example:
Big_map.find_opt("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address, moves);
```reasonligo group=big_map
let my_balance : option (move) =
Big_map.find_opt ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address, moves);
``` ```
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
## Big_map.find(k: a', m: (a', b') big_map) : b' ## Updating a Binding in a Big Map
Forcefully retrieve the value associated with a particular key. If that value Given a map, we may want to add a new binding, remove one, or modify
doesn't exist, this function throws an error. one by changing the value associated to an already existing key. We
may even want to retain the key but not the associated value. All
<!--DOCUSAURUS_CODE_TABS--> those operations are called *updates*.
<!--Pascaligo-->
```pascaligo
const my_balance : move =
get_force (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), moves);
```
<!--CameLIGO-->
```cameligo
let my_balance : move =
Big_map.find ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address) moves
```
<!--ReasonLIGO-->
```reasonligo
let my_balance : move =
Big_map.find ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address, moves);
```
<!--END_DOCUSAURUS_CODE_TABS-->
## Big_map.update(k: a', v: b', m: (a', b') big_map) : (a', b') big_map
Change the value associated with a particular key, if that value doesn't already
exist add it.
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
@ -131,138 +131,123 @@ exist add it.
The values of a PascaLIGO big map can be updated using the ordinary The values of a PascaLIGO big map can be updated using the ordinary
assignment syntax: assignment syntax:
```pascaligo ```pascaligo group=big_map
function add (var m : register) : register is
function set_ (var m : moveset) : moveset is
block { block {
m [("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address)] := (4,9); m [("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address)] := (4,9)
} with m } with m
const updated_map : register = add (moves)
``` ```
See further for the removal of bindings.
<!--Cameligo--> <!--Cameligo-->
```cameligo In CameLIGO, you need the predefined function `Big_map.update` whose
let updated_map : moveset = type is `'key -> 'value option -> ('key, 'value) big_map -> ('key,
Big_map.update ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address) (Some (4,9)) moves 'value) big_map`. If the value (second argument) is `None`, then the
binding is to be removed. Recall that the function `Big_map.update`
must always be fully applied to its arguments. Here is an example:
```cameligo group=big_map
let updated_map : register =
Big_map.update
("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) (Some (4,9)) moves
``` ```
<!--Reasonligo--> <!--Reasonligo-->
```reasonligo In ReasonLIGO, you need the predefined function `Big_map.update` whose
let updated_map : moveset = type is `('key, 'value option, ('key, 'value) big_map) : ('key,
Big_map.update(("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), Some((4,9)), moves); 'value) big_map`. If the value (second componenat) is `None`, then the
binding is to be removed. Here is an example:
```reasonligo group=big_map
let updated_map : register =
Big_map.update
(("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), Some ((4,9)), moves);
``` ```
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
## Big_map.add(k: a', v: b', m: (a', b') big_map) : (a', b') big_map ## Adding a Binding to a Big Map
Add a key and its associated value to the big map. Add a key and its associated value to the big map.
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO--> ```pascaligo group=big_map
```pascaligo function add (var m : register) : register is
function set_ (var n : int ; var m : foo) : foo is block { block {
m[23] := n ; m [("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address)] := (4,9)
} with m } with m
const updated_map : register = add (moves)
``` ```
<!--CameLIGO--> <!--CameLIGO-->
```cameligo
let add (n,m : int * foo) : foo = Big_map.add 23 n m In CameLIGO, we use the predefined function `Big_map.add`, whose type
is `'key -> 'value -> ('key, 'value) big_map -> ('key, 'value)
big_map`. Recall that the function `Big_map.add` must always be fully
applied to its arguments. Here is an example:
```cameligo group=big_map
let add (m : register) : register =
Map.add
("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) (4,9) m
``` ```
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo
let add = ((n,m): (int, foo)): foo => Big_map.add(23, n, m); In ReasonLIGO, we use the predefined function `Big_map.add`, whose
type is `('key, 'value, ('key, 'value) big_map : ('key, 'value)
big_map`. Here is an example:
```reasonligo group=big_map
let add = (m : register) : register =>
Map.add
(("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address), (4,9), m);
``` ```
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
## Big_map.remove(k: a', m: (a', b') big_map) : (a', b') big_map ## Removing a Binding from a Big Map
Remove a key and its associated value from the big map. Remove a key and its associated value from the big map.
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO--> <!--PascaLIGO-->
```pascaligo ```pascaligo group=big_map
function rm (var m : foo) : foo is block { function delete (const key : address; var moves : register) : register is
remove 42 from map m; block {
} with m remove key from map moves
``` } with moves
<!--CameLIGO-->
```cameligo
let rm (m : foo) : foo = Big_map.remove 42 m
```
<!--ReasonLIGO-->
```reasonligo
let rm = (m: foo): foo => Big_map.remove(42, m);
```
<!--END_DOCUSAURUS_CODE_TABS-->
## Big_map.literal(key_value_pair_list: (a', b') list) : (a', b') big_map
Constructs a big map from a list of key-value pair tuples.
<!--DOCUSAURUS_CODE_TABS-->
<!--Pascaligo-->
```pascaligo
const moves: moveset =
big_map
("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address) -> (1,2);
("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address) -> (0,3);
end
``` ```
<!--CameLIGO--> <!--CameLIGO-->
```cameligo In CameLIGO, we use the predefined function `Big_map.remove` whose
let moves: moveset = type is `'key -> ('key, 'value) big_map -> ('key, 'value)
Big_map.literal [ big_map`. Note that, despite being curried, the calls to that function
(("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address), (1,2)); must be complete. Here is an example:
(("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), (0,3));
] ```cameligo group=big_map
let delete (key, moves : address * register) : register =
Map.remove key moves
``` ```
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo In ReasonLIGO, we use the predefined function `Big_map.remove` whose
let moves: moveset = type is `('key, ('key, 'value) big_map) : ('key, 'value)
Big_map.literal ([ big_map`. Here is an example:
("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address, (1,2)),
("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address, (0,3)), ```reasonligo group=big_map
]); let delete = ((key, moves) : (address, register)) : register =>
Map.remove (key, moves);
``` ```
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
## Big_map.empty() : (a', b') big_map
Create an empty big map.
<!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO-->
```pascaligo
const empty_big_map : big_map(int,int) = big_map end
```
<!--CameLIGO-->
```cameligo
let empty_map : foo = Big_map.empty
```
<!--ReasonLIGO-->
```reasonligo
let empty_map: foo = Big_map.empty;
```
<!--END_DOCUSAURUS_CODE_TABS-->

View File

@ -1,9 +1,182 @@
--- ---
id: list-reference id: list-reference
title: List — Ordered collection of a type title: List — Linear Collections
--- ---
## List.size(lst: a' list) : nat 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.
## Defining Lists
<!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO-->
```pascaligo group=lists
const empty_list : list (int) = nil // Or list []
const my_list : list (int) = list [1; 2; 2] // The head is 1
```
<!--CameLIGO-->
```cameligo group=lists
let empty_list : int list = []
let my_list : int list = [1; 2; 2] // The head is 1
```
<!--ReasonLIGO-->
```reasonligo group=lists
let empty_list : list (int) = [];
let my_list : list (int) = [1, 2, 2]; // The head is 1
```
<!--END_DOCUSAURUS_CODE_TABS-->
### 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*).
<!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO-->
```pascaligo group=lists
const larger_list : list (int) = 5 # my_list // [5;1;2;2]
```
<!--CameLIGO-->
```cameligo group=lists
let larger_list : int list = 5 :: my_list // [5;1;2;2]
```
<!--ReasonLIGO-->
```reasonligo group=lists
let larger_list : list (int) = [5, ...my_list]; // [5,1,2,2]
```
<!--END_DOCUSAURUS_CODE_TABS-->
### 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.
<!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO-->
```pascaligo group=lists
function iter_op (const l : list (int)) : unit is
block {
function iterated (const i : int) : unit is
if i > 2 then Unit else (failwith ("Below range.") : unit)
} with list_iter (iterated, l)
```
<!--CameLIGO-->
```cameligo group=lists
let iter_op (l : int list) : unit =
let predicate = fun (i : int) -> assert (i > 3)
in List.iter predicate l
```
<!--ReasonLIGO-->
```reasonligo group=lists
let iter_op = (l : list (int)) : unit => {
let predicate = (i : int) => assert (i > 3);
List.iter (predicate, l);
};
```
<!--END_DOCUSAURUS_CODE_TABS-->
#### 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.
<!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO-->
```pascaligo group=lists
function increment (const i : int): int is i + 1
// Creates a new list with all elements incremented by 1
const plus_one : list (int) = list_map (increment, larger_list)
```
<!--CameLIGO-->
```cameligo group=lists
let increment (i : int) : int = i + 1
// Creates a new list with all elements incremented by 1
let plus_one : int list = List.map increment larger_list
```
<!--ReasonLIGO-->
```reasonligo group=lists
let increment = (i : int) : int => i + 1;
// Creates a new list with all elements incremented by 1
let plus_one : list (int) = List.map (increment, larger_list);
```
<!--END_DOCUSAURUS_CODE_TABS-->
#### 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.
<!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO-->
```pascaligo group=lists
function sum (const acc : int; const i : int): int is acc + i
const sum_of_elements : int = list_fold (sum, my_list, 0)
```
<!--CameLIGO-->
```cameligo group=lists
let sum (acc, i: int * int) : int = acc + i
let sum_of_elements : int = List.fold sum my_list 0
```
<!--ReasonLIGO-->
```reasonligo group=lists
let sum = ((result, i): (int, int)): int => result + i;
let sum_of_elements : int = List.fold (sum, my_list, 0);
```
<!--END_DOCUSAURUS_CODE_TABS-->
## List Length
Get the number of elements in a list. Get the number of elements in a list.
@ -11,29 +184,25 @@ Get the number of elements in a list.
<!--PascaLIGO--> <!--PascaLIGO-->
```pascaligo ```pascaligo
function size_ (const m : list(int)) : nat is size(m) function size_of (const l : list (int)) : nat is List.length (l)
``` ```
<!--CameLIGO--> <!--CameLIGO-->
```cameligo ```cameligo
let size_ (s: int list) : nat = List.size s let size_of (l : int list) : nat = List.length l
``` ```
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo ```reasonligo
let size_ = (s: list(int)): nat => List.size(s); let size_of = (l : list (int)) : nat => List.length (l);
``` ```
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
## List.length(lst: a' list) : nat
Alias of `List.size`.
## List.map(map_function: a' -> b', lst: a' list) : 'b list ## List.map(map_function: a' -> b', lst: a' list) : 'b list
Apply an operation defined by `map_function` to each element of a list and return Apply an operation defined by `map_function` to each element of a list
a list of the modified elements. and return a list of the modified elements.
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--Pascaligo--> <!--Pascaligo-->

View File

@ -1,392 +1,274 @@
--- ---
id: map-reference id: map-reference
title: Map — Hashmaps that it makes sense to iterate over title: Map
--- ---
## Defining A Map Type ## Defining A Map Type
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--Pascaligo--> <!--Pascaligo-->
```pascaligo ```pascaligo group=map
type move is int * int type move is int * int
type moveset is map(address, move) type register is map (address, move)
``` ```
<!--CameLIGO--> <!--CameLIGO-->
```cameligo ```cameligo group=map
type move = int * int type move = int * int
type moveset = (address, move) map type register = (address, move) map
``` ```
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo ```reasonligo group=map
type move = (int, int); type move = (int, int);
type moveset = map(address, move); type register = map (address, move);
``` ```
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
## Creating A Map ## Creating an Empty Map
<!--DOCUSAURUS_CODE_TABS-->
<!--Pascaligo-->
```pascaligo
const moves: moveset = map
("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address) -> (1, 2);
("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address) -> (0, 3);
end
```
<!--CameLIGO-->
```cameligo
let moves: moveset = Map.literal
[ (("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address), (1, 2)) ;
(("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), (0, 3)) ;
]
```
<!--ReasonLIGO-->
```reasonligo
let moves : moveset =
Map.literal([
("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address, (1, 2)),
("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address, (0, 3)),
]);
```
<!--END_DOCUSAURUS_CODE_TABS-->
## Map.find_opt(k: a', m: (a',b') map) : b' option
Retrieve the value associated with a particular key. This version returns an option
which can either shift logic in response to a missing value or throw an error.
<!--DOCUSAURUS_CODE_TABS-->
<!--Pascaligo-->
```pascaligo
const my_balance : option(move) = moves[("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address)];
```
<!--CameLIGO-->
```cameligo
let my_balance : move option = Map.find_opt ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address) moves
```
<!--ReasonLIGO-->
```reasonligo
let my_balance : option(move) =
Map.find_opt("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address, moves);
```
<!--END_DOCUSAURUS_CODE_TABS-->
## Map.find(k: a', m: (a', b') map) : b'
Forcefully retrieve the value associated with a particular key. If that value
doesn't exist, this function throws an error.
<!--DOCUSAURUS_CODE_TABS-->
<!--Pascaligo-->
```pascaligo
const my_balance : move = get_force(("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), moves);
```
<!--CameLIGO-->
```cameligo
let my_balance : move = Map.find ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address) moves
```
<!--ReasonLIGO-->
```reasonligo
let my_balance : move =
Map.find("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address, moves);
```
<!--END_DOCUSAURUS_CODE_TABS-->
## Map.update(k: a', v: b', m: (a', b') map) : (a', b') map
Change the value associated with a particular key, if that value doesn't already
exist add it.
<!--DOCUSAURUS_CODE_TABS-->
<!--Pascaligo-->
The values of a PascaLIGO map can be updated using the ordinary assignment syntax:
```pascaligo
function set_ (var m: moveset) : moveset is
block {
m[("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address)] := (4,9);
} with m
```
<!--Cameligo-->
We can update a map in CameLIGO using the `Map.update` built-in:
```cameligo
let updated_map: moveset = Map.update ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address) (Some (4,9)) moves
```
<!--Reasonligo-->
We can update a map in ReasonLIGO using the `Map.update` built-in:
```reasonligo
let updated_map: moveset = Map.update(("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), Some((4,9)), moves);
```
<!--END_DOCUSAURUS_CODE_TABS-->
## Map.add(k: a', v: b', m: (a', b') map) : (a', b') map
<!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO-->
```pascaligo
function set_ (var n : int ; var m : map(int, int)) : map(int, int) is block {
m[23] := n ;
} with m
```
<!--CameLIGO-->
```cameligo
let add (n,m: int * (int, int) map) : foobar = Map.add 23 n m
```
<!--ReasonLIGO-->
```reasonligo
let add = (n: int, m: map(int, int)) : foobar => Map.add(23, n, m);
```
<!--END_DOCUSAURUS_CODE_TABS-->
## Map.remove(k: a', m: (a', b') map) : (a', b') map
Remove a key and its associated value from the map.
<!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO-->
```pascaligo
function rm (var m : map(int, int)) : map(int, int) is block {
remove 42 from map m
} with m
```
<!--CameLIGO-->
```cameligo
let rm (m: (int, int) map) : (int, int) map = Map.remove 42 m
```
<!--ReasonLIGO-->
```reasonligo
let rm = (m: map(int, int)): map(int, int) => Map.remove(42, m);
```
<!--END_DOCUSAURUS_CODE_TABS-->
## Map.iter(iterator_function: (a', b') -> unit, m: (a', b') map) : unit
Run a function returning unit over the contents of a map's key-value pairs.
For example an assertion.
<!--DOCUSAURUS_CODE_TABS-->
<!--Pascaligo-->
```pascaligo
function iter_op (const m : moveset) : unit is
block {
function aggregate (const i : address ; const j : move) : unit is block
{ if j.1 > 1 then skip else failwith("fail") } with unit
} with map_iter(aggregate, m);
```
<!--CameLIGO-->
```cameligo
let iter_op (m : moveset) : unit =
let assert_eq = fun (i,j: address * move) -> assert (j.0 > 1)
in Map.iter assert_eq m
```
<!--ReasonLIGO-->
```reasonligo
let iter_op = (m: moveset): unit => {
let assert_eq = ((i,j): (address, move)) => assert (j[0] > 1);
Map.iter(assert_eq, m);
};
```
<!--END_DOCUSAURUS_CODE_TABS-->
## Map.map(mapping_function: (a', b') -> b', m: (a', b') map) : (a', b') map
Update the values associated with every key in the map according to some update
rule `mapping_function`.
<!--DOCUSAURUS_CODE_TABS-->
<!--Pascaligo-->
```pascaligo
function map_op (const m : moveset) : moveset is
block {
function increment (const i : address ; const j : move) : move is (j.0, j.1 + 1);
} with map_map (increment, m);
```
<!--CameLIGO-->
```cameligo
let map_op (m : moveset) : moveset =
let increment = fun (i,j: address * move) -> (j.0, j.1 + 1)
in Map.map increment m
```
<!--ReasonLIGO-->
```reasonligo
let map_op = (m: moveset): moveset => {
let increment = ((i,j): (address, move)) => (j[0], j[1] + 1);
Map.map(increment, m);
};
```
<!--END_DOCUSAURUS_CODE_TABS-->
## Map.fold(folding_function: (b', (a', b')) -> b', m: (a', b') map, initial: b') : b'
Combine every value in the map together according to a fold rule `folding_function`.
<!--DOCUSAURUS_CODE_TABS-->
<!--Pascaligo-->
```pascaligo
function fold_op (const m : moveset) : int is
block {
function aggregate (const j : int; const cur : address * (int * int)) : int is j + cur.1.1
} with map_fold(aggregate, m, 5)
```
<!--CameLIGO-->
```cameligo
let fold_op (m : moveset) : moveset =
let aggregate = fun (i,j: int * (address * (int * int))) -> i + j.1.1
in Map.fold aggregate m 5
```
<!--ReasonLIGO-->
```reasonligo
let fold_op = (m: moveset): moveset => {
let aggregate = ((i,j): (int, (address, (int,int)))) => i + j[1][1];
Map.fold(aggregate, m, 5);
};
```
<!--END_DOCUSAURUS_CODE_TABS-->
## Map.mem(k: a', m: (a', b') map) : bool
Test whether a particular key `k` exists in a given map `m`.
<!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO-->
```pascaligo
function mem (const k: int; const m: map(int, int)) : bool is map_mem(k, m)
```
<!--CameLIGO-->
```cameligo
let mem (k,m: int * (int, int) map) : bool = Map.mem k m
```
<!--ReasonLIGO-->
```reasonligo
let mem = ((k,m): (int, map(int,int))): bool => Map.mem(k, m);
```
<!--END_DOCUSAURUS_CODE_TABS-->
## Map.empty() : (a', b') map
Create an empty map. Create an empty map.
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO--> <!--PascaLIGO-->
```pascaligo ```pascaligo group=map
const empty_map : map(int, int) = map end const empty : register = map []
``` ```
<!--CameLIGO--> <!--CameLIGO-->
```cameligo ```cameligo group=map
let empty_map : (int, int) map = Map.empty let empty : register = Map.empty
``` ```
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo ```reasonligo group=map
let empty_map: map(int, int) = Map.empty; let empty : register = Map.empty
``` ```
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
## Map.literal(key_value_pair_list: (a', b') list) : (a', b') map ## Populating A Map
Constructs a map from a list of key-value pair tuples. <!--DOCUSAURUS_CODE_TABS-->
<!--Pascaligo-->
```pascaligo group=map
const moves: register =
map [
("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address) -> (1,2);
("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) -> (0,3)]
```
<!--CameLIGO-->
```cameligo group=map
let moves: register =
Map.literal [
(("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address), (1,2));
(("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address), (0,3))]
```
<!--ReasonLIGO-->
```reasonligo group=map
let moves: register =
Map.literal ([
("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address, (1,2)),
("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address, (0,3))]);
```
<!--END_DOCUSAURUS_CODE_TABS-->
## Retrieving a Value in a Map
Retrieve the value associated with a particular key. This version
returns an option which can either shift logic in response to a
missing value or throw an error.
<!--DOCUSAURUS_CODE_TABS-->
<!--Pascaligo-->
```pascaligo group=map
const my_balance : option (move) =
moves [("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address)]
```
<!--CameLIGO-->
The function is `Map.find_opt` whose type is `'key ->
('key,'value) map) -> 'value option`. Recall that the function
`Map.find_opt` must always be fully applied to its arguments. Here
is an example:
```cameligo group=map
let my_balance : move option =
Map.find_opt ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) moves
```
<!--ReasonLIGO-->
The function is `Map.find_opt` whose type is `('key, ('key,
'value) map) : 'value option`. Here is an example:
```reasonligo group=map
let my_balance : option (move) =
Map.find_opt ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address, moves);
```
<!--END_DOCUSAURUS_CODE_TABS-->
## Updating a Binding in 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. We
may even want to retain the key but not the associated value. All
those operations are called *updates*.
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--Pascaligo--> <!--Pascaligo-->
```pascaligo The values of a PascaLIGO map can be updated using the ordinary
const moves: moveset = map assignment syntax:
("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address) -> (1, 2);
("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address) -> (0, 3); ```pascaligo group=map
end function add (var m : register) : register is
block {
m [("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address)] := (4,9)
} with m
const updated_map : register = add (moves)
```
See further for the removal of bindings.
<!--Cameligo-->
In CameLIGO, you need the predefined function `Map.update` whose
type is `'key -> 'value option -> ('key, 'value) map -> ('key,
'value) map`. If the value (second argument) is `None`, then the
binding is to be removed. Recall that the function `Map.update`
must always be fully applied to its arguments. Here is an example:
```cameligo group=map
let updated_map : register =
Map.update
("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) (Some (4,9)) moves
```
<!--Reasonligo-->
In ReasonLIGO, you need the predefined function `Map.update` whose
type is `('key, 'value option, ('key, 'value) map) : ('key,
'value) map`. If the value (second componenat) is `None`, then the
binding is to be removed. Here is an example:
```reasonligo group=map
let updated_map : register =
Map.update
(("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), Some ((4,9)), moves);
```
<!--END_DOCUSAURUS_CODE_TABS-->
## Adding a Binding to a Map
Add a key and its associated value to the map.
<!--DOCUSAURUS_CODE_TABS-->
```pascaligo group=map
function add (var m : register) : register is
block {
m [("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address)] := (4,9)
} with m
const updated_map : register = add (moves)
``` ```
<!--CameLIGO--> <!--CameLIGO-->
```cameligo In CameLIGO, we use the predefined function `Map.add`, whose type
let moves: moveset = Map.literal is `'key -> 'value -> ('key, 'value) map -> ('key, 'value)
[ (("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address), (1, 2)) ; map`. Recall that the function `Map.add` must always be fully
(("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), (0, 3)) ; applied to its arguments. Here is an example:
]
```cameligo group=map
let add (m : register) : register =
Map.add
("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) (4,9) m
``` ```
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo In ReasonLIGO, we use the predefined function `Map.add`, whose
let moves : moveset = type is `('key, 'value, ('key, 'value) map : ('key, 'value)
Map.literal([ map`. Here is an example:
("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address, (1, 2)),
("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address, (0, 3)), ```reasonligo group=map
]); let add = (m : register) : register =>
Map.add
(("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address), (4,9), m);
``` ```
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
## Map.size(m: (a', b') map) : nat ## Removing a Binding from a Map
Get the size of a given map `m`. Remove a key and its associated value from the map.
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO--> <!--PascaLIGO-->
```pascaligo ```pascaligo group=map
function size_ (const m : map(int, int)) : nat is function delete (const key : address; var moves : register) : register is
block {skip} with (size(m)) block {
remove key from map moves
} with moves
``` ```
<!--CameLIGO--> <!--CameLIGO-->
```cameligo
let size_ (m: (int, int) map) : nat = Map.size m In CameLIGO, we use the predefined function `Map.remove` whose
type is `'key -> ('key, 'value) map -> ('key, 'value)
map`. Note that, despite being curried, the calls to that function
must be complete. Here is an example:
```cameligo group=map
let delete (key, moves : address * register) : register =
Map.remove key moves
``` ```
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo
let size_ = (m: map(int, int)): nat => Map.size(m); In ReasonLIGO, we use the predefined function `Map.remove` whose
type is `('key, ('key, 'value) map) : ('key, 'value)
map`. Here is an example:
```reasonligo group=map
let delete = ((key, moves) : (address, register)) : register =>
Map.remove (key, moves);
```
<!--END_DOCUSAURUS_CODE_TABS-->
## Getting the Size of a Map
The size of a map is its number of bindings.
<!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO-->
```pascaligo group=map
function size_of (const m : register) : nat is size (m)
```
<!--CameLIGO-->
```cameligo group=map
let size_of (m : register) : nat = Map.size m
```
<!--ReasonLIGO-->
```reasonligo group=map
let size_of = (m : register): nat => Map.size (m);
``` ```
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->

View File

@ -1,10 +0,0 @@
type action is
| Increment of int
| Decrement of int
function main (const p : action ; const s : int) : (list(operation) * int) is
block {skip} with ((nil : list(operation)),
case p of
| Increment n -> s + n
| Decrement n -> s - n
end)

View File

@ -1,10 +0,0 @@
function multiply (const a : int ; const b : int) : int is
begin
const result : int = a * b ;
end with result
function add (const a : int ; const b : int) : int is
block { skip } with a + b
function main (const p : unit ; const s : unit) : (list(operation) * unit) is
block {skip} with ((nil : list(operation)), s)

View File

@ -1,16 +0,0 @@
type action is
| Increment of int
| Decrement of int
function add (const a : int ; const b : int) : int is
block { skip } with a + b
function subtract (const a : int ; const b : int) : int is
block { skip } with a - b
function main (const p : action ; const s : int) : (list(operation) * int) is
block {skip} with ((nil : list(operation)),
case p of
| Increment n -> add(s, n)
| Decrement n -> subtract(s, n)
end)

View File

@ -1,5 +0,0 @@
const four : int = 4;
const name : string = "John Doe";
function main (const p : unit ; const s : unit) : (list(operation) * unit) is
block {skip} with ((nil : list(operation)), s)

View File

@ -20,3 +20,4 @@ $HOME/git/ligo/vendors/ligo-utils/simple-utils/region.ml
../shared/LexerUnit.ml ../shared/LexerUnit.ml
../shared/ParserUnit.ml ../shared/ParserUnit.ml
Stubs/Simple_utils.ml Stubs/Simple_utils.ml
$HOME/git/ligo/_build/default/src/passes/1-parser/cameligo/ParErr.ml

View File

@ -266,7 +266,6 @@ let keywords = [
let reserved = let reserved =
let open SSet in let open SSet in
empty empty
|> add "and"
|> add "as" |> add "as"
|> add "asr" |> add "asr"
|> add "class" |> add "class"

View File

@ -1,5 +1,7 @@
(* Driver for the CameLIGO lexer *) (* Driver for the CameLIGO lexer *)
module Region = Simple_utils.Region
module IO = module IO =
struct struct
let ext = ".mligo" let ext = ".mligo"

View File

@ -593,10 +593,14 @@ core_expr:
| par(expr ":" type_expr {$1,$2,$3}) { EAnnot $1 } | par(expr ":" type_expr {$1,$2,$3}) { EAnnot $1 }
module_field: module_field:
module_name "." field_name { module_name "." module_fun {
let region = cover $1.region $3.region in let region = cover $1.region $3.region in
{region; value = $1.value ^ "." ^ $3.value} } {region; value = $1.value ^ "." ^ $3.value} }
module_fun:
field_name { $1 }
| "or" { {value="or"; region=$1} }
projection: projection:
struct_name "." nsepseq(selection,".") { struct_name "." nsepseq(selection,".") {
let start = $1.region in let start = $1.region in

View File

@ -24,3 +24,4 @@ $HOME/git/ligo/vendors/ligo-utils/simple-utils/region.ml
../shared/Memo.mli ../shared/Memo.mli
../shared/Memo.ml ../shared/Memo.ml
Stubs/Simple_utils.ml Stubs/Simple_utils.ml
$HOME/git/ligo/_build/default/src/passes/1-parser/pascaligo/ParErr.ml

View File

@ -98,11 +98,12 @@ sepseq(X,Sep):
(* Inlines *) (* Inlines *)
%inline var : "<ident>" { $1 } %inline var : "<ident>" { $1 }
%inline type_name : "<ident>" { $1 } %inline type_name : "<ident>" { $1 }
%inline fun_name : "<ident>" { $1 } %inline fun_name : "<ident>" { $1 }
%inline field_name : "<ident>" { $1 } %inline field_name : "<ident>" { $1 }
%inline struct_name : "<ident>" { $1 } %inline struct_name : "<ident>" { $1 }
%inline module_name : "<constr>" { $1 }
(* Main *) (* Main *)
@ -829,7 +830,7 @@ core_expr:
"<int>" { EArith (Int $1) } "<int>" { EArith (Int $1) }
| "<nat>" { EArith (Nat $1) } | "<nat>" { EArith (Nat $1) }
| "<mutez>" { EArith (Mutez $1) } | "<mutez>" { EArith (Mutez $1) }
| var { EVar $1 } | "<ident>" | module_field { EVar $1 }
| "<string>" { EString (String $1) } | "<string>" { EString (String $1) }
| "<bytes>" { EBytes $1 } | "<bytes>" { EBytes $1 }
| "False" { ELogic (BoolExpr (False $1)) } | "False" { ELogic (BoolExpr (False $1)) }
@ -902,13 +903,32 @@ path:
var { Name $1 } var { Name $1 }
| projection { Path $1 } | projection { Path $1 }
module_field:
module_name "." module_fun {
let region = cover $1.region $3.region in
{region; value = $1.value ^ "." ^ $3.value} }
module_fun:
field_name { $1 }
| "map" { {value="map"; region=$1} }
| "or" { {value="or"; region=$1} }
| "and" { {value="and"; region=$1} }
| "remove" { {value="remove"; region=$1} }
projection: projection:
struct_name "." nsepseq(selection,".") { struct_name "." nsepseq(selection,".") {
let stop = nsepseq_to_region selection_to_region $3 in let stop = nsepseq_to_region selection_to_region $3 in
let region = cover $1.region stop let region = cover $1.region stop
and value = {struct_name = $1; and value = {struct_name=$1; selector=$2; field_path=$3}
selector = $2; in {region; value}
field_path = $3} }
| module_name "." field_name "." nsepseq(selection,".") {
let value = $1.value ^ "." ^ $3.value in
let struct_name = {$1 with value} in
let start = $1.region in
let stop = nsepseq_to_region selection_to_region $5 in
let region = cover start stop in
let value = {struct_name; selector=$4; field_path=$5}
in {region; value} } in {region; value} }
selection: selection:
@ -939,31 +959,26 @@ record_expr:
update_record: update_record:
path "with" ne_injection("record",field_path_assignment){ path "with" ne_injection("record",field_path_assignment){
let region = cover (path_to_region $1) $3.region in let region = cover (path_to_region $1) $3.region in
let value = { let value = {record=$1; kwd_with=$2; updates=$3}
record = $1;
kwd_with = $2;
updates = $3}
in {region; value} } in {region; value} }
field_assignment: field_assignment:
field_name "=" expr { field_name "=" expr {
let region = cover $1.region (expr_to_region $3) let region = cover $1.region (expr_to_region $3)
and value = {field_name = $1; and value = {field_name=$1; equal=$2; field_expr=$3}
equal = $2;
field_expr = $3}
in {region; value} } in {region; value} }
field_path_assignment: field_path_assignment:
nsepseq(field_name,".") "=" expr { nsepseq(field_name,".") "=" expr {
let region = cover (nsepseq_to_region (fun x -> x.region) $1) (expr_to_region $3) let start = nsepseq_to_region (fun x -> x.region) $1
and value = {field_path = $1; and stop = expr_to_region $3 in
equal = $2; let region = cover start stop
field_expr = $3} and value = {field_path=$1; equal=$2; field_expr=$3}
in {region; value} } in {region; value} }
fun_call: fun_call:
fun_name arguments { fun_name arguments
| module_field arguments {
let region = cover $1.region $2.region let region = cover $1.region $2.region
in {region; value = (EVar $1),$2} } in {region; value = (EVar $1),$2} }

View File

@ -25,4 +25,5 @@ Stubs/Parser_cameligo.ml
../cameligo/ParserLog.mli ../cameligo/ParserLog.mli
../cameligo/ParserLog.ml ../cameligo/ParserLog.ml
../cameligo/Scoping.mli ../cameligo/Scoping.mli
../cameligo/Scoping.ml ../cameligo/Scoping.ml
$HOME/git/ligo/_build/default/src/passes/1-parser/reasonligo/ParErr.ml

View File

@ -238,12 +238,9 @@ let keywords = [
(fun reg -> True reg); (fun reg -> True reg);
(fun reg -> Type reg)] (fun reg -> Type reg)]
(* See: http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#sec86 and
https://github.com/facebook/reason/blob/master/src/reason-parser/reason_parser.mly *)
let reserved = let reserved =
let open SSet in let open SSet in
empty empty
|> add "and"
|> add "as" |> add "as"
|> add "asr" |> add "asr"
|> add "begin" |> add "begin"

View File

@ -1,5 +1,7 @@
(* Driver for the ReasonLIGO lexer *) (* Driver for the ReasonLIGO lexer *)
module Region = Simple_utils.Region
module IO = module IO =
struct struct
let ext = ".religo" let ext = ".religo"

View File

@ -24,22 +24,22 @@ type 'a sequence_or_record =
let (<@) f g x = f (g x) let (<@) f g x = f (g x)
(** (**
Covert nsepseq to a chain of TFun's. Covert nsepseq to a chain of TFun's.
Necessary to handle cases like: Necessary to handle cases like:
`type foo = (int, int) => int;` `type foo = (int, int) => int;`
*) *)
let rec nsepseq_to_curry hd rest = let rec nsepseq_to_curry hd rest =
match hd, rest with match hd, rest with
| hd, (sep, item) :: rest -> | hd, (sep, item) :: rest ->
let start = type_expr_to_region hd in let start = type_expr_to_region hd in
let stop = nsepseq_to_region type_expr_to_region (hd, rest) in let stop = nsepseq_to_region type_expr_to_region (hd, rest) in
let region = cover start stop in let region = cover start stop in
TFun { TFun {
value = hd, sep, (nsepseq_to_curry item rest); value = hd, sep, (nsepseq_to_curry item rest);
region region
} }
| hd, [] -> hd | hd, [] -> hd
(* END HEADER *) (* END HEADER *)
@ -178,34 +178,34 @@ type_expr:
cartesian | sum_type | record_type { $1 } cartesian | sum_type | record_type { $1 }
type_expr_func: type_expr_func:
"=>" cartesian { "=>" cartesian {
$1, $2 $1, $2
} }
cartesian: cartesian:
core_type { $1 } core_type { $1 }
| type_name type_expr_func { | type_name type_expr_func {
let (arrow, c) = $2 in let (arrow, c) = $2 in
let value = TVar $1, arrow, c in let value = TVar $1, arrow, c in
let region = cover $1.region (type_expr_to_region c) in let region = cover $1.region (type_expr_to_region c) in
TFun { region; value } TFun { region; value }
} }
| "(" cartesian ")" type_expr_func { | "(" cartesian ")" type_expr_func {
let (arrow, c) = $4 in let (arrow, c) = $4 in
let value = $2, arrow, c in let value = $2, arrow, c in
let region = cover $1 (type_expr_to_region c) in let region = cover $1 (type_expr_to_region c) in
TFun { region; value } TFun { region; value }
} }
| "(" cartesian "," nsepseq(cartesian,",") ")" type_expr_func? { | "(" cartesian "," nsepseq(cartesian,",") ")" type_expr_func? {
match $6 with match $6 with
| Some (arrow, c) -> | Some (arrow, c) ->
let (hd, rest) = Utils.nsepseq_cons $2 $3 $4 in let (hd, rest) = Utils.nsepseq_cons $2 $3 $4 in
let rest = rest @ [(arrow, c)] in let rest = rest @ [(arrow, c)] in
nsepseq_to_curry hd rest nsepseq_to_curry hd rest
| None -> | None ->
let value = Utils.nsepseq_cons $2 $3 $4 in let value = Utils.nsepseq_cons $2 $3 $4 in
let region = cover $1 $5 in let region = cover $1 $5 in
TProd {region; value} TProd {region; value}
} }
core_type: core_type:
@ -515,30 +515,30 @@ fun_expr:
_ _
}; _ }; region} -> }; _ }; region} ->
let expr_to_type = function let expr_to_type = function
| EVar v -> TVar v | EVar v -> TVar v
| e -> let open! SyntaxError | e -> let open! SyntaxError
in raise (Error (WrongFunctionArguments e)) in raise (Error (WrongFunctionArguments e))
in in
let type_expr = ( let type_expr = (
match type_expr with match type_expr with
| TProd {value; _} -> | TProd {value; _} ->
let (hd, rest) = value in let (hd, rest) = value in
let rest = rest @ [(arrow, expr_to_type body)] in let rest = rest @ [(arrow, expr_to_type body)] in
nsepseq_to_curry hd rest nsepseq_to_curry hd rest
| e -> | e ->
TFun { TFun {
value = e, arrow, expr_to_type body; value = e, arrow, expr_to_type body;
region = fun_region region = fun_region
} }
) )
in in
PTyped { PTyped {
value = { value = {
pattern; pattern;
colon; colon;
type_expr type_expr
}; };
region; region;
}, [] }, []
| EPar {value = {inside = fun_arg; _ }; _} -> | EPar {value = {inside = fun_arg; _ }; _} ->
@ -552,7 +552,7 @@ fun_expr:
arg_to_pattern (fst fun_args), bindings arg_to_pattern (fst fun_args), bindings
| EUnit _ as e -> | EUnit _ as e ->
arg_to_pattern e, [] arg_to_pattern e, []
| EVar _ as e -> | EVar _ as e ->
arg_to_pattern e, [] arg_to_pattern e, []
| e -> let open! SyntaxError | e -> let open! SyntaxError
in raise (Error (WrongFunctionArguments e)) in raise (Error (WrongFunctionArguments e))
@ -834,10 +834,13 @@ core_expr:
| par(expr) { EPar $1 } | par(expr) { EPar $1 }
module_field: module_field:
module_name "." field_name { module_name "." module_fun {
let region = cover $1.region $3.region let region = cover $1.region $3.region in
and value = $1.value ^ "." ^ $3.value {region; value = $1.value ^ "." ^ $3.value} }
in {region; value} }
module_fun:
field_name { $1 }
| "or" { {value="or"; region=$1} }
selection: selection:
"[" "<int>" "]" selection { "[" "<int>" "]" selection {

View File

@ -35,8 +35,8 @@ module Simplify = struct
let unit_expr = make_t @@ T_constant TC_unit let unit_expr = make_t @@ T_constant TC_unit
let type_constants s = let type_constants s =
match s with match s with
| "chain_id" -> ok TC_chain_id "chain_id" -> ok TC_chain_id
| "unit" -> ok TC_unit | "unit" -> ok TC_unit
| "string" -> ok TC_string | "string" -> ok TC_string
| "bytes" -> ok TC_bytes | "bytes" -> ok TC_bytes
@ -50,95 +50,196 @@ module Simplify = struct
| "key_hash" -> ok TC_key_hash | "key_hash" -> ok TC_key_hash
| "signature" -> ok TC_signature | "signature" -> ok TC_signature
| "timestamp" -> ok TC_timestamp | "timestamp" -> ok TC_timestamp
| _ -> simple_fail @@ "Not a type_constant " ^ s | _ -> simple_fail @@ "Not a built-in type (" ^ s ^ ")."
let type_operators s = let type_operators s =
match s with match s with
| "list" -> ok @@ TC_list unit_expr "list" -> ok @@ TC_list unit_expr
| "option" -> ok @@ TC_option unit_expr | "option" -> ok @@ TC_option unit_expr
| "set" -> ok @@ TC_set unit_expr | "set" -> ok @@ TC_set unit_expr
| "map" -> ok @@ TC_map (unit_expr,unit_expr) | "map" -> ok @@ TC_map (unit_expr,unit_expr)
| "big_map" -> ok @@ TC_big_map (unit_expr,unit_expr) | "big_map" -> ok @@ TC_big_map (unit_expr,unit_expr)
| "contract" -> ok @@ TC_contract unit_expr | "contract" -> ok @@ TC_contract unit_expr
| _ -> simple_fail @@ "Not a typ_operator " ^ s | _ -> simple_fail @@ "Not a built-in type (" ^ s ^ ")."
module Pascaligo = struct module Pascaligo = struct
let constants = function let constants = function
| "assert" -> ok C_ASSERTION (* Tezos module (ex-Michelson) *)
| "get_chain_id" -> ok C_CHAIN_ID
| "transaction" -> ok C_CALL | "Tezos.chain_id" -> ok C_CHAIN_ID
| "get_contract" -> ok C_CONTRACT | "chain_id" -> ok C_CHAIN_ID (* Deprecated *)
| "get_contract_opt"-> ok C_CONTRACT_OPT | "get_chain_id" -> ok C_CHAIN_ID (* Deprecated *)
| "get_entrypoint" -> ok C_CONTRACT_ENTRYPOINT | "Tezos.balance" -> ok C_BALANCE
| "get_entrypoint_opt" -> ok C_CONTRACT_ENTRYPOINT_OPT | "balance" -> ok C_BALANCE (* Deprecated *)
| "size" -> ok C_SIZE | "Tezos.now" -> ok C_NOW
| "int" -> ok C_INT | "now" -> ok C_NOW (* Deprecated *)
| "abs" -> ok C_ABS | "Tezos.amount" -> ok C_AMOUNT
| "is_nat" -> ok C_IS_NAT | "amount" -> ok C_AMOUNT (* Deprecated *)
| "amount" -> ok C_AMOUNT | "Tezos.sender" -> ok C_SENDER
| "balance" -> ok C_BALANCE | "sender" -> ok C_SENDER (* Deprecated *)
| "now" -> ok C_NOW | "Tezos.address" -> ok C_ADDRESS
| "unit" -> ok C_UNIT | "address" -> ok C_ADDRESS (* Deprecated *)
| "source" -> ok C_SOURCE | "Tezos.self_address" -> ok C_SELF_ADDRESS
| "sender" -> ok C_SENDER | "self_address" -> ok C_SELF_ADDRESS (* Deprecated *)
| "failwith" -> ok C_FAILWITH | "Tezos.implicit_account" -> ok C_IMPLICIT_ACCOUNT
| "bitwise_or" -> ok C_OR | "implicit_account" -> ok C_IMPLICIT_ACCOUNT (* Deprecated *)
| "bitwise_and" -> ok C_AND | "Tezos.source" -> ok C_SOURCE
| "bitwise_xor" -> ok C_XOR | "source" -> ok C_SOURCE (* Deprecated *)
| "bitwise_lsl" -> ok C_LSL | "Tezos.failwith" -> ok C_FAILWITH
| "bitwise_lsr" -> ok C_LSR | "failwith" -> ok C_FAILWITH
| "string_concat" -> ok C_CONCAT
| "string_slice" -> ok C_SLICE | "Tezos.transaction" -> ok C_CALL
| "crypto_check" -> ok C_CHECK_SIGNATURE | "transaction" -> ok C_CALL (* Deprecated *)
| "crypto_hash_key" -> ok C_HASH_KEY | "Tezos.set_delegate" -> ok C_SET_DELEGATE
| "bytes_concat" -> ok C_CONCAT | "set_delegate" -> ok C_SET_DELEGATE (* Deprecated *)
| "bytes_slice" -> ok C_SLICE | "get_contract" -> ok C_CONTRACT (* Deprecated *)
| "bytes_pack" -> ok C_BYTES_PACK | "Tezos.get_contract_opt" -> ok C_CONTRACT_OPT
| "bytes_unpack" -> ok C_BYTES_UNPACK | "get_contract_opt" -> ok C_CONTRACT_OPT (* Deprecated *)
| "set_empty" -> ok C_SET_EMPTY | "get_entrypoint" -> ok C_CONTRACT_ENTRYPOINT (* Deprecated *)
| "set_mem" -> ok C_SET_MEM | "Tezos.get_entrypoint_opt" -> ok C_CONTRACT_ENTRYPOINT_OPT
| "set_add" -> ok C_SET_ADD | "get_entrypoint_opt" -> ok C_CONTRACT_ENTRYPOINT_OPT (* Deprecated *)
| "set_remove" -> ok C_SET_REMOVE
| "set_iter" -> ok C_SET_ITER | "Michelson.is_nat" -> ok C_IS_NAT (* Deprecated *)
| "set_fold" -> ok C_SET_FOLD | "is_nat" -> ok C_IS_NAT
| "list_iter" -> ok C_LIST_ITER | "int" -> ok C_INT
| "list_fold" -> ok C_LIST_FOLD | "abs" -> ok C_ABS
| "list_map" -> ok C_LIST_MAP | "unit" -> ok C_UNIT
| "get_force" -> ok C_MAP_FIND
| "map_iter" -> ok C_MAP_ITER | "NEG" -> ok C_NEG
| "map_map" -> ok C_MAP_MAP | "ADD" -> ok C_ADD
| "map_fold" -> ok C_MAP_FOLD | "SUB" -> ok C_SUB
| "map_remove" -> ok C_MAP_REMOVE | "TIMES" -> ok C_MUL
| "map_update" -> ok C_MAP_UPDATE | "DIV" -> ok C_DIV
| "map_get" -> ok C_MAP_FIND_OPT | "MOD" -> ok C_MOD
| "map_mem" -> ok C_MAP_MEM | "EQ" -> ok C_EQ
| "sha_256" -> ok C_SHA256 | "NOT" -> ok C_NOT
| "sha_512" -> ok C_SHA512 | "AND" -> ok C_AND
| "blake2b" -> ok C_BLAKE2b | "OR" -> ok C_OR
| "cons" -> ok C_CONS | "GT" -> ok C_GT
| "EQ" -> ok C_EQ | "GE" -> ok C_GE
| "NEQ" -> ok C_NEQ | "LT" -> ok C_LT
| "NEG" -> ok C_NEG | "LE" -> ok C_LE
| "ADD" -> ok C_ADD | "CONS" -> ok C_CONS
| "SUB" -> ok C_SUB | "cons" -> ok C_CONS (* Deprecated *)
| "TIMES" -> ok C_MUL | "NEQ" -> ok C_NEQ
| "DIV" -> ok C_DIV
| "MOD" -> ok C_MOD (* Crypto module *)
| "NOT" -> ok C_NOT
| "AND" -> ok C_AND | "Crypto.check" -> ok C_CHECK_SIGNATURE
| "OR" -> ok C_OR | "crypto_check" -> ok C_CHECK_SIGNATURE (* Deprecated *)
| "GT" -> ok C_GT | "Crypto.hash_key" -> ok C_HASH_KEY
| "GE" -> ok C_GE | "crypto_hash_key" -> ok C_HASH_KEY (* Deprecated *)
| "LT" -> ok C_LT | "Crypto.blake2b" -> ok C_BLAKE2b
| "LE" -> ok C_LE | "blake2b" -> ok C_BLAKE2b (* Deprecated *)
| "CONS" -> ok C_CONS | "Crypto.sha256" -> ok C_SHA256
| "address" -> ok C_ADDRESS | "sha_256" -> ok C_SHA256 (* Deprecated *)
| "self_address" -> ok C_SELF_ADDRESS | "Crypto.sha512" -> ok C_SHA512
| "implicit_account"-> ok C_IMPLICIT_ACCOUNT | "sha_512" -> ok C_SHA512 (* Deprecated *)
| "set_delegate" -> ok C_SET_DELEGATE
| _ -> simple_fail "Not a PascaLIGO constant" (* Bytes module *)
| "Bytes.pack" -> ok C_BYTES_PACK
| "bytes_pack" -> ok C_BYTES_PACK (* Deprecated *)
| "Bytes.unpack" -> ok C_BYTES_UNPACK
| "bytes_unpack" -> ok C_BYTES_UNPACK (* Deprecated *)
| "Bytes.length" -> ok C_SIZE
| "Bytes.size" -> ok C_SIZE
| "bytes_concat" -> ok C_CONCAT (* Deprecated *)
| "Bytes.concat" -> ok C_CONCAT
| "Bytes.slice" -> ok C_SLICE
| "bytes_slice" -> ok C_SLICE (* Deprecated *)
| "Bytes.sub" -> ok C_SLICE
(* List module *)
| "List.length" -> ok C_SIZE
| "List.size" -> ok C_SIZE
| "list_size" -> ok C_SIZE (* Deprecated *)
| "List.iter" -> ok C_LIST_ITER
| "list_iter" -> ok C_LIST_ITER (* Deprecated *)
| "List.map" -> ok C_LIST_MAP
| "list_map" -> ok C_LIST_MAP (* Deprecated *)
| "List.fold" -> ok C_LIST_FOLD
| "list_fold" -> ok C_LIST_FOLD (* Deprecated *)
(* Set module *)
| "Set.size" -> ok C_SIZE
| "set_size" -> ok C_SIZE (* Deprecated *)
| "set_empty" -> ok C_SET_EMPTY (* Deprecated *)
| "Set.mem" -> ok C_SET_MEM
| "set_mem" -> ok C_SET_MEM (* Deprecated *)
| "Set.add" -> ok C_SET_ADD
| "set_add" -> ok C_SET_ADD (* Deprecated *)
| "Set.remove" -> ok C_SET_REMOVE
| "set_remove" -> ok C_SET_REMOVE (* Deprecated *)
| "Set.iter" -> ok C_SET_ITER
| "set_iter" -> ok C_SET_ITER (* Deprecated *)
| "Set.fold" -> ok C_SET_FOLD
| "set_fold" -> ok C_SET_FOLD (* Deprecated *)
(* Map module *)
| "get_force" -> ok C_MAP_FIND (* Deprecated *)
| "map_get" -> ok C_MAP_FIND_OPT (* Deprecated *)
| "Map.find_opt" -> ok C_MAP_FIND_OPT
| "Map.update" -> ok C_MAP_UPDATE
| "map_update" -> ok C_MAP_UPDATE (* Deprecated *)
| "map_remove" -> ok C_MAP_REMOVE (* Deprecated *)
| "Map.iter" -> ok C_MAP_ITER
| "map_iter" -> ok C_MAP_ITER (* Deprecated *)
| "Map.map" -> ok C_MAP_MAP
| "map_map" -> ok C_MAP_MAP (* Deprecated *)
| "Map.fold" -> ok C_MAP_FOLD
| "map_fold" -> ok C_MAP_FOLD (* Deprecated *)
| "Map.mem" -> ok C_MAP_MEM
| "map_mem" -> ok C_MAP_MEM (* Deprecated *)
| "Map.size" -> ok C_SIZE
| "map_size" -> ok C_SIZE (* Deprecated *)
(* Big_map module *)
| "Big_map.find_opt" -> ok C_MAP_FIND_OPT
| "Big_map.update" -> ok C_MAP_UPDATE
| "Big_map.literal" -> ok C_BIG_MAP_LITERAL
| "Big_map.empty" -> ok C_BIG_MAP_EMPTY
| "Big_map.size" -> ok C_SIZE
| "Big_map.mem" -> ok C_MAP_MEM
| "Big_map.iter" -> ok C_MAP_ITER
| "Big_map.map" -> ok C_MAP_MAP
| "Big_map.fold" -> ok C_MAP_FOLD
| "Big_map.remove" -> ok C_MAP_REMOVE
(* Bitwise module *)
| "Bitwise.or" -> ok C_OR
| "bitwise_or" -> ok C_OR (* Deprecated *)
| "Bitwise.and" -> ok C_AND
| "bitwise_and" -> ok C_AND (* Deprecated *)
| "Bitwise.xor" -> ok C_XOR
| "bitwise_xor" -> ok C_XOR (* Deprecated *)
| "Bitwise.shift_left" -> ok C_LSL
| "bitwise_lsl" -> ok C_LSL (* Deprecated *)
| "Bitwise.shift_right" -> ok C_LSR
| "bitwise_lsr" -> ok C_LSR (* Deprecated *)
(* String module *)
| "String.length" -> ok C_SIZE
| "String.size" -> ok C_SIZE
| "String.slice" -> ok C_SLICE
| "string_slice" -> ok C_SLICE (* Deprecated *)
| "String.sub" -> ok C_SLICE
| "String.concat" -> ok C_CONCAT
| "string_concat" -> ok C_CONCAT (* Deprecated *)
(* Others *)
| "assert" -> ok C_ASSERTION
| "size" -> ok C_SIZE (* Deprecated *)
| _ -> simple_fail "Not a PascaLIGO built-in."
let type_constants = type_constants let type_constants = type_constants
let type_operators = type_operators let type_operators = type_operators
@ -147,119 +248,163 @@ module Simplify = struct
module Cameligo = struct module Cameligo = struct
let constants = function let constants = function
| "assert" -> ok C_ASSERTION (* Tezos (ex-Michelson, ex-Current, ex-Operation) *)
| "chain_id" -> ok C_CHAIN_ID
| "Current.balance" -> ok C_BALANCE
| "balance" -> ok C_BALANCE
| "Current.time" -> ok C_NOW
| "time" -> ok C_NOW
| "Current.amount" -> ok C_AMOUNT
| "amount" -> ok C_AMOUNT
| "Current.sender" -> ok C_SENDER
| "Current.address" -> ok C_ADDRESS
| "Current.self_address" -> ok C_SELF_ADDRESS
| "Current.implicit_account" -> ok C_IMPLICIT_ACCOUNT
| "sender" -> ok C_SENDER
| "Current.source" -> ok C_SOURCE
| "source" -> ok C_SOURCE
| "Current.failwith" -> ok C_FAILWITH
| "failwith" -> ok C_FAILWITH
| "Crypto.blake2b" -> ok C_BLAKE2b | "Tezos.chain_id" -> ok C_CHAIN_ID
| "Crypto.sha256" -> ok C_SHA256 | "chain_id" -> ok C_CHAIN_ID (* Deprecated *)
| "Crypto.sha512" -> ok C_SHA512 | "Tezos.balance" -> ok C_BALANCE
| "Crypto.hash_key" -> ok C_HASH_KEY | "Current.balance" -> ok C_BALANCE (* Deprecated *)
| "Crypto.check" -> ok C_CHECK_SIGNATURE | "balance" -> ok C_BALANCE (* Deprecated *)
| "Tezos.now" -> ok C_NOW
| "Current.time" -> ok C_NOW (* Deprecated *)
| "time" -> ok C_NOW (* Deprecated *)
| "Tezos.amount" -> ok C_AMOUNT
| "Current.amount" -> ok C_AMOUNT (* Deprecated *)
| "amount" -> ok C_AMOUNT (* Deprecated *)
| "Tezos.sender" -> ok C_SENDER
| "Current.sender" -> ok C_SENDER (* Deprecated *)
| "sender" -> ok C_SENDER (* Deprecated *)
| "Tezos.address" -> ok C_ADDRESS
| "Current.address" -> ok C_ADDRESS (* Deprecated *)
| "Tezos.self_address" -> ok C_SELF_ADDRESS
| "Current.self_address" -> ok C_SELF_ADDRESS (* Deprecated *)
| "Tezos.implicit_account" -> ok C_IMPLICIT_ACCOUNT
| "Current.implicit_account" -> ok C_IMPLICIT_ACCOUNT (* Deprecated *)
| "Tezos.source" -> ok C_SOURCE
| "Current.source" -> ok C_SOURCE (* Deprecated *)
| "source" -> ok C_SOURCE (* Deprecated *)
| "Tezos.failwith" -> ok C_FAILWITH
| "Current.failwith" -> ok C_FAILWITH (* Deprecated *)
| "failwith" -> ok C_FAILWITH
| "Bytes.pack" -> ok C_BYTES_PACK | "Tezos.transaction" -> ok C_CALL
| "Bytes.unpack" -> ok C_BYTES_UNPACK | "Operation.transaction" -> ok C_CALL (* Deprecated *)
| "Bytes.length" -> ok C_SIZE | "Tezos.set_delegate" -> ok C_SET_DELEGATE (* Deprecated *)
| "Bytes.size" -> ok C_SIZE | "Operation.set_delegate" -> ok C_SET_DELEGATE (* Deprecated *)
| "Bytes.concat" -> ok C_CONCAT | "Operation.get_contract" -> ok C_CONTRACT (* Deprecated *)
| "Bytes.slice" -> ok C_SLICE | "Tezos.get_contract_opt" -> ok C_CONTRACT_OPT
| "Bytes.sub" -> ok C_SLICE | "Operation.get_contract_opt" -> ok C_CONTRACT_OPT (* Deprecated *)
| "Operation.get_entrypoint" -> ok C_CONTRACT_ENTRYPOINT (* Deprecated *)
| "Tezos.get_entrypoint_opt" -> ok C_CONTRACT_ENTRYPOINT_OPT
| "Operation.get_entrypoint_opt" -> ok C_CONTRACT_ENTRYPOINT_OPT (* Deprecated *)
| "Set.mem" -> ok C_SET_MEM | "Michelson.is_nat" -> ok C_IS_NAT (* Deprecated *)
| "Set.iter" -> ok C_SET_ITER | "is_nat" -> ok C_IS_NAT
| "Set.empty" -> ok C_SET_EMPTY | "int" -> ok C_INT
| "Set.literal" -> ok C_SET_LITERAL | "abs" -> ok C_ABS
| "Set.add" -> ok C_SET_ADD | "unit" -> ok C_UNIT
| "Set.remove" -> ok C_SET_REMOVE
| "Set.fold" -> ok C_SET_FOLD
| "Set.size" -> ok C_SIZE
| "Map.find_opt" -> ok C_MAP_FIND_OPT | "NEG" -> ok C_NEG
| "Map.find" -> ok C_MAP_FIND | "ADD" -> ok C_ADD
| "Map.update" -> ok C_MAP_UPDATE | "SUB" -> ok C_SUB
| "Map.add" -> ok C_MAP_ADD | "TIMES" -> ok C_MUL
| "Map.remove" -> ok C_MAP_REMOVE | "DIV" -> ok C_DIV
| "Map.iter" -> ok C_MAP_ITER | "MOD" -> ok C_MOD
| "Map.map" -> ok C_MAP_MAP | "EQ" -> ok C_EQ
| "Map.fold" -> ok C_MAP_FOLD | "NOT" -> ok C_NOT
| "Map.mem" -> ok C_MAP_MEM | "AND" -> ok C_AND
| "Map.empty" -> ok C_MAP_EMPTY | "OR" -> ok C_OR
| "Map.literal" -> ok C_MAP_LITERAL | "GT" -> ok C_GT
| "Map.size" -> ok C_SIZE | "GE" -> ok C_GE
| "LT" -> ok C_LT
| "LE" -> ok C_LE
| "CONS" -> ok C_CONS
| "NEQ" -> ok C_NEQ
| "Big_map.find_opt" -> ok C_MAP_FIND_OPT (* Crypto module *)
| "Big_map.find" -> ok C_MAP_FIND
| "Big_map.update" -> ok C_MAP_UPDATE
| "Big_map.add" -> ok C_MAP_ADD
| "Big_map.remove" -> ok C_MAP_REMOVE
| "Big_map.literal" -> ok C_BIG_MAP_LITERAL
| "Big_map.empty" -> ok C_BIG_MAP_EMPTY
| "Bitwise.lor" -> ok C_OR | "Crypto.check" -> ok C_CHECK_SIGNATURE
| "Bitwise.land" -> ok C_AND | "Crypto.hash_key" -> ok C_HASH_KEY
| "Bitwise.lxor" -> ok C_XOR | "Crypto.blake2b" -> ok C_BLAKE2b
| "Bitwise.shift_left" -> ok C_LSL | "Crypto.sha256" -> ok C_SHA256
| "Bitwise.shift_right" -> ok C_LSR | "Crypto.sha512" -> ok C_SHA512
| "String.length" -> ok C_SIZE (* Bytes module *)
| "String.size" -> ok C_SIZE
| "String.slice" -> ok C_SLICE
| "String.sub" -> ok C_SLICE
| "String.concat" -> ok C_CONCAT
| "List.length" -> ok C_SIZE | "Bytes.pack" -> ok C_BYTES_PACK
| "List.size" -> ok C_SIZE | "Bytes.unpack" -> ok C_BYTES_UNPACK
| "List.iter" -> ok C_LIST_ITER | "Bytes.length" -> ok C_SIZE
| "List.map" -> ok C_LIST_MAP | "Bytes.size" -> ok C_SIZE
| "List.fold" -> ok C_LIST_FOLD | "Bytes.concat" -> ok C_CONCAT
| "Bytes.slice" -> ok C_SLICE
| "Bytes.sub" -> ok C_SLICE
| "Loop.fold_while" -> ok C_FOLD_WHILE (* List module *)
| "continue" -> ok C_CONTINUE
| "stop" -> ok C_STOP
| "Operation.transaction" -> ok C_CALL | "List.length" -> ok C_SIZE
| "Operation.set_delegate" -> ok C_SET_DELEGATE | "List.size" -> ok C_SIZE
| "Operation.get_contract" -> ok C_CONTRACT | "List.iter" -> ok C_LIST_ITER
| "Operation.get_contract_opt" -> ok C_CONTRACT_OPT | "List.map" -> ok C_LIST_MAP
| "Operation.get_entrypoint" -> ok C_CONTRACT_ENTRYPOINT | "List.fold" -> ok C_LIST_FOLD
| "Operation.get_entrypoint_opt" -> ok C_CONTRACT_ENTRYPOINT_OPT
| "int" -> ok C_INT
| "abs" -> ok C_ABS
| "unit" -> ok C_UNIT
| "NEG" -> ok C_NEG (* Set module *)
| "ADD" -> ok C_ADD
| "SUB" -> ok C_SUB
| "TIMES" -> ok C_MUL
| "DIV" -> ok C_DIV
| "MOD" -> ok C_MOD
| "EQ" -> ok C_EQ
| "NOT" -> ok C_NOT
| "AND" -> ok C_AND
| "OR" -> ok C_OR
| "GT" -> ok C_GT
| "GE" -> ok C_GE
| "LT" -> ok C_LT
| "LE" -> ok C_LE
| "CONS" -> ok C_CONS
| "NEQ" -> ok C_NEQ
| "Michelson.is_nat" -> ok C_IS_NAT | "Set.mem" -> ok C_SET_MEM
| _ -> simple_fail "Not a constant" | "Set.iter" -> ok C_SET_ITER
| "Set.empty" -> ok C_SET_EMPTY
| "Set.literal" -> ok C_SET_LITERAL
| "Set.add" -> ok C_SET_ADD
| "Set.remove" -> ok C_SET_REMOVE
| "Set.fold" -> ok C_SET_FOLD
| "Set.size" -> ok C_SIZE
(* Map module *)
| "Map.find_opt" -> ok C_MAP_FIND_OPT
| "Map.find" -> ok C_MAP_FIND (* Deprecated *)
| "Map.update" -> ok C_MAP_UPDATE
| "Map.add" -> ok C_MAP_ADD
| "Map.remove" -> ok C_MAP_REMOVE
| "Map.iter" -> ok C_MAP_ITER
| "Map.map" -> ok C_MAP_MAP
| "Map.fold" -> ok C_MAP_FOLD
| "Map.mem" -> ok C_MAP_MEM
| "Map.empty" -> ok C_MAP_EMPTY
| "Map.literal" -> ok C_MAP_LITERAL
| "Map.size" -> ok C_SIZE
(* Big_map module *)
| "Big_map.find_opt" -> ok C_MAP_FIND_OPT
| "Big_map.find" -> ok C_MAP_FIND
| "Big_map.update" -> ok C_MAP_UPDATE
| "Big_map.add" -> ok C_MAP_ADD
| "Big_map.remove" -> ok C_MAP_REMOVE
| "Big_map.literal" -> ok C_BIG_MAP_LITERAL
| "Big_map.empty" -> ok C_BIG_MAP_EMPTY
(* Bitwise module *)
| "Bitwise.or" -> ok C_OR
| "Bitwise.lor" -> ok C_OR (* Deprecated *)
| "Bitwise.and" -> ok C_AND
| "Bitwise.land" -> ok C_AND (* Deprecated *)
| "Bitwise.xor" -> ok C_XOR
| "Bitwise.lxor" -> ok C_XOR (* Deprecated *)
| "Bitwise.shift_left" -> ok C_LSL
| "Bitwise.shift_right" -> ok C_LSR
(* String module *)
| "String.length" -> ok C_SIZE
| "String.size" -> ok C_SIZE
| "String.slice" -> ok C_SLICE
| "String.sub" -> ok C_SLICE
| "String.concat" -> ok C_CONCAT
(* Loop module *)
| "Loop.fold_while" -> ok C_FOLD_WHILE
| "Loop.continue" -> ok C_CONTINUE
| "continue" -> ok C_CONTINUE (* Deprecated *)
| "Loop.stop" -> ok C_STOP
| "stop" -> ok C_STOP (* Deprecated *)
(* Others *)
| "assert" -> ok C_ASSERTION
| _ -> simple_fail "Not a CameLIGO built-in."
let type_constants = type_constants let type_constants = type_constants
let type_operators = type_operators let type_operators = type_operators
@ -821,19 +966,19 @@ module Typer = struct
let%bind key = get_t_set set in let%bind key = get_t_set set in
if eq_1 elt key if eq_1 elt key
then ok @@ t_bool () then ok @@ t_bool ()
else fail @@ Operator_errors.type_error "Set_mem: elt and set don't match" elt key () else fail @@ Operator_errors.type_error "Set.mem: elt and set don't match" elt key ()
let set_add = typer_2 "SET_ADD" @@ fun elt set -> let set_add = typer_2 "SET_ADD" @@ fun elt set ->
let%bind key = get_t_set set in let%bind key = get_t_set set in
if eq_1 elt key if eq_1 elt key
then ok set then ok set
else fail @@ Operator_errors.type_error "Set_add: elt and set don't match" elt key () else fail @@ Operator_errors.type_error "Set.add: elt and set don't match" elt key ()
let set_remove = typer_2 "SET_REMOVE" @@ fun elt set -> let set_remove = typer_2 "SET_REMOVE" @@ fun elt set ->
let%bind key = get_t_set set in let%bind key = get_t_set set in
if eq_1 elt key if eq_1 elt key
then ok set then ok set
else fail @@ Operator_errors.type_error "Set_remove: elt and set don't match" key elt () else fail @@ Operator_errors.type_error "Set.remove: elt and set don't match" key elt ()
let set_iter = typer_2 "SET_ITER" @@ fun body set -> let set_iter = typer_2 "SET_ITER" @@ fun body set ->
let%bind (arg , res) = get_t_function body in let%bind (arg , res) = get_t_function body in

View File

@ -1,11 +1,7 @@
// Test PascaLIGO bitwise operators // Test PascaLIGO bitwise operators
function or_op (const n : nat) : nat is bitwise_or (n, 4n) function or_op (const n : nat) : nat is Bitwise.or (n, 4n)
function and_op (const n : nat) : nat is Bitwise.and (n, 7n)
function and_op (const n : nat) : nat is bitwise_and (n, 7n) function xor_op (const n : nat) : nat is Bitwise.xor (n, 7n)
function lsl_op (const n : nat) : nat is Bitwise.shift_left (n, 7n)
function xor_op (const n : nat) : nat is bitwise_xor (n, 7n) function lsr_op (const n : nat) : nat is Bitwise.shift_right (n, 7n)
function lsl_op (const n : nat) : nat is bitwise_lsl (n, 7n)
function lsr_op (const n : nat) : nat is bitwise_lsr (n, 7n)

View File

@ -1,7 +1,7 @@
(* Test CameLIGO bitwise operators *) (* Test CameLIGO bitwise operators *)
let or_op (n: nat) : nat = Bitwise.lor n 4n let or_op (n: nat) : nat = Bitwise.or n 4n
let and_op (n: nat) : nat = Bitwise.land n 7n let and_op (n: nat) : nat = Bitwise.and n 7n
let xor_op (n: nat) : nat = Bitwise.lxor n 7n let xor_op (n: nat) : nat = Bitwise.xor n 7n
let lsl_op (n: nat) : nat = Bitwise.shift_left n 7n let lsl_op (n: nat) : nat = Bitwise.shift_left n 7n
let lsr_op (n: nat) : nat = Bitwise.shift_right n 7n let lsr_op (n: nat) : nat = Bitwise.shift_right n 7n

View File

@ -1,7 +1,7 @@
/* Test ReasonLigo bitwise operators */ /* Test ReasonLigo bitwise operators */
let or_op = (n: nat): nat => Bitwise.lor(n, 4n); let or_op = (n : nat) : nat => Bitwise.or (n, 4n);
let and_op = (n: nat): nat => Bitwise.land(n, 7n); let and_op = (n : nat) : nat => Bitwise.and (n, 7n);
let xor_op = (n: nat): nat => Bitwise.lxor(n, 7n); let xor_op = (n : nat) : nat => Bitwise.xor (n, 7n);
let lsl_op = (n: nat) : nat => Bitwise.shift_left(n, 7n); let lsl_op = (n : nat) : nat => Bitwise.shift_left (n, 7n);
let lsr_op = (n: nat) : nat => Bitwise.shift_right(n, 7n); let lsr_op = (n : nat) : nat => Bitwise.shift_right (n, 7n);