Merge branch 'rinderknecht@contracts' into 'dev'

First batch of rewritten contracts (PascaLIGO).

See merge request ligolang/ligo!405
This commit is contained in:
Suzanne Dupéron 2020-02-10 19:35:22 +00:00
commit f10cb1616e
56 changed files with 866 additions and 899 deletions

View File

@ -1079,7 +1079,7 @@ let%expect_test _ =
let%expect_test _ =
run_ligo_bad [ "compile-contract" ; contract "bad_timestamp.ligo" ; "main" ] ;
[%expect {|
ligo: in file "bad_timestamp.ligo", line 5, characters 29-43. Badly formatted timestamp "badtimestamp": {"location":"in file \"bad_timestamp.ligo\", line 5, characters 29-43"}
ligo: in file "bad_timestamp.ligo", line 7, characters 30-44. Badly formatted timestamp "badtimestamp": {"location":"in file \"bad_timestamp.ligo\", line 7, characters 30-44"}
If you're not sure how to fix this error, you can

View File

@ -1153,9 +1153,7 @@ module Compiler = struct
| C_BYTES_PACK -> ok @@ simple_unary @@ prim I_PACK
| C_CONCAT -> ok @@ simple_binary @@ prim I_CONCAT
| C_CHAIN_ID -> ok @@ simple_constant @@ prim I_CHAIN_ID
| _ -> simple_fail @@ Format.asprintf "operator not implemented for %a" 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.

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 {
const c : contract(unit) = implicit_account(p) ;
} with address(c)
const c : contract (unit) = implicit_account (p);
} with address (c)

View File

@ -1,6 +1,6 @@
(* 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 =
("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address)

View File

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

View File

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

View File

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

View File

@ -1,19 +1,19 @@
const x : int = 1; attributes ["inline"]
function foo (const a : int) : int is
begin
block {
const test : int = 2 + a;
attributes ["inline"];
end with test;
} with test;
attributes ["inline"];
const y : int = 1; attributes ["inline"; "other"]
function bar (const b : int) : int is
begin
block {
function test (const z : int) : int is
begin
block {
const r : int = 2 + b + z
end with r;
} with r;
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 {
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 s is map(t)
type parameter is unit
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.
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 return is list (operation) * storage
function main (const p : unit; const s: tez) : list(operation) * storage is
((nil : list(operation)), balance)
function main (const param : parameter; const store: storage) : return is
((nil : list (operation)), balance)

View File

@ -1,36 +1,35 @@
type storage_ is big_map(int, int) * unit
type foo is big_map(int, int)
type parameter is unit
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 {
var toto : option (int) := Some(0);
var toto : option (int) := Some (0);
toto := s.0[23];
s.0[2] := 444;
s.0[2] := 444
}
with ((nil: list(operation)), s)
function set_ (var n : int ; var m : foo) : foo is block {
m[23] := n ;
type foo is big_map (int, int)
function set_ (var n : int; var m : foo) : foo is block {
m[23] := n
} with m
function rm (var m : foo) : foo is block {
remove 42 from map m;
remove 42 from map 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
23 -> 0 ;
42 -> 0 ;
end
const big_map1 : big_map (int,int) = big_map [23 -> 0; 42 -> 0]
function mutimaps (const m : foo ; const n : foo) : foo is block
{
var bar : foo := m ;
bar[42] := 0 ;
n[42] := get_force(42, bar) ;
function mutimaps (const m : foo; const n : foo) : foo is block {
var bar : foo := m;
bar[42] := 0;
n[42] := get_force (42, bar)
} with n

View File

@ -1,16 +1,11 @@
// Test PascaLIGO bitwise operators
function or_op (const n : nat) : nat is
bitwise_or(n , 4n)
function or_op (const n : nat) : nat is bitwise_or (n, 4n)
function and_op (const n : nat) : nat is
bitwise_and(n , 7n)
function and_op (const n : nat) : nat is bitwise_and (n, 7n)
function xor_op (const n : nat) : nat is
bitwise_xor(n , 7n)
function xor_op (const n : nat) : nat is bitwise_xor (n, 7n)
function lsl_op (const n : nat) : nat is
bitwise_lsl(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 lsr_op (const n : nat) : nat is bitwise_lsr (n, 7n)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,2 +1,4 @@
function check_signature (const pk: key; const signed: signature; const msg: bytes) : bool is
crypto_check(pk, signed, msg)
function check_signature (const pk : key;
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
block {
function bar (const j : int) : int is
i + j ;
} with bar (i)
function add (const j : int) : int is i+j
} with add (i)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,16 +1,10 @@
// Test if conditional in PascaLIGO
function main (const i : int) : int is
begin
var result : int := 23 ;
if i = 2 then
result := 42
else
result := 0
end with result
block {
var result : int := 23;
if i = 2 then result := 42 else result := 0
} with result
function foo (const b : bool) : int is
begin
var x : int := 41 ;
x := 1 + (if b then x else main(x)) ;
end with x
block {
const x : int = 41
} with 1 + (if b then x else main (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
block { skip } // skip is a do nothing instruction, needed for empty blocks
function main (const p : int ; const s : t) : list (operation) * int is
block {
skip
} // skip is a do nothing instruction, needed for empty blocks
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
function main (const i : int) : int is block {
const j : int = 42 ;
const j : int = 42
} with j

View File

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

View File

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

View File

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

View File

@ -1,9 +1,9 @@
type foo is
| Bar of int
| Baz
type t is
Bar of int
| Baz
function main (const f: foo) : int is
(case f of
| Bar (n) -> n
function main (const x : t) : int is
case x of
Bar (n) -> n
| 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 {
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 {
const c : contract(unit) =
case (get_entrypoint_opt("%cbo", a) : option(contract (unit))) of
| Some (c) -> c
const c : contract (unit) =
case (get_entrypoint_opt ("%cbo", a) : option (contract (unit))) of
Some (c) -> c
| None -> (failwith ("entrypoint not found") : contract (unit))
end
}
with (list transaction(unit, 0mutez, c) end, s)
} with (list [transaction(unit, 0mutez, c)], s)

View File

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

View File

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

View File

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

View File

@ -1,6 +1,3 @@
// Test a trivial PascaLIGO function
function main (const i : int) : int is
begin
skip
end with i
function main (const i : int) : int is 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 {
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 {
const c : contract(unit) =
case (get_contract_opt(source) : option(contract (unit))) of
| Some (c) -> c
const c : contract (unit) =
case (get_contract_opt (source) : option (contract (unit))) of
Some (c) -> c
| None -> (failwith ("contract not found") : contract (unit))
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
block { skip } with x.0 < y.0
function heap_elt_lt (const x : heap_elt;
const y : heap_elt) : bool is x.0 < y.0
#include "heap.ligo"

View File

@ -1,93 +1,95 @@
// Implementation of the heap data structure in PascaLIGO
// 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
block {skip} with size(h) = 0n
function is_empty (const h : heap) : bool is size (h) = 0n
function get_top (const h : heap) : heap_element is
block {skip} with get_force(1n, h)
function get_top (const h : heap) : heap_elt is get_force (1n, h)
function pop_switch (const h : heap) : heap is
block {
const result : heap_element = get_top (h) ;
const s : nat = size(h) ;
const last : heap_element = get_force(s, h) ;
remove 1n from map h ;
h[1n] := last ;
const result : heap_elt = get_top (h);
const s : nat = size (h);
const last : heap_elt = get_force (s, h);
remove 1n from map h;
h[1n] := last
} with h
function pop_ (const h : heap) : nat is
begin
const result : heap_element = get_top (h) ;
const s : nat = size(h) ;
var current : heap_element := get_force(s, h) ;
const i : nat = 1n ;
const left : nat = 2n * i ;
const right : nat = left + 1n ;
remove 1n from map h ;
h[1n] := current ;
var largest : nat := i ;
if (left <= s and heap_element_lt(get_force(s , h) , get_force(left , h))) then
largest := left
else if (right <= s and heap_element_lt(get_force(s , h) , get_force(right , h))) then
largest := right
block {
const result : heap_elt = get_top (h);
const s : nat = size (h);
var current : heap_elt := get_force (s, h);
const i : nat = 1n;
const left : nat = 2n * i;
const right : nat = left + 1n;
remove 1n from map h;
h[1n] := current;
var largest : nat := i;
const tmp : heap_elt = get_force (s, h);
if left <= s and heap_elt_lt (tmp, get_force (left,h))
then largest := left
else
if right <= s and heap_elt_lt (tmp, get_force (right,h))
then largest := right
else skip
end with largest
} with largest
function insert (const h : heap ; const e : heap_element) : heap is
begin
var i : nat := size(h) + 1n ;
h[i] := e ;
var largest : nat := i ;
var parent : nat := 0n ;
while (largest =/= i) block {
parent := i / 2n ;
largest := i ;
if (parent >= 1n) then block {
if (heap_element_lt(get_force(parent , h) , get_force(i , h))) then block {
largest := parent ;
const tmp : heap_element = get_force(i , h) ;
h[i] := get_force(parent , h) ;
h[parent] := tmp ;
function insert (const h : heap ; const e : heap_elt) : heap is
block {
var i : nat := size (h) + 1n;
h[i] := e;
var largest : nat := i;
var parent : nat := 0n;
while largest =/= i block {
parent := i/2n;
largest := i;
if parent >= 1n then {
if heap_elt_lt (get_force (parent,h), get_force(i,h))) then {
largest := parent;
const tmp : heap_elt = get_force (i,h);
h[i] := get_force(parent, h);
h[parent] := tmp
} else skip
} else skip
}
end with h
} with h
function pop (const h : heap) : (heap * heap_element * nat) is
begin
const result : heap_element = get_top (h) ;
var s : nat := size(h) ;
const last : heap_element = get_force(s, h) ;
remove s from map h ;
h[1n] := last ;
s := size(h) ;
var i : nat := 0n ;
var largest : nat := 1n ;
var left : nat := 0n ;
var right : nat := 0n ;
var c : nat := 0n ;
while (largest =/= i) block {
c := c + 1n ;
i := largest ;
left := 2n * i ;
right := left + 1n ;
if (left <= s) then begin
if (heap_element_lt(get_force(left , h) , get_force(i , h))) then begin
largest := left ;
const tmp : heap_element = get_force(i , h) ;
h[i] := get_force(left , h) ;
h[left] := tmp ;
end else skip ;
end else if (right <= s) then begin
if (heap_element_lt(get_force(right , h) , get_force(i , h))) then begin
largest := right ;
const tmp : heap_element = get_force(i , h) ;
h[i] := get_force(right , h) ;
h[left] := tmp ;
end else skip ;
end else skip ;
function pop (const h : heap) : heap * heap_elt * nat is
block {
const result : heap_elt = get_top (h);
var s : nat := size (h);
const last : heap_elt = get_force (s,h);
remove s from map h;
h[1n] := last;
s := size (h);
var i : nat := 0n;
var largest : nat := 1n;
var left : nat := 0n;
var right : nat := 0n;
var c : nat := 0n;
while largest =/= i block {
c := c + 1n;
i := largest;
left := 2n * i;
right := left + 1n;
if left <= s then {
if heap_elt_lt (get_force (left,h), get_force(i,h)) then {
largest := left;
const tmp : heap_elt = get_force(i,h);
h[i] := get_force (left, h);
h[left] := tmp
} else skip
}
end with (h , result , c)
else
if right <= s then {
if heap_elt_lt (get_force (right, h), get_force (i,h)) then {
largest := right;
const tmp : heap_elt = get_force (i,h);
h[i] := get_force (right, h);
h[left] := tmp
} else skip
} 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
begin
block {
function foo (const i : int) : int is 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
function higher2(const i : int; const f : int -> int): int is
begin
const ii: int = f (i)
end with ii
function higher2 (const i : int; const f : int -> int): int is f (i)
function foobar2 (const i : int) : int is
begin
block {
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
begin
block {
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
@ -29,17 +29,15 @@ function g (const i : int) : int is f (i)
function foobar4 (const i : int) : int is g (g (i))
function higher3(const i : int; const f : int -> int; const g : int -> int)
: int is
begin
const ii : int = f(g(i))
end with ii
function higher3 (const i : int;
const f : int -> int;
const g : int -> int) : int is f (g (i))
function foobar5 (const i : int) : int is
begin
block {
const a : int = 0;
function foo (const i : int) : int is a+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

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
block {skip} with is_nat(i)
function main (const i : int) : option (nat) is 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 {
var ret : bool := False ;
var kh2 : key_hash := crypto_hash_key(k2) ;
if kh1 = kh2 then ret := True else skip;
} with (ret, kh2)
function check_hash_key (const kh1 : key_hash;
const k2 : key) : bool * key_hash is
block {
var ret : bool := False;
var kh2 : key_hash := crypto_hash_key (k2);
if kh1 = kh2 then ret := True else skip
} with (ret, kh2)

View File

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

View File

@ -1,49 +1,33 @@
// Test list type and related built-in functions in PascaLIGO
type foobar is list(int)
type foobar is list (int)
const fb : foobar = list
23 ;
42 ;
end
const fb : foobar = list [23; 42]
const fb2 : foobar = 144 # fb
const fb3 : foobar = cons(688 , fb2)
const fb3 : foobar = cons (688, fb2)
function size_ (const m : foobar) : nat is
block {skip} with (size(m))
function size_ (const m : foobar) : nat is 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
144 ;
51 ;
42 ;
120 ;
421 ;
end
const bl : foobar = list [144; 51; 42; 120; 421]
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
function fold_op (const s : list (int)) : int is
block {
function increment (const i : int) : int is block { skip } with i + 1
} with list_map(increment, s)
function aggregate (const prec: int; const cur: int) : int is prec+cur
} 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
function counter (var n : nat) : nat is block {
var i : nat := 0n ;
function counter (var n : nat) : nat is
block {
var i : nat := 0n;
while i < n block {
i := i + 1n
}
} with i
function while_sum (var n : nat) : nat is
block {
var i : nat := 0n;
var r : nat := 0n;
while i < n block {
i := i + 1n;
r := r + i
}
} with i
} with r
function while_sum (var n : nat) : nat is block {
var i : nat := 0n ;
var r : nat := 0n ;
while i < n block {
i := i + 1n;
r := r + i;
function for_sum (var n : nat) : int is
block {
var acc : int := 0;
for i := 1 to int (n)
block {
acc := acc + i
}
} with r
} with acc
function for_sum (var n : nat) : int is block {
var acc : int := 0 ;
for i := 1 to int(n)
begin
acc := acc + i;
end
} with acc
function for_collection_list (var nee : unit) : (int * string) is block {
function for_collection_list (var nee : unit) : (int * string) is
block {
var acc : int := 0;
var st : string := "to";
var mylist : list(int) := list 1; 1; 1 end;
var mylist : list (int) := list [1; 1; 1];
for x in list mylist
begin
block {
acc := acc + x;
st := st ^ "to";
end
} with (acc, st)
st := st ^ "to"
}
} with (acc, st)
function for_collection_set (var nee : unit) : (int * string) is block {
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 end;
for x in set myset
begin
acc := acc + x ;
st := st^"to" ;
end
} with (acc, st)
var myset : set (int) := set [1; 2; 3];
for x in set myset block {
acc := acc + x;
st := st ^ "to"
}
} with (acc, st)
function for_collection_if_and_local_var (var nee : unit) : int is block {
var acc : int := 0 ;
const theone : int = 1 ;
var myset : set(int) := set 1 ; 2 ; 3 end ;
for x in set myset
begin
const thetwo : int = 2 ;
if x=theone then
acc := acc + x
else if x=thetwo then
acc := acc + thetwo;
else
acc := acc + 10;
end
} with acc
function for_collection_if_and_local_var (var nee : unit) : int is
block {
var acc : int := 0;
const theone : int = 1;
var myset : set (int) := set [1; 2; 3];
for x in set myset block {
const thetwo : int = 2;
if x = theone then acc := acc + x
else if x = thetwo then acc := acc + thetwo
else acc := acc + 10
}
} with acc
function for_collection_rhs_capture (var nee : unit) : int is block {
var acc : int := 0 ;
const mybigint : int = 1000 ;
var myset : set(int) := set 1 ; 2 ; 3 end ;
for x in set myset
begin
if x=1 then acc := acc + mybigint;
else acc := acc + 10;
end
} with acc
function for_collection_rhs_capture (var nee : unit) : int is
block {
var acc : int := 0;
const mybigint : int = 1000;
var myset : set (int) := set [1; 2; 3];
for x in set myset block {
if x = 1 then acc := acc + mybigint
else acc := acc + 10
}
} with acc
function for_collection_proc_call (var nee : unit) : int is block {
var acc : int := 0 ;
var myset : set(int) := set 1 ; 2 ; 3 end ;
for x in set myset
begin
if x=1 then
acc := acc + for_collection_rhs_capture(unit);
else
acc := acc + 10;
end
} with acc
function for_collection_proc_call (var nee : unit) : int is
block {
var acc : int := 0;
var myset : set (int) := set [1; 2; 3];
for x in set myset block {
if x = 1 then
acc := acc + for_collection_rhs_capture (unit)
else acc := acc + 10
}
} 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
function for_collection_comp_with_acc (var nee : unit) : int is
block {
var myint : int := 0;
var mylist : list (int) := list [1; 10; 15];
for x in list mylist block {
if x < myint then skip;
else myint := myint + 10
end
} with myint
}
} with myint
function for_collection_with_patches (var nee : unit) : map(string,int) is block {
var myint : int := 12 ;
var mylist : list(string) := list "I"; "am"; "foo" end;
var mymap : map(string,int) := map end;
for x in list mylist
begin
patch mymap with map [x -> myint];
end
} with mymap
function for_collection_with_patches (var nee : unit) : map (string,int) is
block {
var myint : int := 12;
var mylist : list (string) := list ["I"; "am"; "foo"];
var mymap : map (string,int) := map [];
for x in list mylist block {
patch mymap with map [x -> myint]
}
} with mymap
function for_collection_empty (var nee : unit) : int is block {
var acc : int := 0 ;
var myset : set(int) := set 1; 2; 3 end;
for x in set myset
begin
function for_collection_empty (var nee : unit) : int is
block {
var acc : int := 0;
var myset : set(int) := set [1; 2; 3];
for x in set myset block {
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
block {
var acc : int := 0;
var st : string := "";
var mymap : map(string,int) := map "1" -> 1; "2" -> 2; "3" -> 3 end;
for k -> v in map mymap
begin
var mymap : map (string, int) := map ["1" -> 1; "2" -> 2; "3" -> 3];
for k -> v in map mymap block {
acc := acc + v;
st := st ^ k;
end
} with (acc, st)
}
} with (acc, st)
function for_collection_map_k (var nee : unit) : string is block {
var st : string := "" ;
var mymap : map(string,int) := map "1" -> 1 ; "2" -> 2 ; "3" -> 3 end ;
for k in map mymap
begin
st := st ^ k;
end
} with st
function for_collection_map_k (var nee : unit) : string is
block {
var st : string := "";
var mymap : map (string, int) := map ["1" -> 1; "2" -> 2; "3" -> 3];
for k in map mymap block {
st := st ^ k
}
} with st
function nested_for_collection (var nee : unit) : (int*string) is block {
function nested_for_collection (var nee : unit) : int * string is
block {
var myint : int := 0;
var mystoo : string := "";
var mylist : list(int) := list 1 ; 2 ; 3 end ;
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
begin
myint := myint + i ;
var myset : set(string) := set "1" ; "2" ; "3" end ;
for st in set myset
begin
myint := myint + i ;
mystoo := mystoo ^ st ;
for k -> v in map mymap
begin
mystoo := mystoo ^ k ^ v ;
end
end
end
} with (myint,mystoo)
function nested_for_collection_local_var (var nee : unit) : (int*string) is block {
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)
var mylist : list (int) := list [1; 2; 3];
for i in list mylist block {
var myst_loc : string := "";
myint := myint + i;
var myset : set (string) := set ["1"; "2"; "3"];
for st in set myset block {
myint := myint + i;
myst_loc := myst_loc ^ st;
};
myst := myst_loc ^ myst
}
} with (myint, myst)
function dummy (const n : nat) : nat is block {
while False block { skip }
} with n
function inner_capture_in_conditional_block (var nee : unit) : bool*int is block {
var count : int := 1 ;
var ret : bool := False ;
var mylist : list(int) := list 1 ; 2 ; 3 end ;
function inner_capture_in_conditional_block (var nee : unit) : bool * int is
block {
var count : int := 1;
var ret : bool := False;
var mylist : list (int) := list [1; 2; 3];
for it1 in list mylist block {
for it2 in list mylist block {
if count = it2 then ret := not (ret)
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
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
144 -> 23 ;
51 -> 23 ;
42 -> 23 ;
120 -> 23 ;
421 -> 23 ;
end
const map2 : foobar = map
23 -> 0 ;
42 -> 0 ;
end
const map1 : foobar = map [
144 -> 23;
51 -> 23;
42 -> 23;
120 -> 23;
421 -> 23]
function set_ (var n : int ; var m : foobar) : foobar is block {
m[23] := n ;
const map2 : foobar = map [23 -> 0; 42 -> 0]
function set_ (var n : int; var m : foobar) : foobar is block {
m[23] := n
} with m
@ -25,50 +22,43 @@ function rm (var m : foobar) : foobar is block {
remove 42 from map 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]
} with m
function patch_deep (var m: foobar * nat) : foobar * nat is
begin patch m.0 with map [1 -> 9]; end with m
function patch_deep (var m : foobar * nat) : foobar * nat is
block { patch m.0 with map [1 -> 9] } with m
function size_ (const m : foobar) : nat is
block {skip} with (size(m))
function size_ (const m : foobar) : nat is 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
begin
skip
end with m[42]
function get (const m : foobar) : option (int) is m[42]
function get_ (const m : foobar) : option(int) is
begin
skip
end with map_get(42 , m)
function get_ (const m : foobar) : option (int) is 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
block {
function aggregate (const i : int ; const j : int) : unit is block
{ if (i=j) then skip else failwith("fail") } with unit ;
// map_iter(m , aggregate) ;
} with map_iter(aggregate, m) ;
function aggregate (const i : int; const j : int) : unit is block
{ if i=j then skip else failwith ("fail") } with unit
} with map_iter (aggregate, m)
function map_op (const m : foobar) : foobar is
block {
function increment (const i : int ; const j : int) : int is block { skip } with j + 1 ;
} with map_map(increment, m) ;
function increment (const i : int; const j : int) : int is j+1
} with map_map (increment, m)
function fold_op (const m : foobar) : int is
block {
function aggregate (const i : int ; const j : (int * int)) : int is block { skip } with i + j.0 + j.1 ;
} with map_fold(aggregate, m , 10)
function aggregate (const i : int; const j : int * int) : int is
i + j.0 + j.1
} with map_fold(aggregate, m, 10)
function deep_op (var m : foobar) : foobar is
block {
var coco : (int*foobar) := (0, m);
remove 42 from map coco.1 ;
coco.1[32] := 16 ;
var coco : int * foobar := (0, m);
remove 42 from map coco.1;
coco.1[32] := 16
} with coco.1

View File

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

View File

@ -1,10 +1,14 @@
// Test functions with several parameters in PascaLIGO
function ab(const a : int; const b : int) : int is
begin skip end with (a + b)
function ab (const a : int; const b : int) : int is a+b
function abcd(const a : int; const b : int; const c : int; const d : int) : int is
begin skip end with (a + b + c + d + 2)
function abcd (const a : int;
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
begin skip end with (c + e + 3)
function abcde (const a : int;
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
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
state_hash : state_hash_t ;
threshold : threshold_t ;
max_proposal : max_proposal_t ;
max_message_size : max_message_size_t ;
authorized_addresses : addr_set_t ;
message_store : message_store_t ;
proposal_counters : proposal_counters_t ;
end
type threshold is nat
type max_proposal is nat
type max_message_size is nat
type state_hash is bytes
type addr_set is set (address)
type message_store is map (bytes, addr_set)
type proposal_counters is map (address, nat)
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
type message_t is (bytes -> list(operation))
type send_pt is message_t
type withdraw_pt is message_t
type message is bytes -> list (operation)
type send_pt is message
type withdraw_pt is message
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
| Send of send_pt
type parameter is
Send of send_pt
| Withdraw of withdraw_pt
| Default of default_pt
function send (const param : send_pt; const s : storage_t) : contract_return_t is block {
function send (const param : send_pt; const s : storage) : return is
block {
// check sender against the authorized addresses
if not set_mem(sender,s.authorized_addresses) then failwith("Unauthorized address") else skip ;
if not set_mem (sender, s.authorized_addresses)
then failwith("Unauthorized address")
else skip;
// check message size against the stored limit
var message : message_t := param ;
const packed_msg : bytes = bytes_pack(message) ;
if size(packed_msg) > s.max_message_size then failwith("Message size exceed maximum limit")
else skip ;
// compute the new set of addresses associated with the message and update counters
var new_store : addr_set_t := set_empty ;
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 ;
var message : message := param;
const packed_msg : bytes = bytes_pack (message);
if size (packed_msg) > s.max_message_size
then failwith ("Message size exceed maximum limit")
else skip;
(* compute the new set of addresses associated with the message and
update counters *)
var new_store : addr_set := set_empty;
case map_get (packed_msg, s.message_store) of
Some (voters) ->
block {
(* 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;
new_store := set_add(sender,voters)
}
| None -> block { // the message has never been received before
s.proposal_counters[sender] := get_force(sender,s.proposal_counters) + 1n ;
new_store := set [sender];
| 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 ;
end;
// check sender counters against the maximum number of proposal
var sender_proposal_counter : nat := get_force(sender,s.proposal_counters) ;
if sender_proposal_counter > s.max_proposal then failwith("Maximum number of proposal reached")
else skip ;
var sender_proposal_counter : nat :=
get_force (sender, s.proposal_counters);
if sender_proposal_counter > s.max_proposal
then failwith ("Maximum number of proposal reached")
else skip;
// check the threshold
var ret_ops : list(operation) := (nil : list(operation)) ;
if size(new_store) >= s.threshold then block {
remove packed_msg from map s.message_store ;
ret_ops := message(s.state_hash) ;
var ret_ops : list (operation) := nil;
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) ) ;
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 skip
}
} else
s.message_store[packed_msg] := new_store
} else s.message_store[packed_msg] := new_store
} with (ret_ops, s)
} with ( ret_ops , s)
function withdraw (const param : withdraw_pt; const s : storage_t) : contract_return_t is block {
var message : message_t := param ;
const packed_msg : bytes = bytes_pack(message) ;
function withdraw (const param : withdraw_pt; const s : storage) : return is
block {
var message : message := param;
const packed_msg : bytes = bytes_pack (message);
case map_get(packed_msg, s.message_store) of
| Some(voters) -> block { // the message is stored
const new_set : addr_set_t = set_remove(sender,voters) ;
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)
(* 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
(* 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 isn't stored, ignore
| None -> skip
end // The message is not stored, ignore.
} with ((nil : list (operation)), s)
} with ( (nil: list(operation)) , s)
function default (const p : default_pt; const s : storage) : return is
((nil : list (operation)), s)
function default (const p : default_pt; const s : storage_t) : contract_return_t is
((nil: list(operation)) , 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
// propagate message p if the number authorized addresses having
// voted for the same message p equals the threshold
| Send (p) -> send(p,s)
// withraw vote for message p
| Withdraw (p) -> withdraw(p,s)
// use this entry-point to transfer tez to the contract
| Default (p) -> default(p,s)
end
(* Propagate message p if the number of authorized addresses having
voted for the same message p equals the threshold. *)
| Send (p) -> send (p, s)
(* Withraw vote for message p *)
| Withdraw (p) -> withdraw (p, s)
(* Use this action to transfer tez to the contract *)
| Default (p) -> default (p, s)
end

View File

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