summaryrefslogtreecommitdiff
path: root/bytecomp/translmod.ml
diff options
context:
space:
mode:
Diffstat (limited to 'bytecomp/translmod.ml')
-rw-r--r--bytecomp/translmod.ml59
1 files changed, 38 insertions, 21 deletions
diff --git a/bytecomp/translmod.ml b/bytecomp/translmod.ml
index 1f475565f9..89be6f5da1 100644
--- a/bytecomp/translmod.ml
+++ b/bytecomp/translmod.ml
@@ -83,21 +83,12 @@ let rec apply_coercion strict restr arg =
arg
| Tcoerce_structure(pos_cc_list, id_pos_list) ->
name_lambda strict arg (fun id ->
+ let get_field pos = Lprim(Pfield pos,[Lvar id]) in
let lam =
Lprim(Pmakeblock(0, Immutable),
- List.map (apply_coercion_field id) pos_cc_list) in
- let fv = free_variables lam in
- let (lam,s) =
- List.fold_left (fun (lam,s) (id',pos,c) ->
- if IdentSet.mem id' fv then
- let id'' = Ident.create (Ident.name id') in
- (Llet(Alias,id'',
- apply_coercion Alias c (Lprim(Pfield pos,[Lvar id])),lam),
- Ident.add id' (Lvar id'') s)
- else (lam,s))
- (lam, Ident.empty) id_pos_list
+ List.map (apply_coercion_field get_field) pos_cc_list)
in
- if s == Ident.empty then lam else subst_lambda s lam)
+ wrap_id_pos_list id_pos_list get_field lam)
| Tcoerce_functor(cc_arg, cc_res) ->
let param = Ident.create "funarg" in
name_lambda strict arg (fun id ->
@@ -111,8 +102,26 @@ let rec apply_coercion strict restr arg =
name_lambda strict arg
(fun id -> apply_coercion Alias cc (transl_normal_path path))
-and apply_coercion_field id (pos, cc) =
- apply_coercion Alias cc (Lprim(Pfield pos, [Lvar id]))
+and apply_coercion_field get_field (pos, cc) =
+ apply_coercion Alias cc (get_field pos)
+
+and wrap_id_pos_list id_pos_list get_field lam =
+ let fv = free_variables lam in
+ (*Format.eprintf "%a@." Printlambda.lambda lam;
+ IdentSet.iter (fun id -> Format.eprintf "%a " Ident.print id) fv;
+ Format.eprintf "@.";*)
+ let (lam,s) =
+ List.fold_left (fun (lam,s) (id',pos,c) ->
+ if IdentSet.mem id' fv then
+ let id'' = Ident.create (Ident.name id') in
+ (Llet(Alias,id'',
+ apply_coercion Alias c (get_field pos),lam),
+ Ident.add id' (Lvar id'') s)
+ else (lam,s))
+ (lam, Ident.empty) id_pos_list
+ in
+ if s == Ident.empty then lam else subst_lambda s lam
+
(* Compose two coercions
apply_coercion c1 (apply_coercion c2 e) behaves like
@@ -154,7 +163,7 @@ let compose_coercions c1 c2 =
let c3 = compose_coercions c1 c2 in
let open Includemod in
Format.eprintf "@[<2>compose_coercions@ (%a)@ (%a) =@ %a@]@."
- print_coercion c1 print_coercion c2 print_coercion c2;
+ print_coercion c1 print_coercion c2 print_coercion c3;
c3
*)
@@ -322,7 +331,7 @@ let rec transl_module cc rootpath mexp =
| _ ->
match mexp.mod_desc with
Tmod_ident (path,_) ->
- apply_coercion StrictOpt cc
+ apply_coercion Strict cc
(transl_path ~loc:mexp.mod_loc mexp.mod_env path)
| Tmod_structure str ->
transl_struct [] cc rootpath str
@@ -362,18 +371,26 @@ and transl_structure fields cc rootpath = function
Lprim(Pmakeblock(0, Immutable),
List.map (fun id -> Lvar id) (List.rev fields))
| Tcoerce_structure(pos_cc_list, id_pos_list) ->
- (* ignore id_pos_list as the ids are already bound *)
+ (* Do not ignore id_pos_list ! *)
+ (*Format.eprintf "%a@.@[" Includemod.print_coercion cc;
+ List.iter (fun l -> Format.eprintf "%a@ " Ident.print l)
+ fields;
+ Format.eprintf "@]@.";*)
let v = Array.of_list (List.rev fields) in
- (*List.fold_left
- (fun lam (id, pos) -> Llet(Alias, id, Lvar v.(pos), lam))*)
+ let get_field pos = Lvar v.(pos)
+ and ids = List.fold_right IdentSet.add fields IdentSet.empty in
+ let lam =
(Lprim(Pmakeblock(0, Immutable),
List.map
(fun (pos, cc) ->
match cc with
Tcoerce_primitive p -> transl_primitive Location.none p
- | _ -> apply_coercion Strict cc (Lvar v.(pos)))
+ | _ -> apply_coercion Strict cc (get_field pos))
pos_cc_list))
- (*id_pos_list*)
+ and id_pos_list =
+ List.filter (fun (id,_,_) -> not (IdentSet.mem id ids)) id_pos_list
+ in
+ wrap_id_pos_list id_pos_list get_field lam
| _ ->
fatal_error "Translmod.transl_structure"
end