summaryrefslogtreecommitdiff
path: root/compiler/PureMicroPasses.ml
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/PureMicroPasses.ml')
-rw-r--r--compiler/PureMicroPasses.ml43
1 files changed, 41 insertions, 2 deletions
diff --git a/compiler/PureMicroPasses.ml b/compiler/PureMicroPasses.ml
index 7d01a622..74f3c576 100644
--- a/compiler/PureMicroPasses.ml
+++ b/compiler/PureMicroPasses.ml
@@ -1178,8 +1178,47 @@ let simplify_aggregates (ctx : trans_ctx) (def : fun_decl) : fun_decl =
List.length filt_var_projs = List.length updates
&& List.for_all (fun y -> y = x) filt_var_projs
then { e with e = Var x }
- else (* TODO *)
- super#visit_texpression env e
+ else if
+ (* Attempt to create an "update" expression (i.e., of
+ the shape [{ x with f := v }]).
+
+ This is not supported by Coq *)
+ !Config.backend <> Coq
+ then (
+ (* Compute the number of occurrences of each variable *)
+ let occurs = ref VarId.Map.empty in
+ List.iter
+ (fun x ->
+ let num =
+ match VarId.Map.find_opt x !occurs with
+ | None -> 1
+ | Some n -> n + 1
+ in
+ occurs := VarId.Map.add x num !occurs)
+ filt_var_projs;
+ (* Find the max - note that we can initialize the max at 0,
+ because there is at least one variable *)
+ let max = ref 0 in
+ let x = ref x in
+ List.iter
+ (fun (y, n) ->
+ if n > !max then (
+ max := n;
+ x := y))
+ (VarId.Map.bindings !occurs);
+ (* Create the update expression *)
+ let updates =
+ List.filter_map
+ (fun ((fid, fe), y_opt) ->
+ if y_opt = Some !x then None else Some (fid, fe))
+ (List.combine updates var_projs)
+ in
+ let supd =
+ StructUpdate { struct_id; init = Some !x; updates }
+ in
+ let e = { e with e = supd } in
+ super#visit_texpression env e)
+ else super#visit_texpression env e
| _ -> super#visit_texpression env e
end
in