First batch of rewritten contracts (PascaLIGO).

This commit is contained in:
Christian Rinderknecht 2020-02-10 19:27:58 +01:00
parent 71474e1b0d
commit 541728fc6c
55 changed files with 862 additions and 891 deletions

View File

@ -32,7 +32,7 @@ module Simplify = struct
- The left-hand-side is the reserved name in the given front-end. - The left-hand-side is the reserved name in the given front-end.
- The right-hand-side is the name that will be used in the AST. - The right-hand-side is the name that will be used in the AST.
*) *)
let unit_expr = make_t @@ T_constant TC_unit let unit_expr = make_t @@ T_constant TC_unit
let type_constants s = let type_constants s =
match s with match s with
@ -1157,7 +1157,7 @@ module Compiler = struct
| C_CONCAT -> ok @@ simple_binary @@ prim I_CONCAT | C_CONCAT -> ok @@ simple_binary @@ prim I_CONCAT
| C_CHAIN_ID -> ok @@ simple_constant @@ prim I_CHAIN_ID | C_CHAIN_ID -> ok @@ simple_constant @@ prim I_CHAIN_ID
| _ -> simple_fail @@ Format.asprintf "operator not implemented for %a" Stage_common.PP.constant c | _ -> simple_fail @@ Format.asprintf "operator not implemented for %a" Stage_common.PP.constant c
(* (*
Some complex operators will need to be added in compiler/compiler_program. Some complex operators will need to be added in compiler/compiler_program.

View File

@ -1,5 +1,5 @@
// function main (const c: contract(unit)) : address is address(c) // function main (const c : contract (unit)) : address is address (c)
function main (const p : key_hash) : address is block { function main (const p : key_hash) : address is block {
const c : contract(unit) = implicit_account(p) ; const c : contract (unit) = implicit_account (p);
} with address(c) } with address (c)

View File

@ -1,6 +1,6 @@
(* Test that a string is cast to an address given a type annotation *) (* Test that a string is cast to an address given a type annotation *)
const lst : list(int) = list [] const lst : list (int) = list []
const my_address : address = const my_address : address =
("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address) ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address)

View File

@ -1,21 +1,13 @@
// Test different ways of calling functions in PascaLIGO // Test different ways of calling functions in PascaLIGO
type foo is record type foo is record [bar : int -> int]
bar : int -> int ;
end
function f (const i : int) : int is function f (const i : int) : int is i
begin
skip
end with i
function g (const i : unit) : int -> int is function g (const i : unit) : int -> int is f
begin skip end with f
const r : foo = record const r : foo = record [bar = f]
bar = f ;
end
const x : int = f(42) const x : int = f (42)
const y : int = r.bar(42) const y : int = r.bar (42)
const z : int = (g(unit))(42) const z : int = (g (unit))(42)

View File

@ -1,22 +1,15 @@
// Test PascaLIGO arithmetic operators // Test PascaLIGO arithmetic operators
function mod_op (const n : int) : nat is function mod_op (const n : int) : nat is n mod 42
begin skip end with n mod 42
function plus_op (const n : int) : int is function plus_op (const n : int) : int is n + 42
begin skip end with n + 42
function minus_op (const n : int) : int is function minus_op (const n : int) : int is n - 42
begin skip end with n - 42
function times_op (const n : int) : int is function times_op (const n : int) : int is n * 42
begin skip end with n * 42
function div_op (const n : int) : int is function div_op (const n : int) : int is n / 2
begin skip end with n / 2
function int_op (const n : nat) : int is function int_op (const n : nat) : int is int (n)
block { skip } with int(n)
function neg_op (const n : int) : int is function neg_op (const n : int) : int is -n
begin skip end with -n

View File

@ -1,4 +1,4 @@
function main (const i : int) : int is function main (const i : int) : int is
begin block {
i := i + 1 ; i := i + 1
end with i } with i

View File

@ -1,19 +1,19 @@
const x : int = 1; attributes ["inline"] const x : int = 1; attributes ["inline"]
function foo (const a : int) : int is function foo (const a : int) : int is
begin block {
const test : int = 2 + a; const test : int = 2 + a;
attributes ["inline"]; attributes ["inline"];
end with test; } with test;
attributes ["inline"]; attributes ["inline"];
const y : int = 1; attributes ["inline"; "other"] const y : int = 1; attributes ["inline"; "other"]
function bar (const b : int) : int is function bar (const b : int) : int is
begin block {
function test (const z : int) : int is function test (const z : int) : int is
begin block {
const r : int = 2 + b + z const r : int = 2 + b + z
end with r; } with r;
attributes ["inline"; "foo"; "bar"] attributes ["inline"; "foo"; "bar"]
end with test(b) } with test (b)

View File

@ -1,7 +1,9 @@
type storage_ is timestamp type parameter is unit
type storage is timestamp
type return is list (operation) * storage
function main(const p : unit; const s : storage_) : list(operation) * storage_ is function main (const p : parameter; const s : storage) : return is
block { block {
var toto : timestamp := ("badtimestamp" : timestamp); var stamp : timestamp := ("badtimestamp" : timestamp)
} }
with ((nil: list(operation)), toto) with ((nil: list(operation)), stamp)

View File

@ -1,4 +1,9 @@
type t is (nat * nat) type parameter is unit
type s is map(t)
function main (const u : unit; const s : s) : (list(operation) * s) is ((nil : list(operation)), s) type binding is nat * nat
type storage is map (binding)
type return is list (operation) * storage
function main (const param : parameter; const store : storage) : return is
((nil : list (operation)), store)

View File

@ -1,11 +1,12 @@
(** (*
This test makes sure that the balance is accessible in PascaLIGO. This test makes sure that the balance is accessible in PascaLIGO.
It's there to detect a regression of: https://gitlab.com/ligolang/ligo/issues/68
It is meant to detect the regression detailled in the following issue: https://gitlab.com/ligolang/ligo/issues/68
*) *)
type parameter is unit
type storage is tez type storage is tez
type return is list (operation) * storage
function main (const p : unit; const s: tez) : list(operation) * storage is function main (const param : parameter; const store: storage) : return is
((nil : list(operation)), balance) ((nil : list (operation)), balance)

View File

@ -1,36 +1,35 @@
type storage_ is big_map(int, int) * unit type parameter is unit
type foo is big_map(int, int) type storage is big_map (int, int) * unit
type return is list (operation) * storage
function main(const p : unit; const s : storage_) : list(operation) * storage_ is function main (const p : parameter; const s : storage) : return is
block { block {
var toto : option (int) := Some(0); var toto : option (int) := Some (0);
toto := s.0[23]; toto := s.0[23];
s.0[2] := 444; s.0[2] := 444
} }
with ((nil: list(operation)), s) with ((nil: list(operation)), s)
function set_ (var n : int ; var m : foo) : foo is block { type foo is big_map (int, int)
m[23] := n ;
function set_ (var n : int; var m : foo) : foo is block {
m[23] := n
} with m } with m
function rm (var m : foo) : foo is block { function rm (var m : foo) : foo is block {
remove 42 from map m; remove 42 from map m
} with m } with m
function gf (const m : foo) : int is begin skip end with get_force(23, m) function gf (const m : foo) : int is get_force (23, m)
function get (const m : foo) : option(int) is begin skip end with m[42] function get (const m : foo) : option (int) is m[42]
const empty_big_map : big_map(int,int) = big_map end const empty_big_map : big_map (int,int) = big_map []
const big_map1 : big_map(int,int) = big_map const big_map1 : big_map (int,int) = big_map [23 -> 0; 42 -> 0]
23 -> 0 ;
42 -> 0 ;
end
function mutimaps (const m : foo ; const n : foo) : foo is block function mutimaps (const m : foo; const n : foo) : foo is block {
{ var bar : foo := m;
var bar : foo := m ; bar[42] := 0;
bar[42] := 0 ; n[42] := get_force (42, bar)
n[42] := get_force(42, bar) ;
} with n } with n

View File

@ -1,10 +1,7 @@
// Test PascaLIGO bitwise operators // Test PascaLIGO bitwise operators
function or_op (const n : nat) : nat is function or_op (const n : nat) : nat is bitwise_or (n, 4n)
begin skip end with bitwise_or(n , 4n)
function and_op (const n : nat) : nat is function and_op (const n : nat) : nat is bitwise_and (n, 7n)
begin skip end with bitwise_and(n , 7n)
function xor_op (const n : nat) : nat is function xor_op (const n : nat) : nat is bitwise_xor (n, 7n)
begin skip end with bitwise_xor(n , 7n)

View File

@ -1,2 +1 @@
function blockless (const n: int) : int is function blockless (const n : int) : int is n + 10
n + 10;

View File

@ -1,16 +1,11 @@
// Test PascaLIGO boolean operators // Test PascaLIGO boolean operators
function or_true (const b : bool) : bool is function or_true (const b : bool) : bool is b or True
begin skip end with b or True
function or_false (const b : bool) : bool is function or_false (const b : bool) : bool is b or False
begin skip end with b or False
function and_true (const b : bool) : bool is function and_true (const b : bool) : bool is b and True
begin skip end with b and True
function and_false (const b : bool) : bool is function and_false (const b : bool) : bool is b and False
begin skip end with b and False
function not_bool (const b: bool) : bool is function not_bool (const b : bool) : bool is not b
begin skip end with not b

View File

@ -1,8 +1,5 @@
function concat_op (const s : bytes) : bytes is function concat_op (const s : bytes) : bytes is bytes_concat (s, 0x7070)
begin skip end with bytes_concat(s , 0x7070)
function slice_op (const s : bytes) : bytes is function slice_op (const s : bytes) : bytes is bytes_slice (1n, 2n, s)
begin skip end with bytes_slice(1n , 2n , s)
function hasherman (const s : bytes) : bytes is function hasherman (const s : bytes) : bytes is sha_256 (s)
begin skip end with sha_256(s)

View File

@ -1,11 +1,11 @@
function id_string (const p : string) : option(string) is block { function id_string (const p : string) : option (string) is block {
const packed : bytes = bytes_pack(p) ; const packed : bytes = bytes_pack (p)
} with (bytes_unpack(packed): option(string)) } with (bytes_unpack (packed) : option (string))
function id_int (const p : int) : option(int) is block { function id_int (const p : int) : option (int) is block {
const packed : bytes = bytes_pack(p) ; const packed : bytes = bytes_pack (p)
} with (bytes_unpack(packed): option(int)) } with (bytes_unpack (packed) : option (int))
function id_address (const p : address) : option(address) is block { function id_address (const p : address) : option (address) is block {
const packed : bytes = bytes_pack(p) ; const packed : bytes = bytes_pack (p)
} with (bytes_unpack(packed): option(address)) } with (bytes_unpack (packed) : option (address))

View File

@ -1,5 +1 @@
function chain_id (const tt : chain_id) : chain_id is get_chain_id
function chain_id (const tt : chain_id) : chain_id is
block {
var toto : chain_id := get_chain_id ;
} with ( toto )

View File

@ -1,2 +1,4 @@
function check_signature (const pk: key; const signed: signature; const msg: bytes) : bool is function check_signature (const pk : key;
crypto_check(pk, signed, msg) const signed : signature;
const msg: bytes) : bool
is crypto_check (pk, signed, msg)

View File

@ -1,5 +1,4 @@
function foo (const i : int) : int is function foo (const i : int) : int is
block { block {
function bar (const j : int) : int is function add (const j : int) : int is i+j
i + j ; } with add (i)
} with bar (i)

View File

@ -1,6 +1,5 @@
function foobar(const i : int) : int is function foobar (const i : int) : int is
block { block {
const j : int = 3 ; const j : int = 3;
function toto(const k : int) : int is function add (const k : int) : int is i+j+k
i + j + k ; } with add (42)
} with toto(42)

View File

@ -1,12 +1,10 @@
// This might seem like it's covered by induction with closure-2.ligo // This might seem like it is covered by induction with closure-2.ligo,
// But it exists to prevent a regression on the bug patched by: // but it exists to prevent a regression on the bug patched by:
// https://gitlab.com/ligolang/ligo/commit/faf3bbc06106de98189f1c1673bd57e78351dc7e // https://gitlab.com/ligolang/ligo/commit/faf3bbc06106de98189f1c1673bd57e78351dc7e
function foobar(const i : int) : int is function foobar (const i : int) : int is
block { block {
const j : int = 3 ; const j : int = 3;
const k : int = 4 ; const k : int = 4;
function toto(const l : int) : int is function add (const l : int) : int is i+j+k+l
i + j + k + l; } with add (42)
} with toto(42)

View File

@ -1,7 +1,5 @@
function toto (const i : int) : int is function toto (const i : int) : int is
block { block {
function tata (const j : int) : int is function tata (const j : int) : int is i+j;
i + j ; function titi (const j : int) : int is i+j
function titi (const j : int) : int is } with tata (i) + titi (i)
i + j ;
} with tata(i) + titi(i)

View File

@ -1,98 +1,113 @@
// Copyright Coase, Inc 2019 // Copyright Coase, Inc 2019
type card_pattern_id is nat type card_pattern_id is nat
type card_pattern is record [ type card_pattern is record [
coefficient : tez ; coefficient : tez;
quantity : nat ; quantity : nat
] ]
type card_patterns is map(card_pattern_id , card_pattern) type card_patterns is map (card_pattern_id, card_pattern)
type card_id is nat type card_id is nat
type card is record [
card_owner : address ;
card_pattern : card_pattern_id ;
]
type cards is map(card_id , card)
type storage_type is record [ type card is record [
cards : cards ; card_owner : address;
card_patterns : card_patterns ; card_pattern : card_pattern_id
next_id : nat ;
] ]
type cards is map (card_id, card)
type storage is record [
cards : cards;
card_patterns : card_patterns;
next_id : nat
]
type return is list (operation) * storage
type action_buy_single is record [ type action_buy_single is record [
card_to_buy : card_pattern_id ; card_to_buy : card_pattern_id
]
type action_sell_single is record [
card_to_sell : card_id ;
]
type action_transfer_single is record [
card_to_transfer : card_id ;
destination : address ;
] ]
type action is type action_sell_single is record [
| Buy_single of action_buy_single card_to_sell : card_id
| Sell_single of action_sell_single ]
type action_transfer_single is record [
card_to_transfer : card_id;
destination : address
]
type parameter is
Buy_single of action_buy_single
| Sell_single of action_sell_single
| Transfer_single of action_transfer_single | Transfer_single of action_transfer_single
function transfer_single(const action : action_transfer_single ; const s : storage_type) : (list(operation) * storage_type) is function transfer_single (const action : action_transfer_single;
begin const s : storage) : return is block {
const cards : cards = s.cards ; const cards : cards = s.cards;
const card : card = get_force(action.card_to_transfer , cards) ; const card : card = get_force (action.card_to_transfer, cards);
if (card.card_owner =/= source) then failwith ("This card doesn't belong to you") else skip ; if card.card_owner =/= source then
card.card_owner := action.destination ; failwith ("This card doesn't belong to you")
cards[action.card_to_transfer] := card ; else skip;
s.cards := cards ; card.card_owner := action.destination;
const operations : list(operation) = nil ; cards[action.card_to_transfer] := card;
end with (operations , s) ; s.cards := cards;
const operations : list (operation) = nil
} with (operations, s)
function sell_single(const action : action_sell_single ; const s : storage_type) : (list(operation) * storage_type) is function sell_single (const action : action_sell_single;
begin const s : storage) : return is
const card : card = get_force(action.card_to_sell , s.cards) ; block {
if (card.card_owner =/= source) then failwith ("This card doesn't belong to you") else skip ; const card : card = get_force (action.card_to_sell, s.cards);
const card_pattern : card_pattern = get_force(card.card_pattern , s.card_patterns) ; if card.card_owner =/= source
card_pattern.quantity := abs(card_pattern.quantity - 1n); then failwith ("This card doesn't belong to you")
const card_patterns : card_patterns = s.card_patterns ; else skip;
card_patterns[card.card_pattern] := card_pattern ; const card_pattern : card_pattern =
s.card_patterns := card_patterns ; get_force (card.card_pattern, s.card_patterns);
const cards : cards = s.cards ; card_pattern.quantity := abs (card_pattern.quantity - 1n);
remove action.card_to_sell from map cards ; const card_patterns : card_patterns = s.card_patterns;
s.cards := cards ; card_patterns[card.card_pattern] := card_pattern;
const price : tez = card_pattern.coefficient * card_pattern.quantity ; s.card_patterns := card_patterns;
const receiver : contract(unit) = get_contract(source) ; const cards : cards = s.cards;
const op : operation = transaction(unit , price , receiver) ; remove action.card_to_sell from map cards;
const operations : list(operation) = list op end ; s.cards := cards;
end with (operations , s) const price : tez = card_pattern.coefficient * card_pattern.quantity;
const receiver : contract (unit) = get_contract (source);
const op : operation = transaction (unit, price, receiver);
const operations : list (operation) = list [op]
} with (operations, s)
function buy_single(const action : action_buy_single ; const s : storage_type) : (list(operation) * storage_type) is function buy_single (const action : action_buy_single;
begin const s : storage) : return is
block {
// Check funds // Check funds
const card_pattern : card_pattern = get_force(action.card_to_buy , s.card_patterns) ; const card_pattern : card_pattern =
const price : tez = card_pattern.coefficient * (card_pattern.quantity + 1n) ; get_force (action.card_to_buy, s.card_patterns);
if (price > amount) then failwith ("Not enough money") else skip ; const price : tez =
card_pattern.coefficient * (card_pattern.quantity + 1n);
if price > amount then failwith ("Not enough money") else skip;
// Administrative procedure // Administrative procedure
const operations : list(operation) = nil ; const operations : list(operation) = nil;
// Increase quantity // Increase quantity
card_pattern.quantity := card_pattern.quantity + 1n ; card_pattern.quantity := card_pattern.quantity + 1n;
const card_patterns : card_patterns = s.card_patterns ; const card_patterns : card_patterns = s.card_patterns;
card_patterns[action.card_to_buy] := card_pattern ; card_patterns[action.card_to_buy] := card_pattern;
s.card_patterns := card_patterns ; s.card_patterns := card_patterns;
// Add card // Add card
const cards : cards = s.cards ; const cards : cards = s.cards;
cards[s.next_id] := record cards[s.next_id] := record [
card_owner = source ; card_owner = source;
card_pattern = action.card_to_buy ; card_pattern = action.card_to_buy
end ; ];
s.cards := cards ; s.cards := cards;
s.next_id := s.next_id + 1n ; s.next_id := s.next_id + 1n
end with (operations , s) } with (operations, s)
function main(const action : action ; const s : storage_type) : (list(operation) * storage_type) is function main (const action : parameter; const s : storage) : return is
block {skip} with
case action of case action of
| Buy_single (bs) -> buy_single (bs , s) Buy_single (bs) -> buy_single (bs, s)
| Sell_single (as) -> sell_single (as , s) | Sell_single (as) -> sell_single (as, s)
| Transfer_single (at) -> transfer_single (at , s) | Transfer_single (at) -> transfer_single (at, s)
end end

View File

@ -1,10 +1 @@
// Test if conditional with trivial conditions in PascaLIGO function main (const i : int) : int is if 1 = 1 then 42 else 0
function main (const i : int) : int is
begin
if 1 = 1 then
i := 42
else
i := 0
end with i

View File

@ -1,16 +1,10 @@
// Test if conditional in PascaLIGO
function main (const i : int) : int is function main (const i : int) : int is
begin block {
var result : int := 23 ; var result : int := 23;
if i = 2 then if i = 2 then result := 42 else result := 0
result := 42 } with result
else
result := 0
end with result
function foo (const b : bool) : int is function foo (const b : bool) : int is
begin block {
var x : int := 41 ; const x : int = 41
x := 1 + (if b then x else main(x)) ; } with 1 + (if b then x else main (x))
end with x

View File

@ -1,6 +1,7 @@
type some_type is int type t is int
function main (const p : int ; const s : some_type) : (list(operation) * int) is function main (const p : int ; const s : t) : list (operation) * int is
block { skip } // skip is a do nothing instruction, needed for empty blocks block {
skip
} // skip is a do nothing instruction, needed for empty blocks
with ((nil : list(operation)), p + s) with ((nil : list(operation)), p + s)

View File

@ -1,3 +1,3 @@
function hasherman512 (const s: bytes) : bytes is sha_512(s) function hasherman512 (const s: bytes) : bytes is sha_512 (s)
function hasherman_blake (const s: bytes) : bytes is blake2b(s) function hasherman_blake (const s: bytes) : bytes is blake2b (s)

View File

@ -1,5 +1,5 @@
// Test PasaLIGO variable declarations inside of a block // Test PasaLIGO variable declarations inside of a block
function main (const i : int) : int is block { function main (const i : int) : int is block {
const j : int = 42 ; const j : int = 42
} with j } with j

View File

@ -1,8 +1,5 @@
// Test PascaLIGO top level declarations // Test PascaLIGO top-level declarations
const foo : int = 42 const foo : int = 42
function main (const i : int) : int is function main (const i : int) : int is i + foo
begin
skip
end with i + foo

View File

@ -1,31 +1,29 @@
//Test deep_access in PascalLigo // Test deep access
type pii is (int*int)
type ppi is record x:pii; y:pii end
type ppp is (ppi*ppi)
function main (const toto : unit) : int is block { type pii is int * int
var a : ppp := (
record type ppi is record [x : pii; y : pii]
x = (0,1);
y = (10,11); type ppp is ppi * ppi
end ,
record function main (const toto : unit) : int is
x = (100,101); block {
y = (110,111); var a : ppp :=
end (record [x = (0,1); y = (10,11)],
) ; record [x = (100,101); y = (110,111)]);
a.0.x.0 := 2; a.0.x.0 := 2;
const b:int = a.0.x.0; } with a.0.x.0
} with b
function asymetric_tuple_access(const foo : unit) : int is block { function asymetric_tuple_access (const foo : unit) : int is
var mytuple : int * (int * (int * int)) := (0,(1,(2,3))) ; block {
} with mytuple.0 + mytuple.1.0 + mytuple.1.1.0 + mytuple.1.1.1 var tuple : int * (int * (int * int)) := (0,(1,(2,3)))
} with tuple.0 + tuple.1.0 + tuple.1.1.0 + tuple.1.1.1
type nested_record_t is record type nested_record_t is
nesty : (record mymap : map(int,string) ; end) ; record [nesty : record [mymap : map (int,string)]]
end
function nested_record (var nee : nested_record_t) : string is block { function nested_record (var nee : nested_record_t) : string is
nee.nesty.mymap[1] := "one" ; block {
} with ( get_force(1, nee.nesty.mymap) ) nee.nesty.mymap[1] := "one"
} with get_force (1, nee.nesty.mymap)

View File

@ -1,16 +1,19 @@
type action is type parameter is
| Increment of int Increment of int
| Decrement of int | Decrement of int
function increment(const i : int ; const n : int) : int is type storage is int
block { skip } with (i + n)
function decrement(const i : int ; const n : int) : int is type return is list (operation) * storage
block { skip } with (i - n)
function main (const p : action ; const s : int) : (list(operation) * int) is function increment (const i : int; const n : int) : int is i+n
block {skip} with ((nil : list(operation)),
case p of function decrement (const i : int; const n : int) : int is i-n
| Increment (n) -> increment (s, n)
| Decrement (n) -> decrement (s, n) const nop : list (operation) = nil
end)
function main (const action : parameter; const store : storage) : return is
case action of
Increment (n) -> (nop, increment (store, n))
| Decrement (n) -> (nop, decrement (store, n))
end

View File

@ -1,8 +1,11 @@
function main(const p : unit; const s : int) : list(operation) * int is type parameter is unit
((list end : list(operation)), s + 1) type storage is int
type return is list (operation) * storage
function main(const p : unit; const s : int) : list(operation) * int is function main(const p : parameter; const s : storage) : return is
begin ((nil : list(operation)), s+1)
const ret : list(operation) * int = main(p, s)
end function main (const p : parameter; const s : storage) : return is
with (ret.0, ret.1 + 1) block {
const ret : return = main (p, s)
} with (ret.0, ret.1 + 1)

View File

@ -1,9 +1,9 @@
type foo is type t is
| Bar of int Bar of int
| Baz | Baz
function main (const f: foo) : int is function main (const x : t) : int is
(case f of case x of
| Bar (n) -> n Bar (n) -> n
| Baz -> -1 | Baz -> -1
end) end

View File

@ -1,16 +1,19 @@
function cb(const a : address; const s : unit) : list(operation) * unit is type storage is unit
type return is list (operation) * storage
function cb (const a : address; const s : storage) : return is
block { block {
const c : contract(unit) = get_entrypoint("%cb", a) const c : contract (unit) = get_entrypoint ("%cb", a)
} }
with (list transaction(unit, 0mutez, c) end, s) with (list [transaction (unit, 0mutez, c)], s)
function cbo(const a : address; const s : unit) : list(operation) * unit is function cbo (const a : address; const s : storage) : return is
block { block {
const c : contract(unit) = const c : contract (unit) =
case (get_entrypoint_opt("%cbo", a) : option(contract (unit))) of case (get_entrypoint_opt ("%cbo", a) : option (contract (unit))) of
| Some (c) -> c Some (c) -> c
| None -> (failwith ("entrypoint not found") : contract (unit)) | None -> (failwith ("entrypoint not found") : contract (unit))
end end
} } with (list [transaction(unit, 0mutez, c)], s)
with (list transaction(unit, 0mutez, c) end, s)

View File

@ -1,11 +1,5 @@
type myrec is record type t is record [foo : nat; bar : string]
foo : nat;
bar : string;
end;
const a : myrec = record const a : t = record [foo = 0n; bar = "bar"]
foo = 0n;
bar = "bar";
end;
const b : int = 2 ; const b : int = 2

View File

@ -1,37 +1,43 @@
type param is type parameter is
| Zero of nat Zero of nat
| Pos of nat | Pos of nat
function main (const p : param; const s : unit) : list(operation) * unit is type storage is unit
type return is list (operation) * storage
function main (const p : parameter; const s : storage) : return is
block { block {
case p of case p of
| Zero (n) -> if n > 0n then failwith("fail") else skip Zero (n) -> if n > 0n then failwith ("fail") else skip
| Pos (n) -> if n > 0n then skip else failwith("fail") | Pos (n) -> if n > 0n then skip else failwith ("fail")
end end
} }
with ((nil : list(operation)), s) with ((nil : list (operation)), s)
function foobar (const i : int) : int is function foobar (const i : int) : int is
block { block {
var p : param := Zero (42n) ; var p : parameter := Zero (42n);
if i > 0 then block { if i > 0 then {
i := i + 1 ; i := i + 1;
if i > 10 then block { if i > 10 then {
i := 20 ; i := 20;
failwith ("who knows") ; failwith ("who knows");
i := 30 ; i := 30 // Should be no-op
} else skip }
} else block { else skip
case p of
| Zero (n) -> failwith ("wooo")
| Pos (n) -> skip
end
} }
} with case p of else
| Zero (n) -> i case p of
| Pos (n) -> (failwith ("waaaa") : int) Zero (n) -> failwith ("wooo")
end | Pos (n) -> skip
end
} with
case p of
Zero (n) -> i
| Pos (n) -> (failwith ("waaaa") : int)
end
function failer(const p : int) : int is block { function failer (const p : int) : int is block {
if p = 1 then failwith("some_string") else skip ; if p = 1 then failwith ("some_string") else skip
} with p } with p

View File

@ -1,11 +1,2 @@
// This was meant to test the for loop in PascaLIGO
// But for whatever reason, the LIGO compiler currently thinks this is a 'complex loop'
// even though it isn't.
// See this error:
// $ ligo dry-run for.ligo main 0 0
// bounded iterators: only simple for loops are supported yet
// {"loop_loc":"in file \"for.ligo\", line 4, characters 10-42"}
function main (const a: int) : int is function main (const a: int) : int is
block { for i := 0 to 100 block { skip } } with i; block { for i := 0 to 100 block { skip } } with i

View File

@ -1,9 +1,9 @@
// Test a PascaLIGO function with more complex logic than function.ligo // Test a PascaLIGO function with more complex logic than function.ligo
function main (const i : int) : int is function main (const i : int) : int is
begin block {
var j : int := 0 ; var j : int := 0;
var k : int := 1 ; var k : int := 1;
j := k + i ; j := k + i;
k := i + j ; k := i + j
end with (k + j) } with k + j

View File

@ -1,10 +1,7 @@
// Test a PascaLIGO function which uses other functions as subroutines // Test a PascaLIGO function which uses other functions as subroutines
function inc ( const i : int ) : int is function inc (const i : int) : int is i+1
block { skip } with i + 1
function double_inc ( const i : int ) : int is function double_inc (const i : int) : int is inc (i+1)
block { skip } with inc(i + 1)
function foo ( const i : int ) : int is function foo (const i : int) : int is inc (i) + double_inc (i)
block { skip } with inc(i) + double_inc(i)

View File

@ -1,6 +1,3 @@
// Test a trivial PascaLIGO function // Test a trivial PascaLIGO function
function main (const i : int) : int is function main (const i : int) : int is i
begin
skip
end with i

View File

@ -1,16 +1,19 @@
function cb(const s : unit) : list(operation) * unit is type storage is unit
type return is list (operation) * storage
function cb (const s : storage) : return is
block { block {
const c : contract(unit) = get_contract(source) const c : contract (unit) = get_contract (source)
} }
with (list transaction(unit, 0mutez, c) end, s) with (list [transaction(unit, 0mutez, c)], s)
function cbo(const s : unit) : list(operation) * unit is function cbo (const s : unit) : return is
block { block {
const c : contract(unit) = const c : contract (unit) =
case (get_contract_opt(source) : option(contract (unit))) of case (get_contract_opt (source) : option (contract (unit))) of
| Some (c) -> c Some (c) -> c
| None -> (failwith ("contract not found") : contract (unit)) | None -> (failwith ("contract not found") : contract (unit))
end end
} }
with (list transaction(unit, 0mutez, c) end, s) with (list [transaction(unit, 0mutez, c)], s)

View File

@ -1,6 +1,6 @@
type heap_element is int * string type heap_elt is int * string
function heap_element_lt(const x : heap_element ; const y : heap_element) : bool is function heap_elt_lt (const x : heap_elt;
block { skip } with x.0 < y.0 const y : heap_elt) : bool is x.0 < y.0
#include "heap.ligo" #include "heap.ligo"

View File

@ -1,93 +1,95 @@
// Implementation of the heap data structure in PascaLIGO // Implementation of the heap data structure in PascaLIGO
// See: https://en.wikipedia.org/wiki/Heap_%28data_structure%29 // See: https://en.wikipedia.org/wiki/Heap_%28data_structure%29
type heap is map(nat, heap_element) ; type heap is map (nat, heap_elt)
function is_empty (const h : heap) : bool is function is_empty (const h : heap) : bool is size (h) = 0n
block {skip} with size(h) = 0n
function get_top (const h : heap) : heap_element is function get_top (const h : heap) : heap_elt is get_force (1n, h)
block {skip} with get_force(1n, h)
function pop_switch (const h : heap) : heap is function pop_switch (const h : heap) : heap is
block { block {
const result : heap_element = get_top (h) ; const result : heap_elt = get_top (h);
const s : nat = size(h) ; const s : nat = size (h);
const last : heap_element = get_force(s, h) ; const last : heap_elt = get_force (s, h);
remove 1n from map h ; remove 1n from map h;
h[1n] := last ; h[1n] := last
} with h } with h
function pop_ (const h : heap) : nat is function pop_ (const h : heap) : nat is
begin block {
const result : heap_element = get_top (h) ; const result : heap_elt = get_top (h);
const s : nat = size(h) ; const s : nat = size (h);
var current : heap_element := get_force(s, h) ; var current : heap_elt := get_force (s, h);
const i : nat = 1n ; const i : nat = 1n;
const left : nat = 2n * i ; const left : nat = 2n * i;
const right : nat = left + 1n ; const right : nat = left + 1n;
remove 1n from map h ; remove 1n from map h;
h[1n] := current ; h[1n] := current;
var largest : nat := i ; var largest : nat := i;
if (left <= s and heap_element_lt(get_force(s , h) , get_force(left , h))) then const tmp : heap_elt = get_force (s, h);
largest := left if left <= s and heap_elt_lt (tmp, get_force (left,h))
else if (right <= s and heap_element_lt(get_force(s , h) , get_force(right , h))) then then largest := left
largest := right else
else skip if right <= s and heap_elt_lt (tmp, get_force (right,h))
end with largest then largest := right
else skip
} with largest
function insert (const h : heap ; const e : heap_element) : heap is function insert (const h : heap ; const e : heap_elt) : heap is
begin block {
var i : nat := size(h) + 1n ; var i : nat := size (h) + 1n;
h[i] := e ; h[i] := e;
var largest : nat := i ; var largest : nat := i;
var parent : nat := 0n ; var parent : nat := 0n;
while (largest =/= i) block { while largest =/= i block {
parent := i / 2n ; parent := i/2n;
largest := i ; largest := i;
if (parent >= 1n) then block { if parent >= 1n then {
if (heap_element_lt(get_force(parent , h) , get_force(i , h))) then block { if heap_elt_lt (get_force (parent,h), get_force(i,h))) then {
largest := parent ; largest := parent;
const tmp : heap_element = get_force(i , h) ; const tmp : heap_elt = get_force (i,h);
h[i] := get_force(parent , h) ; h[i] := get_force(parent, h);
h[parent] := tmp ; h[parent] := tmp
} else skip } else skip
} else skip } else skip
} }
end with h } with h
function pop (const h : heap) : (heap * heap_element * nat) is function pop (const h : heap) : heap * heap_elt * nat is
begin block {
const result : heap_element = get_top (h) ; const result : heap_elt = get_top (h);
var s : nat := size(h) ; var s : nat := size (h);
const last : heap_element = get_force(s, h) ; const last : heap_elt = get_force (s,h);
remove s from map h ; remove s from map h;
h[1n] := last ; h[1n] := last;
s := size(h) ; s := size (h);
var i : nat := 0n ; var i : nat := 0n;
var largest : nat := 1n ; var largest : nat := 1n;
var left : nat := 0n ; var left : nat := 0n;
var right : nat := 0n ; var right : nat := 0n;
var c : nat := 0n ; var c : nat := 0n;
while (largest =/= i) block { while largest =/= i block {
c := c + 1n ; c := c + 1n;
i := largest ; i := largest;
left := 2n * i ; left := 2n * i;
right := left + 1n ; right := left + 1n;
if (left <= s) then begin if left <= s then {
if (heap_element_lt(get_force(left , h) , get_force(i , h))) then begin if heap_elt_lt (get_force (left,h), get_force(i,h)) then {
largest := left ; largest := left;
const tmp : heap_element = get_force(i , h) ; const tmp : heap_elt = get_force(i,h);
h[i] := get_force(left , h) ; h[i] := get_force (left, h);
h[left] := tmp ; h[left] := tmp
end else skip ; } else skip
end else if (right <= s) then begin }
if (heap_element_lt(get_force(right , h) , get_force(i , h))) then begin else
largest := right ; if right <= s then {
const tmp : heap_element = get_force(i , h) ; if heap_elt_lt (get_force (right, h), get_force (i,h)) then {
h[i] := get_force(right , h) ; largest := right;
h[left] := tmp ; const tmp : heap_elt = get_force (i,h);
end else skip ; h[i] := get_force (right, h);
end else skip ; h[left] := tmp
} } else skip
end with (h , result , c) } else skip
}
} with (h, result, c)

View File

@ -1,27 +1,27 @@
// Test a PascaLIGO function which takes another PascaLIGO function as an argument (* Test a PascaLIGO function which takes another function as an
argument *)
function foobar (const i : int) : int is function foobar (const i : int) : int is
begin block {
function foo (const i : int) : int is i; function foo (const i : int) : int is i;
function bar (const f : int -> int) : int is f (i); function bar (const f : int -> int) : int is f (i);
end with bar (foo); } with bar (foo)
// higher order function with more than one argument // higher order function with more than one argument
function higher2(const i : int; const f : int -> int): int is
begin function higher2 (const i : int; const f : int -> int): int is f (i)
const ii: int = f (i)
end with ii
function foobar2 (const i : int) : int is function foobar2 (const i : int) : int is
begin block {
function foo2 (const i : int) : int is i function foo2 (const i : int) : int is i
end with higher2 (i,foo2) } with higher2 (i, foo2)
const a : int = 0; const a : int = 0
function foobar3 (const i : int) : int is function foobar3 (const i : int) : int is
begin block {
function foo2 (const i : int) : int is a+i function foo2 (const i : int) : int is a+i
end with higher2 (i,foo2) } with higher2 (i, foo2)
function f (const i : int) : int is i function f (const i : int) : int is i
@ -29,17 +29,15 @@ function g (const i : int) : int is f (i)
function foobar4 (const i : int) : int is g (g (i)) function foobar4 (const i : int) : int is g (g (i))
function higher3(const i : int; const f : int -> int; const g : int -> int) function higher3 (const i : int;
: int is const f : int -> int;
begin const g : int -> int) : int is f (g (i))
const ii : int = f(g(i))
end with ii
function foobar5 (const i : int) : int is function foobar5 (const i : int) : int is
begin block {
const a : int = 0; const a : int = 0;
function foo (const i : int) : int is a+i; function foo (const i : int) : int is a+i;
function goo (const i : int) : int is foo (i) function goo (const i : int) : int is foo (i)
end with higher3(i,foo,goo) } with higher3 (i, foo, goo)
function foobar6 (const i : int) : int -> int is f function foobar6 (const i : int) : int -> int is f

View File

@ -1 +1 @@
function main (const kh: key_hash) : contract(unit) is implicit_account(kh) function main (const kh: key_hash) : contract (unit) is implicit_account (kh)

View File

@ -1,2 +1 @@
function main (const i: int) : option(nat) is function main (const i : int) : option (nat) is is_nat (i)
block {skip} with is_nat(i)

View File

@ -1,5 +1,7 @@
function check_hash_key (const kh1 : key_hash; const k2 : key) : bool*key_hash is block { function check_hash_key (const kh1 : key_hash;
var ret : bool := False ; const k2 : key) : bool * key_hash is
var kh2 : key_hash := crypto_hash_key(k2) ; block {
if kh1 = kh2 then ret := True else skip; var ret : bool := False;
} with (ret, kh2) var kh2 : key_hash := crypto_hash_key (k2);
if kh1 = kh2 then ret := True else skip
} with (ret, kh2)

View File

@ -1,7 +1,3 @@
function f (const x : unit) : unit is function f (const x : unit) : unit is Unit
begin skip end with unit
function main (const p : unit ; const s : unit) : unit is function main (const p : unit ; const s : unit) : unit is f (Unit)
begin
var y : unit := f(unit) ;
end with y

View File

@ -1,49 +1,33 @@
// Test list type and related built-in functions in PascaLIGO // Test list type and related built-in functions in PascaLIGO
type foobar is list(int) type foobar is list (int)
const fb : foobar = list const fb : foobar = list [23; 42]
23 ;
42 ;
end
const fb2 : foobar = 144 # fb const fb2 : foobar = 144 # fb
const fb3 : foobar = cons(688 , fb2) const fb3 : foobar = cons (688, fb2)
function size_ (const m : foobar) : nat is function size_ (const m : foobar) : nat is size (m)
block {skip} with (size(m))
// function hdf (const m : foobar) : int is begin skip end with hd(m) // function hdf (const m : foobar) : int is hd (m)
const bl : foobar = list const bl : foobar = list [144; 51; 42; 120; 421]
144 ;
51 ;
42 ;
120 ;
421 ;
end
function fold_op (const s: list(int)) : int is function fold_op (const s : list (int)) : int is
begin
function aggregate (const prec: int; const cur: int) : int is
begin
skip
end with prec + cur
end with list_fold(aggregate, s, 10)
function iter_op (const s : list(int)) : int is
begin
var r : int := 0 ;
function aggregate (const i : int) : unit is
begin
r := r + i ;
end with unit ;
list_iter(aggregate, s) ;
end with r
function map_op (const s : list(int)) : list(int) is
block { block {
function increment (const i : int) : int is block { skip } with i + 1 function aggregate (const prec: int; const cur: int) : int is prec+cur
} with list_map(increment, s) } with list_fold (aggregate, s, 10)
function iter_op (const s : list (int)) : int is
block {
var r : int := 0;
function aggregate (const i : int) : unit is
block { r := r + i } with unit;
list_iter (aggregate, s)
} with r
function map_op (const s : list (int)) : list (int) is
block {
function increment (const i : int) : int is i+1
} with list_map (increment, s)

View File

@ -1,193 +1,188 @@
// Test while loops in PascaLIGO // Test while loops in PascaLIGO
function counter (var n : nat) : nat is block { function counter (var n : nat) : nat is
var i : nat := 0n ; block {
while i < n block { var i : nat := 0n;
i := i + 1n; while i < n block {
} i := i + 1n
} with i }
} with i
function while_sum (var n : nat) : nat is block { function while_sum (var n : nat) : nat is
var i : nat := 0n ; block {
var r : nat := 0n ; var i : nat := 0n;
while i < n block { var r : nat := 0n;
i := i + 1n; while i < n block {
r := r + i; i := i + 1n;
} r := r + i
} with r }
} with r
function for_sum (var n : nat) : int is block { function for_sum (var n : nat) : int is
var acc : int := 0 ; block {
for i := 1 to int(n) var acc : int := 0;
begin for i := 1 to int (n)
acc := acc + i; block {
end acc := acc + i
} with acc }
} with acc
function for_collection_list (var nee : unit) : (int * string) is block { function for_collection_list (var nee : unit) : (int * string) is
var acc : int := 0; block {
var st : string := "to"; var acc : int := 0;
var mylist : list(int) := list 1; 1; 1 end; var st : string := "to";
for x in list mylist var mylist : list (int) := list [1; 1; 1];
begin for x in list mylist
block {
acc := acc + x;
st := st ^ "to"
}
} with (acc, st)
function for_collection_set (var nee : unit) : int * string is
block {
var acc : int := 0;
var st : string := "to";
var myset : set (int) := set [1; 2; 3];
for x in set myset block {
acc := acc + x; acc := acc + x;
st := st ^ "to"; st := st ^ "to"
end }
} with (acc, st) } with (acc, st)
function for_collection_set (var nee : unit) : (int * string) is block { function for_collection_if_and_local_var (var nee : unit) : int is
var acc : int := 0; block {
var st : string := "to"; var acc : int := 0;
var myset : set(int) := set 1; 2; 3 end; const theone : int = 1;
for x in set myset var myset : set (int) := set [1; 2; 3];
begin for x in set myset block {
acc := acc + x ; const thetwo : int = 2;
st := st^"to" ; if x = theone then acc := acc + x
end else if x = thetwo then acc := acc + thetwo
} with (acc, st) else acc := acc + 10
}
} with acc
function for_collection_if_and_local_var (var nee : unit) : int is block { function for_collection_rhs_capture (var nee : unit) : int is
var acc : int := 0 ; block {
const theone : int = 1 ; var acc : int := 0;
var myset : set(int) := set 1 ; 2 ; 3 end ; const mybigint : int = 1000;
for x in set myset var myset : set (int) := set [1; 2; 3];
begin for x in set myset block {
const thetwo : int = 2 ; if x = 1 then acc := acc + mybigint
if x=theone then else acc := acc + 10
acc := acc + x }
else if x=thetwo then } with acc
acc := acc + thetwo;
else
acc := acc + 10;
end
} with acc
function for_collection_rhs_capture (var nee : unit) : int is block { function for_collection_proc_call (var nee : unit) : int is
var acc : int := 0 ; block {
const mybigint : int = 1000 ; var acc : int := 0;
var myset : set(int) := set 1 ; 2 ; 3 end ; var myset : set (int) := set [1; 2; 3];
for x in set myset for x in set myset block {
begin if x = 1 then
if x=1 then acc := acc + mybigint; acc := acc + for_collection_rhs_capture (unit)
else acc := acc + 10; else acc := acc + 10
end }
} with acc } with acc
function for_collection_proc_call (var nee : unit) : int is block { function for_collection_comp_with_acc (var nee : unit) : int is
var acc : int := 0 ; block {
var myset : set(int) := set 1 ; 2 ; 3 end ; var myint : int := 0;
for x in set myset var mylist : list (int) := list [1; 10; 15];
begin for x in list mylist block {
if x=1 then
acc := acc + for_collection_rhs_capture(unit);
else
acc := acc + 10;
end
} with acc
function for_collection_comp_with_acc (var nee : unit) : int is block {
var myint : int := 0 ;
var mylist : list(int) := list 1 ; 10 ; 15 end;
for x in list mylist
begin
if x < myint then skip; if x < myint then skip;
else myint := myint + 10 else myint := myint + 10
end }
} with myint } with myint
function for_collection_with_patches (var nee : unit) : map(string,int) is block { function for_collection_with_patches (var nee : unit) : map (string,int) is
var myint : int := 12 ; block {
var mylist : list(string) := list "I"; "am"; "foo" end; var myint : int := 12;
var mymap : map(string,int) := map end; var mylist : list (string) := list ["I"; "am"; "foo"];
for x in list mylist var mymap : map (string,int) := map [];
begin for x in list mylist block {
patch mymap with map [x -> myint]; patch mymap with map [x -> myint]
end }
} with mymap } with mymap
function for_collection_empty (var nee : unit) : int is block { function for_collection_empty (var nee : unit) : int is
var acc : int := 0 ; block {
var myset : set(int) := set 1; 2; 3 end; var acc : int := 0;
for x in set myset var myset : set(int) := set [1; 2; 3];
begin for x in set myset block {
skip skip
end }
} with acc } with acc
function for_collection_map_kv (var nee : unit) : (int * string) is block { function for_collection_map_kv (var nee : unit) : int * string is
var acc : int := 0; block {
var st : string := ""; var acc : int := 0;
var mymap : map(string,int) := map "1" -> 1; "2" -> 2; "3" -> 3 end; var st : string := "";
for k -> v in map mymap var mymap : map (string, int) := map ["1" -> 1; "2" -> 2; "3" -> 3];
begin for k -> v in map mymap block {
acc := acc + v; acc := acc + v;
st := st ^ k; st := st ^ k;
end }
} with (acc, st) } with (acc, st)
function for_collection_map_k (var nee : unit) : string is block { function for_collection_map_k (var nee : unit) : string is
var st : string := "" ; block {
var mymap : map(string,int) := map "1" -> 1 ; "2" -> 2 ; "3" -> 3 end ; var st : string := "";
for k in map mymap var mymap : map (string, int) := map ["1" -> 1; "2" -> 2; "3" -> 3];
begin for k in map mymap block {
st := st ^ k; st := st ^ k
end }
} with st } with st
function nested_for_collection (var nee : unit) : (int*string) is block { function nested_for_collection (var nee : unit) : int * string is
var myint : int := 0; block {
var mystoo : string := ""; var myint : int := 0;
var mylist : list(int) := list 1 ; 2 ; 3 end ; var mystoo : string := "";
var mymap : map(string,string) := map " one" -> "," ; "two" -> " " end ; var mylist : list(int) := list [1; 2; 3];
var mymap : map (string, string) := map [" one" -> ","; "two" -> " "];
for i in list mylist block {
myint := myint + i;
var myset : set (string) := set ["1"; "2"; "3"];
for st in set myset block {
myint := myint + i;
mystoo := mystoo ^ st;
for k -> v in map mymap block {
mystoo := mystoo ^ k ^ v
}
}
}
} with (myint, mystoo)
for i in list mylist function nested_for_collection_local_var (var nee : unit) : int*string is
begin block {
myint := myint + i ; var myint : int := 0;
var myset : set(string) := set "1" ; "2" ; "3" end ; var myst : string := "";
for st in set myset var mylist : list (int) := list [1; 2; 3];
begin for i in list mylist block {
myint := myint + i ; var myst_loc : string := "";
mystoo := mystoo ^ st ; myint := myint + i;
for k -> v in map mymap var myset : set (string) := set ["1"; "2"; "3"];
begin for st in set myset block {
mystoo := mystoo ^ k ^ v ; myint := myint + i;
end myst_loc := myst_loc ^ st;
end };
end myst := myst_loc ^ myst
} with (myint,mystoo) }
} with (myint, myst)
function nested_for_collection_local_var (var nee : unit) : (int*string) is block {
var myint : int := 0;
var myst : string := "";
var mylist : list(int) := list 1 ; 2 ; 3 end ;
for i in list mylist
begin
var myst_loc : string := "" ;
myint := myint + i ;
var myset : set(string) := set "1" ; "2" ; "3" end ;
for st in set myset
begin
myint := myint + i ;
myst_loc := myst_loc ^ st ;
end;
myst := myst_loc ^ myst ;
end
} with (myint,myst)
function dummy (const n : nat) : nat is block { function dummy (const n : nat) : nat is block {
while False block { skip } while False block { skip }
} with n } with n
function inner_capture_in_conditional_block (var nee : unit) : bool*int is block { function inner_capture_in_conditional_block (var nee : unit) : bool * int is
var count : int := 1 ; block {
var ret : bool := False ; var count : int := 1;
var mylist : list(int) := list 1 ; 2 ; 3 end ; var ret : bool := False;
for it1 in list mylist block { var mylist : list (int) := list [1; 2; 3];
for it2 in list mylist block { for it1 in list mylist block {
if count = it2 then ret := not (ret) for it2 in list mylist block {
else skip; if count = it2 then ret := not (ret) else skip
}; };
count := count + 1; count := count + 1
} }
} with (ret,count) } with (ret, count)

View File

@ -1,23 +1,20 @@
// Test map type and related built-in functions in PascaLIGO // Test map type and related built-in functions in PascaLIGO
type foobar is map(int, int) type foobar is map (int, int)
const empty_map : foobar = map end const empty_map : foobar = map []
const map1 : foobar = map const map1 : foobar = map [
144 -> 23 ; 144 -> 23;
51 -> 23 ; 51 -> 23;
42 -> 23 ; 42 -> 23;
120 -> 23 ; 120 -> 23;
421 -> 23 ; 421 -> 23]
end
const map2 : foobar = map
23 -> 0 ;
42 -> 0 ;
end
function set_ (var n : int ; var m : foobar) : foobar is block { const map2 : foobar = map [23 -> 0; 42 -> 0]
m[23] := n ;
function set_ (var n : int; var m : foobar) : foobar is block {
m[23] := n
} with m } with m
@ -25,50 +22,43 @@ function rm (var m : foobar) : foobar is block {
remove 42 from map m remove 42 from map m
} with m } with m
function patch_ (var m: foobar) : foobar is block { function patch_ (var m : foobar) : foobar is block {
patch m with map [0 -> 5; 1 -> 6; 2 -> 7] patch m with map [0 -> 5; 1 -> 6; 2 -> 7]
} with m } with m
function patch_deep (var m: foobar * nat) : foobar * nat is function patch_deep (var m : foobar * nat) : foobar * nat is
begin patch m.0 with map [1 -> 9]; end with m block { patch m.0 with map [1 -> 9] } with m
function size_ (const m : foobar) : nat is function size_ (const m : foobar) : nat is size (m)
block {skip} with (size(m))
function gf (const m : foobar) : int is begin skip end with get_force(23, m) function gf (const m : foobar) : int is get_force (23, m)
function get (const m : foobar) : option(int) is function get (const m : foobar) : option (int) is m[42]
begin
skip
end with m[42]
function get_ (const m : foobar) : option(int) is function get_ (const m : foobar) : option (int) is map_get (42, m)
begin
skip
end with map_get(42 , m)
function mem (const k: int; const m: foobar) : bool is map_mem(k, m) function mem (const k: int; const m: foobar) : bool is map_mem (k, m)
function iter_op (const m : foobar) : unit is function iter_op (const m : foobar) : unit is
block { block {
function aggregate (const i : int ; const j : int) : unit is block function aggregate (const i : int; const j : int) : unit is block
{ if (i=j) then skip else failwith("fail") } with unit ; { if i=j then skip else failwith ("fail") } with unit
// map_iter(m , aggregate) ; } with map_iter (aggregate, m)
} with map_iter(aggregate, m) ;
function map_op (const m : foobar) : foobar is function map_op (const m : foobar) : foobar is
block { block {
function increment (const i : int ; const j : int) : int is block { skip } with j + 1 ; function increment (const i : int; const j : int) : int is j+1
} with map_map(increment, m) ; } with map_map (increment, m)
function fold_op (const m : foobar) : int is function fold_op (const m : foobar) : int is
block { block {
function aggregate (const i : int ; const j : (int * int)) : int is block { skip } with i + j.0 + j.1 ; function aggregate (const i : int; const j : int * int) : int is
} with map_fold(aggregate, m , 10) i + j.0 + j.1
} with map_fold(aggregate, m, 10)
function deep_op (var m : foobar) : foobar is function deep_op (var m : foobar) : foobar is
block { block {
var coco : (int*foobar) := (0, m); var coco : int * foobar := (0, m);
remove 42 from map coco.1 ; remove 42 from map coco.1;
coco.1[32] := 16 ; coco.1[32] := 16
} with coco.1 } with coco.1

View File

@ -1,37 +1,37 @@
// Test the pattern matching functionality of PascaLIGO // Test the pattern matching functionality of PascaLIGO
function match_bool (const i : int) : int is function match_bool (const i : int) : int is
begin block {
var result : int := 23 ; var result : int := 23;
case i = 2 of case i = 2 of
| True -> result := 42 True -> result := 42
| False -> result := 0 | False -> result := 0
end end
end with result } with result
function match_option (const o : option(int)) : int is function match_option (const o : option (int)) : int is
begin block {
var result : int := 23 ; var result : int := 23;
case o of case o of
| None -> skip None -> skip
| Some (s) -> result := s | Some (s) -> result := s
end end
end with result } with result
function match_expr_bool (const i : int) : int is function match_expr_bool (const i : int) : int is
case i = 2 of case i = 2 of
| True -> 42 True -> 42
| False -> 0 | False -> 0
end end
function match_expr_option (const o : option(int)) : int is function match_expr_option (const o : option (int)) : int is
case o of case o of
| None -> 42 None -> 42
| Some (s) -> s | Some (s) -> s
end end
function match_expr_list (const l : list(int)) : int is function match_expr_list (const l : list (int)) : int is
case l of case l of
| nil -> -1 nil -> -1
| hd # tl -> hd | hd # tl -> hd
end end

View File

@ -1,10 +1,14 @@
// Test functions with several parameters in PascaLIGO // Test functions with several parameters in PascaLIGO
function ab(const a : int; const b : int) : int is function ab (const a : int; const b : int) : int is a+b
begin skip end with (a + b)
function abcd(const a : int; const b : int; const c : int; const d : int) : int is function abcd (const a : int;
begin skip end with (a + b + c + d + 2) const b : int;
const c : int;
const d : int) : int is a+b+c+d+2
function abcde(const a : int; const b : int; const c : int; const d : int; const e : int) : int is function abcde (const a : int;
begin skip end with (c + e + 3) const b : int;
const c : int;
const d : int;
const e : int) : int is c+e+3

View File

@ -1,118 +1,150 @@
// storage type // storage type
type threshold_t is nat
type max_proposal_t is nat
type max_message_size_t is nat
type state_hash_t is bytes
type addr_set_t is set(address)
type message_store_t is map(bytes,addr_set_t)
type proposal_counters_t is map(address,nat)
type storage_t is record type threshold is nat
state_hash : state_hash_t ; type max_proposal is nat
threshold : threshold_t ; type max_message_size is nat
max_proposal : max_proposal_t ; type state_hash is bytes
max_message_size : max_message_size_t ; type addr_set is set (address)
authorized_addresses : addr_set_t ; type message_store is map (bytes, addr_set)
message_store : message_store_t ; type proposal_counters is map (address, nat)
proposal_counters : proposal_counters_t ;
end type storage is
record [
state_hash : state_hash;
threshold : threshold;
max_proposal : max_proposal;
max_message_size : max_message_size;
authorized_addresses : addr_set;
message_store : message_store;
proposal_counters : proposal_counters
]
// I/O types // I/O types
type message_t is (bytes -> list(operation))
type send_pt is message_t type message is bytes -> list (operation)
type withdraw_pt is message_t type send_pt is message
type withdraw_pt is message
type default_pt is unit type default_pt is unit
type contract_return_t is (list(operation) * storage_t) type return is list (operation) * storage
type entry_point_t is type parameter is
| Send of send_pt Send of send_pt
| Withdraw of withdraw_pt | Withdraw of withdraw_pt
| Default of default_pt | Default of default_pt
function send (const param : send_pt; const s : storage) : return is
block {
// check sender against the authorized addresses
function send (const param : send_pt; const s : storage_t) : contract_return_t is block { if not set_mem (sender, s.authorized_addresses)
then failwith("Unauthorized address")
else skip;
// check sender against the authorized addresses // check message size against the stored limit
if not set_mem(sender,s.authorized_addresses) then failwith("Unauthorized address") else skip ;
// check message size against the stored limit var message : message := param;
var message : message_t := param ; const packed_msg : bytes = bytes_pack (message);
const packed_msg : bytes = bytes_pack(message) ; if size (packed_msg) > s.max_message_size
if size(packed_msg) > s.max_message_size then failwith("Message size exceed maximum limit") then failwith ("Message size exceed maximum limit")
else skip ; else skip;
// compute the new set of addresses associated with the message and update counters (* compute the new set of addresses associated with the message and
var new_store : addr_set_t := set_empty ; update counters *)
case map_get(packed_msg, s.message_store) of
| Some(voters) -> block { // the message is already stored
// increment the counter only if the sender isn't already associated with the message
if set_mem(sender,voters) then skip
else s.proposal_counters[sender] := get_force(sender,s.proposal_counters) + 1n ;
new_store := set_add(sender,voters) var new_store : addr_set := set_empty;
}
| None -> block { // the message has never been received before
s.proposal_counters[sender] := get_force(sender,s.proposal_counters) + 1n ;
new_store := set [sender];
}
end ;
// check sender counters against the maximum number of proposal case map_get (packed_msg, s.message_store) of
var sender_proposal_counter : nat := get_force(sender,s.proposal_counters) ; Some (voters) ->
if sender_proposal_counter > s.max_proposal then failwith("Maximum number of proposal reached") block {
else skip ; (* The message is already stored.
Increment the counter only if the sender is not already
associated with the message. *)
if set_mem (sender, voters)
then skip
else s.proposal_counters[sender] :=
get_force (sender, s.proposal_counters) + 1n;
// check the threshold new_store := set_add(sender,voters)
var ret_ops : list(operation) := (nil : list(operation)) ; }
if size(new_store) >= s.threshold then block { | None ->
remove packed_msg from map s.message_store ; block {
ret_ops := message(s.state_hash) ; // the message has never been received before
// update the state hash s.proposal_counters[sender] :=
s.state_hash := sha_256 ( bytes_concat (s.state_hash , packed_msg) ) ; get_force (sender, s.proposal_counters) + 1n;
// decrement the counters new_store := set [sender]
for addr -> ctr in map s.proposal_counters block { }
if set_mem(addr,new_store) then end;
s.proposal_counters[addr] := abs (ctr - 1n)
else skip ;
}
} else
s.message_store[packed_msg] := new_store
} with ( ret_ops , s)
function withdraw (const param : withdraw_pt; const s : storage_t) : contract_return_t is block { // check sender counters against the maximum number of proposal
var message : message_t := param ; var sender_proposal_counter : nat :=
const packed_msg : bytes = bytes_pack(message) ; get_force (sender, s.proposal_counters);
case map_get(packed_msg, s.message_store) of if sender_proposal_counter > s.max_proposal
| Some(voters) -> block { // the message is stored then failwith ("Maximum number of proposal reached")
const new_set : addr_set_t = set_remove(sender,voters) ; else skip;
// decrement the counter only if the sender was already associated with the message // check the threshold
if size(voters) =/= size(new_set) then
s.proposal_counters[sender] := abs (get_force(sender,s.proposal_counters) - 1n)
else skip ;
// if the message is left without any associated addresses, remove the corresponding message_store field var ret_ops : list (operation) := nil;
if size(new_set) = 0n then remove packed_msg from map s.message_store
else s.message_store[packed_msg] := new_set
}
| None -> skip end // the message isn't stored, ignore
} with ( (nil: list(operation)) , s) if size (new_store) >= s.threshold then {
remove packed_msg from map s.message_store;
ret_ops := message (s.state_hash);
// update the state hash
s.state_hash := sha_256 (bytes_concat (s.state_hash, packed_msg));
// decrement the counters
for addr -> ctr in map s.proposal_counters block {
if set_mem(addr,new_store) then
s.proposal_counters[addr] := abs (ctr - 1n)
else skip
}
} else s.message_store[packed_msg] := new_store
} with (ret_ops, s)
function default (const p : default_pt; const s : storage_t) : contract_return_t is function withdraw (const param : withdraw_pt; const s : storage) : return is
((nil: list(operation)) , s) block {
var message : message := param;
const packed_msg : bytes = bytes_pack (message);
function main(const param : entry_point_t; const s : storage_t) : contract_return_t is case map_get(packed_msg, s.message_store) of
Some (voters) ->
block {
// The message is stored
const new_set : addr_set = set_remove (sender, voters);
(* Decrement the counter only if the sender was already
associated with the message *)
if size (voters) =/= size (new_set)
then s.proposal_counters[sender] :=
abs (get_force (sender, s.proposal_counters) - 1n)
else skip ;
(* If the message is left without any associated addresses,
remove the corresponding message_store field *)
if size (new_set) = 0n
then remove packed_msg from map s.message_store
else s.message_store[packed_msg] := new_set
}
| None -> skip
end // The message is not stored, ignore.
} with ((nil : list (operation)), s)
function default (const p : default_pt; const s : storage) : return is
((nil : list (operation)), s)
function main (const param : parameter; const s : storage) : return is
case param of case param of
// propagate message p if the number authorized addresses having (* Propagate message p if the number of authorized addresses having
// voted for the same message p equals the threshold voted for the same message p equals the threshold. *)
| Send (p) -> send(p,s) | Send (p) -> send (p, s)
// withraw vote for message p
| Withdraw (p) -> withdraw(p,s) (* Withraw vote for message p *)
// use this entry-point to transfer tez to the contract | Withdraw (p) -> withdraw (p, s)
| Default (p) -> default(p,s)
end (* Use this action to transfer tez to the contract *)
| Default (p) -> default (p, s)
end

View File

@ -1,62 +1,66 @@
// storage type // storage type
type counter_t is nat
type threshold_t is nat
type authorized_keys_t is list(key)
type id_t is string
type storage_t is record type counter is nat
id : id_t ; type threshold is nat
counter : counter_t ; type authorized_keys is list (key)
threshold : threshold_t ; type id is string
auth : authorized_keys_t ;
end type storage is
record [
id : id;
counter : counter;
threshold : threshold;
auth : authorized_keys
]
// I/O types // I/O types
type message_t is (unit -> list(operation))
type signatures_t is list(key_hash * signature)
type check_message_pt is record
counter : counter_t ;
message : message_t ;
signatures : signatures_t ;
end
type contract_return_t is (list(operation) * storage_t) type message is unit -> list (operation)
type entry_point_t is type signatures is list (key_hash * signature)
| CheckMessage of check_message_pt
type check_message_pt is
record [
counter : counter;
message : message;
signatures : signatures
]
type return is list (operation) * storage
type parameter is CheckMessage of check_message_pt
function check_message (const param : check_message_pt; function check_message (const param : check_message_pt;
const s : storage_t) : contract_return_t is block { const s : storage) : return is block {
var message : message_t := param.message ; var message : message := param.message;
if param.counter =/= s.counter then if param.counter =/= s.counter then
failwith ("Counters does not match") failwith ("Counters does not match")
else block { else {
const packed_payload : bytes = const packed_payload : bytes =
bytes_pack((message , param.counter , s.id , get_chain_id)); bytes_pack ((message, param.counter, s.id, get_chain_id));
var valid : nat := 0n ; var valid : nat := 0n;
var keys : authorized_keys_t := s.auth ; var keys : authorized_keys := s.auth;
for pkh_sig in list param.signatures block { for pkh_sig in list param.signatures block {
case keys of case keys of
| nil -> skip nil -> skip
| key # tl -> block { | key # tl -> block {
keys := tl ; keys := tl;
if pkh_sig.0 = crypto_hash_key(key) then if pkh_sig.0 = crypto_hash_key (key) then
if crypto_check(key,pkh_sig.1,packed_payload) then valid := valid + 1n ; if crypto_check (key, pkh_sig.1, packed_payload)
else failwith ("Invalid signature") then valid := valid + 1n
else skip; else failwith ("Invalid signature")
} else skip
}
end end
}; };
if valid < s.threshold then if valid < s.threshold then
failwith ("Not enough signatures passed the check") failwith ("Not enough signatures passed the check")
else s.counter := s.counter + 1n ; else s.counter := s.counter + 1n
} }
} with (message(unit), s) } with (message (unit), s)
function main(const param : entry_point_t; const s : storage_t) : contract_return_t is function main (const param : parameter; const s : storage) : return is
case param of case param of CheckMessage (p) -> check_message (p,s) end
| CheckMessage (p) -> check_message(p,s)
end