Merge branch 'rinderknecht@contracts' into 'dev'
First batch of rewritten contracts (PascaLIGO). See merge request ligolang/ligo!405
This commit is contained in:
commit
f10cb1616e
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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)
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -1,4 +1,4 @@
|
||||
function main (const i : int) : int is
|
||||
begin
|
||||
i := i + 1 ;
|
||||
end with i
|
||||
block {
|
||||
i := i + 1
|
||||
} with i
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -1,2 +1 @@
|
||||
function blockless (const n: int) : int is
|
||||
n + 10;
|
||||
function blockless (const n : int) : int is n + 10
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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))
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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))
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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"
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user