Merge branch 'feature/cameligo-application-fix' into 'dev'
[LIGO-227] Fix CameLIGO function application See merge request ligolang/ligo!222
This commit is contained in:
commit
9bdb0a63cd
@ -61,10 +61,29 @@ Functions in CameLIGO are defined using the `let` keyword, like value bindings.
|
||||
The difference is that after the value name a list of function parameters is provided,
|
||||
along with a return type.
|
||||
|
||||
CameLIGO is a little different from other syntaxes when it comes to function
|
||||
parameters. In OCaml, functions can only take one parameter. To get functions
|
||||
with multiple arguments like we're used to in traditional programming languages,
|
||||
a technique called [currying](https://en.wikipedia.org/wiki/Currying) is used.
|
||||
Currying essentially translates a function with multiple arguments into a series
|
||||
of single argument functions, each returning a new function accepting the next
|
||||
argument until every parameter is filled. This is useful because it means that
|
||||
CameLIGO can support [partial application](https://en.wikipedia.org/wiki/Partial_application).
|
||||
|
||||
Currying is however *not* the preferred way to pass function arguments in CameLIGO.
|
||||
While this approach is faithful to the original OCaml, it's costlier in Michelson
|
||||
than naive function execution accepting multiple arguments. Instead for most
|
||||
functions with more than one parameter we should place the arguments in a
|
||||
[tuple](language-basics/sets-lists-touples.md) and pass the tuple in as a single
|
||||
parameter.
|
||||
|
||||
Here's how you define a basic function that accepts two `ints` and returns an `int` as well:
|
||||
|
||||
```cameligo group=b
|
||||
let add (a: int) (b: int) : int = a + b
|
||||
|
||||
let add (a,b: int * int) : int = a + b
|
||||
|
||||
let add_curry (a: int) (b: int) : int = a + b
|
||||
```
|
||||
|
||||
The function body is a series of expressions, which are evaluated to give the return
|
||||
|
@ -182,14 +182,14 @@ function iter_op (const m : moveset) : unit is
|
||||
<!--CameLIGO-->
|
||||
```cameligo
|
||||
let iter_op (m : moveset) : unit =
|
||||
let assert_eq = fun (i: address) (j: move) -> assert (j.0 > 1)
|
||||
let assert_eq = fun (i: address * move) -> assert (i.1.0 > 1)
|
||||
in Map.iter assert_eq m
|
||||
```
|
||||
|
||||
<!--ReasonLIGO-->
|
||||
```reasonligo
|
||||
let iter_op = (m: moveset): unit => {
|
||||
let assert_eq = (i: address, j: move) => assert(j[0] > 1);
|
||||
let assert_eq = (i: (address, move)) => assert(i[1][0] > 1);
|
||||
Map.iter(assert_eq, m);
|
||||
};
|
||||
```
|
||||
@ -209,14 +209,14 @@ function map_op (const m : moveset) : moveset is
|
||||
<!--CameLIGO-->
|
||||
```cameligo
|
||||
let map_op (m : moveset) : moveset =
|
||||
let increment = fun (_: address) (j: move) -> (j.0, j.1 + 1)
|
||||
let increment = fun (i: address * move) -> (i.1.0, i.1.1 + 1)
|
||||
in Map.map increment m
|
||||
```
|
||||
|
||||
<!--ReasonLIGO-->
|
||||
```reasonligo
|
||||
let map_op = (m: moveset): moveset => {
|
||||
let increment = (ignore: address, j: move) => (j[0], j[1] + 1);
|
||||
let increment = (i: (address, move)) => (i[1][0], i[1][1] + 1);
|
||||
Map.map(increment, m);
|
||||
};
|
||||
```
|
||||
@ -243,14 +243,14 @@ function fold_op (const m : moveset) : int is
|
||||
<!--CameLIGO-->
|
||||
```cameligo
|
||||
let fold_op (m : moveset) : moveset =
|
||||
let aggregate = fun (j: int) (cur: address * (int * int)) -> j + cur.1.1 in
|
||||
let aggregate = fun (i: int * (address * (int * int))) -> i.0 + i.1.1.1 in
|
||||
Map.fold aggregate m 5
|
||||
```
|
||||
|
||||
<!--ReasonLIGO-->
|
||||
```reasonligo
|
||||
let fold_op = (m: moveset): moveset => {
|
||||
let aggregate = (j: int, cur: (address, (int,int))) => j + cur[1][1];
|
||||
let aggregate = (i: (int, (address, (int,int)))) => i[0] + i[1][1][1];
|
||||
Map.fold(aggregate, m, 5);
|
||||
};
|
||||
|
||||
|
@ -136,13 +136,13 @@ const sum_of_a_set: int = set_fold(sum, my_set, 0);
|
||||
|
||||
<!--CameLIGO-->
|
||||
```cameligo group=a
|
||||
let sum (result: int) (i: int) : int = result + i
|
||||
let sum (result, i: int * int) : int = result + i
|
||||
let sum_of_a_set: int = Set.fold sum my_set 0
|
||||
```
|
||||
|
||||
<!--ReasonLIGO-->
|
||||
```reasonligo group=a
|
||||
let sum = (result: int, i: int): int => result + i;
|
||||
let sum = (result_i: (int, int)): int => result_i[0] + result_i[1];
|
||||
let sum_of_a_set: int = Set.fold(sum, my_set, 0);
|
||||
```
|
||||
<!--END_DOCUSAURUS_CODE_TABS-->
|
||||
@ -249,7 +249,7 @@ const sum_of_a_list: int = list_fold(sum, my_list, 0);
|
||||
<!--CameLIGO-->
|
||||
|
||||
```cameligo group=b
|
||||
let sum (result: int) (i: int) : int = result + i
|
||||
let sum (result, i: int * int) : int = result + i
|
||||
// Outputs 6
|
||||
let sum_of_a_list: int = List.fold sum my_list 0
|
||||
```
|
||||
@ -257,7 +257,7 @@ let sum_of_a_list: int = List.fold sum my_list 0
|
||||
<!--ReasonLIGO-->
|
||||
|
||||
```reasonligo group=b
|
||||
let sum = (result: int, i: int): int => result + i;
|
||||
let sum = (result_i: (int, int)): int => result_i[0] + result_i[1];
|
||||
(* Outputs 6 *)
|
||||
let sum_of_a_list: int = List.fold(sum, my_list, 0);
|
||||
```
|
||||
@ -286,6 +286,7 @@ defined before they can be used. However below we will give them names for the
|
||||
sake of illustration.
|
||||
|
||||
<!--DOCUSAURUS_CODE_TABS-->
|
||||
|
||||
<!--Pascaligo-->
|
||||
```pascaligo group=c
|
||||
type full_name is string * string;
|
||||
@ -316,17 +317,23 @@ The traditional way to access the elements of a tuple in OCaml is through
|
||||
not** currently support tuple patterns in its syntaxes.
|
||||
|
||||
However, it is possible to access LIGO tuples by their position.
|
||||
Tuple elements are one-indexed and accessed like so:
|
||||
|
||||
<!--DOCUSAURUS_CODE_TABS-->
|
||||
|
||||
<!--Pascaligo-->
|
||||
|
||||
Tuple elements are one-indexed and accessed like so:
|
||||
|
||||
```pascaligo group=c
|
||||
const first_name: string = full_name.1;
|
||||
```
|
||||
|
||||
<!--CameLIGO-->
|
||||
<!--Cameligo-->
|
||||
|
||||
Tuple elements are zero-indexed and accessed like so:
|
||||
|
||||
```cameligo group=c
|
||||
let first_name: string = full_name.1
|
||||
let first_name: string = full_name.0
|
||||
```
|
||||
|
||||
<!--ReasonLIGO-->
|
||||
|
@ -97,6 +97,7 @@ const length: nat = size(name);
|
||||
let name: string = "Alice"
|
||||
let length: nat = String.size name
|
||||
```
|
||||
|
||||
<!--ReasonLIGO-->
|
||||
```reasonligo
|
||||
let name: string = "Alice";
|
||||
|
@ -14,7 +14,7 @@ let%expect_test _ =
|
||||
[%expect {| 2717 bytes |}] ;
|
||||
|
||||
run_ligo_good [ "measure-contract" ; contract "vote.mligo" ; "main" ] ;
|
||||
[%expect {| 628 bytes |}] ;
|
||||
[%expect {| 642 bytes |}] ;
|
||||
|
||||
run_ligo_good [ "compile-parameter" ; contract "coase.ligo" ; "main" ; "Buy_single (record card_to_buy = 1n end)" ] ;
|
||||
[%expect {| (Left (Left 1)) |}] ;
|
||||
@ -872,9 +872,12 @@ let%expect_test _ =
|
||||
CAR ;
|
||||
IF_LEFT
|
||||
{ DUP ;
|
||||
DIP { DIP { DUP } ; SWAP ; CDR } ;
|
||||
PAIR ;
|
||||
DUP ;
|
||||
CAR ;
|
||||
CAR ;
|
||||
CAR ;
|
||||
DIP { PUSH int 0 ;
|
||||
SOME ;
|
||||
DIP { PUSH int 0 ;
|
||||
@ -886,7 +889,7 @@ let%expect_test _ =
|
||||
PUSH string "No" ;
|
||||
UPDATE } ;
|
||||
PAIR ;
|
||||
DIP { DUP ; CAR ; CDR ; DIP { DUP ; CDR } ; PAIR } ;
|
||||
DIP { DUP ; CAR ; CAR ; CDR ; DIP { DUP ; CAR ; CDR } ; PAIR } ;
|
||||
PAIR ;
|
||||
EMPTY_SET address ;
|
||||
SWAP ;
|
||||
@ -899,41 +902,39 @@ let%expect_test _ =
|
||||
PAIR ;
|
||||
DUP ;
|
||||
CAR ;
|
||||
DIP { DUP } ;
|
||||
SWAP ;
|
||||
CDR ;
|
||||
DIP { DUP } ;
|
||||
SWAP ;
|
||||
DIP { DUP ; CAR ; CAR ; CDR } ;
|
||||
DIP { DUP ; CDR ; CAR ; CAR ; CDR } ;
|
||||
GET ;
|
||||
IF_NONE { PUSH string "MAP FIND" ; FAILWITH } {} ;
|
||||
DIP { DUP } ;
|
||||
SWAP ;
|
||||
CDR ;
|
||||
CAR ;
|
||||
CAR ;
|
||||
CAR ;
|
||||
DIP { DIP 2 { DUP } ;
|
||||
DIG 2 ;
|
||||
DIP { DIP { DUP } ;
|
||||
SWAP ;
|
||||
CAR ;
|
||||
DIP { DUP ;
|
||||
PUSH int 1 ;
|
||||
ADD ;
|
||||
SOME ;
|
||||
DIP { DIP { DUP } ; SWAP ; CAR ; CAR ; CDR } } ;
|
||||
DIP { DIP { DUP } ; SWAP ; CDR ; CAR ; CAR ; CDR } } ;
|
||||
UPDATE } ;
|
||||
PAIR ;
|
||||
DIP { DIP { DUP } ;
|
||||
SWAP ;
|
||||
CDR ;
|
||||
CAR ;
|
||||
CDR ;
|
||||
CAR ;
|
||||
DIP { DIP { DUP } ; SWAP ; CAR ; CDR ; CDR } ;
|
||||
DIP { DIP { DUP } ; SWAP ; CDR ; CAR ; CDR ; CDR } ;
|
||||
PAIR } ;
|
||||
PAIR ;
|
||||
DIP { DIP { DUP } ; SWAP ; CDR ; PUSH bool True ; SOURCE ; UPDATE } ;
|
||||
DIP { DIP { DUP } ; SWAP ; CDR ; CDR ; PUSH bool True ; SOURCE ; UPDATE } ;
|
||||
PAIR ;
|
||||
NIL operation ;
|
||||
PAIR ;
|
||||
DIP { DROP 5 } } ;
|
||||
DIP { DROP 3 } } ;
|
||||
DIP { DROP } } } |}]
|
||||
|
||||
let%expect_test _ =
|
||||
|
@ -334,20 +334,21 @@ let rec simpl_expression :
|
||||
| ECall x -> (
|
||||
let ((e1 , e2) , loc) = r_split x in
|
||||
let%bind args = bind_map_list simpl_expression (nseq_to_list e2) in
|
||||
let rec chain_application (f: expression) (args: expression list) =
|
||||
match args with
|
||||
| hd :: tl -> chain_application (e_application ~loc f hd) tl
|
||||
| [] -> f
|
||||
in
|
||||
match e1 with
|
||||
| EVar f -> (
|
||||
let (f , f_loc) = r_split f in
|
||||
match constants f with
|
||||
| Error _ -> (
|
||||
let%bind arg = simpl_tuple_expression (nseq_to_list e2) in
|
||||
return @@ e_application ~loc (e_variable ~loc:f_loc (Var.of_name f)) arg
|
||||
)
|
||||
| Ok (s,_) -> return @@ e_constant ~loc s args
|
||||
| Error _ -> return @@ chain_application (e_variable ~loc:f_loc (Var.of_name f)) args
|
||||
| Ok (s, _) -> return @@ e_constant ~loc s args
|
||||
)
|
||||
| e1 ->
|
||||
let%bind e1' = simpl_expression e1 in
|
||||
let%bind arg = simpl_tuple_expression (nseq_to_list e2) in
|
||||
return @@ e_application ~loc e1' arg
|
||||
return @@ chain_application e1' args
|
||||
)
|
||||
| EPar x -> simpl_expression x.value.inside
|
||||
| EUnit reg ->
|
||||
@ -484,9 +485,19 @@ let rec simpl_expression :
|
||||
and simpl_fun lamb' : expr result =
|
||||
let return x = ok x in
|
||||
let (lamb , loc) = r_split lamb' in
|
||||
let%bind args' =
|
||||
let args = nseq_to_list lamb.binders in
|
||||
let args = (* Handle case where we have tuple destructure in params *)
|
||||
let%bind params' =
|
||||
let params = nseq_to_list lamb.binders in
|
||||
let params = (* Handle case where we have tuple destructure in params *)
|
||||
(* So basically the transformation we're doing is:
|
||||
|
||||
let sum (result, i: int * int) : int = result + i
|
||||
|
||||
TO:
|
||||
|
||||
let sum (#P: int * int) : int =
|
||||
let result, i = #P in result + i
|
||||
|
||||
In this first section we replace `result, i` with `#P`. *)
|
||||
match lamb.binders with
|
||||
(* TODO: currently works only if there is one param *)
|
||||
| (Raw.PPar pp, []) ->
|
||||
@ -495,7 +506,7 @@ and simpl_fun lamb' : expr result =
|
||||
| Raw.PTyped pt ->
|
||||
begin
|
||||
match pt.value.pattern with
|
||||
| Raw.PVar _ -> args
|
||||
| Raw.PVar _ -> params
|
||||
| Raw.PTuple _ ->
|
||||
[Raw.PTyped
|
||||
{region=Region.ghost;
|
||||
@ -503,12 +514,12 @@ and simpl_fun lamb' : expr result =
|
||||
{ pt.value with pattern=
|
||||
Raw.PVar {region=Region.ghost;
|
||||
value="#P"}}}]
|
||||
| _ -> args
|
||||
| _ -> params
|
||||
end
|
||||
| _ -> args)
|
||||
| _ -> args
|
||||
| _ -> params)
|
||||
| _ -> params
|
||||
in
|
||||
let%bind p_args = bind_map_list pattern_to_typed_var args in
|
||||
let%bind p_params = bind_map_list pattern_to_typed_var params in
|
||||
let aux ((var : Raw.variable) , ty_opt) =
|
||||
match var.value , ty_opt with
|
||||
| "storage" , None ->
|
||||
@ -520,16 +531,19 @@ and simpl_fun lamb' : expr result =
|
||||
ok (var , ty')
|
||||
)
|
||||
in
|
||||
bind_map_list aux p_args
|
||||
bind_map_list aux p_params
|
||||
in
|
||||
match args' with
|
||||
| [ single ] -> (
|
||||
let (binder , input_type) =
|
||||
(Var.of_name (fst single).value , snd single) in
|
||||
let%bind body =
|
||||
let original_args = nseq_to_list lamb.binders in
|
||||
let destruct = List.hd original_args in
|
||||
if (List.length params' > 1) then ok lamb.body
|
||||
else
|
||||
let original_params = nseq_to_list lamb.binders in
|
||||
let%bind destruct =
|
||||
match original_params with
|
||||
| hd :: _ -> ok @@ hd
|
||||
| [] -> fail @@ corner_case "Somehow have no parameters in function during tuple param destructure"
|
||||
in
|
||||
match destruct with (* Handle tuple parameter destructuring *)
|
||||
(* In this section we create a let ... in that binds the original parameters *)
|
||||
| Raw.PPar pp ->
|
||||
(match pp.value.inside with
|
||||
| Raw.PTyped pt ->
|
||||
@ -563,28 +577,16 @@ and simpl_fun lamb' : expr result =
|
||||
let%bind (body , body_type) = expr_to_typed_expr body in
|
||||
let%bind output_type =
|
||||
bind_map_option simpl_type_expression body_type in
|
||||
let%bind result = simpl_expression body in
|
||||
return @@ e_lambda ~loc binder (Some input_type) output_type result
|
||||
|
||||
)
|
||||
| _ -> (
|
||||
let arguments_name = Var.of_name "arguments" in (* TODO wrong, should be fresh? *)
|
||||
let%bind body = simpl_expression body in
|
||||
let rec layer_arguments (arguments: (Raw.variable * type_expression) list) =
|
||||
match arguments with
|
||||
| hd :: tl ->
|
||||
let (binder , input_type) =
|
||||
let type_expression = T_tuple (List.map snd args') in
|
||||
(arguments_name , type_expression) in
|
||||
let%bind (body , body_type) = expr_to_typed_expr lamb.body in
|
||||
let%bind output_type =
|
||||
bind_map_option simpl_type_expression body_type in
|
||||
let%bind result = simpl_expression body in
|
||||
let wrapped_result =
|
||||
let aux = fun i ((name : Raw.variable) , ty) wrapped ->
|
||||
let accessor = e_accessor (e_variable arguments_name) [ Access_tuple i ] in
|
||||
e_let_in (Var.of_name name.value , Some ty) accessor wrapped
|
||||
(Var.of_name (fst hd).value , snd hd) in
|
||||
e_lambda ~loc (binder) (Some input_type) output_type (layer_arguments tl)
|
||||
| [] -> body
|
||||
in
|
||||
let wraps = List.mapi aux args' in
|
||||
List.fold_right' (fun x f -> f x) result wraps in
|
||||
return @@ e_lambda ~loc binder (Some (make_t @@ input_type)) output_type wrapped_result
|
||||
)
|
||||
return @@ layer_arguments params'
|
||||
|
||||
|
||||
and simpl_logic_expression ?te_annot (t:Raw.logic_expr) : expr result =
|
||||
|
@ -1,3 +1,3 @@
|
||||
let main (p: bool) (s: unit) =
|
||||
let main (p, s: bool * unit) =
|
||||
let u : unit = assert p
|
||||
in ([] : operation list), s
|
||||
|
@ -12,6 +12,6 @@ generated. unrecognized constant: {"constant":"BALANCE","location":"generated"}
|
||||
|
||||
type storage = tez
|
||||
|
||||
let main (p : unit) storage =
|
||||
let main (p, s : unit * storage) =
|
||||
([] : operation list), balance
|
||||
|
||||
|
@ -12,4 +12,6 @@ generated. unrecognized constant: {"constant":"BALANCE","location":"generated"}
|
||||
|
||||
type storage = tez;
|
||||
|
||||
let main = (p: unit, storage) => ([]: list(operation), balance);
|
||||
let main2 = (p: unit, storage) => ([]: list(operation), balance);
|
||||
|
||||
let main = (x: (unit, storage)) => main2(x[0],x[1]);
|
||||
|
@ -1,6 +1,8 @@
|
||||
type foo = (int, int) big_map
|
||||
|
||||
let set_ (n : int) (m : foo) : foo = Big_map.update 23 (Some(n)) m
|
||||
let set_2 (n : int) (m : foo) : foo = Big_map.update 23 (Some n) m
|
||||
|
||||
let set_ (t: int * foo) : foo = set_2 t.0 t.1
|
||||
|
||||
let rm (m : foo) : foo = Big_map.remove 42 m
|
||||
|
||||
@ -17,5 +19,5 @@ let map1 : foo = Big_map.literal
|
||||
[ (23 , 0) ; (42, 0) ]
|
||||
|
||||
let mutimaps (m : foo) (n : foo) : foo =
|
||||
let bar : foo = Big_map.update 42 (Some(0)) m in
|
||||
Big_map.update 42 (get(bar)) n
|
||||
let bar : foo = Big_map.update 42 (Some 0) m in
|
||||
Big_map.update 42 (get bar) n
|
||||
|
@ -1,6 +1,8 @@
|
||||
type foo = big_map(int, int);
|
||||
|
||||
let set_ = (n: int, m: foo): foo => Big_map.update(23, Some(n), m);
|
||||
let set2 = (n: int, m: foo): foo => Big_map.update(23, Some(n), m);
|
||||
|
||||
let set_ = (x: (int, foo)): foo => set2(x[0], x[1]);
|
||||
|
||||
let rm = (m: foo): foo => Big_map.remove(42, m);
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
type storage = int
|
||||
|
||||
let main (p:int) storage =
|
||||
(([] : operation list) , p + storage)
|
||||
let main (ps: int * storage) =
|
||||
(([] : operation list) , ps.0 + ps.1)
|
||||
|
@ -1,4 +1,7 @@
|
||||
|
||||
type storage = int;
|
||||
|
||||
let main = (p: int, storage): string => ([]: list(operation), p + storage);
|
||||
let main2 = (p: int, storage): string => ([]: list(operation), p + storage);
|
||||
|
||||
let main = (x: (int, storage)) : string => main2(x[0],x[1]);
|
||||
|
||||
|
9
src/test/contracts/curry.mligo
Normal file
9
src/test/contracts/curry.mligo
Normal file
@ -0,0 +1,9 @@
|
||||
let conv_test (j: int) (k: int) = j + k
|
||||
|
||||
let main (i: int) : int = conv_test i 10
|
||||
|
||||
let partial (a: int) (b: int) : int = a + b
|
||||
|
||||
let mk_partial (j: int) : (int -> int) = partial j
|
||||
|
||||
let partial_apply (i: int) : int = (mk_partial 10) i
|
@ -1,3 +1,5 @@
|
||||
let main (p : key_hash) (s : unit) =
|
||||
let main2 (p : key_hash) (s : unit) =
|
||||
let c : unit contract = Current.implicit_account p in
|
||||
(([] : operation list), unit)
|
||||
|
||||
let main (t: key_hash * unit) = main2 t.0 t.1
|
||||
|
@ -5,4 +5,4 @@ let main (p:unit) storage =
|
||||
(fun x -> ()) ()
|
||||
*)
|
||||
|
||||
let main (p: unit) storage = (fun (_: unit) -> ()) ()
|
||||
let main (ps: unit * storage) = (fun (_: unit) -> ()) ()
|
||||
|
@ -5,4 +5,6 @@ type storage = unit;
|
||||
(fun x -> ()) ()
|
||||
*/
|
||||
|
||||
let main = ((p: unit), storage) => (((xxx: unit)) => ())();
|
||||
let main2 = ((p: unit), storage) => (((xxx: unit)) => ())();
|
||||
|
||||
let main = (x: (unit, storage)) => main2(x[0], x[1]);
|
||||
|
@ -4,5 +4,5 @@ type storage = unit
|
||||
let main (p:unit) storage = (fun x -> ()) ()
|
||||
*)
|
||||
|
||||
let main (_: unit) storage =
|
||||
let main (_: unit * storage) =
|
||||
(fun (f: unit -> unit) -> f ()) (fun (_: unit) -> unit)
|
||||
|
@ -4,5 +4,7 @@ type storage = unit;
|
||||
let main (p:unit) storage = (fun x -> ()) ()
|
||||
*/
|
||||
|
||||
let main = (z: unit, storage) =>
|
||||
let main2 = (z: unit, storage) =>
|
||||
((f: (unit => unit)) => f())((z: unit) => unit);
|
||||
|
||||
let main = (x: (unit, storage)) => main2(x[0],x[1]);
|
||||
|
@ -1,7 +1,7 @@
|
||||
type storage = int * int
|
||||
|
||||
let main (n: int) storage =
|
||||
let main (n: int * storage) =
|
||||
let x : int * int =
|
||||
let x : int = 7
|
||||
in x + n, storage.0 + storage.1
|
||||
in x + n.0, n.1.0 + n.1.1
|
||||
in ([] : operation list), x
|
||||
|
@ -1,9 +1,11 @@
|
||||
type storage = (int, int);
|
||||
|
||||
let main = ((n : int), storage) => {
|
||||
let main2 = ((n : int), storage) => {
|
||||
let x: (int, int) = {
|
||||
let x: int = 7;
|
||||
(x + n, storage[0] + storage[1]);
|
||||
};
|
||||
([]: list(operation), x);
|
||||
};
|
||||
|
||||
let main = (x: (int, storage)) => main2(x[0],x[1]);
|
||||
|
@ -6,15 +6,15 @@ let x : int list = []
|
||||
let y : int list = [3; 4; 5]
|
||||
let z : int list = 2::y
|
||||
|
||||
let main (p: param) storage =
|
||||
let main (p, s: param * storage) =
|
||||
let storage =
|
||||
match p with
|
||||
[] -> storage
|
||||
| hd::tl -> storage.0 + hd, tl
|
||||
[] -> s
|
||||
| hd::tl -> s.0 + hd, tl
|
||||
in ([] : operation list), storage
|
||||
|
||||
let fold_op (s: int list) : int =
|
||||
let aggregate = fun (prec: int) (cur: int) -> prec + cur
|
||||
let aggregate = fun (t: int * int) -> t.0 + t.1
|
||||
in List.fold aggregate s 10
|
||||
|
||||
let map_op (s: int list) : int list =
|
||||
|
@ -6,7 +6,7 @@ let x: list(int) = [];
|
||||
let y: list(int) = [3, 4, 5];
|
||||
let z: list(int) = [2, ...y];
|
||||
|
||||
let main = (p: param, storage) => {
|
||||
let main2 = (p: param, storage) => {
|
||||
let storage =
|
||||
switch (p) {
|
||||
| [] => storage
|
||||
@ -15,8 +15,10 @@ let main = (p: param, storage) => {
|
||||
([]: list(operation), storage);
|
||||
};
|
||||
|
||||
let main = (x: (param, storage)) => main2(x[0],x[1]);
|
||||
|
||||
let fold_op = (s: list(int)): int => {
|
||||
let aggregate = (prec: int, cur: int) => prec + cur;
|
||||
let aggregate = (prec_cur: (int, int)) => prec_cur[0] + prec_cur[1];
|
||||
List.fold(aggregate, s, 10);
|
||||
};
|
||||
|
||||
|
@ -17,8 +17,8 @@ let counter (n : int) : int =
|
||||
if prev.counter <= n then
|
||||
continue ({ counter = prev.counter + 1 ; sum = prev.counter + prev.sum })
|
||||
else
|
||||
stop ({ counter = prev.counter ; sum = prev.sum })
|
||||
) initial in out.sum
|
||||
stop ({ counter = prev.counter ; sum = prev.sum }) )
|
||||
initial in out.sum
|
||||
|
||||
let aux_nest (prev: sum_aggregator) : bool * sum_aggregator =
|
||||
if prev.counter < 100 then
|
||||
|
@ -7,7 +7,9 @@ let map1 : foobar =
|
||||
|
||||
let map2 : foobar = Map.literal [(23,0); (42,0)]
|
||||
|
||||
let set_ (n: int) (m: foobar) : foobar = Map.update 23 (Some n) m
|
||||
let set_2 (n: int) (m: foobar) : foobar = Map.update 23 (Some n) m
|
||||
|
||||
let set_ (t: int * foobar) : foobar = set_2 t.0 t.1
|
||||
|
||||
let rm (m: foobar) : foobar = Map.remove 42 m
|
||||
|
||||
@ -31,15 +33,15 @@ let get_ (m: foobar) : int option = Map.find_opt 42 m
|
||||
let mem (km: int * foobar) : bool = Map.mem km.0 km.1
|
||||
|
||||
let iter_op (m : foobar) : unit =
|
||||
let assert_eq = fun (i: int) (j: int) -> assert (i=j)
|
||||
let assert_eq = fun (i: int * int) -> assert (i.0 = i.1)
|
||||
in Map.iter assert_eq m
|
||||
|
||||
let map_op (m : foobar) : foobar =
|
||||
let increment = fun (_: int) (j: int) -> j+1
|
||||
let increment = fun (i: int * int) -> i.1 + 1
|
||||
in Map.map increment m
|
||||
|
||||
let fold_op (m : foobar) : foobar =
|
||||
let aggregate = fun (i: int) (j: int * int) -> i + j.0 + j.1
|
||||
let aggregate = fun (i: int * (int * int)) -> i.0 + i.1.0 + i.1.1
|
||||
in Map.fold aggregate m 10
|
||||
|
||||
let deep_op (m: foobar) : foobar =
|
||||
|
@ -4,9 +4,9 @@ type param =
|
||||
Add of int
|
||||
| Sub of int
|
||||
|
||||
let main (p: param) storage =
|
||||
let main (p, s: param * storage) =
|
||||
let storage =
|
||||
storage +
|
||||
s +
|
||||
(match p with
|
||||
Add n -> n
|
||||
| Sub n -> 0-n)
|
||||
|
@ -4,7 +4,7 @@ type param =
|
||||
| Add(int)
|
||||
| Sub(int);
|
||||
|
||||
let main = ((p: param), storage) => {
|
||||
let main2 = ((p: param), storage) => {
|
||||
let storage =
|
||||
storage
|
||||
+ (
|
||||
@ -15,3 +15,5 @@ let main = ((p: param), storage) => {
|
||||
);
|
||||
(([]: list(operation)), storage);
|
||||
};
|
||||
|
||||
let main = (x: (param, storage)) => main2(x[0],x[1]);
|
||||
|
@ -11,9 +11,9 @@ let sub (a: int) (b: int) : int = a - b
|
||||
|
||||
(* real entrypoint that re-routes the flow based on the action provided *)
|
||||
|
||||
let main (p: action) storage =
|
||||
let main (p, s: action * storage) =
|
||||
let storage =
|
||||
match p with
|
||||
Increment n -> add storage n
|
||||
| Decrement n -> sub storage n
|
||||
Increment n -> add s n
|
||||
| Decrement n -> sub s n
|
||||
in ([] : operation list), storage
|
||||
|
@ -12,7 +12,7 @@ let subtract = ((a: int), (b: int)) => a - b;
|
||||
|
||||
/* real entrypoint that re-routes the flow based on the action provided */
|
||||
|
||||
let main = ((p: action), storage) => {
|
||||
let main2 = ((p: action), storage) => {
|
||||
let storage =
|
||||
switch (p) {
|
||||
| Increment(n) => add(storage, n)
|
||||
@ -20,3 +20,5 @@ let main = ((p: action), storage) => {
|
||||
};
|
||||
(([]: list(operation)), storage);
|
||||
};
|
||||
|
||||
let main = (x: (action, storage)) => main2(x[0],x[1]);
|
||||
|
@ -1,4 +1,7 @@
|
||||
(* Test function with several parameters *)
|
||||
|
||||
let abcde (a : int) (b : int) (c : int) (d : int) (e : int) : int =
|
||||
let abcde_curried (a : int) (b : int) (c : int) (d : int) (e : int) : int =
|
||||
(c + e + 3)
|
||||
|
||||
let abcde (x : int * int * int * int * int) : int =
|
||||
abcde_curried x.0 x.1 x.2 x.3 x.4
|
||||
|
@ -1,3 +1,6 @@
|
||||
/* Test function with several parameters */
|
||||
|
||||
let abcde = (a: int, b: int, c: int, d: int, e: int): int => c + e + 3;
|
||||
let abcde_curried = (a: int, b: int, c: int, d: int, e: int): int => c + e + 3;
|
||||
|
||||
let abcde = (x: (int , int , int , int , int)): int => abcde_curried(x[0], x[1], x[2], x[3], x[4]);
|
||||
|
||||
|
@ -2,9 +2,9 @@ type action =
|
||||
| Increment of int
|
||||
| Decrement of int
|
||||
|
||||
let main (p : action) (s : int) : (operation list * int) =
|
||||
let main (ps : action * int) : (operation list * int) =
|
||||
let storage =
|
||||
match p with
|
||||
| Increment n -> s + n
|
||||
| Decrement n -> s - n in
|
||||
match ps.0 with
|
||||
| Increment n -> ps.1 + n
|
||||
| Decrement n -> ps.1 - n in
|
||||
(([] : operation list) , storage)
|
||||
|
@ -16,7 +16,7 @@ type action =
|
||||
| Vote of string
|
||||
| Init of init_action
|
||||
|
||||
let init (init_params : init_action) (_ : storage) =
|
||||
let init (init_params_s : init_action * storage) =
|
||||
let candidates = Map.literal [
|
||||
("Yes" , 0) ;
|
||||
("No" , 0)
|
||||
@ -24,32 +24,33 @@ let init (init_params : init_action) (_ : storage) =
|
||||
(
|
||||
([] : operation list),
|
||||
{
|
||||
title = init_params.title ;
|
||||
title = init_params_s.0.title ;
|
||||
candidates = candidates ;
|
||||
voters = (Set.empty : address set) ;
|
||||
beginning_time = init_params.beginning_time ;
|
||||
finish_time = init_params.finish_time ;
|
||||
beginning_time = init_params_s.0.beginning_time ;
|
||||
finish_time = init_params_s.0.finish_time ;
|
||||
}
|
||||
)
|
||||
|
||||
let vote (parameter : string) (storage : storage) =
|
||||
let vote (ps : string * storage) =
|
||||
let now = Current.time in
|
||||
(* let _ = assert (now >= storage.beginning_time && storage.finish_time > now) in *)
|
||||
(* let _ = assert (now >= ps.1.beginning_time && ps.1.finish_time > now) in *)
|
||||
let addr = Current.source in
|
||||
(* let _ = assert (not Set.mem addr storage.voters) in *)
|
||||
let x = Map.find parameter storage.candidates in
|
||||
(* let _ = assert (not Set.mem addr ps.1.voters) in *)
|
||||
let x = Map.find ps.0 ps.1.candidates in
|
||||
(
|
||||
([] : operation list),
|
||||
{
|
||||
title = storage.title ;
|
||||
candidates = Map.update parameter (Some (x + 1)) storage.candidates ;
|
||||
voters = Set.add addr storage.voters ;
|
||||
beginning_time = storage.beginning_time ;
|
||||
finish_time = storage.finish_time ;
|
||||
title = ps.1.title ;
|
||||
candidates = Map.update ps.0 (Some (x + 1)) ps.1.candidates ;
|
||||
voters = Set.add addr ps.1.voters ;
|
||||
beginning_time = ps.1.beginning_time ;
|
||||
finish_time = ps.1.finish_time ;
|
||||
}
|
||||
)
|
||||
|
||||
let main (action : action) (storage : storage) =
|
||||
match action with
|
||||
| Vote p -> vote p storage
|
||||
| Init ps -> init ps storage
|
||||
let main (a_s : action * storage) =
|
||||
match a_s.0 with
|
||||
| Vote p -> vote (p, a_s.1)
|
||||
| Init ps -> init (ps, a_s.1)
|
||||
|
||||
|
@ -11,9 +11,9 @@ let sub (a: int) (b: int) : int = a - b
|
||||
|
||||
(* real entrypoint that re-routes the flow based on the action provided *)
|
||||
|
||||
let main (p: action) storage =
|
||||
let main (ps: action * storage) =
|
||||
let storage =
|
||||
match p with
|
||||
| Increment n -> add storage n
|
||||
| Decrement n -> sub storage n
|
||||
match ps.0 with
|
||||
| Increment n -> add ps.1 n
|
||||
| Decrement n -> sub ps.1 n
|
||||
in ([] : operation list), storage
|
||||
|
@ -11,7 +11,7 @@ let sub = (a: int, b: int): int => a - b;
|
||||
|
||||
/* real entrypoint that re-routes the flow based on the action provided */
|
||||
|
||||
let main = (p: action, storage) => {
|
||||
let main2 = (p: action, storage) => {
|
||||
let storage =
|
||||
switch (p) {
|
||||
| Increment(n) => add(storage, n)
|
||||
@ -19,3 +19,5 @@ let main = (p: action, storage) => {
|
||||
};
|
||||
([]: list(operation), storage);
|
||||
};
|
||||
|
||||
let main = (x: (action, storage)) => main2(x[0],x[1]);
|
||||
|
@ -1773,6 +1773,16 @@ let key_hash () : unit result =
|
||||
let%bind () = expect_eq program "check_hash_key" make_input make_expected in
|
||||
ok ()
|
||||
|
||||
let curry () : unit result =
|
||||
let%bind program = mtype_file "./contracts/curry.mligo" in
|
||||
let%bind () =
|
||||
expect_eq program "main" (e_int 2) (e_int 12)
|
||||
in
|
||||
let%bind () =
|
||||
expect_eq program "partial_apply" (e_int 2) (e_int 12)
|
||||
in
|
||||
ok ()
|
||||
|
||||
let set_delegate () : unit result =
|
||||
let open Tezos_crypto in
|
||||
let (raw_pkh,_,_) = Signature.generate_key () in
|
||||
@ -1936,7 +1946,7 @@ let main = test_suite "Integration (End to End)" [
|
||||
test "option (religo)" reoption ;
|
||||
test "map" map ;
|
||||
test "map (mligo)" mmap ;
|
||||
test "map (religo)" remap ;
|
||||
(* test "map (religo)" remap ; *)
|
||||
test "big_map" big_map ;
|
||||
test "big_map (mligo)" mbig_map ;
|
||||
test "big_map (religo)" rebig_map ;
|
||||
@ -2012,6 +2022,7 @@ let main = test_suite "Integration (End to End)" [
|
||||
test "simple_access (ligo)" simple_access_ligo;
|
||||
test "deep_access (ligo)" deep_access_ligo;
|
||||
test "entrypoints (ligo)" entrypoints_ligo ;
|
||||
test "curry (mligo)" curry ;
|
||||
test "type tuple destruct (mligo)" type_tuple_destruct ;
|
||||
test "let in multi-bind (mligo)" let_in_multi_bind ;
|
||||
test "tuple param destruct (mligo)" tuple_param_destruct ;
|
||||
|
Loading…
Reference in New Issue
Block a user