Merge branch 'nested-collect-loop-issue' into 'dev'

Fix issue with nested collection loop where inner loop iterated elements were...

See merge request ligolang/ligo!199
This commit is contained in:
Rémi Lesenechal 2019-11-18 14:37:21 +00:00
commit ef25bcddaa
3 changed files with 21 additions and 15 deletions

View File

@ -990,8 +990,8 @@ and simpl_for_int : Raw.for_int -> (_ -> expression result) result = fun fi ->
record st = st; acc = acc; end; record st = st; acc = acc; end;
lamby = fun arguments -> ( lamby = fun arguments -> (
let #COMPILER#acc = arguments.0 in let #COMPILER#acc = arguments.0 in
let #COMPILER#elt = arguments.1 in let #COMPILER#elt_x = arguments.1 in
#COMPILER#acc.myint := #COMPILER#acc.myint + #COMPILER#elt ; #COMPILER#acc.myint := #COMPILER#acc.myint + #COMPILER#elt_x ;
#COMPILER#acc.myst := #COMPILER#acc.myst ^ "to" ; #COMPILER#acc.myst := #COMPILER#acc.myst ^ "to" ;
#COMPILER#acc #COMPILER#acc
) )
@ -1013,7 +1013,7 @@ and simpl_for_int : Raw.for_int -> (_ -> expression result) result = fun fi ->
that were already renamed in the inner loop. that were already renamed in the inner loop.
e.g : e.g :
``` ```
#COMPILER#acc.myint := #COMPILER#acc.myint + #COMPILER#elt ; #COMPILER#acc.myint := #COMPILER#acc.myint + #COMPILER#elt_x ;
#COMPILER#acc.myst := #COMPILER#acc.myst ^ "to" ; #COMPILER#acc.myst := #COMPILER#acc.myst ^ "to" ;
``` ```
They must not be considered as free variables They must not be considered as free variables
@ -1026,10 +1026,10 @@ and simpl_for_int : Raw.for_int -> (_ -> expression result) result = fun fi ->
- free variable of name X as rhs ==> accessor `#COMPILER#acc.X` - free variable of name X as rhs ==> accessor `#COMPILER#acc.X`
- free variable of name X as lhs ==> accessor `#COMPILER#acc.X` - free variable of name X as lhs ==> accessor `#COMPILER#acc.X`
And, in the case of a map: And, in the case of a map:
- references to the iterated key ==> variable `#COMPILER#elt_key` - references to the iterated key ==> variable `#COMPILER#elt_K`
- references to the iterated value ==> variable `#COMPILER#elt_value` - references to the iterated value ==> variable `#COMPILER#elt_V`
in the case of a set/list: in the case of a set/list:
- references to the iterated value ==> variable `#COMPILER#elt` - references to the iterated value ==> variable `#COMPILER#elt_X`
Note: In the case of an inner loop capturing variable from an outer loop Note: In the case of an inner loop capturing variable from an outer loop
the free variable name can be `#COMPILER#acc.Y` and because we do not the free variable name can be `#COMPILER#acc.Y` and because we do not
capture the accumulator record in the inner loop, we don't want to capture the accumulator record in the inner loop, we don't want to
@ -1043,10 +1043,11 @@ and simpl_for_int : Raw.for_int -> (_ -> expression result) result = fun fi ->
tuple holding: tuple holding:
* In the case of `list` or ̀set`: * In the case of `list` or ̀set`:
( folding record , current list/set element ) as ( folding record , current list/set element ) as
( #COMPILER#acc , #COMPILER#elt ) ( #COMPILER#acc , #COMPILER#elt_X )
* In the case of `map`: * In the case of `map`:
( folding record , current map key , current map value ) as ( folding record , current map key , current map value ) as
( #COMPILER#acc , #COMPILER#elt_key , #COMPILER#elt_value ) ( #COMPILER#acc , #COMPILER#elt_K , #COMPILER#elt_V )
Note: X , K and V above have to be replaced with their given name
7) Build the lambda using the final body of (6) 7) Build the lambda using the final body of (6)
@ -1059,6 +1060,10 @@ and simpl_for_int : Raw.for_int -> (_ -> expression result) result = fun fi ->
**) **)
and simpl_for_collect : Raw.for_collect -> (_ -> expression result) result = fun fc -> and simpl_for_collect : Raw.for_collect -> (_ -> expression result) result = fun fc ->
let elt_name = "#COMPILER#elt_"^fc.var.value in
let elt_v_name = match fc.bind_to with
| Some v -> "#COMPILER#elt"^(snd v).value
| None -> "#COMPILER#elt_unused" in
(* STEP 1 *) (* STEP 1 *)
let%bind for_body = simpl_block fc.block.value in let%bind for_body = simpl_block fc.block.value in
let%bind for_body = for_body None in let%bind for_body = for_body None in
@ -1095,13 +1100,13 @@ and simpl_for_collect : Raw.for_collect -> (_ -> expression result) result = fun
else match fc.collection with else match fc.collection with
(* loop on map *) (* loop on map *)
| Map _ -> | Map _ ->
let k' = e_variable "#COMPILER#collec_elt_k" in let k' = e_variable elt_name in
if ( name = fc.var.value ) then if ( name = fc.var.value ) then
ok @@ k' (* replace references to the the key *) ok @@ k' (* replace references to the the key *)
else ( else (
match fc.bind_to with match fc.bind_to with
| Some (_,v) -> | Some (_,v) ->
let v' = e_variable "#COMPILER#collec_elt_v" in let v' = e_variable elt_v_name in
if ( name = v.value ) then if ( name = v.value ) then
ok @@ v' (* replace references to the the value *) ok @@ v' (* replace references to the the value *)
else ok @@ exp else ok @@ exp
@ -1111,7 +1116,7 @@ and simpl_for_collect : Raw.for_collect -> (_ -> expression result) result = fun
| (Set _ | List _) -> | (Set _ | List _) ->
if (name = fc.var.value ) then if (name = fc.var.value ) then
(* replace references to the collection element *) (* replace references to the collection element *)
ok @@ (e_variable "#COMPILER#collec_elt") ok @@ (e_variable elt_name)
else ok @@ exp else ok @@ exp
) )
| _ -> ok @@ exp in | _ -> ok @@ exp in
@ -1130,13 +1135,13 @@ and simpl_for_collect : Raw.for_collect -> (_ -> expression result) result = fun
let collec_elt_v = arg_access [Access_tuple 1 ; Access_tuple 0] in let collec_elt_v = arg_access [Access_tuple 1 ; Access_tuple 0] in
let collec_elt_k = arg_access [Access_tuple 1 ; Access_tuple 1] in let collec_elt_k = arg_access [Access_tuple 1 ; Access_tuple 1] in
e_let_in ("#COMPILER#acc", None) acc @@ e_let_in ("#COMPILER#acc", None) acc @@
e_let_in ("#COMPILER#collec_elt_k", None) collec_elt_v @@ e_let_in (elt_name, None) collec_elt_v @@
e_let_in ("#COMPILER#collec_elt_v", None) collec_elt_k (for_body) e_let_in (elt_v_name, None) collec_elt_k (for_body)
| _ -> | _ ->
let acc = arg_access [Access_tuple 0] in let acc = arg_access [Access_tuple 0] in
let collec_elt = arg_access [Access_tuple 1] in let collec_elt = arg_access [Access_tuple 1] in
e_let_in ("#COMPILER#acc", None) acc @@ e_let_in ("#COMPILER#acc", None) acc @@
e_let_in ("#COMPILER#collec_elt", None) collec_elt (for_body) e_let_in (elt_name, None) collec_elt (for_body)
) in ) in
(* STEP 7 *) (* STEP 7 *)
let%bind collect = simpl_expression fc.expr in let%bind collect = simpl_expression fc.expr in

View File

@ -146,6 +146,7 @@ function nested_for_collection (var nee : unit) : (int*string) is block {
var myset : set(string) := set "1" ; "2" ; "3" end ; var myset : set(string) := set "1" ; "2" ; "3" end ;
for st in set myset for st in set myset
begin begin
myint := myint + i ;
mystoo := mystoo ^ st ; mystoo := mystoo ^ st ;
for k -> v in map mymap for k -> v in map mymap
begin begin

View File

@ -826,7 +826,7 @@ let loop () : unit result =
let expected = (e_int 20) in let expected = (e_int 20) in
expect_eq program "for_collection_comp_with_acc" input expected in expect_eq program "for_collection_comp_with_acc" input expected in
let%bind () = let%bind () =
let expected = e_pair (e_int 6) let expected = e_pair (e_int 24)
(e_string "1 one,two 2 one,two 3 one,two 1 one,two 2 one,two 3 one,two 1 one,two 2 one,two 3 one,two ") in (e_string "1 one,two 2 one,two 3 one,two 1 one,two 2 one,two 3 one,two 1 one,two 2 one,two 3 one,two ") in
expect_eq program "nested_for_collection" input expected in expect_eq program "nested_for_collection" input expected in
let%bind () = let%bind () =