for loop have a optional step parameter

This commit is contained in:
Pierre-Emmanuel Wulfman 2020-04-09 19:17:51 +02:00
parent 23912411e1
commit 9796cd2e8f
11 changed files with 61 additions and 16 deletions

View File

@ -1117,7 +1117,7 @@ let%expect_test _ =
let%expect_test _ = let%expect_test _ =
run_ligo_bad [ "compile-contract" ; bad_contract "create_contract_toplevel.mligo" ; "main" ] ; run_ligo_bad [ "compile-contract" ; bad_contract "create_contract_toplevel.mligo" ; "main" ] ;
[%expect {| [%expect {|
ligo: in file "create_contract_toplevel.mligo", line 4, character 35 to line 8, character 8. No free variable allowed in this lambda: variable 'store' {"expression":"CREATE_CONTRACT(lambda (#P:Some(( nat * string ))) : None return\n let rhs#712 = #P in\n let p = rhs#712.0 in\n let s = rhs#712.1 in\n ( LIST_EMPTY() : (type_operator: list(operation)) , store ) ,\n NONE() : (type_operator: option(key_hash)) ,\n 300000000mutez ,\n \"un\")","location":"in file \"create_contract_toplevel.mligo\", line 4, character 35 to line 8, character 8"} ligo: in file "create_contract_toplevel.mligo", line 4, character 35 to line 8, character 8. No free variable allowed in this lambda: variable 'store' {"expression":"CREATE_CONTRACT(lambda (#P:Some(( nat * string ))) : None return\n let rhs#713 = #P in\n let p = rhs#713.0 in\n let s = rhs#713.1 in\n ( LIST_EMPTY() : (type_operator: list(operation)) , store ) ,\n NONE() : (type_operator: option(key_hash)) ,\n 300000000mutez ,\n \"un\")","location":"in file \"create_contract_toplevel.mligo\", line 4, character 35 to line 8, character 8"}
If you're not sure how to fix this error, you can If you're not sure how to fix this error, you can
@ -1130,7 +1130,7 @@ ligo: in file "create_contract_toplevel.mligo", line 4, character 35 to line 8,
run_ligo_bad [ "compile-contract" ; bad_contract "create_contract_var.mligo" ; "main" ] ; run_ligo_bad [ "compile-contract" ; bad_contract "create_contract_var.mligo" ; "main" ] ;
[%expect {| [%expect {|
ligo: in file "create_contract_var.mligo", line 6, character 35 to line 10, character 5. No free variable allowed in this lambda: variable 'a' {"expression":"CREATE_CONTRACT(lambda (#P:Some(( nat * int ))) : None return\n let rhs#715 = #P in\n let p = rhs#715.0 in\n let s = rhs#715.1 in\n ( LIST_EMPTY() : (type_operator: list(operation)) , a ) ,\n NONE() : (type_operator: option(key_hash)) ,\n 300000000mutez ,\n 1)","location":"in file \"create_contract_var.mligo\", line 6, character 35 to line 10, character 5"} ligo: in file "create_contract_var.mligo", line 6, character 35 to line 10, character 5. No free variable allowed in this lambda: variable 'a' {"expression":"CREATE_CONTRACT(lambda (#P:Some(( nat * int ))) : None return\n let rhs#716 = #P in\n let p = rhs#716.0 in\n let s = rhs#716.1 in\n ( LIST_EMPTY() : (type_operator: list(operation)) , a ) ,\n NONE() : (type_operator: option(key_hash)) ,\n 300000000mutez ,\n 1)","location":"in file \"create_contract_var.mligo\", line 6, character 35 to line 10, character 5"}
If you're not sure how to fix this error, you can If you're not sure how to fix this error, you can

View File

@ -13,7 +13,7 @@ let%expect_test _ =
(* list-declarations *) (* list-declarations *)
let%expect_test _ = let%expect_test _ =
run_ligo_good [ "list-declarations" ; "../../test/contracts/loop.ligo" ] ; run_ligo_good [ "list-declarations" ; "../../test/contracts/loop.ligo" ] ;
[%expect {| {"source_file":"../../test/contracts/loop.ligo","declarations":["inner_capture_in_conditional_block","dummy","nested_for_collection_local_var","nested_for_collection","for_collection_map_k","for_collection_map_kv","for_collection_empty","for_collection_with_patches","for_collection_comp_with_acc","for_collection_proc_call","for_collection_rhs_capture","for_collection_if_and_local_var","for_collection_set","for_collection_list","for_sum","while_sum","counter"]} |} ]; [%expect {| {"source_file":"../../test/contracts/loop.ligo","declarations":["inner_capture_in_conditional_block","dummy","nested_for_collection_local_var","nested_for_collection","for_collection_map_k","for_collection_map_kv","for_collection_empty","for_collection_with_patches","for_collection_comp_with_acc","for_collection_proc_call","for_collection_rhs_capture","for_collection_if_and_local_var","for_collection_set","for_collection_list","for_sum_step","for_sum","while_sum","counter"]} |} ];
run_ligo_good [ "list-declarations" ; "../../test/contracts/loop.mligo" ] ; run_ligo_good [ "list-declarations" ; "../../test/contracts/loop.mligo" ] ;
[%expect {| {"source_file":"../../test/contracts/loop.mligo","declarations":["counter_nest","aux_nest","counter","counter_simple","aux_simple"]} |} ]; [%expect {| {"source_file":"../../test/contracts/loop.mligo","declarations":["counter_nest","aux_nest","counter","counter_simple","aux_simple"]} |} ];

View File

@ -420,6 +420,8 @@ and for_int = {
assign : var_assign reg; assign : var_assign reg;
kwd_to : kwd_to; kwd_to : kwd_to;
bound : expr; bound : expr;
kwd_step : kwd_step option;
step : expr option;
block : block reg block : block reg
} }

View File

@ -105,6 +105,7 @@ type t =
| Remove of Region.t (* "remove" *) | Remove of Region.t (* "remove" *)
| Set of Region.t (* "set" *) | Set of Region.t (* "set" *)
| Skip of Region.t (* "skip" *) | Skip of Region.t (* "skip" *)
| Step of Region.t (* "step" *)
| Then of Region.t (* "then" *) | Then of Region.t (* "then" *)
| To of Region.t (* "to" *) | To of Region.t (* "to" *)
| True of Region.t (* "True" *) | True of Region.t (* "True" *)

View File

@ -103,6 +103,7 @@ type t =
| Remove of Region.t (* "remove" *) | Remove of Region.t (* "remove" *)
| Set of Region.t (* "set" *) | Set of Region.t (* "set" *)
| Skip of Region.t (* "skip" *) | Skip of Region.t (* "skip" *)
| Step of Region.t (* "step" *)
| Then of Region.t (* "then" *) | Then of Region.t (* "then" *)
| To of Region.t (* "to" *) | To of Region.t (* "to" *)
| True of Region.t (* "True" *) | True of Region.t (* "True" *)
@ -216,6 +217,7 @@ let proj_token = function
| Remove region -> region, "Remove" | Remove region -> region, "Remove"
| Set region -> region, "Set" | Set region -> region, "Set"
| Skip region -> region, "Skip" | Skip region -> region, "Skip"
| Step region -> region, "Step"
| Then region -> region, "Then" | Then region -> region, "Then"
| To region -> region, "To" | To region -> region, "To"
| True region -> region, "True" | True region -> region, "True"
@ -307,6 +309,7 @@ let to_lexeme = function
| Remove _ -> "remove" | Remove _ -> "remove"
| Set _ -> "set" | Set _ -> "set"
| Skip _ -> "skip" | Skip _ -> "skip"
| Step _ -> "step"
| Then _ -> "then" | Then _ -> "then"
| To _ -> "to" | To _ -> "to"
| True _ -> "True" | True _ -> "True"
@ -368,6 +371,7 @@ let keywords = [
(fun reg -> Remove reg); (fun reg -> Remove reg);
(fun reg -> Set reg); (fun reg -> Set reg);
(fun reg -> Skip reg); (fun reg -> Skip reg);
(fun reg -> Step reg);
(fun reg -> Then reg); (fun reg -> Then reg);
(fun reg -> To reg); (fun reg -> To reg);
(fun reg -> True reg); (fun reg -> True reg);
@ -605,6 +609,7 @@ let is_kwd = function
| Remove _ | Remove _
| Set _ | Set _
| Skip _ | Skip _
| Step _
| Then _ | Then _
| To _ | To _
| True _ | True _

View File

@ -74,6 +74,7 @@
%token <Region.t> Remove "remove" %token <Region.t> Remove "remove"
%token <Region.t> Set "set" %token <Region.t> Set "set"
%token <Region.t> Skip "skip" %token <Region.t> Skip "skip"
%token <Region.t> Step "step"
%token <Region.t> Then "then" %token <Region.t> Then "then"
%token <Region.t> To "to" %token <Region.t> To "to"
%token <Region.t> True "True" %token <Region.t> True "True"

View File

@ -627,9 +627,22 @@ for_loop:
assign = $2; assign = $2;
kwd_to = $3; kwd_to = $3;
bound = $4; bound = $4;
kwd_step = None;
step = None;
block = $5} block = $5}
in For (ForInt {region; value}) in For (ForInt {region; value})
} }
| "for" var_assign "to" expr "step" expr block {
let region = cover $1 $7.region in
let value = {kwd_for = $1;
assign = $2;
kwd_to = $3;
bound = $4;
kwd_step = Some $5;
step = Some $6;
block = $7}
in For (ForInt {region; value})
}
| "for" var arrow_clause? "in" collection expr block { | "for" var arrow_clause? "in" collection expr block {
Scoping.check_reserved_name $2; Scoping.check_reserved_name $2;
let region = cover $1 $7.region in let region = cover $1 $7.region in

View File

@ -392,11 +392,19 @@ and print_for_loop state = function
| ForCollect for_collect -> print_for_collect state for_collect | ForCollect for_collect -> print_for_collect state for_collect
and print_for_int state ({value; _} : for_int reg) = and print_for_int state ({value; _} : for_int reg) =
let {kwd_for; assign; kwd_to; bound; block} = value in let {kwd_for; assign; kwd_to; bound; kwd_step; step; block} = value in
print_token state kwd_for "for"; print_token state kwd_for "for";
print_var_assign state assign; print_var_assign state assign;
print_token state kwd_to "to"; print_token state kwd_to "to";
print_expr state bound; print_expr state bound;
match kwd_step with
| None -> ();
| Some kwd_step ->
print_token state kwd_step "step";
match step with
| None -> ();
| Some step ->
print_expr state step;
print_block state block print_block state block
and print_var_assign state {value; _} = and print_var_assign state {value; _} =

View File

@ -766,10 +766,12 @@ and compile_single_instruction : Raw.instruction -> (_ -> expression result) res
let binder = Var.of_name fi.assign.value.name.value in let binder = Var.of_name fi.assign.value.name.value in
let%bind start = compile_expression fi.assign.value.expr in let%bind start = compile_expression fi.assign.value.expr in
let%bind bound = compile_expression fi.bound in let%bind bound = compile_expression fi.bound in
let increment = e_int 1 in let%bind step = match fi.step with
| None -> ok @@ e_int 1
| Some step -> compile_expression step in
let%bind body = compile_block fi.block.value in let%bind body = compile_block fi.block.value in
let%bind body = body @@ None in let%bind body = body @@ None in
return_statement @@ e_for ~loc binder start bound increment body return_statement @@ e_for ~loc binder start bound step body
) )
| Loop (For (ForCollect fc)) -> | Loop (For (ForCollect fc)) ->
let (fc,loc) = r_split fc in let (fc,loc) = r_split fc in

View File

@ -27,6 +27,15 @@ function for_sum (var n : nat) : int is
} }
} with acc } with acc
function for_sum_step (var n : nat) : int is
block {
var acc : int := 0;
for i := 1 to int (2n*n) step 2
block {
acc := acc + i
}
} with acc
function for_collection_list (var nee : unit) : (int * string) is function for_collection_list (var nee : unit) : (int * string) is
block { block {
var acc : int := 0; var acc : int := 0;

View File

@ -1241,6 +1241,10 @@ let loop () : unit result =
let make_input = e_nat in let make_input = e_nat in
let make_expected = fun n -> e_int (n * (n + 1) / 2) in let make_expected = fun n -> e_int (n * (n + 1) / 2) in
expect_eq_n_pos_mid program "for_sum" make_input make_expected in expect_eq_n_pos_mid program "for_sum" make_input make_expected in
let%bind () =
let make_input = e_nat in
let make_expected = fun n -> e_int (n * n) in
expect_eq_n_pos_mid program "for_sum_step" make_input make_expected in
let input = e_unit () in let input = e_unit () in
let%bind () = let%bind () =
let expected = e_pair (e_int 3) (e_string "totototo") in let expected = e_pair (e_int 3) (e_string "totototo") in