Merge branch 'collect-loop-last-fixes' into 'dev'
Pascaligo for collection loops: take locally declared variable into account See merge request ligolang/ligo!202
This commit is contained in:
commit
fe76f82bb0
@ -3,6 +3,7 @@ open Ast_simplified
|
|||||||
|
|
||||||
module Raw = Parser.Pascaligo.AST
|
module Raw = Parser.Pascaligo.AST
|
||||||
module SMap = Map.String
|
module SMap = Map.String
|
||||||
|
module SSet = Set.Make (String)
|
||||||
|
|
||||||
open Combinators
|
open Combinators
|
||||||
|
|
||||||
@ -14,6 +15,39 @@ let pseq_to_list = function
|
|||||||
let get_value : 'a Raw.reg -> 'a = fun x -> x.value
|
let get_value : 'a Raw.reg -> 'a = fun x -> x.value
|
||||||
let is_compiler_generated = fun name -> String.contains name '#'
|
let is_compiler_generated = fun name -> String.contains name '#'
|
||||||
|
|
||||||
|
let detect_local_declarations (for_body : expression) =
|
||||||
|
let%bind aux = Self_ast_simplified.fold_expression
|
||||||
|
(fun (nlist, cur_loop : type_name list * bool) (ass_exp : expression) ->
|
||||||
|
if cur_loop then
|
||||||
|
match ass_exp.expression with
|
||||||
|
| E_let_in {binder;rhs = _;result = _} ->
|
||||||
|
let (name,_) = binder in
|
||||||
|
ok (name::nlist, cur_loop)
|
||||||
|
| E_constant ("MAP_FOLD", _)
|
||||||
|
| E_constant ("SET_FOLD", _)
|
||||||
|
| E_constant ("LIST_FOLD", _) -> ok @@ (nlist, false)
|
||||||
|
| _ -> ok (nlist, cur_loop)
|
||||||
|
else
|
||||||
|
ok @@ (nlist, cur_loop)
|
||||||
|
)
|
||||||
|
([], true)
|
||||||
|
for_body in
|
||||||
|
ok @@ fst aux
|
||||||
|
|
||||||
|
let detect_free_variables (for_body : expression) (local_decl_names : string list) =
|
||||||
|
let%bind captured_names = Self_ast_simplified.fold_expression
|
||||||
|
(fun (prev : type_name list) (ass_exp : expression) ->
|
||||||
|
match ass_exp.expression with
|
||||||
|
| E_assign ( name , _ , _ ) ->
|
||||||
|
if is_compiler_generated name then ok prev
|
||||||
|
else ok (name::prev)
|
||||||
|
| _ -> ok prev )
|
||||||
|
[]
|
||||||
|
for_body in
|
||||||
|
ok @@ SSet.elements
|
||||||
|
@@ SSet.diff (SSet.of_list captured_names) (SSet.of_list local_decl_names)
|
||||||
|
|
||||||
|
|
||||||
module Errors = struct
|
module Errors = struct
|
||||||
let unsupported_cst_constr p =
|
let unsupported_cst_constr p =
|
||||||
let title () = "constant constructor" in
|
let title () = "constant constructor" in
|
||||||
@ -1033,7 +1067,8 @@ and simpl_for_int : Raw.for_int -> (_ -> expression result) result = fun fi ->
|
|||||||
|
|
||||||
2) Detect the free variables and build a list of their names
|
2) Detect the free variables and build a list of their names
|
||||||
(myint and myst in the previous example)
|
(myint and myst in the previous example)
|
||||||
Free variables are simply variables being assigned.
|
Free variables are simply variables being assigned but not defined
|
||||||
|
locally.
|
||||||
Note: In the case of a nested loops, assignements to a compiler
|
Note: In the case of a nested loops, assignements to a compiler
|
||||||
generated value (#COMPILER#acc) correspond to variables
|
generated value (#COMPILER#acc) correspond to variables
|
||||||
that were already renamed in the inner loop.
|
that were already renamed in the inner loop.
|
||||||
@ -1094,15 +1129,8 @@ and simpl_for_collect : Raw.for_collect -> (_ -> expression result) result = fun
|
|||||||
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
|
||||||
(* STEP 2 *)
|
(* STEP 2 *)
|
||||||
let%bind captured_name_list = Self_ast_simplified.fold_expression
|
let%bind local_decl_name_list = detect_local_declarations for_body in
|
||||||
(fun (prev : type_name list) (ass_exp : expression) ->
|
let%bind captured_name_list = detect_free_variables for_body local_decl_name_list in
|
||||||
match ass_exp.expression with
|
|
||||||
| E_assign ( name , _ , _ ) ->
|
|
||||||
if is_compiler_generated name then ok prev
|
|
||||||
else ok (name::prev)
|
|
||||||
| _ -> ok prev )
|
|
||||||
[]
|
|
||||||
for_body in
|
|
||||||
(* STEP 3 *)
|
(* STEP 3 *)
|
||||||
let add_to_record (prev: expression type_name_map) (captured_name: string) =
|
let add_to_record (prev: expression type_name_map) (captured_name: string) =
|
||||||
SMap.add captured_name (e_variable captured_name) prev in
|
SMap.add captured_name (e_variable captured_name) prev in
|
||||||
@ -1112,13 +1140,16 @@ and simpl_for_collect : Raw.for_collect -> (_ -> expression result) result = fun
|
|||||||
match exp.expression with
|
match exp.expression with
|
||||||
(* replace references to fold accumulator as lhs *)
|
(* replace references to fold accumulator as lhs *)
|
||||||
| E_assign ( name , path , expr ) -> (
|
| E_assign ( name , path , expr ) -> (
|
||||||
let path' = List.filter
|
if (List.mem name local_decl_name_list ) then
|
||||||
( fun el ->
|
ok @@ exp
|
||||||
match el with
|
else
|
||||||
| Access_record name -> not @@ is_compiler_generated name
|
let path' = List.filter
|
||||||
| _ -> true )
|
( fun el ->
|
||||||
((Access_record name)::path) in
|
match el with
|
||||||
ok @@ e_assign "#COMPILER#acc" path' expr)
|
| Access_record name -> not @@ is_compiler_generated name
|
||||||
|
| _ -> true )
|
||||||
|
((Access_record name)::path) in
|
||||||
|
ok @@ e_assign "#COMPILER#acc" path' expr )
|
||||||
| E_variable name -> (
|
| E_variable name -> (
|
||||||
if (List.mem name captured_name_list) then
|
if (List.mem name captured_name_list) then
|
||||||
(* replace references to fold accumulator as rhs *)
|
(* replace references to fold accumulator as rhs *)
|
||||||
|
@ -156,6 +156,25 @@ function nested_for_collection (var nee : unit) : (int*string) is block {
|
|||||||
end
|
end
|
||||||
} with (myint,mystoo)
|
} with (myint,mystoo)
|
||||||
|
|
||||||
|
function nested_for_collection_local_var (var nee : unit) : (int*string) is block {
|
||||||
|
var myint : int := 0;
|
||||||
|
var myst : string := "";
|
||||||
|
var mylist : list(int) := list 1 ; 2 ; 3 end ;
|
||||||
|
|
||||||
|
for i in list mylist
|
||||||
|
begin
|
||||||
|
var myst_loc : string := "" ;
|
||||||
|
myint := myint + i ;
|
||||||
|
var myset : set(string) := set "1" ; "2" ; "3" end ;
|
||||||
|
for st in set myset
|
||||||
|
begin
|
||||||
|
myint := myint + i ;
|
||||||
|
myst_loc := myst_loc ^ st ;
|
||||||
|
end;
|
||||||
|
myst := myst_loc ^ myst ;
|
||||||
|
end
|
||||||
|
} with (myint,myst)
|
||||||
|
|
||||||
function dummy (const n : nat) : nat is block {
|
function dummy (const n : nat) : nat is block {
|
||||||
while False block { skip }
|
while False block { skip }
|
||||||
} with n
|
} with n
|
||||||
|
@ -836,6 +836,10 @@ let loop () : unit result =
|
|||||||
let expected = e_pair (e_int 24)
|
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 expected = e_pair (e_int 24)
|
||||||
|
(e_string "123123123") in
|
||||||
|
expect_eq program "nested_for_collection_local_var" input expected in
|
||||||
let%bind () =
|
let%bind () =
|
||||||
let ez lst =
|
let ez lst =
|
||||||
let open Ast_simplified.Combinators in
|
let open Ast_simplified.Combinators in
|
||||||
|
Loading…
Reference in New Issue
Block a user