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:
Christian Rinderknecht 2020-01-08 20:58:26 +00:00
commit 9bdb0a63cd
36 changed files with 260 additions and 176 deletions

View File

@ -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

View File

@ -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);
};

View File

@ -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-->

View File

@ -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";

View File

@ -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 _ =

View File

@ -334,21 +334,22 @@ 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 ->
let (_ , loc) = r_split reg in
@ -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,71 +531,62 @@ 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%bind body =
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 ->
let vars = pt.value in
(match vars.pattern with
| PTuple vars ->
let let_in_binding: Raw.let_binding =
{binders = (PTuple vars, []) ;
lhs_type=None;
eq=Region.ghost;
let_rhs=(Raw.EVar {region=Region.ghost; value="#P"});
}
in
let let_in: Raw.let_in =
{kwd_let= Region.ghost;
binding= let_in_binding;
kwd_in= Region.ghost;
body= lamb.body;
}
in
ok (Raw.ELetIn
{
region=Region.ghost;
value=let_in
})
| Raw.PVar _ -> ok lamb.body
| _ -> ok lamb.body)
| _ -> ok lamb.body)
| _ -> ok lamb.body
in
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 body = simpl_expression body in
let rec layer_arguments (arguments: (Raw.variable * type_expression) list) =
match arguments with
| hd :: tl ->
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
match destruct with (* Handle tuple parameter destructuring *)
| Raw.PPar pp ->
(match pp.value.inside with
| Raw.PTyped pt ->
let vars = pt.value in
(match vars.pattern with
| PTuple vars ->
let let_in_binding: Raw.let_binding =
{binders = (PTuple vars, []) ;
lhs_type=None;
eq=Region.ghost;
let_rhs=(Raw.EVar {region=Region.ghost; value="#P"});
}
in
let let_in: Raw.let_in =
{kwd_let= Region.ghost;
binding= let_in_binding;
kwd_in= Region.ghost;
body= lamb.body;
}
in
ok (Raw.ELetIn
{
region=Region.ghost;
value=let_in
})
| Raw.PVar _ -> ok lamb.body
| _ -> ok lamb.body)
| _ -> ok lamb.body)
| _ -> ok lamb.body
in
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 (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
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
)
(Var.of_name (fst hd).value , snd hd) in
e_lambda ~loc (binder) (Some input_type) output_type (layer_arguments tl)
| [] -> body
in
return @@ layer_arguments params'
and simpl_logic_expression ?te_annot (t:Raw.logic_expr) : expr result =

View File

@ -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

View File

@ -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

View File

@ -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]);

View File

@ -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

View File

@ -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);

View File

@ -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)

View File

@ -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]);

View 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

View File

@ -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

View File

@ -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) -> ()) ()

View File

@ -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]);

View File

@ -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)

View File

@ -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]);

View File

@ -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

View File

@ -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]);

View File

@ -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 =

View File

@ -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);
};

View File

@ -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

View File

@ -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 =

View File

@ -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)

View File

@ -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]);

View File

@ -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

View File

@ -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]);

View File

@ -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

View File

@ -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]);

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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]);

View File

@ -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 ;