diff --git a/gitlab-pages/docs/advanced/entrypoints-contracts.md b/gitlab-pages/docs/advanced/entrypoints-contracts.md index 6e5abbca0..429962a33 100644 --- a/gitlab-pages/docs/advanced/entrypoints-contracts.md +++ b/gitlab-pages/docs/advanced/entrypoints-contracts.md @@ -194,8 +194,8 @@ how those built-ins can be utilized. ### Accepting or Declining Tokens in a Smart Contract -This example shows how `amount` and `failwith` can be used to decline -any transaction that sends more tez than `0mutez`, that is, no +This example shows how `Tezos.amount` and `failwith` can be used to +decline any transaction that sends more tez than `0tez`, that is, no incoming tokens are accepted. @@ -206,11 +206,13 @@ type storage is unit type return is list (operation) * storage 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) else ((nil : list (operation)), store) ``` +> Note that `amount` is *deprecated*. + ```cameligo group=c type parameter = unit @@ -218,11 +220,13 @@ type storage = unit type return = operation list * storage let deny (action, store : parameter * storage) : return = - if amount > 0mutez then - (failwith "This contract does not accept tokens.": return) + if Tezos.amount > 0tez then + (failwith "This contract does not accept tokens." : return) else (([] : operation list), store) ``` +> Note that `amount` is *deprecated*. + ```reasonligo group=c type parameter = unit; @@ -230,17 +234,20 @@ type storage = unit; type return = (list (operation), storage); let deny = ((action, store): (parameter, storage)) : return => { - if (amount > 0mutez) { + if (Tezos.amount > 0tez) { (failwith("This contract does not accept tokens."): return); } else { (([] : list (operation)), store); }; }; ``` +> Note that `amount` is *deprecated*. + ### 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. @@ -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); function main (const action : parameter; const store : storage) : return is - if source =/= owner then (failwith ("Access denied.") : return) - else ((nil : list(operation)), store) + if Tezos.source =/= owner then (failwith ("Access denied.") : return) + else ((nil : list (operation)), store) ``` +> Note that `source` is *deprecated*. + ```cameligo group=c let owner : address = ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address) 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) ``` +> Note that `source` is *deprecated*. + ```reasonligo group=c let owner : address = ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address); -let main = ((action, store): (parameter, storage)) : storage => { - if (source != owner) { (failwith ("Access denied.") : return); } +let main = ((action, store) : (parameter, storage)) : storage => { + if (Tezos.source != owner) { (failwith ("Access denied.") : return); } else { (([] : list (operation)), store); }; }; ``` + +> Note that `source` is *deprecated*. + ### Inter-Contract Invocations @@ -327,11 +341,15 @@ const dest : address = ("KT19wgxcuXG9VH4Af5Tpm1vqEKdaMFpznXT3" : address) function proxy (const action : parameter; const store : storage): return is 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 transaction or use another one, `mock_param`. *) 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] } with (ops, store) ``` @@ -363,14 +381,20 @@ type return = operation list * storage let dest : address = ("KT19wgxcuXG9VH4Af5Tpm1vqEKdaMFpznXT3" : address) 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 transaction or use another one, `mock_param`. *) 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 ``` +> Note that `Operation.get_contract` and `Operation.transaction` are +> *deprecated*. + ```reasonligo skip // counter.religo @@ -398,13 +422,20 @@ type return = (list (operation), storage); let dest : address = ("KT19wgxcuXG9VH4Af5Tpm1vqEKdaMFpznXT3" : address); 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 transaction or use another one, `mock_param`. *) let mock_param : parameter = Increment (5n); - let op : operation = Operation.transaction (action, 0mutez, counter); + let op : operation = Tezos.transaction (action, 0tez, counter); ([op], store) }; ``` +> Note that `Operation.get_contract` and `Operation.transaction` are +> *deprecated*. + diff --git a/gitlab-pages/docs/advanced/first-contract.md b/gitlab-pages/docs/advanced/first-contract.md index 00bed6f7c..eb63a25c4 100644 --- a/gitlab-pages/docs/advanced/first-contract.md +++ b/gitlab-pages/docs/advanced/first-contract.md @@ -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 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). ``` -type action is +type parameter is Increment 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)), - (case p of - | Increment (n) -> s + n - | Decrement (n) -> s - n - end)) + case action of + Increment (n) -> add (n, store) + | Decrement (n) -> sub (n, store) + end) ``` ```cameligo -type action = -| Increment of int +type parameter = + Increment of int | Decrement of int -let main (p, s: action * int) : operation list * int = - let result = - match p with - | Increment n -> s + n - | Decrement n -> s - n - in - (([]: operation list), result) +type storage = int + +type return = (operation) list * storage + +let add (n, store : int * storage) : storage = store + n +let sub (n, store : int * storage) : storage = store - n + +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 -type action = -| Increment(int) -| Decrement(int); +type parameter = + Increment (int) +| Decrement (int) +; -let main = (p_s: (action, int)) : (list(operation), int) => { - let p, s = p_s; - let result = - switch (p) { - | Increment(n) => s + n - | Decrement(n) => s - n - }; - (([]: list(operation)), result); -}; +type storage = int; + +type return = (list (operation), storage); + +let add = ((n, store) : (int, storage)) : storage => store + n; +let sub = ((n, store) : (int, storage)) : storage => store - n; + +let main = ((action, store) : (parameter, storage)) : return => + (([]: list (operation)), + (switch (action) { + | Increment (n) => add ((n, store)) + | Decrement (n) => sub ((n, store)) + })); ``` -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`. @@ -131,39 +150,30 @@ Command above will output the following Michelson code: { parameter (or (int %decrement) (int %increment)) ; storage int ; code { DUP ; - CAR ; - DIP { DUP } ; - SWAP ; CDR ; DIP { DUP } ; SWAP ; + CAR ; IF_LEFT { DUP ; - DIP 2 { DUP } ; - DIG 2 ; - DIP { DUP } ; + DIP { DIP { DUP } ; SWAP } ; + PAIR ; + DUP ; + CDR ; + DIP { DUP ; CAR } ; SUB ; - SWAP ; - DROP ; - SWAP ; - DROP } + DIP { DROP 2 } } { DUP ; - DIP 2 { DUP } ; - DIG 2 ; - DIP { DUP } ; + DIP { DIP { DUP } ; SWAP } ; + PAIR ; + DUP ; + CDR ; + DIP { DUP ; CAR } ; ADD ; - SWAP ; - DROP ; - SWAP ; - DROP } ; + DIP { DROP 2 } } ; NIL operation ; PAIR ; - SWAP ; - DROP ; - SWAP ; - DROP ; - SWAP ; - DROP } } + DIP { DROP 2 } } } ``` @@ -180,12 +190,15 @@ ligo compile-storage src/counter.ligo main 5 ``` - -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. +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. ## 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: @@ -195,6 +208,5 @@ ligo compile-parameter src/counter.ligo main 'Increment(5)' ``` - 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` diff --git a/gitlab-pages/docs/advanced/src/counter.ligo b/gitlab-pages/docs/advanced/src/counter.ligo new file mode 100644 index 000000000..301b662c4 --- /dev/null +++ b/gitlab-pages/docs/advanced/src/counter.ligo @@ -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) diff --git a/gitlab-pages/docs/advanced/src/functions.ligo b/gitlab-pages/docs/advanced/src/functions.ligo new file mode 100644 index 000000000..6e0f83bf5 --- /dev/null +++ b/gitlab-pages/docs/advanced/src/functions.ligo @@ -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) diff --git a/gitlab-pages/docs/advanced/src/multiple-entrypoints.ligo b/gitlab-pages/docs/advanced/src/multiple-entrypoints.ligo new file mode 100644 index 000000000..301b662c4 --- /dev/null +++ b/gitlab-pages/docs/advanced/src/multiple-entrypoints.ligo @@ -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) diff --git a/gitlab-pages/docs/advanced/src/variables.ligo b/gitlab-pages/docs/advanced/src/variables.ligo new file mode 100644 index 000000000..e8e40f1f7 --- /dev/null +++ b/gitlab-pages/docs/advanced/src/variables.ligo @@ -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) diff --git a/gitlab-pages/docs/advanced/timestamps-addresses.md b/gitlab-pages/docs/advanced/timestamps-addresses.md index fb2154bc8..b3a4d2391 100644 --- a/gitlab-pages/docs/advanced/timestamps-addresses.md +++ b/gitlab-pages/docs/advanced/timestamps-addresses.md @@ -18,23 +18,29 @@ current timestamp value. ```pascaligo group=a -const today : timestamp = now +const today : timestamp = Tezos.now ``` +> Note that `now` is *deprecated*. + ```cameligo group=a -let today : timestamp = Current.time +let today : timestamp = Tezos.now ``` +> Note that `Current.time` is *deprecated*. + ```reasonligo group=a -let today : timestamp = Current.time; +let today : timestamp = Tezos.now; ``` +> Note that `Current.time` is *deprecated*. + -> When running code, the LIGO CLI option -> `--predecessor-timestamp` allows you to control what `now` returns. +> When running code, the LIGO CLI option `--predecessor-timestamp` +> allows you to control what `Tezos.now` returns. ### Timestamp Arithmetics @@ -46,31 +52,37 @@ constraints on your smart contracts. Consider the following scenarios. ```pascaligo group=b -const today : timestamp = now +const today : timestamp = Tezos.now const one_day : int = 86400 const in_24_hrs : timestamp = today + one_day const some_date : timestamp = ("2000-01-01T10:10:10Z" : timestamp) const one_day_later : timestamp = some_date + one_day ``` +> Note that `now` is *deprecated*. + ```cameligo group=b -let today : timestamp = Current.time +let today : timestamp = Tezos.now let one_day : int = 86400 let in_24_hrs : timestamp = today + one_day let some_date : timestamp = ("2000-01-01t10:10:10Z" : timestamp) let one_day_later : timestamp = some_date + one_day ``` +> Note that `Current.time` is *deprecated*. + ```reasonligo group=b -let today : timestamp = Current.time; +let today : timestamp = Tezos.now; let one_day : int = 86400; let in_24_hrs : timestamp = today + one_day; let some_date : timestamp = ("2000-01-01t10:10:10Z" : timestamp); let one_day_later : timestamp = some_date + one_day; ``` +> Note that `Current.time` is *deprecated*. + #### 24 hours Ago @@ -78,25 +90,32 @@ let one_day_later : timestamp = some_date + one_day; ```pascaligo group=c -const today : timestamp = now +const today : timestamp = Tezos.now const one_day : int = 86400 const in_24_hrs : timestamp = today - one_day ``` +> Note that `now` is *deprecated*. + ```cameligo group=c -let today : timestamp = Current.time +let today : timestamp = Tezos.now let one_day : int = 86400 let in_24_hrs : timestamp = today - one_day ``` +> Note that `Current.time` is *deprecated*. + ```reasonligo group=c -let today : timestamp = Current.time; +let today : timestamp = Tezos.now; let one_day : int = 86400; let in_24_hrs : timestamp = today - one_day; ``` +> Note that `Current.time` is *deprecated*. + + ### Comparing Timestamps @@ -107,19 +126,26 @@ applying to numbers. ```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 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 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*. + + ## Addresses diff --git a/gitlab-pages/docs/api/cheat-sheet.md b/gitlab-pages/docs/api/cheat-sheet.md index 8f8baebdb..15e10bfe4 100644 --- a/gitlab-pages/docs/api/cheat-sheet.md +++ b/gitlab-pages/docs/api/cheat-sheet.md @@ -4,7 +4,7 @@ title: Cheat Sheet ---
- @@ -30,7 +30,7 @@ Note that this table is not compiled before production and currently needs to be |Includes|```#include "library.ligo"```| |Functions (short form)|
function add (const a : int ; const b : int) : int is
  block { skip } with a + b
| |Functions (long form)|
function add (const a : int ; const b : int) : int is
  block {
    const result: int = a + b;
  } with result
| -| If Statement |
if age < 16 
then fail("Too young to drive.");
else const new_id: int = prev_id + 1;
| +| If Statement |
if age < 16 
then fail("Too young to drive.");
else const new_id: int = prev_id + 1;
| |Options|
type middleName is option(string);
const middleName : middleName = Some("Foo");
const middleName : middleName = None;
| |Assignment| ```const age: int = 5;```| |Assignment on an existing variable

*⚠️ 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|
let a: action = Increment 5
match a with
| Increment n -> n + 1
| Decrement n -> n - 1
| |Records|
type person = {
  age: int ;
  name: string ;
}

let john : person = {
  age = 18;
  name = "John Doe";
}

let name: string = john.name
| |Maps|
type prices = (nat, tez) map

let prices : prices = Map.literal [
  (10n, 60mutez);
  (50n, 30mutez);
  (100n, 10mutez)
]

let price: tez option = Map.find_opt 50n prices

let prices: prices = Map.update 200n (Some 5mutez) prices
| -|Contracts & Accounts|
let destination_address : address = "tz1..."
let contract : unit contract =
Operation.get_contract destination_address
| -|Transactions|
let payment : operation = 
Operation.transaction unit amount receiver
| +|Contracts & Accounts|
let destination_address : address = "tz1..."
let contract : unit contract =
Tezos.get_contract destination_address
| +|Transactions|
let payment : operation = 
Tezos.transaction unit amount receiver
| |Exception/Failure|`failwith("Your descriptive error message for the user goes here.")`| @@ -103,8 +103,8 @@ Note that this table is not compiled before production and currently needs to be |Variant *(pattern)* matching|
let a: action = Increment(5);
switch(a) {
| Increment(n) => n + 1
| Decrement(n) => n - 1;
}
| |Records|
type person = {
  age: int,
  name: string
}

let john : person = {
  age: 18,
  name: "John Doe"
};

let name: string = john.name;
| |Maps|
type prices = map(nat, tez);

let prices : prices = Map.literal([
  (10n, 60mutez),
  (50n, 30mutez),
  (100n, 10mutez)
]);

let price: option(tez) = Map.find_opt(50n, prices);

let prices: prices = Map.update(200n, Some (5mutez), prices);
| -|Contracts & Accounts|
let destination_address : address = "tz1...";
let contract : contract(unit) =
Operation.get_contract(destination_address);
| -|Transactions|
let payment : operation = 
Operation.transaction (unit, amount, receiver);
| +|Contracts & Accounts|
let destination_address : address = "tz1...";
let contract : contract(unit) =
Tezos.get_contract(destination_address);
| +|Transactions|
let payment : operation = 
Tezos.transaction (unit, amount, receiver);
| |Exception/Failure|`failwith("Your descriptive error message for the user goes here.");`| diff --git a/gitlab-pages/docs/language-basics/boolean-if-else.md b/gitlab-pages/docs/language-basics/boolean-if-else.md index 8a872d777..e9b38291a 100644 --- a/gitlab-pages/docs/language-basics/boolean-if-else.md +++ b/gitlab-pages/docs/language-basics/boolean-if-else.md @@ -11,8 +11,8 @@ value: ```pascaligo group=a -const a : bool = True // Notice the capital letter -const b : bool = False // Same. +const a : bool = True // Also: true +const b : bool = False // Also: false ``` ```cameligo group=a @@ -137,7 +137,7 @@ state. type magnitude is Small | Large // See variant types. 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 @@ -145,7 +145,7 @@ like this: ```shell ligo run-function 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 @@ -161,7 +161,7 @@ else skip; ``` 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: ```pascaligo skip if x < y then { @@ -187,9 +187,15 @@ gitlab-pages/docs/language-basics/boolean-if-else/cond.mligo compare 21n' # 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 group=e -type magnitude = | Small | Large; // See variant types. +type magnitude = Small | Large; // See variant types. let compare = (n : nat) : magnitude => if (n < 10n) { Small; } else { Large; }; diff --git a/gitlab-pages/docs/language-basics/functions.md b/gitlab-pages/docs/language-basics/functions.md index d0344a754..b4c81beb1 100644 --- a/gitlab-pages/docs/language-basics/functions.md +++ b/gitlab-pages/docs/language-basics/functions.md @@ -4,7 +4,15 @@ title: Functions --- 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 @@ -230,10 +238,14 @@ function to all its elements. ```pascaligo group=c 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 ligo run-function gitlab-pages/docs/language-basics/src/functions/incr_map.ligo incr_map diff --git a/gitlab-pages/docs/language-basics/loops.md b/gitlab-pages/docs/language-basics/loops.md index bb31e124f..1ded1ef05 100644 --- a/gitlab-pages/docs/language-basics/loops.md +++ b/gitlab-pages/docs/language-basics/loops.md @@ -79,17 +79,21 @@ let gcd (x,y : nat * nat) : nat = ``` 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 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 x,y = if x < y then y,x else x,y in let x,y = Loop.fold_while iter (x,y) in x ``` + +> Note that `stop` and `continue` are *deprecated*. + You can call the function `gcd` defined above using the LIGO compiler like so: ```shell @@ -131,11 +135,12 @@ let gcd = ((x,y) : (nat, nat)) : nat => { ``` 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 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 (x,y) = if (x < y) { (y,x); } else { (x,y); }; @@ -143,6 +148,9 @@ let gcd = ((x,y) : (nat, nat)) : nat => { x }; ``` + +> Note that `stop` and `continue` are *deprecated*. + ## Bounded Loops diff --git a/gitlab-pages/docs/language-basics/maps-records.md b/gitlab-pages/docs/language-basics/maps-records.md index d691d588e..f1b491b60 100644 --- a/gitlab-pages/docs/language-basics/maps-records.md +++ b/gitlab-pages/docs/language-basics/maps-records.md @@ -19,7 +19,7 @@ Let us first consider and example of record type declaration. -```pascaligo group=a +```pascaligo group=records1 type user is record [ id : nat; @@ -29,7 +29,7 @@ type user is ``` -```cameligo group=a +```cameligo group=records1 type user = { id : nat; is_admin : bool; @@ -38,7 +38,7 @@ type user = { ``` -```reasonligo group=a +```reasonligo group=records1 type user = { id : nat, is_admin : bool, @@ -51,7 +51,7 @@ And here is how a record value is defined: -```pascaligo group=a +```pascaligo group=records1 const alice : user = record [ id = 1n; @@ -61,7 +61,7 @@ const alice : user = ``` -```cameligo group=a +```cameligo group=records1 let alice : user = { id = 1n; is_admin = true; @@ -70,7 +70,7 @@ let alice : user = { ``` -```reasonligo group=a +```reasonligo group=records1 let alice : user = { id : 1n, is_admin : true, @@ -86,17 +86,17 @@ operator, like so: -```pascaligo group=a +```pascaligo group=records1 const alice_admin : bool = alice.is_admin ``` -```cameligo group=a +```cameligo group=records1 let alice_admin : bool = alice.is_admin ``` -```reasonligo group=a +```reasonligo group=records1 let alice_admin : bool = alice.is_admin; ``` @@ -123,7 +123,7 @@ In PascaLIGO, the shape of that expression is ` with `. The record variable is the record to update and the record value is the update itself. -```pascaligo group=b +```pascaligo group=records2 type point is record [x : int; y : int; z : 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 that of OCaml: -```cameligo group=b +```cameligo group=records2 type point = {x : int; y : int; z : 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 that of ReasonML: -```reasonligo group=b +```reasonligo group=records2 type point = {x : int, y : int, z : int}; type vector = {dx : int, dy : int}; @@ -216,7 +216,7 @@ name "patch"). Let us consider defining a function that translates three-dimensional points on a plane. -```pascaligo group=c +```pascaligo group=records3 type point is record [x : int; y : int; z : 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, 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 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 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 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 sense. +### Declaring a Map + Here is how a custom map from addresses to a pair of integers is defined. + -```pascaligo group=f +```pascaligo group=maps type move is int * int type register is map (address, move) ``` -```cameligo group=f +```cameligo group=maps type move = int * int type register = (address, move) map ``` -```reasonligo group=f +```reasonligo group=maps type move = (int, int); type register = map (address, move); ``` -And here is how a map value is defined: +### Creating an Empty Map + +Here is how to create an empty map. + + + + +```pascaligo group=maps +const empty : register = map [] +``` + + +```cameligo group=maps +let empty : register = Map.empty +``` + + +```reasonligo group=maps +let empty : register = Map.empty +``` + + +### Creating a Non-empty Map + +And here is how to create a non-empty map value: -```pascaligo group=f +```pascaligo group=maps const moves : register = map [ ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address) -> (1,2); ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) -> (0,3)] ``` -> Notice the `->` between the key and its value and `;` to separate -> individual map entries. The annotated value `("" : -> address)` means that we cast a string into an address. Also, `map` -> is a keyword. +Notice the `->` between the key and its value and `;` to separate +individual map entries. The annotated value `("" : +address)` means that we cast a string into an address. Also, `map` is +a keyword. -```cameligo group=f +```cameligo group=maps let moves : register = Map.literal [ (("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address), (1,2)); (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address), (0,3))] ``` -> The `Map.literal` predefined function builds a map from a list of -> key-value pair tuples, `(, )`. Note also the `;` to -> separate individual map entries. `("": address)` -> means that we type-cast a string into an address. +The `Map.literal` predefined function builds a map from a list of +key-value pair tuples, `(, )`. Note also the `;` to +separate individual map entries. `("": address)` means +that we type-cast a string into an address. --> -```reasonligo group=f +```reasonligo group=maps let moves : register = Map.literal ([ ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address, (1,2)), ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address, (0,3))]); ``` -> The `Map.literal` predefined function builds a map from a list of -> key-value pair tuples, `(, )`. Note also the `;` to -> separate individual map entries. `("": address)` -> means that we type-cast a string into an address. +The `Map.literal` predefined function builds a map from a list of +key-value pair tuples, `(, )`. Note also the `;` to +separate individual map entries. `("": address)` means +that we type-cast a string into an address. --> @@ -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 is an example: -```pascaligo group=f +```pascaligo group=maps const my_balance : option (move) = moves [("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address)] ``` -```cameligo group=f +```cameligo group=maps let my_balance : move option = Map.find_opt ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) moves ``` -```reasonligo group=f +```reasonligo group=maps let my_balance : option (move) = Map.find_opt (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address), moves); ``` @@ -400,7 +427,7 @@ the reader to account for a missing key in the map. This requires -```pascaligo group=f +```pascaligo group=maps function force_access (const key : address; const moves : register) : move is case moves[key] of Some (move) -> move @@ -409,7 +436,7 @@ function force_access (const key : address; const moves : register) : move is ``` -```cameligo group=f +```cameligo group=maps let force_access (key, moves : address * register) : move = match Map.find_opt key moves with Some move -> move @@ -417,7 +444,7 @@ let force_access (key, moves : address * register) : move = ``` -```reasonligo group=f +```reasonligo group=maps let force_access = ((key, moves) : (address, register)) : move => { switch (Map.find_opt (key, moves)) { | Some (move) => move @@ -443,7 +470,7 @@ The values of a PascaLIGO map can be updated using the usual assignment syntax `[] := `. Let us consider an example. -```pascaligo group=f +```pascaligo group=maps function assign (var m : register) : register is block { 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 instruction* for maps, similar to that for records. -```pascaligo group=f +```pascaligo group=maps function assignments (var m : register) : register is block { patch m with map [ @@ -463,35 +490,51 @@ function assignments (var m : register) : register is } with m ``` +See further for the removal of bindings. + We can update a binding in a map in CameLIGO by means of the `Map.update` built-in function: -```cameligo group=f +```cameligo group=maps let assign (m : register) : register = Map.update ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) (Some (4,9)) m ``` -> Notice the optional value `Some (4,9)` instead of `(4,9)`. If we had -> use `None` instead, that would have meant that the binding is -> removed. +Notice the optional value `Some (4,9)` instead of `(4,9)`. If we had +use `None` instead, that would have meant that the binding is removed. + +As a particular case, we can only add a key and its associated value. + +```cameligo group=maps +let add (m : register) : register = + Map.add + ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) (4,9) m +``` We can update a binding in a map in ReasonLIGO by means of the `Map.update` built-in function: -```reasonligo group=f +```reasonligo group=maps let assign = (m : register) : register => Map.update (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address), Some ((4,9)), m); ``` -> Notice the optional value `Some (4,9)` instead of `(4,9)`. If we had -> use `None` instead, that would have meant that the binding is -> removed. +Notice the optional value `Some (4,9)` instead of `(4,9)`. If we had +use `None` instead, that would have meant that the binding is removed. + +As a particular case, we can only add a key and its associated value. + +```reasonligo group=maps +let add = (m : register) : register => + Map.add + (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address), (4,9), m); +``` @@ -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 a map. -```pascaligo group=f +```pascaligo group=maps function delete (const key : address; var moves : register) : register is block { 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: -```cameligo group=f +```cameligo group=maps let delete (key, moves : address * register) : register = 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: -```reasonligo group=f +```reasonligo group=maps let delete = ((key, moves) : (address, register)) : register => 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 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`. + -In PascaLIGO, 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`. - -```pascaligo group=f +```pascaligo group=maps function iter_op (const m : register) : unit is block { function iterated (const i : address; const j : move) : unit is 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 -> variables. +> Note that `map_iter` is *deprecated*. -In CameLIGO, the predefinded 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`. - -```cameligo group=f +```cameligo group=maps let iter_op (m : register) : unit = let predicate = fun (i,j : address * move) -> assert (j.0 > 3) in Map.iter predicate m @@ -584,12 +621,7 @@ let iter_op (m : register) : unit = -In ReasonLIGO, 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`. - -```reasonligo group=f +```reasonligo group=maps let iter_op = (m : register) : unit => { let predicate = ((i,j) : (address, move)) => assert (j[0] > 3); 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 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. -In PascaLIGO, the predefined functional iterator implementing the map -operation over maps is called `map_map` and is used as follows: - -```pascaligo group=f +```pascaligo group=maps function map_op (const m : register) : register is block { function increment (const i : address; const j : move) : move is - (j.0, j.1 + 1); - } with map_map (increment, m) + (j.0, j.1 + 1) + } with Map.map (increment, m) ``` -> The mapped function must be pure, that is, it cannot mutate -> variables. +> Note that `map_map` is *deprecated*. -In CameLIGO, the predefined functional iterator implementing the map -operation over maps is called `Map.map` and is used as follows: - -```cameligo group=f +```cameligo group=maps let map_op (m : register) : register = let increment = fun (i,j : address * move) -> j.0, j.1 + 1 in Map.map increment m @@ -634,10 +662,7 @@ let map_op (m : register) : register = -In ReasonLIGO, the predefined functional iteratir implementing the map -operation over maps is called `Map.map` and is used as follows: - -```reasonligo group=f +```reasonligo group=maps let map_op = (m : register) : register => { let increment = ((i,j): (address, move)) => (j[0], j[1] + 1); 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 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. + -In PascaLIGO, the predefined functional iterator implementing the -folded operation over maps is called `map_fold` and is used as -follows: - -```pascaligo group=f -function fold_op (const m : register) : int is block { - function folded (const j : int; const cur : address * move) : int is - j + cur.1.1 - } with map_fold (folded, m, 5) +```pascaligo group=maps +function fold_op (const m : register) : int is + block { + function folded (const i : int; const j : address * move) : int is + i + j.1.1 + } with Map.fold (folded, m, 5) ``` -> The folded function must be pure, that is, it cannot mutate -> variables. +> Note that `map_fold` is *deprecated*. -In CameLIGO, the predefined functional iterator implementing the -folded operation over maps is called `Map.fold` and is used as -follows: - -```cameligo group=f +```cameligo group=maps let fold_op (m : register) : register = let folded = fun (i,j : int * (address * move)) -> i + j.1.1 in Map.fold folded m 5 @@ -685,11 +705,7 @@ let fold_op (m : register) : register = -In ReasonLIGO, the predefined functional iterator implementing the -folded operation over maps is called `Map.fold` and is used as -follows: - -```reasonligo group=f +```reasonligo group=maps let fold_op = (m : register) : register => { let folded = ((i,j): (int, (address, move))) => i + j[1][1]; 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 interface for big maps is analogous to the one used for ordinary maps. +### Declaring a Map + Here is how we define a big map: -```pascaligo group=g +```pascaligo group=big_maps type move is int * int type register is big_map (address, move) ``` -```cameligo group=g +```cameligo group=big_maps type move = int * int type register = (address, move) big_map ``` -```reasonligo group=g +```reasonligo group=big_maps type move = (int, int); type register = big_map (address, move); ``` -And here is how a map value is created: +### Creating an Empty Big Map + +Here is how to create an empty big map. + + + + + +```pascaligo group=big_maps +const empty : register = big_map [] +``` + + +```cameligo group=big_maps +let empty : register = Big_map.empty +``` + + +```reasonligo group=big_maps +let empty : register = Big_map.empty +``` + + +### Creating a Non-empty Map + +And here is how to create a non-empty map value: -```pascaligo group=g +```pascaligo group=big_maps const moves : register = big_map [ ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address) -> (1,2); ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) -> (0,3)] ``` -> Notice the right arrow `->` between the key and its value and the -> semicolon separating individual map entries. The value annotation -> `("" : address)` means that we cast a string into an -> address. + Notice the right arrow `->` between the key and its value and the --> + semicolon separating individual map entries. The value annotation --> + `("" : address)` means that we cast a string into an --> + address. --> -```cameligo group=g +```cameligo group=big_maps let moves : register = Big_map.literal [ (("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address), (1,2)); (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address), (0,3))] ``` -> The predefind function `Big_map.literal` constructs a big map from a -> list of key-value pairs `(, )`. Note also the semicolon -> separating individual map entries. The annotated value `(" value>" : address)` means that we cast a string into an address. +The predefind function `Big_map.literal` constructs a big map from a +list of key-value pairs `(, )`. Note also the semicolon +separating individual map entries. The annotated value `(" +value>" : address)` means that we cast a string into an address. -```reasonligo group=g +```reasonligo group=big_maps let moves : register = Big_map.literal ([ ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address, (1,2)), ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address, (0,3))]); ``` -> The predefind function `Big_map.literal` constructs a big map from a -> list of key-value pairs `(, )`. Note also the semicolon -> separating individual map entries. The annotated value `(" value>" : address)` means that we cast a string into an address. +The predefind function `Big_map.literal` constructs a big map from a +list of key-value pairs `(, )`. Note also the semicolon +separating individual map entries. The annotated value `(" +value>" : address)` means that we cast a string into an address. @@ -793,21 +836,21 @@ the value we read is an optional value (in our case, of type `option -```pascaligo group=g +```pascaligo group=big_maps const my_balance : option (move) = moves [("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address)] ``` -```cameligo group=g +```cameligo group=big_maps let my_balance : move option = Big_map.find_opt ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) moves ``` -```reasonligo group=g +```reasonligo group=big_maps let my_balance : option (move) = 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 assignment syntax for ordinary maps -```pascaligo group=g +```pascaligo group=big_maps function add (var m : register) : register is block { 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` built-in: -```cameligo group=g +```cameligo group=big_maps let updated_map : register = Big_map.update ("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` built-in: -```reasonligo group=g +```reasonligo group=big_maps let updated_map : register = Big_map.update - (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), Some((4,9)), moves); + (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), Some ((4,9)), moves); ``` @@ -867,7 +910,7 @@ syntax. PascaLIGO features a special syntactic construct to remove bindings from maps, of the form `remove from map `. For example, -```pascaligo group=g +```pascaligo group=big_maps function rem (var m : register) : register is block { 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 is called `Map.remove` and is used as follows: -```cameligo group=g +```cameligo group=big_maps let updated_map : register = 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 is called `Map.remove` and is used as follows: -```reasonligo group=g +```reasonligo group=big_maps let updated_map : register = Map.remove (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), moves) ``` diff --git a/gitlab-pages/docs/language-basics/operators.md b/gitlab-pages/docs/language-basics/operators.md index fc988c658..07dddbafc 100644 --- a/gitlab-pages/docs/language-basics/operators.md +++ b/gitlab-pages/docs/language-basics/operators.md @@ -3,13 +3,14 @@ id: 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 | |--- |--- |--- | -| `SENDER` | `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) -| `AMOUNT` | `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. \ No newline at end of file +| `SENDER` | `Tezos.sender` | Address that initiated the current transaction +| `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` | `Tezos.amount` | Amount of tez sent by the transaction that invoked the contract +| `NOW` | `Tezos.now` | Timestamp of the block whose validation triggered execution of the contract, i.e. current time when the contract is run. diff --git a/gitlab-pages/docs/language-basics/sets-lists-tuples.md b/gitlab-pages/docs/language-basics/sets-lists-tuples.md index 57132e9b6..abf8b4b20 100644 --- a/gitlab-pages/docs/language-basics/sets-lists-tuples.md +++ b/gitlab-pages/docs/language-basics/sets-lists-tuples.md @@ -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 *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 @@ -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 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 -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`. -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 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) + if i > 3 then Unit else (failwith ("Below range.") : unit) + } with List.iter (iterated, l) ``` -> The iterated function must be pure, that is, it cannot mutate -> variables. +> Note that `list_iter` is *deprecated*. -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 let iter_op (l : int list) : unit = let predicate = fun (i : int) -> assert (i > 3) @@ -227,12 +213,6 @@ let iter_op (l : int list) : unit = -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 let iter_op = (l : list (int)) : unit => { 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 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. -In PascaLIGO, the predefined functional iterator implementing the -mapped operation over lists is called `list_map` and is used as -follows: - ```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) +const plus_one : list (int) = List.map (increment, larger_list) ``` -> The mapped function must be pure, that is, it cannot mutate -> variables. +> Note that `list_map` is *deprecated*. -In CameLIGO, the predefined functional iterator implementing the -mapped operation over lists is called `List.map` and is used as -follows: - ```cameligo group=lists let increment (i : int) : int = i + 1 @@ -282,10 +255,6 @@ let plus_one : int list = List.map increment larger_list -In ReasonLIGO, the predefined functional iterator implementing the -mapped operation over lists is called `List.map` and is used as -follows: - ```reasonligo group=lists 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 *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. +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. -In PascaLIGO, the predefined functional iterator implementing the -folded operation over lists is called `list_fold` and is used as -follows: - ```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) +const sum_of_elements : int = List.fold (sum, my_list, 0) ``` -> The folded function must be pure, that is, it cannot mutate -> variables. +> Note that `list_fold` is *deprecated*. -In CameLIGO, the predefined functional iterator implementing the folded -operation over lists is called `List.fold` and is used as follows: - ```cameligo group=lists let sum (acc, i: int * int) : int = acc + i 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 -In ReasonLIGO, the predefined functional iterator implementing the -folded operation over lists is called `List.fold` and is used as -follows: - ```reasonligo group=lists let sum = ((result, i): (int, int)): int => result + i; let sum_of_elements : int = List.fold (sum, my_list, 0); @@ -472,36 +431,31 @@ in a set as follows: ```reasonligo group=sets let contains_3 : bool = Set.mem (3, my_set); ``` + ### Cardinal of Sets +The predefined function `Set.size` returns the number of +elements in a given set as follows. + -In PascaLIGO, the predefined function `size` returns the number of -elements in a given set as follows: - ```pascaligo group=sets -const set_size : nat = size (my_set) +const cardinal : nat = Set.size (my_set) ``` -In CameLIGO, the predefined function `Set.size` returns the number of -elements in a given set as follows: - ```cameligo group=sets -let set_size : nat = Set.size my_set +let cardinal : nat = Set.size my_set ``` -In ReasonLIGO, the predefined function `Set.size` returns the number -of elements in a given set as follows: - ```reasonligo group=sets -let set_size : nat = Set.size (my_set); +let cardinal : nat = Set.size (my_set); ``` @@ -509,20 +463,23 @@ let set_size : nat = Set.size (my_set); ### Updating Sets +There are two ways to update a set, that is to add or remove from +it. + -In PascaLIGO, there are two ways to update a set, that is to add or -remove from it. Either we create a new set from the given one, or we +In PascaLIGO, either we create a new set from the given one, or we modify it in-place. First, let us consider the former way: ```pascaligo group=sets -const larger_set : set (int) = set_add (4, my_set) - -const smaller_set : set (int) = set_remove (3, my_set) +const larger_set : set (int) = Set.add (4, my_set) +const smaller_set : set (int) = Set.remove (3, my_set) ``` +> Note that `set_add` and `set_remove` are *deprecated*. + If we are in a block, we can use an instruction to modify the set bound to a given variable. This is called a *patch*. It is only possible to add elements by means of a patch, not remove any: it is @@ -544,23 +501,23 @@ const new_set : set (int) = update (my_set) -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. ```cameligo group=sets let larger_set : int set = Set.add 4 my_set - let smaller_set : int set = Set.remove 3 my_set ``` -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. ```reasonligo group=sets let larger_set : set (int) = Set.add (4, my_set); - let smaller_set : set (int) = Set.remove (3, my_set); ``` @@ -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 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`. + -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 function iter_op (const s : set (int)) : unit is block { function iterated (const i : int) : unit is 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 -> variables. +> Note that `set_iter` is *deprecated*. -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 let iter_op (s : int set) : unit = let predicate = fun (i : int) -> assert (i > 3) @@ -621,12 +570,6 @@ let iter_op (s : int set) : unit = -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 let iter_op = (s : set (int)) : unit => { let predicate = (i : int) => assert (i > 3); @@ -637,51 +580,51 @@ let iter_op = (s : set (int)) : unit => { -#### Mapped Operation (NOT IMPLEMENTED YET) + -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 -confused with the map data structure. + + + - + - + -In PascaLIGO, the predefined functional iterator implementing the -mapped operation over sets is called `set_map` and is used as follows: + + -```pascaligo skip -function increment (const i : int): int is i + 1 + + -// Creates a new set with all elements incremented by 1 -const plus_one : set (int) = set_map (increment, larger_set) -``` + + + - + -In CameLIGO, the predefined functional iterator implementing the -mapped operation over sets is called `Set.map` and is used as follows: + + -```cameligo skip -let increment (i : int) : int = i + 1 + + -// Creates a new set with all elements incremented by 1 -let plus_one : int set = Set.map increment larger_set -``` + + + - + -In ReasonLIGO, the predefined functional iterator implementing the -mapped operation over sets is called `Set.map` and is used as follows: + + -```reasonligo skip -let increment = (i : int) : int => i + 1; + + -// Creates a new set with all elements incremented by 1 -let plus_one : set (int) = Set.map (increment, larger_set); -``` + + + - + #### 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 *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. +traversal of the data structure is over. The predefined fold over sets +is called `Set.fold`. -In PascaLIGO, the predefined functional iterator implementing the -folded operation over sets is called `set_fold` and is used as -follows: - ```pascaligo group=sets 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 -> variables. +> Note that `set_fold` is *deprecated*. 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 { -In CameLIGO, the predefined fold over sets is called `Set.fold`. - ```cameligo group=sets let sum (acc, i : int * int) : int = acc + i @@ -731,8 +668,6 @@ let sum_of_elements : int = Set.fold sum my_set 0 -In ReasonLIGO, the predefined fold over sets is called `Set.fold`. - ```reasonligo group=sets let sum = ((acc, i) : (int, int)) : int => acc + i; diff --git a/gitlab-pages/docs/language-basics/src/boolean-if-else/cond.ligo b/gitlab-pages/docs/language-basics/src/boolean-if-else/cond.ligo index 68f01d71b..9722fbac3 100644 --- a/gitlab-pages/docs/language-basics/src/boolean-if-else/cond.ligo +++ b/gitlab-pages/docs/language-basics/src/boolean-if-else/cond.ligo @@ -1,4 +1,4 @@ type magnitude is Small | Large // See variant types function compare (const n : nat) : magnitude is - if n < 10n then Small (Unit) else Large (Unit) + if n < 10n then Small else Large diff --git a/gitlab-pages/docs/language-basics/src/functions/incr_map.ligo b/gitlab-pages/docs/language-basics/src/functions/incr_map.ligo index e5f915847..75bbb9c3a 100644 --- a/gitlab-pages/docs/language-basics/src/functions/incr_map.ligo +++ b/gitlab-pages/docs/language-basics/src/functions/incr_map.ligo @@ -2,4 +2,4 @@ function increment (const b : int) : int is (function (const a : int) : int is a + 1) (b) 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) diff --git a/gitlab-pages/docs/language-basics/src/sets-lists-tuples/lists.ligo b/gitlab-pages/docs/language-basics/src/sets-lists-tuples/lists.ligo index 7d2d49fbc..70e2b0655 100644 --- a/gitlab-pages/docs/language-basics/src/sets-lists-tuples/lists.ligo +++ b/gitlab-pages/docs/language-basics/src/sets-lists-tuples/lists.ligo @@ -4,9 +4,8 @@ const larger_list : int_list = 5 # my_list 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 -const sum_of_elements : int = list_fold (sum, my_list, 0) +const sum_of_elements : int = List.fold (sum, my_list, 0) diff --git a/gitlab-pages/docs/language-basics/src/sets-lists-tuples/sets.ligo b/gitlab-pages/docs/language-basics/src/sets-lists-tuples/sets.ligo index b6ede8212..885d21e02 100644 --- a/gitlab-pages/docs/language-basics/src/sets-lists-tuples/sets.ligo +++ b/gitlab-pages/docs/language-basics/src/sets-lists-tuples/sets.ligo @@ -6,9 +6,9 @@ const contains_3 : bool = my_set contains 3 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 { 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 -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 { var sum : int := 0; diff --git a/gitlab-pages/docs/language-basics/src/unit-option-pattern-matching/flip.ligo b/gitlab-pages/docs/language-basics/src/unit-option-pattern-matching/flip.ligo index 5f54bc61e..f50bc7757 100644 --- a/gitlab-pages/docs/language-basics/src/unit-option-pattern-matching/flip.ligo +++ b/gitlab-pages/docs/language-basics/src/unit-option-pattern-matching/flip.ligo @@ -2,6 +2,6 @@ type coin is Head | Tail function flip (const c : coin) : coin is case c of - Head -> Tail (Unit) // Unit needed because of a bug - | Tail -> Head (Unit) // Unit needed because of a bug + Head -> Tail + | Tail -> Head end diff --git a/gitlab-pages/docs/language-basics/strings.md b/gitlab-pages/docs/language-basics/strings.md index 461d0e38d..9a4022998 100644 --- a/gitlab-pages/docs/language-basics/strings.md +++ b/gitlab-pages/docs/language-basics/strings.md @@ -59,21 +59,27 @@ Strings can be sliced using a built-in function: ```pascaligo group=b 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 group=b let name : string = "Alice" let slice : string = String.slice 0n 1n name ``` + ```reasonligo group=b let name : string = "Alice"; let slice : string = String.slice (0n, 1n, name); ``` + -> ⚠️ 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 @@ -83,8 +89,11 @@ The length of a string can be found using a built-in function: ```pascaligo group=c 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 group=c let name : string = "Alice" diff --git a/gitlab-pages/docs/language-basics/tezos-specific.md b/gitlab-pages/docs/language-basics/tezos-specific.md index e63764b66..9fed6760a 100644 --- a/gitlab-pages/docs/language-basics/tezos-specific.md +++ b/gitlab-pages/docs/language-basics/tezos-specific.md @@ -26,9 +26,11 @@ functionality can be accessed from within LIGO. ```pascaligo group=a function id_string (const p : string) : option (string) is block { 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 group=a let id_string (p : string) : string option = @@ -103,9 +105,11 @@ function check_signature (const pk : key; const signed : signature; const msg : bytes) : bool - is crypto_check (pk, signed, msg) + is Crypto.check (pk, signed, msg) ``` +> Note that `crypto_check` is *deprecated*. + ```cameligo group=c let check_signature (pk, signed, msg : key * signature * bytes) : bool = @@ -124,27 +128,29 @@ let check_signature = ## Contract's Own Address 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 -> only allowed at the top-level. Using it in an embedded function will -> cause an error. +> Note that `self_address` is *deprecated*. + +> ⚠️ 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. ```pascaligo group=d -const current_addr : address = self_address +const current_addr : address = Tezos.self_address ``` ```cameligo group=d -let current_addr : address = Current.self_address +let current_addr : address = Tezos.self_address ``` ```reasonligo group=d -let current_addr : address = Current.self_address; +let current_addr : address = Tezos.self_address; ``` diff --git a/gitlab-pages/docs/language-basics/types.md b/gitlab-pages/docs/language-basics/types.md index 1ea5eeba0..68b79357e 100644 --- a/gitlab-pages/docs/language-basics/types.md +++ b/gitlab-pages/docs/language-basics/types.md @@ -229,7 +229,7 @@ type return = operation list * storage let back (param, store : unit * storage) : return = let no_op : operation list = [] in - if Current.time > store.deadline then + if Tezos.now > store.deadline then (failwith "Deadline passed." : return) // Annotation else 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 no_op : list (operation) = []; - if (Current.time > store.deadline) { + if (Tezos.now > store.deadline) { (failwith ("Deadline passed.") : return); // Annotation } else { diff --git a/gitlab-pages/docs/language-basics/unit-option-pattern-matching.md b/gitlab-pages/docs/language-basics/unit-option-pattern-matching.md index ff497a6b3..881e29d56 100644 --- a/gitlab-pages/docs/language-basics/unit-option-pattern-matching.md +++ b/gitlab-pages/docs/language-basics/unit-option-pattern-matching.md @@ -56,8 +56,8 @@ else): ```pascaligo group=b type coin is Head | Tail -const head : coin = Head (Unit) // Unit needed for now. -const tail : coin = Tail (Unit) // Unit needed for now. +const head : coin = Head +const tail : coin = Tail ``` @@ -69,14 +69,16 @@ let tail : coin = Tail ```reasonligo group=b -type coin = | Head | Tail; +type coin = Head | Tail; let head : coin = Head; let tail : coin = Tail; ``` 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, and thus go beyond enumerated types. In the following, we show how to @@ -94,7 +96,7 @@ type user is | Guest const u : user = Admin (1000n) -const g : user = Guest (Unit) // Unit needed because of a bug +const g : user = Guest ``` @@ -125,6 +127,9 @@ let g : user = Guest; +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 @@ -172,8 +177,8 @@ type coin is Head | Tail function flip (const c : coin) : coin is case c of - Head -> Tail (Unit) // Unit needed because of a bug - | Tail -> Head (Unit) // Unit needed because of a bug + Head -> Tail + | Tail -> Head end ``` @@ -181,7 +186,7 @@ You can call the function `flip` by using the LIGO compiler like so: ```shell ligo run-function gitlab-pages/docs/language-basics/src/unit-option-pattern-matching/flip.ligo -flip "(Head (Unit))" +flip "Head" # Outputs: Tail(Unit) ``` diff --git a/gitlab-pages/docs/language-basics/variables-and-constants.md b/gitlab-pages/docs/language-basics/variables-and-constants.md index 3fe31ff18..8c8f48577 100644 --- a/gitlab-pages/docs/language-basics/variables-and-constants.md +++ b/gitlab-pages/docs/language-basics/variables-and-constants.md @@ -60,7 +60,10 @@ a *global scope*, but they can be declared and used within functions, or as function parameters. > ⚠️ 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 diff --git a/gitlab-pages/docs/reference/big_map.md b/gitlab-pages/docs/reference/big_map.md index cb733d61c..fa0fa3ebc 100644 --- a/gitlab-pages/docs/reference/big_map.md +++ b/gitlab-pages/docs/reference/big_map.md @@ -1,128 +1,128 @@ --- id: big-map-reference -title: Big Map — Scalable hashmap primitive +title: Big Map — Scalable Maps --- ## Defining A Big Map Type -```pascaligo -type move is (int * int) -type moveset is big_map (address, move) -type foo is big_map (int, int) +```pascaligo group=big_map +type move is int * int +type register is big_map (address, move) ``` -```cameligo +```cameligo group=big_map type move = int * int -type moveset = (address, move) big_map -type foo = (int, int) big_map +type register = (address, move) big_map ``` -```reasonligo +```reasonligo group=big_map type move = (int, int); -type moveset = big_map(address, move); -type foo = big_map(int, int); +type register = big_map (address, move); ``` -## Creating A Map +## Creating an Empty Big Map + +Create an empty big map. + + + + +```pascaligo group=big_map +const empty : register = big_map [] +``` + + +```cameligo group=big_map +let empty : register = Big_map.empty +``` + + +```reasonligo group=big_map +let empty : register = Big_map.empty +``` + + + +## Populating A Big Map -```pascaligo -const moves: moveset = - big_map - ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address) -> (1,2); - ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address) -> (0,3); - end +```pascaligo group=big_map +const moves: register = + big_map [ + ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address) -> (1,2); + ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) -> (0,3)] ``` -```cameligo -let moves: moveset = +```cameligo group=big_map +let moves: register = Big_map.literal [ - (("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address), (1,2)); - (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), (0,3)); - ] + (("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address), (1,2)); + (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address), (0,3))] ``` -```reasonligo -let moves: moveset = +```reasonligo group=big_map +let moves: register = Big_map.literal ([ - ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address, (1,2)), - ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address, (0,3)), - ]); + ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address, (1,2)), + ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address, (0,3))]); ``` -## 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 -which can either shift logic in response to a missing value or throw an error. +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. -```pascaligo -const my_balance : option(move) = - moves [("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address)] +```pascaligo group=big_map +const my_balance : option (move) = + moves [("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address)] ``` -```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 = - Big_map.find_opt ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address) moves + Big_map.find_opt ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) moves ``` -```reasonligo -let my_balance : option(move) = - Big_map.find_opt("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address, moves); +The function is `Big_map.find_opt` whose type is `('key, ('key, +'value) big_map) : 'value option`. Here is an example: + +```reasonligo group=big_map +let my_balance : option (move) = + Big_map.find_opt ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address, moves); ``` -## 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 -doesn't exist, this function throws an error. - - - -```pascaligo -const my_balance : move = - get_force (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), moves); -``` - - - -```cameligo -let my_balance : move = - Big_map.find ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address) moves -``` - - - -```reasonligo -let my_balance : move = - Big_map.find ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address, moves); -``` - - - -## 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. +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*. @@ -131,138 +131,123 @@ exist add it. The values of a PascaLIGO big map can be updated using the ordinary assignment syntax: -```pascaligo - -function set_ (var m : moveset) : moveset is +```pascaligo group=big_map +function add (var m : register) : register is block { - m [("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address)] := (4,9); + m [("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address)] := (4,9) } with m + +const updated_map : register = add (moves) ``` +See further for the removal of bindings. + -```cameligo -let updated_map : moveset = - Big_map.update ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address) (Some (4,9)) moves +In CameLIGO, you need the predefined function `Big_map.update` whose +type is `'key -> 'value option -> ('key, 'value) big_map -> ('key, +'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 -let updated_map : moveset = - Big_map.update(("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), Some((4,9)), moves); +In ReasonLIGO, you need the predefined function `Big_map.update` whose +type is `('key, 'value option, ('key, 'value) big_map) : ('key, +'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); ``` -## 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. - -```pascaligo -function set_ (var n : int ; var m : foo) : foo is block { - m[23] := n ; -} with m +```pascaligo group=big_map +function add (var m : register) : register is + block { + m [("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address)] := (4,9) + } with m + +const updated_map : register = add (moves) ``` -```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 -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); ``` -## 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. -```pascaligo -function rm (var m : foo) : foo is block { - remove 42 from map m; -} with m -``` - - -```cameligo -let rm (m : foo) : foo = Big_map.remove 42 m -``` - - -```reasonligo -let rm = (m: foo): foo => Big_map.remove(42, m); -``` - - - -## 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. - - - - -```pascaligo -const moves: moveset = - big_map - ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address) -> (1,2); - ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address) -> (0,3); - end +```pascaligo group=big_map +function delete (const key : address; var moves : register) : register is + block { + remove key from map moves + } with moves ``` -```cameligo -let moves: moveset = - Big_map.literal [ - (("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address), (1,2)); - (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), (0,3)); - ] +In CameLIGO, we use the predefined function `Big_map.remove` whose +type is `'key -> ('key, 'value) big_map -> ('key, 'value) +big_map`. Note that, despite being curried, the calls to that function +must be complete. Here is an example: + +```cameligo group=big_map +let delete (key, moves : address * register) : register = + Map.remove key moves ``` -```reasonligo -let moves: moveset = - Big_map.literal ([ - ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address, (1,2)), - ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address, (0,3)), - ]); +In ReasonLIGO, we use the predefined function `Big_map.remove` whose +type is `('key, ('key, 'value) big_map) : ('key, 'value) +big_map`. Here is an example: + +```reasonligo group=big_map +let delete = ((key, moves) : (address, register)) : register => + Map.remove (key, moves); ``` - - -## Big_map.empty() : (a', b') big_map - -Create an empty big map. - - - - -```pascaligo -const empty_big_map : big_map(int,int) = big_map end -``` - - -```cameligo -let empty_map : foo = Big_map.empty -``` - - -```reasonligo -let empty_map: foo = Big_map.empty; -``` - - - diff --git a/gitlab-pages/docs/reference/list.md b/gitlab-pages/docs/reference/list.md index 63efcf66a..1c34215fe 100644 --- a/gitlab-pages/docs/reference/list.md +++ b/gitlab-pages/docs/reference/list.md @@ -1,9 +1,182 @@ --- 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 + + + +```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 group=lists +let empty_list : int list = [] +let my_list : int list = [1; 2; 2] // The head is 1 +``` + + +```reasonligo group=lists +let empty_list : list (int) = []; +let my_list : list (int) = [1, 2, 2]; // The head is 1 +``` + + + +### Adding to Lists + +Lists can be augmented by adding an element before the head (or, in +terms of stack, by *pushing an element on top*). + + + + + +```pascaligo group=lists +const larger_list : list (int) = 5 # my_list // [5;1;2;2] +``` + + + +```cameligo group=lists +let larger_list : int list = 5 :: my_list // [5;1;2;2] +``` + + + +```reasonligo group=lists +let larger_list : list (int) = [5, ...my_list]; // [5,1,2,2] +``` + + + +### Functional Iteration over Lists + +A *functional iterator* is a function that traverses a data structure +and calls in turn a given function over the elements of that structure +to compute some value. Another approach is possible in PascaLIGO: +*loops* (see the relevant section). + +There are three kinds of functional iterations over LIGO lists: the +*iterated operation*, the *map operation* (not to be confused with the +*map data structure*) and the *fold operation*. + +#### Iterated Operation over Lists + +The first, the *iterated operation*, is an iteration over the list +with a unit return value. It is useful to enforce certain invariants +on the element of a list, or fail. + + + + + +```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 group=lists +let iter_op (l : int list) : unit = + let predicate = fun (i : int) -> assert (i > 3) + in List.iter predicate l +``` + + + +```reasonligo group=lists +let iter_op = (l : list (int)) : unit => { + let predicate = (i : int) => assert (i > 3); + List.iter (predicate, l); +}; +``` + + + +#### 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. + + + + + +```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 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 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); +``` + + +#### 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. + + + + + +```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 group=lists +let sum (acc, i: int * int) : int = acc + i +let sum_of_elements : int = List.fold sum my_list 0 +``` + + + +```reasonligo group=lists +let sum = ((result, i): (int, int)): int => result + i; +let sum_of_elements : int = List.fold (sum, my_list, 0); +``` + + +## List Length Get the number of elements in a list. @@ -11,29 +184,25 @@ Get the number of elements in a list. ```pascaligo -function size_ (const m : list(int)) : nat is size(m) +function size_of (const l : list (int)) : nat is List.length (l) ``` ```cameligo -let size_ (s: int list) : nat = List.size s +let size_of (l : int list) : nat = List.length l ``` ```reasonligo -let size_ = (s: list(int)): nat => List.size(s); +let size_of = (l : list (int)) : nat => List.length (l); ``` -## List.length(lst: a' list) : nat - -Alias of `List.size`. - ## 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 -a list of the modified elements. +Apply an operation defined by `map_function` to each element of a list +and return a list of the modified elements. diff --git a/gitlab-pages/docs/reference/map.md b/gitlab-pages/docs/reference/map.md index 70710e8b7..c7a5590e7 100644 --- a/gitlab-pages/docs/reference/map.md +++ b/gitlab-pages/docs/reference/map.md @@ -1,392 +1,274 @@ --- id: map-reference -title: Map — Hashmaps that it makes sense to iterate over +title: Map --- ## Defining A Map Type -```pascaligo +```pascaligo group=map type move is int * int -type moveset is map(address, move) +type register is map (address, move) ``` -```cameligo +```cameligo group=map type move = int * int -type moveset = (address, move) map +type register = (address, move) map ``` -```reasonligo +```reasonligo group=map type move = (int, int); -type moveset = map(address, move); +type register = map (address, move); ``` -## Creating A Map - - - - -```pascaligo -const moves: moveset = map - ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address) -> (1, 2); - ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address) -> (0, 3); -end -``` - - - -```cameligo -let moves: moveset = Map.literal - [ (("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address), (1, 2)) ; - (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), (0, 3)) ; - ] -``` - - - -```reasonligo -let moves : moveset = - Map.literal([ - ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address, (1, 2)), - ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address, (0, 3)), - ]); -``` - - -## 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. - - - -```pascaligo -const my_balance : option(move) = moves[("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address)]; -``` - - - -```cameligo -let my_balance : move option = Map.find_opt ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address) moves -``` - - - -```reasonligo -let my_balance : option(move) = - Map.find_opt("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address, moves); -``` - - -## 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. - - - -```pascaligo -const my_balance : move = get_force(("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), moves); -``` - - - -```cameligo -let my_balance : move = Map.find ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address) moves -``` - - - -```reasonligo -let my_balance : move = - Map.find("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address, moves); -``` - - - -## 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. - - - - - -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 -``` - - - -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 -``` - - - -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); -``` - - - -## Map.add(k: a', v: b', m: (a', b') map) : (a', b') map - - - - -```pascaligo -function set_ (var n : int ; var m : map(int, int)) : map(int, int) is block { - m[23] := n ; -} with m -``` - - -```cameligo -let add (n,m: int * (int, int) map) : foobar = Map.add 23 n m -``` - - -```reasonligo -let add = (n: int, m: map(int, int)) : foobar => Map.add(23, n, m); -``` - - - -## Map.remove(k: a', m: (a', b') map) : (a', b') map - -Remove a key and its associated value from the map. - - - - -```pascaligo -function rm (var m : map(int, int)) : map(int, int) is block { - remove 42 from map m -} with m -``` - - -```cameligo -let rm (m: (int, int) map) : (int, int) map = Map.remove 42 m -``` - - -```reasonligo -let rm = (m: map(int, int)): map(int, int) => Map.remove(42, m); -``` - - - -## 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. - - - -```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 -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 -let iter_op = (m: moveset): unit => { - let assert_eq = ((i,j): (address, move)) => assert (j[0] > 1); - Map.iter(assert_eq, m); -}; -``` - - - -## 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`. - - - -```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 -let map_op (m : moveset) : moveset = - let increment = fun (i,j: address * move) -> (j.0, j.1 + 1) - in Map.map increment m -``` - - -```reasonligo -let map_op = (m: moveset): moveset => { - let increment = ((i,j): (address, move)) => (j[0], j[1] + 1); - Map.map(increment, m); -}; -``` - - -## 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`. - - - -```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 -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 -let fold_op = (m: moveset): moveset => { - let aggregate = ((i,j): (int, (address, (int,int)))) => i + j[1][1]; - Map.fold(aggregate, m, 5); -}; - -``` - - - - -## Map.mem(k: a', m: (a', b') map) : bool - -Test whether a particular key `k` exists in a given map `m`. - - - - -```pascaligo -function mem (const k: int; const m: map(int, int)) : bool is map_mem(k, m) -``` - -```cameligo -let mem (k,m: int * (int, int) map) : bool = Map.mem k m -``` - - -```reasonligo -let mem = ((k,m): (int, map(int,int))): bool => Map.mem(k, m); -``` - - - -## Map.empty() : (a', b') map +## Creating an Empty Map Create an empty map. -```pascaligo -const empty_map : map(int, int) = map end +```pascaligo group=map +const empty : register = map [] ``` + -```cameligo -let empty_map : (int, int) map = Map.empty +```cameligo group=map +let empty : register = Map.empty ``` -```reasonligo -let empty_map: map(int, int) = Map.empty; +```reasonligo group=map +let empty : register = Map.empty ``` -## 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. + + + +```pascaligo group=map +const moves: register = + map [ + ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address) -> (1,2); + ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) -> (0,3)] +``` + + + +```cameligo group=map +let moves: register = + Map.literal [ + (("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address), (1,2)); + (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address), (0,3))] +``` + + + +```reasonligo group=map +let moves: register = + Map.literal ([ + ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address, (1,2)), + ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address, (0,3))]); +``` + + + +## 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. + + + +```pascaligo group=map +const my_balance : option (move) = + moves [("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address)] +``` + + + +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 +``` + + + +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); +``` + + +## 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*. -```pascaligo -const moves: moveset = map - ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address) -> (1, 2); - ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address) -> (0, 3); -end +The values of a PascaLIGO map can be updated using the ordinary +assignment syntax: + +```pascaligo group=map +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. + + + +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 +``` + + + +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); +``` + + + +## Adding a Binding to a Map + +Add a key and its associated value to the map. + + + +```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 -let moves: moveset = Map.literal - [ (("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address), (1, 2)) ; - (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), (0, 3)) ; - ] +In CameLIGO, we use the predefined function `Map.add`, whose type +is `'key -> 'value -> ('key, 'value) map -> ('key, 'value) +map`. Recall that the function `Map.add` must always be fully +applied to its arguments. Here is an example: + +```cameligo group=map +let add (m : register) : register = + Map.add + ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) (4,9) m ``` -```reasonligo -let moves : moveset = - Map.literal([ - ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address, (1, 2)), - ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address, (0, 3)), - ]); +In ReasonLIGO, we use the predefined function `Map.add`, whose +type is `('key, 'value, ('key, 'value) map : ('key, 'value) +map`. Here is an example: + +```reasonligo group=map +let add = (m : register) : register => + Map.add + (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address), (4,9), m); ``` + -## 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. -```pascaligo -function size_ (const m : map(int, int)) : nat is - block {skip} with (size(m)) +```pascaligo group=map +function delete (const key : address; var moves : register) : register is + block { + remove key from map moves + } with moves ``` + -```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 -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); +``` + + + +## Getting the Size of a Map + +The size of a map is its number of bindings. + + + + +```pascaligo group=map +function size_of (const m : register) : nat is size (m) +``` + +```cameligo group=map +let size_of (m : register) : nat = Map.size m +``` + +```reasonligo group=map +let size_of = (m : register): nat => Map.size (m); ``` diff --git a/gitlab-pages/examples/counter.ligo b/gitlab-pages/examples/counter.ligo deleted file mode 100644 index 45ce7462a..000000000 --- a/gitlab-pages/examples/counter.ligo +++ /dev/null @@ -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) diff --git a/gitlab-pages/examples/functions.ligo b/gitlab-pages/examples/functions.ligo deleted file mode 100644 index 4f8e4dae1..000000000 --- a/gitlab-pages/examples/functions.ligo +++ /dev/null @@ -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) \ No newline at end of file diff --git a/gitlab-pages/examples/multiple-entrypoints.ligo b/gitlab-pages/examples/multiple-entrypoints.ligo deleted file mode 100644 index 3b77ff009..000000000 --- a/gitlab-pages/examples/multiple-entrypoints.ligo +++ /dev/null @@ -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) diff --git a/gitlab-pages/examples/variables.ligo b/gitlab-pages/examples/variables.ligo deleted file mode 100644 index 09254da96..000000000 --- a/gitlab-pages/examples/variables.ligo +++ /dev/null @@ -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) \ No newline at end of file diff --git a/src/passes/1-parser/cameligo/.links b/src/passes/1-parser/cameligo/.links index 6f2bb3b81..a3ac060f6 100644 --- a/src/passes/1-parser/cameligo/.links +++ b/src/passes/1-parser/cameligo/.links @@ -20,3 +20,4 @@ $HOME/git/ligo/vendors/ligo-utils/simple-utils/region.ml ../shared/LexerUnit.ml ../shared/ParserUnit.ml Stubs/Simple_utils.ml +$HOME/git/ligo/_build/default/src/passes/1-parser/cameligo/ParErr.ml \ No newline at end of file diff --git a/src/passes/1-parser/cameligo/LexToken.mll b/src/passes/1-parser/cameligo/LexToken.mll index d16388591..f17ea903a 100644 --- a/src/passes/1-parser/cameligo/LexToken.mll +++ b/src/passes/1-parser/cameligo/LexToken.mll @@ -266,7 +266,6 @@ let keywords = [ let reserved = let open SSet in empty - |> add "and" |> add "as" |> add "asr" |> add "class" diff --git a/src/passes/1-parser/cameligo/LexerMain.ml b/src/passes/1-parser/cameligo/LexerMain.ml index 5ef471c37..60874bda0 100644 --- a/src/passes/1-parser/cameligo/LexerMain.ml +++ b/src/passes/1-parser/cameligo/LexerMain.ml @@ -1,5 +1,7 @@ (* Driver for the CameLIGO lexer *) +module Region = Simple_utils.Region + module IO = struct let ext = ".mligo" diff --git a/src/passes/1-parser/cameligo/Parser.mly b/src/passes/1-parser/cameligo/Parser.mly index 0901ab875..c8c0470a8 100644 --- a/src/passes/1-parser/cameligo/Parser.mly +++ b/src/passes/1-parser/cameligo/Parser.mly @@ -593,10 +593,14 @@ core_expr: | par(expr ":" type_expr {$1,$2,$3}) { EAnnot $1 } module_field: - module_name "." field_name { + module_name "." module_fun { let region = cover $1.region $3.region in {region; value = $1.value ^ "." ^ $3.value} } +module_fun: + field_name { $1 } +| "or" { {value="or"; region=$1} } + projection: struct_name "." nsepseq(selection,".") { let start = $1.region in diff --git a/src/passes/1-parser/pascaligo/.links b/src/passes/1-parser/pascaligo/.links index 831099d9e..70b9b360f 100644 --- a/src/passes/1-parser/pascaligo/.links +++ b/src/passes/1-parser/pascaligo/.links @@ -24,3 +24,4 @@ $HOME/git/ligo/vendors/ligo-utils/simple-utils/region.ml ../shared/Memo.mli ../shared/Memo.ml Stubs/Simple_utils.ml +$HOME/git/ligo/_build/default/src/passes/1-parser/pascaligo/ParErr.ml \ No newline at end of file diff --git a/src/passes/1-parser/pascaligo/Parser.mly b/src/passes/1-parser/pascaligo/Parser.mly index e5afdc3b5..f31407fca 100644 --- a/src/passes/1-parser/pascaligo/Parser.mly +++ b/src/passes/1-parser/pascaligo/Parser.mly @@ -98,11 +98,12 @@ sepseq(X,Sep): (* Inlines *) -%inline var : "" { $1 } -%inline type_name : "" { $1 } -%inline fun_name : "" { $1 } -%inline field_name : "" { $1 } -%inline struct_name : "" { $1 } +%inline var : "" { $1 } +%inline type_name : "" { $1 } +%inline fun_name : "" { $1 } +%inline field_name : "" { $1 } +%inline struct_name : "" { $1 } +%inline module_name : "" { $1 } (* Main *) @@ -829,7 +830,7 @@ core_expr: "" { EArith (Int $1) } | "" { EArith (Nat $1) } | "" { EArith (Mutez $1) } -| var { EVar $1 } +| "" | module_field { EVar $1 } | "" { EString (String $1) } | "" { EBytes $1 } | "False" { ELogic (BoolExpr (False $1)) } @@ -902,13 +903,32 @@ path: var { Name $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: struct_name "." nsepseq(selection,".") { let stop = nsepseq_to_region selection_to_region $3 in let region = cover $1.region stop - and value = {struct_name = $1; - selector = $2; - field_path = $3} + and value = {struct_name=$1; selector=$2; field_path=$3} + in {region; value} + } +| 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} } selection: @@ -939,31 +959,26 @@ record_expr: update_record: path "with" ne_injection("record",field_path_assignment){ let region = cover (path_to_region $1) $3.region in - let value = { - record = $1; - kwd_with = $2; - updates = $3} + let value = {record=$1; kwd_with=$2; updates=$3} in {region; value} } - field_assignment: field_name "=" expr { let region = cover $1.region (expr_to_region $3) - and value = {field_name = $1; - equal = $2; - field_expr = $3} + and value = {field_name=$1; equal=$2; field_expr=$3} in {region; value} } field_path_assignment: nsepseq(field_name,".") "=" expr { - let region = cover (nsepseq_to_region (fun x -> x.region) $1) (expr_to_region $3) - and value = {field_path = $1; - equal = $2; - field_expr = $3} + let start = nsepseq_to_region (fun x -> x.region) $1 + and stop = expr_to_region $3 in + let region = cover start stop + and value = {field_path=$1; equal=$2; field_expr=$3} in {region; value} } fun_call: - fun_name arguments { + fun_name arguments +| module_field arguments { let region = cover $1.region $2.region in {region; value = (EVar $1),$2} } diff --git a/src/passes/1-parser/reasonligo/.links b/src/passes/1-parser/reasonligo/.links index 543bf9ea3..d93e4b610 100644 --- a/src/passes/1-parser/reasonligo/.links +++ b/src/passes/1-parser/reasonligo/.links @@ -25,4 +25,5 @@ Stubs/Parser_cameligo.ml ../cameligo/ParserLog.mli ../cameligo/ParserLog.ml ../cameligo/Scoping.mli -../cameligo/Scoping.ml \ No newline at end of file +../cameligo/Scoping.ml +$HOME/git/ligo/_build/default/src/passes/1-parser/reasonligo/ParErr.ml \ No newline at end of file diff --git a/src/passes/1-parser/reasonligo/LexToken.mll b/src/passes/1-parser/reasonligo/LexToken.mll index e4689082a..842c0fee1 100644 --- a/src/passes/1-parser/reasonligo/LexToken.mll +++ b/src/passes/1-parser/reasonligo/LexToken.mll @@ -238,12 +238,9 @@ let keywords = [ (fun reg -> True 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 open SSet in empty - |> add "and" |> add "as" |> add "asr" |> add "begin" diff --git a/src/passes/1-parser/reasonligo/LexerMain.ml b/src/passes/1-parser/reasonligo/LexerMain.ml index f0589990c..7e8e063da 100644 --- a/src/passes/1-parser/reasonligo/LexerMain.ml +++ b/src/passes/1-parser/reasonligo/LexerMain.ml @@ -1,5 +1,7 @@ (* Driver for the ReasonLIGO lexer *) +module Region = Simple_utils.Region + module IO = struct let ext = ".religo" diff --git a/src/passes/1-parser/reasonligo/Parser.mly b/src/passes/1-parser/reasonligo/Parser.mly index 48765c19a..defde2e55 100644 --- a/src/passes/1-parser/reasonligo/Parser.mly +++ b/src/passes/1-parser/reasonligo/Parser.mly @@ -24,22 +24,22 @@ type 'a sequence_or_record = 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: `type foo = (int, int) => int;` *) -let rec nsepseq_to_curry hd rest = - match hd, rest with - | hd, (sep, item) :: rest -> +let rec nsepseq_to_curry hd rest = + match hd, rest with + | hd, (sep, item) :: rest -> let start = type_expr_to_region hd 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 { - value = hd, sep, (nsepseq_to_curry item rest); + value = hd, sep, (nsepseq_to_curry item rest); region - } + } | hd, [] -> hd (* END HEADER *) @@ -178,34 +178,34 @@ type_expr: cartesian | sum_type | record_type { $1 } type_expr_func: - "=>" cartesian { + "=>" cartesian { $1, $2 } cartesian: core_type { $1 } -| type_name type_expr_func { +| type_name type_expr_func { let (arrow, c) = $2 in let value = TVar $1, arrow, c in let region = cover $1.region (type_expr_to_region c) in TFun { region; value } } -| "(" cartesian ")" type_expr_func { +| "(" cartesian ")" type_expr_func { let (arrow, c) = $4 in let value = $2, arrow, c in let region = cover $1 (type_expr_to_region c) in TFun { region; value } } | "(" cartesian "," nsepseq(cartesian,",") ")" type_expr_func? { - match $6 with - | Some (arrow, c) -> + match $6 with + | Some (arrow, c) -> 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 | None -> let value = Utils.nsepseq_cons $2 $3 $4 in let region = cover $1 $5 in - TProd {region; value} + TProd {region; value} } core_type: @@ -515,30 +515,30 @@ fun_expr: _ }; _ }; region} -> - let expr_to_type = function + let expr_to_type = function | EVar v -> TVar v | e -> let open! SyntaxError in raise (Error (WrongFunctionArguments e)) in let type_expr = ( match type_expr with - | TProd {value; _} -> + | TProd {value; _} -> let (hd, rest) = value in - let rest = rest @ [(arrow, expr_to_type body)] in - nsepseq_to_curry hd rest - | e -> + let rest = rest @ [(arrow, expr_to_type body)] in + nsepseq_to_curry hd rest + | e -> TFun { value = e, arrow, expr_to_type body; region = fun_region - } + } ) - in + in PTyped { value = { pattern; colon; type_expr - }; + }; region; }, [] | EPar {value = {inside = fun_arg; _ }; _} -> @@ -552,7 +552,7 @@ fun_expr: arg_to_pattern (fst fun_args), bindings | EUnit _ as e -> arg_to_pattern e, [] - | EVar _ as e -> + | EVar _ as e -> arg_to_pattern e, [] | e -> let open! SyntaxError in raise (Error (WrongFunctionArguments e)) @@ -834,10 +834,13 @@ core_expr: | par(expr) { EPar $1 } module_field: - module_name "." field_name { - let region = cover $1.region $3.region - and value = $1.value ^ "." ^ $3.value - in {region; value} } + module_name "." module_fun { + let region = cover $1.region $3.region in + {region; value = $1.value ^ "." ^ $3.value} } + +module_fun: + field_name { $1 } +| "or" { {value="or"; region=$1} } selection: "[" "" "]" selection { diff --git a/src/passes/operators/operators.ml b/src/passes/operators/operators.ml index 456c0172a..07a1484c6 100644 --- a/src/passes/operators/operators.ml +++ b/src/passes/operators/operators.ml @@ -35,8 +35,8 @@ module Simplify = struct let unit_expr = make_t @@ T_constant TC_unit let type_constants s = - match s with - | "chain_id" -> ok TC_chain_id + match s with + "chain_id" -> ok TC_chain_id | "unit" -> ok TC_unit | "string" -> ok TC_string | "bytes" -> ok TC_bytes @@ -50,95 +50,196 @@ module Simplify = struct | "key_hash" -> ok TC_key_hash | "signature" -> ok TC_signature | "timestamp" -> ok TC_timestamp - | _ -> simple_fail @@ "Not a type_constant " ^ s + | _ -> simple_fail @@ "Not a built-in type (" ^ s ^ ")." let type_operators s = - match s with - | "list" -> ok @@ TC_list unit_expr + match s with + "list" -> ok @@ TC_list unit_expr | "option" -> ok @@ TC_option unit_expr | "set" -> ok @@ TC_set unit_expr | "map" -> ok @@ TC_map (unit_expr,unit_expr) | "big_map" -> ok @@ TC_big_map (unit_expr,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 - let constants = function - | "assert" -> ok C_ASSERTION - | "get_chain_id" -> ok C_CHAIN_ID - | "transaction" -> ok C_CALL - | "get_contract" -> ok C_CONTRACT - | "get_contract_opt"-> ok C_CONTRACT_OPT - | "get_entrypoint" -> ok C_CONTRACT_ENTRYPOINT - | "get_entrypoint_opt" -> ok C_CONTRACT_ENTRYPOINT_OPT - | "size" -> ok C_SIZE - | "int" -> ok C_INT - | "abs" -> ok C_ABS - | "is_nat" -> ok C_IS_NAT - | "amount" -> ok C_AMOUNT - | "balance" -> ok C_BALANCE - | "now" -> ok C_NOW - | "unit" -> ok C_UNIT - | "source" -> ok C_SOURCE - | "sender" -> ok C_SENDER - | "failwith" -> ok C_FAILWITH - | "bitwise_or" -> ok C_OR - | "bitwise_and" -> ok C_AND - | "bitwise_xor" -> ok C_XOR - | "bitwise_lsl" -> ok C_LSL - | "bitwise_lsr" -> ok C_LSR - | "string_concat" -> ok C_CONCAT - | "string_slice" -> ok C_SLICE - | "crypto_check" -> ok C_CHECK_SIGNATURE - | "crypto_hash_key" -> ok C_HASH_KEY - | "bytes_concat" -> ok C_CONCAT - | "bytes_slice" -> ok C_SLICE - | "bytes_pack" -> ok C_BYTES_PACK - | "bytes_unpack" -> ok C_BYTES_UNPACK - | "set_empty" -> ok C_SET_EMPTY - | "set_mem" -> ok C_SET_MEM - | "set_add" -> ok C_SET_ADD - | "set_remove" -> ok C_SET_REMOVE - | "set_iter" -> ok C_SET_ITER - | "set_fold" -> ok C_SET_FOLD - | "list_iter" -> ok C_LIST_ITER - | "list_fold" -> ok C_LIST_FOLD - | "list_map" -> ok C_LIST_MAP - | "get_force" -> ok C_MAP_FIND - | "map_iter" -> ok C_MAP_ITER - | "map_map" -> ok C_MAP_MAP - | "map_fold" -> ok C_MAP_FOLD - | "map_remove" -> ok C_MAP_REMOVE - | "map_update" -> ok C_MAP_UPDATE - | "map_get" -> ok C_MAP_FIND_OPT - | "map_mem" -> ok C_MAP_MEM - | "sha_256" -> ok C_SHA256 - | "sha_512" -> ok C_SHA512 - | "blake2b" -> ok C_BLAKE2b - | "cons" -> ok C_CONS - | "EQ" -> ok C_EQ - | "NEQ" -> ok C_NEQ - | "NEG" -> ok C_NEG - | "ADD" -> ok C_ADD - | "SUB" -> ok C_SUB - | "TIMES" -> ok C_MUL - | "DIV" -> ok C_DIV - | "MOD" -> ok C_MOD - | "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 - | "address" -> ok C_ADDRESS - | "self_address" -> ok C_SELF_ADDRESS - | "implicit_account"-> ok C_IMPLICIT_ACCOUNT - | "set_delegate" -> ok C_SET_DELEGATE - | _ -> simple_fail "Not a PascaLIGO constant" + (* Tezos module (ex-Michelson) *) + + | "Tezos.chain_id" -> ok C_CHAIN_ID + | "chain_id" -> ok C_CHAIN_ID (* Deprecated *) + | "get_chain_id" -> ok C_CHAIN_ID (* Deprecated *) + | "Tezos.balance" -> ok C_BALANCE + | "balance" -> ok C_BALANCE (* Deprecated *) + | "Tezos.now" -> ok C_NOW + | "now" -> ok C_NOW (* Deprecated *) + | "Tezos.amount" -> ok C_AMOUNT + | "amount" -> ok C_AMOUNT (* Deprecated *) + | "Tezos.sender" -> ok C_SENDER + | "sender" -> ok C_SENDER (* Deprecated *) + | "Tezos.address" -> ok C_ADDRESS + | "address" -> ok C_ADDRESS (* Deprecated *) + | "Tezos.self_address" -> ok C_SELF_ADDRESS + | "self_address" -> ok C_SELF_ADDRESS (* Deprecated *) + | "Tezos.implicit_account" -> ok C_IMPLICIT_ACCOUNT + | "implicit_account" -> ok C_IMPLICIT_ACCOUNT (* Deprecated *) + | "Tezos.source" -> ok C_SOURCE + | "source" -> ok C_SOURCE (* Deprecated *) + | "Tezos.failwith" -> ok C_FAILWITH + | "failwith" -> ok C_FAILWITH + + | "Tezos.transaction" -> ok C_CALL + | "transaction" -> ok C_CALL (* Deprecated *) + | "Tezos.set_delegate" -> ok C_SET_DELEGATE + | "set_delegate" -> ok C_SET_DELEGATE (* Deprecated *) + | "get_contract" -> ok C_CONTRACT (* Deprecated *) + | "Tezos.get_contract_opt" -> ok C_CONTRACT_OPT + | "get_contract_opt" -> ok C_CONTRACT_OPT (* Deprecated *) + | "get_entrypoint" -> ok C_CONTRACT_ENTRYPOINT (* Deprecated *) + | "Tezos.get_entrypoint_opt" -> ok C_CONTRACT_ENTRYPOINT_OPT + | "get_entrypoint_opt" -> ok C_CONTRACT_ENTRYPOINT_OPT (* Deprecated *) + + | "Michelson.is_nat" -> ok C_IS_NAT (* Deprecated *) + | "is_nat" -> ok C_IS_NAT + | "int" -> ok C_INT + | "abs" -> ok C_ABS + | "unit" -> ok C_UNIT + + | "NEG" -> ok C_NEG + | "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 + | "cons" -> ok C_CONS (* Deprecated *) + | "NEQ" -> ok C_NEQ + + (* Crypto module *) + + | "Crypto.check" -> ok C_CHECK_SIGNATURE + | "crypto_check" -> ok C_CHECK_SIGNATURE (* Deprecated *) + | "Crypto.hash_key" -> ok C_HASH_KEY + | "crypto_hash_key" -> ok C_HASH_KEY (* Deprecated *) + | "Crypto.blake2b" -> ok C_BLAKE2b + | "blake2b" -> ok C_BLAKE2b (* Deprecated *) + | "Crypto.sha256" -> ok C_SHA256 + | "sha_256" -> ok C_SHA256 (* Deprecated *) + | "Crypto.sha512" -> ok C_SHA512 + | "sha_512" -> ok C_SHA512 (* Deprecated *) + + (* 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_operators = type_operators @@ -147,119 +248,163 @@ module Simplify = struct module Cameligo = struct let constants = function - | "assert" -> ok C_ASSERTION - | "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 + (* Tezos (ex-Michelson, ex-Current, ex-Operation) *) - | "Crypto.blake2b" -> ok C_BLAKE2b - | "Crypto.sha256" -> ok C_SHA256 - | "Crypto.sha512" -> ok C_SHA512 - | "Crypto.hash_key" -> ok C_HASH_KEY - | "Crypto.check" -> ok C_CHECK_SIGNATURE + | "Tezos.chain_id" -> ok C_CHAIN_ID + | "chain_id" -> ok C_CHAIN_ID (* Deprecated *) + | "Tezos.balance" -> ok C_BALANCE + | "Current.balance" -> ok C_BALANCE (* Deprecated *) + | "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 - | "Bytes.unpack" -> ok C_BYTES_UNPACK - | "Bytes.length" -> ok C_SIZE - | "Bytes.size" -> ok C_SIZE - | "Bytes.concat" -> ok C_CONCAT - | "Bytes.slice" -> ok C_SLICE - | "Bytes.sub" -> ok C_SLICE + | "Tezos.transaction" -> ok C_CALL + | "Operation.transaction" -> ok C_CALL (* Deprecated *) + | "Tezos.set_delegate" -> ok C_SET_DELEGATE (* Deprecated *) + | "Operation.set_delegate" -> ok C_SET_DELEGATE (* Deprecated *) + | "Operation.get_contract" -> ok C_CONTRACT (* Deprecated *) + | "Tezos.get_contract_opt" -> ok C_CONTRACT_OPT + | "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 - | "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 + | "Michelson.is_nat" -> ok C_IS_NAT (* Deprecated *) + | "is_nat" -> ok C_IS_NAT + | "int" -> ok C_INT + | "abs" -> ok C_ABS + | "unit" -> ok C_UNIT - | "Map.find_opt" -> ok C_MAP_FIND_OPT - | "Map.find" -> ok C_MAP_FIND - | "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 + | "NEG" -> ok C_NEG + | "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 - | "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 + (* Crypto module *) - | "Bitwise.lor" -> ok C_OR - | "Bitwise.land" -> ok C_AND - | "Bitwise.lxor" -> ok C_XOR - | "Bitwise.shift_left" -> ok C_LSL - | "Bitwise.shift_right" -> ok C_LSR + | "Crypto.check" -> ok C_CHECK_SIGNATURE + | "Crypto.hash_key" -> ok C_HASH_KEY + | "Crypto.blake2b" -> ok C_BLAKE2b + | "Crypto.sha256" -> ok C_SHA256 + | "Crypto.sha512" -> ok C_SHA512 - | "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 + (* Bytes module *) - | "List.length" -> ok C_SIZE - | "List.size" -> ok C_SIZE - | "List.iter" -> ok C_LIST_ITER - | "List.map" -> ok C_LIST_MAP - | "List.fold" -> ok C_LIST_FOLD + | "Bytes.pack" -> ok C_BYTES_PACK + | "Bytes.unpack" -> ok C_BYTES_UNPACK + | "Bytes.length" -> ok C_SIZE + | "Bytes.size" -> ok C_SIZE + | "Bytes.concat" -> ok C_CONCAT + | "Bytes.slice" -> ok C_SLICE + | "Bytes.sub" -> ok C_SLICE - | "Loop.fold_while" -> ok C_FOLD_WHILE - | "continue" -> ok C_CONTINUE - | "stop" -> ok C_STOP + (* List module *) - | "Operation.transaction" -> ok C_CALL - | "Operation.set_delegate" -> ok C_SET_DELEGATE - | "Operation.get_contract" -> ok C_CONTRACT - | "Operation.get_contract_opt" -> ok C_CONTRACT_OPT - | "Operation.get_entrypoint" -> ok C_CONTRACT_ENTRYPOINT - | "Operation.get_entrypoint_opt" -> ok C_CONTRACT_ENTRYPOINT_OPT - | "int" -> ok C_INT - | "abs" -> ok C_ABS - | "unit" -> ok C_UNIT + | "List.length" -> ok C_SIZE + | "List.size" -> ok C_SIZE + | "List.iter" -> ok C_LIST_ITER + | "List.map" -> ok C_LIST_MAP + | "List.fold" -> ok C_LIST_FOLD - | "NEG" -> ok C_NEG - | "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 + (* Set module *) - | "Michelson.is_nat" -> ok C_IS_NAT - | _ -> simple_fail "Not a constant" + | "Set.mem" -> ok C_SET_MEM + | "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_operators = type_operators @@ -821,19 +966,19 @@ module Typer = struct let%bind key = get_t_set set in if eq_1 elt key 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%bind key = get_t_set set in if eq_1 elt key 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%bind key = get_t_set set in if eq_1 elt key 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%bind (arg , res) = get_t_function body in diff --git a/src/test/contracts/bitwise_arithmetic.ligo b/src/test/contracts/bitwise_arithmetic.ligo index 0a0d1079a..5818a47b5 100644 --- a/src/test/contracts/bitwise_arithmetic.ligo +++ b/src/test/contracts/bitwise_arithmetic.ligo @@ -1,11 +1,7 @@ // Test PascaLIGO bitwise operators -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 xor_op (const n : nat) : nat is bitwise_xor (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) +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 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 lsr_op (const n : nat) : nat is Bitwise.shift_right (n, 7n) diff --git a/src/test/contracts/bitwise_arithmetic.mligo b/src/test/contracts/bitwise_arithmetic.mligo index a56375f81..d79cbe348 100644 --- a/src/test/contracts/bitwise_arithmetic.mligo +++ b/src/test/contracts/bitwise_arithmetic.mligo @@ -1,7 +1,7 @@ (* Test CameLIGO bitwise operators *) -let or_op (n: nat) : nat = Bitwise.lor n 4n -let and_op (n: nat) : nat = Bitwise.land n 7n -let xor_op (n: nat) : nat = Bitwise.lxor n 7n +let or_op (n: nat) : nat = Bitwise.or n 4n +let and_op (n: nat) : nat = Bitwise.and n 7n +let xor_op (n: nat) : nat = Bitwise.xor n 7n let lsl_op (n: nat) : nat = Bitwise.shift_left n 7n let lsr_op (n: nat) : nat = Bitwise.shift_right n 7n diff --git a/src/test/contracts/bitwise_arithmetic.religo b/src/test/contracts/bitwise_arithmetic.religo index 2cc390b8a..e75821c3a 100644 --- a/src/test/contracts/bitwise_arithmetic.religo +++ b/src/test/contracts/bitwise_arithmetic.religo @@ -1,7 +1,7 @@ /* Test ReasonLigo bitwise operators */ -let or_op = (n: nat): nat => Bitwise.lor(n, 4n); -let and_op = (n: nat): nat => Bitwise.land(n, 7n); -let xor_op = (n: nat): nat => Bitwise.lxor(n, 7n); -let lsl_op = (n: nat) : nat => Bitwise.shift_left(n, 7n); -let lsr_op = (n: nat) : nat => Bitwise.shift_right(n, 7n); \ No newline at end of file +let or_op = (n : nat) : nat => Bitwise.or (n, 4n); +let and_op = (n : nat) : nat => Bitwise.and (n, 7n); +let xor_op = (n : nat) : nat => Bitwise.xor (n, 7n); +let lsl_op = (n : nat) : nat => Bitwise.shift_left (n, 7n); +let lsr_op = (n : nat) : nat => Bitwise.shift_right (n, 7n); \ No newline at end of file