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;
lamby = fun arguments -> (
let #COMPILER#acc = arguments.0 in
let #COMPILER#elt = arguments.1 in
#COMPILER#acc.myint := #COMPILER#acc.myint + #COMPILER#elt ;
let #COMPILER#elt_x = arguments.1 in
#COMPILER#acc.myint := #COMPILER#acc.myint + #COMPILER#elt_x ;
#COMPILER#acc.myst := #COMPILER#acc.myst ^ "to" ;
#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.
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" ;
```
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 lhs ==> accessor `#COMPILER#acc.X`
And, in the case of a map:
- references to the iterated key ==> variable `#COMPILER#elt_key`
- references to the iterated value ==> variable `#COMPILER#elt_value`
- references to the iterated key ==> variable `#COMPILER#elt_K`
- references to the iterated value ==> variable `#COMPILER#elt_V`
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
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
@ -1043,10 +1043,11 @@ and simpl_for_int : Raw.for_int -> (_ -> expression result) result = fun fi ->
tuple holding:
* In the case of `list` or ̀set`:
( folding record , current list/set element ) as
( #COMPILER#acc , #COMPILER#elt )
( #COMPILER#acc , #COMPILER#elt_X )
* In the case of `map`:
( 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)
@ -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 ->
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 *)
let%bind for_body = simpl_block fc.block.value 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
(* loop on map *)
| Map _ ->
let k' = e_variable "#COMPILER#collec_elt_k" in
let k' = e_variable elt_name in
if ( name = fc.var.value ) then
ok @@ k' (* replace references to the the key *)
else (
match fc.bind_to with
| Some (_,v) ->
let v' = e_variable "#COMPILER#collec_elt_v" in
let v' = e_variable elt_v_name in
if ( name = v.value ) then
ok @@ v' (* replace references to the the value *)
else ok @@ exp
@ -1111,7 +1116,7 @@ and simpl_for_collect : Raw.for_collect -> (_ -> expression result) result = fun
| (Set _ | List _) ->
if (name = fc.var.value ) then
(* replace references to the collection element *)
ok @@ (e_variable "#COMPILER#collec_elt")
ok @@ (e_variable elt_name)
else ok @@ exp
)
| _ -> 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_k = arg_access [Access_tuple 1 ; Access_tuple 1] in
e_let_in ("#COMPILER#acc", None) acc @@
e_let_in ("#COMPILER#collec_elt_k", None) collec_elt_v @@
e_let_in ("#COMPILER#collec_elt_v", None) collec_elt_k (for_body)
e_let_in (elt_name, None) collec_elt_v @@
e_let_in (elt_v_name, None) collec_elt_k (for_body)
| _ ->
let acc = arg_access [Access_tuple 0] in
let collec_elt = arg_access [Access_tuple 1] in
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
(* STEP 7 *)
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 ;
for st in set myset
begin
myint := myint + i ;
mystoo := mystoo ^ st ;
for k -> v in map mymap
begin

View File

@ -826,7 +826,7 @@ let loop () : unit result =
let expected = (e_int 20) in
expect_eq program "for_collection_comp_with_acc" input expected in
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
expect_eq program "nested_for_collection" input expected in
let%bind () =