diff --git a/src/passes/2-simplify/pascaligo.ml b/src/passes/2-simplify/pascaligo.ml index 095ab6ac5..a2c43d0ee 100644 --- a/src/passes/2-simplify/pascaligo.ml +++ b/src/passes/2-simplify/pascaligo.ml @@ -119,7 +119,7 @@ module Errors = struct ] in error ~data title message - let unsupported_map_patches patch = + (* let unsupported_map_patches patch = let title () = "map patches" in let message () = Format.asprintf "map patches (a.k.a. functional updates) are \ @@ -128,7 +128,7 @@ module Errors = struct ("patch_loc", fun () -> Format.asprintf "%a" Location.pp_lift @@ patch.Region.region) ] in - error ~data title message + error ~data title message *) let unsupported_set_patches patch = let title () = "set patches" in @@ -817,8 +817,32 @@ and simpl_single_instruction : Raw.single_instr -> (_ -> expression result) resu in return_statement @@ expr ) - | MapPatch patch -> - fail @@ unsupported_map_patches patch + | MapPatch patch -> ( + let (map_p, loc) = r_split patch in + let (name, access_path) = simpl_path map_p.path in + let%bind inj = bind_list + @@ List.map (fun (x:Raw.binding Region.reg) -> + let (x , loc) = r_split x in + let (key, value) = x.source, x.image in + let%bind key' = simpl_expression key in + let%bind value' = simpl_expression value + in ok @@ (access_path, key', value', loc) + ) + @@ pseq_to_list map_p.map_inj.value.elements in + let%bind expr = + let aux = fun (access, key, value, loc) -> + let map = e_variable name in + e_assign ~loc name access (e_map_add key value map) in + let assigns = List.map aux inj in + match assigns with + | [] -> ok @@ e_skip ~loc () + | hd :: tl -> ( + let aux acc cur = e_sequence acc cur in + ok @@ List.fold_left aux hd tl + ) + in + return_statement @@ expr + ) | SetPatch patch -> fail @@ unsupported_set_patches patch | MapRemove r -> ( diff --git a/src/test/contracts/map.ligo b/src/test/contracts/map.ligo index 7437cfb26..71be5dc20 100644 --- a/src/test/contracts/map.ligo +++ b/src/test/contracts/map.ligo @@ -25,6 +25,10 @@ function rm (var m : foobar) : foobar is block { remove 42 from map m } with m +function patch_ (var m: foobar) : foobar is block { + patch m with map [0 -> 5; 1 -> 6; 2 -> 7] +} with m + function size_ (const m : foobar) : nat is block {skip} with (size(m)) @@ -60,4 +64,4 @@ var coco : (int*foobar) := (0, m); block { remove 42 from map coco.1 ; coco.1[32] := 16 ; -} with coco.1 \ No newline at end of file +} with coco.1 diff --git a/src/test/contracts/map.mligo b/src/test/contracts/map.mligo index 094252c0e..88089d985 100644 --- a/src/test/contracts/map.mligo +++ b/src/test/contracts/map.mligo @@ -11,6 +11,9 @@ let set_ (n : int) (m : foobar) : foobar = let rm (m : foobar) : foobar = Map.remove 42 m +(* Dummy test so that we can add the same test for PascaLIGO *) +let patch_ (m : foobar) : foobar = Map.literal [ (0, 5) ; (1, 6) ; (2, 7) ] + let size_ (m : foobar) : nat = Map.size m let gf (m : foobar) : int = Map.find 23 m @@ -34,4 +37,4 @@ let deep_op (m : foobar) : foobar = let coco = (0,m) in let coco = (0 , Map.remove 42 coco.(1)) in let coco = (0 , Map.update 32 (Some 16) coco.(1)) in - coco.(1) \ No newline at end of file + coco.(1) diff --git a/src/test/integration_tests.ml b/src/test/integration_tests.ml index 7a50ad29b..7e9f5c3b1 100644 --- a/src/test/integration_tests.ml +++ b/src/test/integration_tests.ml @@ -411,6 +411,11 @@ let map_ type_f path : unit result = let expected = ez [23, 23] in expect_eq program "rm" input expected in + let%bind () = + let input = ez [(0,0) ; (1,1) ; (2,2)] in + let expected = ez [(0, 5) ; (1, 6) ; (2, 7)] in + expect_eq program "patch_" input expected + in let%bind () = let make_input = fun n -> ez List.(map (fun x -> (x, x)) @@ range n) in let make_expected = e_nat in