1995-08-09 08:06:35 -07:00
|
|
|
(***********************************************************************)
|
|
|
|
(* *)
|
2011-07-27 07:17:02 -07:00
|
|
|
(* OCaml *)
|
1995-08-09 08:06:35 -07:00
|
|
|
(* *)
|
|
|
|
(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *)
|
|
|
|
(* *)
|
1996-04-30 07:53:58 -07:00
|
|
|
(* Copyright 1996 Institut National de Recherche en Informatique et *)
|
1999-11-17 10:59:06 -08:00
|
|
|
(* en Automatique. All rights reserved. This file is distributed *)
|
|
|
|
(* under the terms of the Q Public License version 1.0. *)
|
1995-08-09 08:06:35 -07:00
|
|
|
(* *)
|
|
|
|
(***********************************************************************)
|
|
|
|
|
1995-05-04 03:15:53 -07:00
|
|
|
(* Translation from typed abstract syntax to lambda terms,
|
|
|
|
for the module language *)
|
|
|
|
|
|
|
|
open Misc
|
1995-11-09 05:22:16 -08:00
|
|
|
open Asttypes
|
2004-08-12 05:55:11 -07:00
|
|
|
open Longident
|
1998-06-23 03:06:50 -07:00
|
|
|
open Path
|
1996-09-23 04:30:27 -07:00
|
|
|
open Types
|
1995-05-04 03:15:53 -07:00
|
|
|
open Typedtree
|
|
|
|
open Lambda
|
1996-04-22 04:15:41 -07:00
|
|
|
open Translobj
|
1995-05-04 03:15:53 -07:00
|
|
|
open Translcore
|
1996-04-22 04:15:41 -07:00
|
|
|
open Translclass
|
1995-05-04 03:15:53 -07:00
|
|
|
|
2003-06-19 08:53:53 -07:00
|
|
|
type error =
|
|
|
|
Circular_dependency of Ident.t
|
|
|
|
|
|
|
|
exception Error of Location.t * error
|
|
|
|
|
1995-05-04 03:15:53 -07:00
|
|
|
(* Compile a coercion *)
|
|
|
|
|
2013-10-02 01:34:01 -07:00
|
|
|
let rec apply_coercion strict restr arg =
|
1995-05-04 03:15:53 -07:00
|
|
|
match restr with
|
|
|
|
Tcoerce_none ->
|
|
|
|
arg
|
2013-09-30 04:35:15 -07:00
|
|
|
| Tcoerce_structure(pos_cc_list, id_pos_list) ->
|
2013-10-02 01:34:01 -07:00
|
|
|
name_lambda strict arg (fun id ->
|
2013-09-30 04:35:15 -07:00
|
|
|
let lam =
|
|
|
|
Lprim(Pmakeblock(0, Immutable),
|
|
|
|
List.map (apply_coercion_field id) pos_cc_list) in
|
|
|
|
let fv = free_variables lam in
|
|
|
|
List.fold_left (fun lam (id',pos,c) ->
|
|
|
|
if IdentSet.mem id' fv then
|
2013-10-02 01:34:01 -07:00
|
|
|
Llet(Alias,id',
|
|
|
|
apply_coercion Alias c (Lprim(Pfield pos,[Lvar id])),lam)
|
2013-09-30 04:35:15 -07:00
|
|
|
else lam)
|
|
|
|
lam id_pos_list)
|
1995-05-04 03:15:53 -07:00
|
|
|
| Tcoerce_functor(cc_arg, cc_res) ->
|
1996-04-22 04:15:41 -07:00
|
|
|
let param = Ident.create "funarg" in
|
2013-10-02 01:34:01 -07:00
|
|
|
name_lambda strict arg (fun id ->
|
1996-10-22 06:36:59 -07:00
|
|
|
Lfunction(Curried, [param],
|
2013-10-02 01:34:01 -07:00
|
|
|
apply_coercion Strict cc_res
|
|
|
|
(Lapply(Lvar id, [apply_coercion Alias cc_arg (Lvar param)],
|
2007-05-16 01:21:41 -07:00
|
|
|
Location.none))))
|
1995-10-23 09:56:52 -07:00
|
|
|
| Tcoerce_primitive p ->
|
2012-08-21 00:12:04 -07:00
|
|
|
transl_primitive Location.none p
|
2013-09-29 00:22:34 -07:00
|
|
|
| Tcoerce_alias (path, cc) ->
|
2013-10-02 01:34:01 -07:00
|
|
|
name_lambda strict arg
|
|
|
|
(fun id -> apply_coercion Alias cc (transl_path path))
|
1995-05-04 03:15:53 -07:00
|
|
|
|
|
|
|
and apply_coercion_field id (pos, cc) =
|
2013-10-02 01:34:01 -07:00
|
|
|
apply_coercion Alias cc (Lprim(Pfield pos, [Lvar id]))
|
1995-05-04 03:15:53 -07:00
|
|
|
|
|
|
|
(* Compose two coercions
|
|
|
|
apply_coercion c1 (apply_coercion c2 e) behaves like
|
|
|
|
apply_coercion (compose_coercions c1 c2) e. *)
|
|
|
|
|
|
|
|
let rec compose_coercions c1 c2 =
|
|
|
|
match (c1, c2) with
|
|
|
|
(Tcoerce_none, c2) -> c2
|
|
|
|
| (c1, Tcoerce_none) -> c1
|
2013-09-30 04:35:15 -07:00
|
|
|
| (Tcoerce_structure (pc1, ids1), Tcoerce_structure (pc2, ids2)) ->
|
1995-05-04 03:15:53 -07:00
|
|
|
let v2 = Array.of_list pc2 in
|
2013-09-30 04:35:15 -07:00
|
|
|
let ids1 =
|
|
|
|
List.map (fun (id,pos1,c1) ->
|
|
|
|
let (pos2,c2) = v2.(pos1) in (id, pos2, compose_coercions c1 c2))
|
|
|
|
ids1
|
|
|
|
in
|
1995-05-04 03:15:53 -07:00
|
|
|
Tcoerce_structure
|
1999-02-04 02:31:16 -08:00
|
|
|
(List.map
|
|
|
|
(function (p1, Tcoerce_primitive p) ->
|
|
|
|
(p1, Tcoerce_primitive p)
|
|
|
|
| (p1, c1) ->
|
|
|
|
let (p2, c2) = v2.(p1) in (p2, compose_coercions c1 c2))
|
2013-09-30 04:35:15 -07:00
|
|
|
pc1,
|
|
|
|
ids1 @ ids2)
|
1995-05-04 03:15:53 -07:00
|
|
|
| (Tcoerce_functor(arg1, res1), Tcoerce_functor(arg2, res2)) ->
|
|
|
|
Tcoerce_functor(compose_coercions arg2 arg1,
|
|
|
|
compose_coercions res1 res2)
|
2013-09-30 04:35:15 -07:00
|
|
|
| (c1, Tcoerce_alias (path, c2)) ->
|
2013-09-29 00:22:34 -07:00
|
|
|
Tcoerce_alias (path, compose_coercions c1 c2)
|
1995-05-04 03:15:53 -07:00
|
|
|
| (_, _) ->
|
|
|
|
fatal_error "Translmod.compose_coercions"
|
|
|
|
|
1995-11-05 09:32:12 -08:00
|
|
|
(* Record the primitive declarations occuring in the module compiled *)
|
1995-10-09 06:37:11 -07:00
|
|
|
|
2008-07-23 22:35:22 -07:00
|
|
|
let primitive_declarations = ref ([] : Primitive.description list)
|
|
|
|
let record_primitive = function
|
2013-03-09 14:38:52 -08:00
|
|
|
| {val_kind=Val_prim p} ->
|
|
|
|
primitive_declarations := p :: !primitive_declarations
|
2008-07-23 22:35:22 -07:00
|
|
|
| _ -> ()
|
2010-01-22 04:48:24 -08:00
|
|
|
|
1998-06-23 03:06:50 -07:00
|
|
|
(* Keep track of the root path (from the root of the namespace to the
|
|
|
|
currently compiled module expression). Useful for naming exceptions. *)
|
|
|
|
|
|
|
|
let global_path glob = Some(Pident glob)
|
|
|
|
let functor_path path param =
|
|
|
|
match path with
|
|
|
|
None -> None
|
|
|
|
| Some p -> Some(Papply(p, Pident param))
|
|
|
|
let field_path path field =
|
|
|
|
match path with
|
|
|
|
None -> None
|
|
|
|
| Some p -> Some(Pdot(p, Ident.name field, Path.nopos))
|
|
|
|
|
2003-06-19 08:53:53 -07:00
|
|
|
(* Utilities for compiling "module rec" definitions *)
|
|
|
|
|
2004-08-12 05:55:11 -07:00
|
|
|
let mod_prim name =
|
|
|
|
try
|
|
|
|
transl_path
|
|
|
|
(fst (Env.lookup_value (Ldot (Lident "CamlinternalMod", name))
|
|
|
|
Env.empty))
|
|
|
|
with Not_found ->
|
|
|
|
fatal_error ("Primitive " ^ name ^ " not found.")
|
|
|
|
|
|
|
|
let undefined_location loc =
|
2011-08-04 07:59:13 -07:00
|
|
|
let (fname, line, char) = Location.get_pos_info loc.Location.loc_start in
|
2004-08-12 05:55:11 -07:00
|
|
|
Lconst(Const_block(0,
|
2013-03-26 04:17:17 -07:00
|
|
|
[Const_base(Const_string (fname, None));
|
2004-08-12 05:55:11 -07:00
|
|
|
Const_base(Const_int line);
|
|
|
|
Const_base(Const_int char)]))
|
2003-06-19 08:53:53 -07:00
|
|
|
|
2004-08-12 05:55:11 -07:00
|
|
|
let init_shape modl =
|
|
|
|
let rec init_shape_mod env mty =
|
2003-06-19 08:53:53 -07:00
|
|
|
match Mtype.scrape env mty with
|
2013-09-29 00:22:34 -07:00
|
|
|
Mty_ident _
|
|
|
|
| Mty_alias _ ->
|
2003-06-19 08:53:53 -07:00
|
|
|
raise Not_found
|
2012-05-30 07:52:37 -07:00
|
|
|
| Mty_signature sg ->
|
2004-08-12 05:55:11 -07:00
|
|
|
Const_block(0, [Const_block(0, init_shape_struct env sg)])
|
2012-05-30 07:52:37 -07:00
|
|
|
| Mty_functor(id, arg, res) ->
|
2004-08-12 05:55:11 -07:00
|
|
|
raise Not_found (* can we do better? *)
|
|
|
|
and init_shape_struct env sg =
|
2003-06-19 08:53:53 -07:00
|
|
|
match sg with
|
|
|
|
[] -> []
|
2012-05-30 07:52:37 -07:00
|
|
|
| Sig_value(id, vdesc) :: rem ->
|
2003-06-19 08:53:53 -07:00
|
|
|
let init_v =
|
|
|
|
match Ctype.expand_head env vdesc.val_type with
|
|
|
|
{desc = Tarrow(_,_,_,_)} ->
|
2004-08-12 05:55:11 -07:00
|
|
|
Const_pointer 0 (* camlinternalMod.Function *)
|
2003-06-19 08:53:53 -07:00
|
|
|
| {desc = Tconstr(p, _, _)} when Path.same p Predef.path_lazy_t ->
|
2004-08-12 05:55:11 -07:00
|
|
|
Const_pointer 1 (* camlinternalMod.Lazy *)
|
2003-06-19 08:53:53 -07:00
|
|
|
| _ -> raise Not_found in
|
2004-08-12 05:55:11 -07:00
|
|
|
init_v :: init_shape_struct env rem
|
2012-05-30 07:52:37 -07:00
|
|
|
| Sig_type(id, tdecl, _) :: rem ->
|
2013-09-17 07:28:31 -07:00
|
|
|
init_shape_struct (Env.add_type ~check:false id tdecl env) rem
|
2012-05-30 07:52:37 -07:00
|
|
|
| Sig_exception(id, edecl) :: rem ->
|
2004-08-12 05:55:11 -07:00
|
|
|
raise Not_found
|
2013-09-27 10:05:39 -07:00
|
|
|
| Sig_module(id, md, _) :: rem ->
|
|
|
|
init_shape_mod env md.md_type ::
|
|
|
|
init_shape_struct (Env.add_module_declaration id md env) rem
|
2012-05-30 07:52:37 -07:00
|
|
|
| Sig_modtype(id, minfo) :: rem ->
|
2004-08-12 05:55:11 -07:00
|
|
|
init_shape_struct (Env.add_modtype id minfo env) rem
|
2012-05-30 07:52:37 -07:00
|
|
|
| Sig_class(id, cdecl, _) :: rem ->
|
2004-08-12 05:55:11 -07:00
|
|
|
Const_pointer 2 (* camlinternalMod.Class *)
|
|
|
|
:: init_shape_struct env rem
|
2012-05-30 07:52:37 -07:00
|
|
|
| Sig_class_type(id, ctyp, _) :: rem ->
|
2004-08-12 05:55:11 -07:00
|
|
|
init_shape_struct env rem
|
2003-06-19 08:53:53 -07:00
|
|
|
in
|
|
|
|
try
|
2004-08-12 05:55:11 -07:00
|
|
|
Some(undefined_location modl.mod_loc,
|
|
|
|
Lconst(init_shape_mod modl.mod_env modl.mod_type))
|
2003-06-19 08:53:53 -07:00
|
|
|
with Not_found ->
|
|
|
|
None
|
|
|
|
|
|
|
|
(* Reorder bindings to honor dependencies. *)
|
|
|
|
|
|
|
|
type binding_status = Undefined | Inprogress | Defined
|
|
|
|
|
|
|
|
let reorder_rec_bindings bindings =
|
|
|
|
let id = Array.of_list (List.map (fun (id,_,_,_) -> id) bindings)
|
|
|
|
and loc = Array.of_list (List.map (fun (_,loc,_,_) -> loc) bindings)
|
|
|
|
and init = Array.of_list (List.map (fun (_,_,init,_) -> init) bindings)
|
|
|
|
and rhs = Array.of_list (List.map (fun (_,_,_,rhs) -> rhs) bindings) in
|
|
|
|
let fv = Array.map Lambda.free_variables rhs in
|
|
|
|
let num_bindings = Array.length id in
|
|
|
|
let status = Array.create num_bindings Undefined in
|
|
|
|
let res = ref [] in
|
|
|
|
let rec emit_binding i =
|
|
|
|
match status.(i) with
|
|
|
|
Defined -> ()
|
|
|
|
| Inprogress -> raise(Error(loc.(i), Circular_dependency id.(i)))
|
|
|
|
| Undefined ->
|
|
|
|
if init.(i) = None then begin
|
|
|
|
status.(i) <- Inprogress;
|
|
|
|
for j = 0 to num_bindings - 1 do
|
|
|
|
if IdentSet.mem id.(j) fv.(i) then emit_binding j
|
|
|
|
done
|
|
|
|
end;
|
|
|
|
res := (id.(i), init.(i), rhs.(i)) :: !res;
|
|
|
|
status.(i) <- Defined in
|
|
|
|
for i = 0 to num_bindings - 1 do
|
|
|
|
match status.(i) with
|
|
|
|
Undefined -> emit_binding i
|
|
|
|
| Inprogress -> assert false
|
|
|
|
| Defined -> ()
|
|
|
|
done;
|
|
|
|
List.rev !res
|
|
|
|
|
|
|
|
(* Generate lambda-code for a reordered list of bindings *)
|
|
|
|
|
|
|
|
let eval_rec_bindings bindings cont =
|
|
|
|
let rec bind_inits = function
|
|
|
|
[] ->
|
|
|
|
bind_strict bindings
|
|
|
|
| (id, None, rhs) :: rem ->
|
|
|
|
bind_inits rem
|
2004-08-12 05:55:11 -07:00
|
|
|
| (id, Some(loc, shape), rhs) :: rem ->
|
2007-05-16 01:21:41 -07:00
|
|
|
Llet(Strict, id, Lapply(mod_prim "init_mod", [loc; shape], Location.none),
|
2004-08-12 05:55:11 -07:00
|
|
|
bind_inits rem)
|
2003-06-19 08:53:53 -07:00
|
|
|
and bind_strict = function
|
|
|
|
[] ->
|
|
|
|
patch_forwards bindings
|
|
|
|
| (id, None, rhs) :: rem ->
|
|
|
|
Llet(Strict, id, rhs, bind_strict rem)
|
2004-08-12 05:55:11 -07:00
|
|
|
| (id, Some(loc, shape), rhs) :: rem ->
|
2003-06-19 08:53:53 -07:00
|
|
|
bind_strict rem
|
|
|
|
and patch_forwards = function
|
|
|
|
[] ->
|
|
|
|
cont
|
|
|
|
| (id, None, rhs) :: rem ->
|
|
|
|
patch_forwards rem
|
2004-08-12 05:55:11 -07:00
|
|
|
| (id, Some(loc, shape), rhs) :: rem ->
|
2007-05-16 01:21:41 -07:00
|
|
|
Lsequence(Lapply(mod_prim "update_mod", [shape; Lvar id; rhs],
|
|
|
|
Location.none),
|
2004-08-12 05:55:11 -07:00
|
|
|
patch_forwards rem)
|
2003-06-19 08:53:53 -07:00
|
|
|
in
|
|
|
|
bind_inits bindings
|
|
|
|
|
|
|
|
let compile_recmodule compile_rhs bindings cont =
|
|
|
|
eval_rec_bindings
|
|
|
|
(reorder_rec_bindings
|
2013-03-26 01:09:26 -07:00
|
|
|
(List.map
|
|
|
|
(fun {mb_id=id; mb_expr=modl; _} ->
|
|
|
|
(id, modl.mod_loc, init_shape modl, compile_rhs id modl))
|
|
|
|
bindings))
|
2003-06-19 08:53:53 -07:00
|
|
|
cont
|
|
|
|
|
2013-07-17 08:25:47 -07:00
|
|
|
(* Extract the list of "value" identifiers bound by a signature.
|
|
|
|
"Value" identifiers are identifiers for signature components that
|
|
|
|
correspond to a run-time value: values, exceptions, modules, classes.
|
|
|
|
Note: manifest primitives do not correspond to a run-time value! *)
|
|
|
|
|
|
|
|
let rec bound_value_identifiers = function
|
|
|
|
[] -> []
|
|
|
|
| Sig_value(id, {val_kind = Val_reg}) :: rem ->
|
|
|
|
id :: bound_value_identifiers rem
|
|
|
|
| Sig_exception(id, decl) :: rem -> id :: bound_value_identifiers rem
|
|
|
|
| Sig_module(id, mty, _) :: rem -> id :: bound_value_identifiers rem
|
|
|
|
| Sig_class(id, decl, _) :: rem -> id :: bound_value_identifiers rem
|
|
|
|
| _ :: rem -> bound_value_identifiers rem
|
2012-05-30 07:52:37 -07:00
|
|
|
|
1995-05-04 03:15:53 -07:00
|
|
|
(* Compile a module expression *)
|
|
|
|
|
1998-06-23 03:06:50 -07:00
|
|
|
let rec transl_module cc rootpath mexp =
|
2013-09-29 04:49:07 -07:00
|
|
|
match mexp.mod_type with
|
2013-10-02 01:34:01 -07:00
|
|
|
Mty_alias _ -> apply_coercion Alias cc lambda_unit
|
2013-09-29 04:49:07 -07:00
|
|
|
| _ ->
|
1995-05-04 03:15:53 -07:00
|
|
|
match mexp.mod_desc with
|
2012-05-30 07:52:37 -07:00
|
|
|
Tmod_ident (path,_) ->
|
2013-10-02 01:34:01 -07:00
|
|
|
apply_coercion StrictOpt cc (transl_ident_path mexp.mod_env path)
|
1995-05-04 03:15:53 -07:00
|
|
|
| Tmod_structure str ->
|
2012-05-30 07:52:37 -07:00
|
|
|
transl_struct [] cc rootpath str
|
|
|
|
| Tmod_functor( param, _, mty, body) ->
|
1998-06-23 03:06:50 -07:00
|
|
|
let bodypath = functor_path rootpath param in
|
2003-11-25 01:20:45 -08:00
|
|
|
oo_wrap mexp.mod_env true
|
|
|
|
(function
|
|
|
|
| Tcoerce_none ->
|
|
|
|
Lfunction(Curried, [param],
|
|
|
|
transl_module Tcoerce_none bodypath body)
|
|
|
|
| Tcoerce_functor(ccarg, ccres) ->
|
|
|
|
let param' = Ident.create "funarg" in
|
|
|
|
Lfunction(Curried, [param'],
|
2013-10-02 01:34:01 -07:00
|
|
|
Llet(Alias, param,
|
|
|
|
apply_coercion Alias ccarg (Lvar param'),
|
2003-11-25 01:20:45 -08:00
|
|
|
transl_module ccres bodypath body))
|
|
|
|
| _ ->
|
|
|
|
fatal_error "Translmod.transl_module")
|
|
|
|
cc
|
1995-05-04 03:15:53 -07:00
|
|
|
| Tmod_apply(funct, arg, ccarg) ->
|
2003-11-25 01:20:45 -08:00
|
|
|
oo_wrap mexp.mod_env true
|
2013-10-02 01:34:01 -07:00
|
|
|
(apply_coercion Strict cc)
|
1998-06-23 03:06:50 -07:00
|
|
|
(Lapply(transl_module Tcoerce_none None funct,
|
2007-05-16 01:21:41 -07:00
|
|
|
[transl_module ccarg None arg], mexp.mod_loc))
|
2012-05-30 07:52:37 -07:00
|
|
|
| Tmod_constraint(arg, mty, _, ccarg) ->
|
1998-06-23 03:06:50 -07:00
|
|
|
transl_module (compose_coercions cc ccarg) rootpath arg
|
2009-10-26 03:53:16 -07:00
|
|
|
| Tmod_unpack(arg, _) ->
|
2013-10-02 01:34:01 -07:00
|
|
|
apply_coercion Strict cc (Translcore.transl_exp arg)
|
1995-05-04 03:15:53 -07:00
|
|
|
|
2012-05-30 07:52:37 -07:00
|
|
|
and transl_struct fields cc rootpath str =
|
|
|
|
transl_structure fields cc rootpath str.str_items
|
|
|
|
|
1998-06-23 03:06:50 -07:00
|
|
|
and transl_structure fields cc rootpath = function
|
1995-05-04 03:15:53 -07:00
|
|
|
[] ->
|
|
|
|
begin match cc with
|
|
|
|
Tcoerce_none ->
|
1995-11-09 05:22:16 -08:00
|
|
|
Lprim(Pmakeblock(0, Immutable),
|
1995-12-15 02:18:29 -08:00
|
|
|
List.map (fun id -> Lvar id) (List.rev fields))
|
2013-09-30 04:35:15 -07:00
|
|
|
| Tcoerce_structure(pos_cc_list, id_pos_list) ->
|
|
|
|
(* ignore id_pos_list as the ids are already bound *)
|
1995-05-04 03:15:53 -07:00
|
|
|
let v = Array.of_list (List.rev fields) in
|
2013-09-30 04:35:15 -07:00
|
|
|
(*List.fold_left
|
|
|
|
(fun lam (id, pos) -> Llet(Alias, id, Lvar v.(pos), lam))*)
|
|
|
|
(Lprim(Pmakeblock(0, Immutable),
|
1995-11-06 03:07:13 -08:00
|
|
|
List.map
|
|
|
|
(fun (pos, cc) ->
|
|
|
|
match cc with
|
2012-08-21 00:12:04 -07:00
|
|
|
Tcoerce_primitive p -> transl_primitive Location.none p
|
2013-10-02 01:34:01 -07:00
|
|
|
| _ -> apply_coercion Strict cc (Lvar v.(pos)))
|
2013-09-30 04:35:15 -07:00
|
|
|
pos_cc_list))
|
|
|
|
(*id_pos_list*)
|
1995-11-25 07:38:43 -08:00
|
|
|
| _ ->
|
1995-05-04 03:15:53 -07:00
|
|
|
fatal_error "Translmod.transl_structure"
|
|
|
|
end
|
2012-05-30 07:52:37 -07:00
|
|
|
| item :: rem ->
|
|
|
|
match item.str_desc with
|
2013-04-11 07:07:32 -07:00
|
|
|
| Tstr_eval (expr, _) ->
|
1998-06-23 03:06:50 -07:00
|
|
|
Lsequence(transl_exp expr, transl_structure fields cc rootpath rem)
|
2013-06-03 08:14:19 -07:00
|
|
|
| Tstr_value(rec_flag, pat_expr_list) ->
|
1996-02-18 06:43:18 -08:00
|
|
|
let ext_fields = rev_let_bound_idents pat_expr_list @ fields in
|
1998-06-23 03:06:50 -07:00
|
|
|
transl_let rec_flag pat_expr_list
|
|
|
|
(transl_structure ext_fields cc rootpath rem)
|
2013-03-25 11:04:40 -07:00
|
|
|
| Tstr_primitive descr ->
|
2012-05-30 07:52:37 -07:00
|
|
|
record_primitive descr.val_val;
|
1998-06-23 03:06:50 -07:00
|
|
|
transl_structure fields cc rootpath rem
|
2012-05-30 07:52:37 -07:00
|
|
|
| Tstr_type(decls) ->
|
1998-06-23 03:06:50 -07:00
|
|
|
transl_structure fields cc rootpath rem
|
2013-03-25 11:42:45 -07:00
|
|
|
| Tstr_exception decl ->
|
|
|
|
let id = decl.cd_id in
|
|
|
|
Llet(Strict, id, transl_exception (field_path rootpath id) decl,
|
1998-06-23 03:06:50 -07:00
|
|
|
transl_structure (id :: fields) cc rootpath rem)
|
2013-03-25 07:16:07 -07:00
|
|
|
| Tstr_exn_rebind( id, _, path, _, _) ->
|
2013-10-02 01:34:01 -07:00
|
|
|
Llet(Strict, id, transl_ident_path item.str_env path,
|
2000-03-12 05:10:29 -08:00
|
|
|
transl_structure (id :: fields) cc rootpath rem)
|
2013-03-26 01:09:26 -07:00
|
|
|
| Tstr_module mb ->
|
|
|
|
let id = mb.mb_id in
|
2013-10-02 01:34:01 -07:00
|
|
|
Llet(pure_module mb.mb_expr, id,
|
2013-03-26 01:09:26 -07:00
|
|
|
transl_module Tcoerce_none (field_path rootpath id) mb.mb_expr,
|
1998-06-23 03:06:50 -07:00
|
|
|
transl_structure (id :: fields) cc rootpath rem)
|
2012-05-30 07:52:37 -07:00
|
|
|
| Tstr_recmodule bindings ->
|
2013-03-26 01:09:26 -07:00
|
|
|
let ext_fields =
|
|
|
|
List.rev_append (List.map (fun mb -> mb.mb_id) bindings) fields
|
|
|
|
in
|
2003-06-19 08:53:53 -07:00
|
|
|
compile_recmodule
|
|
|
|
(fun id modl ->
|
|
|
|
transl_module Tcoerce_none (field_path rootpath id) modl)
|
|
|
|
bindings
|
2003-10-03 07:36:00 -07:00
|
|
|
(transl_structure ext_fields cc rootpath rem)
|
2012-05-30 07:52:37 -07:00
|
|
|
| Tstr_class cl_list ->
|
|
|
|
let ids = List.map (fun (ci,_,_) -> ci.ci_id_class) cl_list in
|
1998-06-24 12:22:26 -07:00
|
|
|
Lletrec(List.map
|
2012-05-30 07:52:37 -07:00
|
|
|
(fun (ci, meths, vf) ->
|
|
|
|
let id = ci.ci_id_class in
|
|
|
|
let cl = ci.ci_expr in
|
|
|
|
(id, transl_class ids id meths cl vf ))
|
1998-06-24 12:22:26 -07:00
|
|
|
cl_list,
|
1998-11-30 10:25:12 -08:00
|
|
|
transl_structure (List.rev ids @ fields) cc rootpath rem)
|
2013-07-22 10:03:39 -07:00
|
|
|
| Tstr_include(modl, sg, _) ->
|
2013-07-17 08:25:47 -07:00
|
|
|
let ids = bound_value_identifiers sg in
|
2000-12-01 01:35:00 -08:00
|
|
|
let mid = Ident.create "include" in
|
|
|
|
let rec rebind_idents pos newfields = function
|
|
|
|
[] ->
|
|
|
|
transl_structure newfields cc rootpath rem
|
|
|
|
| id :: ids ->
|
|
|
|
Llet(Alias, id, Lprim(Pfield pos, [Lvar mid]),
|
|
|
|
rebind_idents (pos + 1) (id :: newfields) ids) in
|
2013-10-02 01:34:01 -07:00
|
|
|
Llet(pure_module modl, mid, transl_module Tcoerce_none None modl,
|
2000-12-01 01:35:00 -08:00
|
|
|
rebind_idents 0 fields ids)
|
1995-05-04 03:15:53 -07:00
|
|
|
|
2013-03-25 07:16:07 -07:00
|
|
|
| Tstr_modtype _
|
|
|
|
| Tstr_open _
|
|
|
|
| Tstr_class_type _
|
|
|
|
| Tstr_attribute _ ->
|
|
|
|
transl_structure fields cc rootpath rem
|
|
|
|
|
2013-10-02 01:34:01 -07:00
|
|
|
and pure_module m =
|
|
|
|
match m.mod_desc with
|
|
|
|
Tmod_ident _ -> Alias
|
|
|
|
| Tmod_constraint (m,_,_,_) -> pure_module m
|
|
|
|
| _ -> Strict
|
|
|
|
|
1998-02-26 04:54:44 -08:00
|
|
|
(* Update forward declaration in Translcore *)
|
|
|
|
let _ =
|
|
|
|
Translcore.transl_module := transl_module
|
|
|
|
|
1995-05-04 03:15:53 -07:00
|
|
|
(* Compile an implementation *)
|
|
|
|
|
1998-04-27 08:16:48 -07:00
|
|
|
let transl_implementation module_name (str, cc) =
|
1996-04-22 04:15:41 -07:00
|
|
|
reset_labels ();
|
1995-11-05 09:32:12 -08:00
|
|
|
primitive_declarations := [];
|
1996-04-22 04:15:41 -07:00
|
|
|
let module_id = Ident.create_persistent module_name in
|
1998-06-23 03:06:50 -07:00
|
|
|
Lprim(Psetglobal module_id,
|
|
|
|
[transl_label_init
|
2012-05-30 07:52:37 -07:00
|
|
|
(transl_struct [] cc (global_path module_id) str)])
|
1995-05-04 03:15:53 -07:00
|
|
|
|
2012-12-13 07:40:25 -08:00
|
|
|
|
|
|
|
(* Build the list of value identifiers defined by a toplevel structure
|
|
|
|
(excluding primitive declarations). *)
|
|
|
|
|
|
|
|
let rec defined_idents = function
|
|
|
|
[] -> []
|
|
|
|
| item :: rem ->
|
|
|
|
match item.str_desc with
|
2013-04-11 07:07:32 -07:00
|
|
|
| Tstr_eval (expr, _) -> defined_idents rem
|
2013-06-03 08:14:19 -07:00
|
|
|
| Tstr_value(rec_flag, pat_expr_list) ->
|
2012-12-13 07:40:25 -08:00
|
|
|
let_bound_idents pat_expr_list @ defined_idents rem
|
2013-03-25 11:04:40 -07:00
|
|
|
| Tstr_primitive desc -> defined_idents rem
|
2012-12-13 07:40:25 -08:00
|
|
|
| Tstr_type decls -> defined_idents rem
|
2013-03-25 11:42:45 -07:00
|
|
|
| Tstr_exception decl -> decl.cd_id :: defined_idents rem
|
2013-03-25 07:16:07 -07:00
|
|
|
| Tstr_exn_rebind(id, _, path, _, _) -> id :: defined_idents rem
|
2013-03-26 01:09:26 -07:00
|
|
|
| Tstr_module mb -> mb.mb_id :: defined_idents rem
|
2012-12-13 07:40:25 -08:00
|
|
|
| Tstr_recmodule decls ->
|
2013-03-26 01:09:26 -07:00
|
|
|
List.map (fun mb -> mb.mb_id) decls @ defined_idents rem
|
2013-03-26 01:21:29 -07:00
|
|
|
| Tstr_modtype _ -> defined_idents rem
|
2013-05-16 06:34:53 -07:00
|
|
|
| Tstr_open _ -> defined_idents rem
|
2012-12-13 07:40:25 -08:00
|
|
|
| Tstr_class cl_list ->
|
|
|
|
List.map (fun (ci, _, _) -> ci.ci_id_class) cl_list @ defined_idents rem
|
|
|
|
| Tstr_class_type cl_list -> defined_idents rem
|
2013-07-22 10:03:39 -07:00
|
|
|
| Tstr_include(modl, sg, _) -> bound_value_identifiers sg @ defined_idents rem
|
2013-03-25 07:16:07 -07:00
|
|
|
| Tstr_attribute _ -> []
|
2012-12-13 07:40:25 -08:00
|
|
|
|
2013-03-09 14:38:52 -08:00
|
|
|
(* second level idents (module M = struct ... let id = ... end),
|
|
|
|
and all sub-levels idents *)
|
2012-12-13 07:40:25 -08:00
|
|
|
let rec more_idents = function
|
|
|
|
[] -> []
|
|
|
|
| item :: rem ->
|
|
|
|
match item.str_desc with
|
2013-04-11 07:07:32 -07:00
|
|
|
| Tstr_eval (expr, _attrs) -> more_idents rem
|
2013-06-03 08:14:19 -07:00
|
|
|
| Tstr_value(rec_flag, pat_expr_list) -> more_idents rem
|
2013-03-25 11:04:40 -07:00
|
|
|
| Tstr_primitive _ -> more_idents rem
|
2012-12-13 07:40:25 -08:00
|
|
|
| Tstr_type decls -> more_idents rem
|
2013-03-25 11:42:45 -07:00
|
|
|
| Tstr_exception _ -> more_idents rem
|
2013-03-25 07:16:07 -07:00
|
|
|
| Tstr_exn_rebind(id, _, path, _, _) -> more_idents rem
|
2012-12-13 07:40:25 -08:00
|
|
|
| Tstr_recmodule decls -> more_idents rem
|
2013-03-26 01:21:29 -07:00
|
|
|
| Tstr_modtype _ -> more_idents rem
|
2013-05-16 06:34:53 -07:00
|
|
|
| Tstr_open _ -> more_idents rem
|
2012-12-13 07:40:25 -08:00
|
|
|
| Tstr_class cl_list -> more_idents rem
|
|
|
|
| Tstr_class_type cl_list -> more_idents rem
|
2013-07-22 10:03:39 -07:00
|
|
|
| Tstr_include(modl, _, _) -> more_idents rem
|
2013-03-26 01:09:26 -07:00
|
|
|
| Tstr_module {mb_expr={mod_desc = Tmod_structure str}} ->
|
|
|
|
all_idents str.str_items @ more_idents rem
|
|
|
|
| Tstr_module _ -> more_idents rem
|
2013-03-25 07:16:07 -07:00
|
|
|
| Tstr_attribute _ -> []
|
2012-12-13 07:40:25 -08:00
|
|
|
|
|
|
|
and all_idents = function
|
|
|
|
[] -> []
|
|
|
|
| item :: rem ->
|
|
|
|
match item.str_desc with
|
2013-04-11 07:07:32 -07:00
|
|
|
| Tstr_eval (expr, _attrs) -> all_idents rem
|
2013-06-03 08:14:19 -07:00
|
|
|
| Tstr_value(rec_flag, pat_expr_list) ->
|
2012-12-13 07:40:25 -08:00
|
|
|
let_bound_idents pat_expr_list @ all_idents rem
|
2013-03-25 11:04:40 -07:00
|
|
|
| Tstr_primitive _ -> all_idents rem
|
2012-12-13 07:40:25 -08:00
|
|
|
| Tstr_type decls -> all_idents rem
|
2013-03-25 11:42:45 -07:00
|
|
|
| Tstr_exception decl -> decl.cd_id :: all_idents rem
|
2013-03-25 07:16:07 -07:00
|
|
|
| Tstr_exn_rebind(id, _, path, _, _) -> id :: all_idents rem
|
2012-12-13 07:40:25 -08:00
|
|
|
| Tstr_recmodule decls ->
|
2013-03-26 01:09:26 -07:00
|
|
|
List.map (fun mb -> mb.mb_id) decls @ all_idents rem
|
2013-03-26 01:21:29 -07:00
|
|
|
| Tstr_modtype _ -> all_idents rem
|
2013-05-16 06:34:53 -07:00
|
|
|
| Tstr_open _ -> all_idents rem
|
2012-12-13 07:40:25 -08:00
|
|
|
| Tstr_class cl_list ->
|
|
|
|
List.map (fun (ci, _, _) -> ci.ci_id_class) cl_list @ all_idents rem
|
|
|
|
| Tstr_class_type cl_list -> all_idents rem
|
2013-07-22 10:03:39 -07:00
|
|
|
| Tstr_include(modl, sg, _) -> bound_value_identifiers sg @ all_idents rem
|
2013-03-26 01:09:26 -07:00
|
|
|
| Tstr_module {mb_id;mb_expr={mod_desc = Tmod_structure str}} ->
|
|
|
|
mb_id :: all_idents str.str_items @ all_idents rem
|
|
|
|
| Tstr_module mb -> mb.mb_id :: all_idents rem
|
2013-03-25 07:16:07 -07:00
|
|
|
| Tstr_attribute _ -> []
|
2012-12-13 07:40:25 -08:00
|
|
|
|
|
|
|
|
1996-02-18 06:43:18 -08:00
|
|
|
(* A variant of transl_structure used to compile toplevel structure definitions
|
|
|
|
for the native-code compiler. Store the defined values in the fields
|
|
|
|
of the global as soon as they are defined, in order to reduce register
|
1999-02-04 02:31:16 -08:00
|
|
|
pressure. Also rewrites the defining expressions so that they
|
|
|
|
refer to earlier fields of the structure through the fields of
|
|
|
|
the global, not by their names.
|
|
|
|
"map" is a table from defined idents to (pos in global block, coercion).
|
|
|
|
"prim" is a list of (pos in global block, primitive declaration). *)
|
1996-02-18 06:43:18 -08:00
|
|
|
|
2007-11-06 07:16:56 -08:00
|
|
|
let transl_store_subst = ref Ident.empty
|
|
|
|
(** In the native toplevel, this reference is threaded through successive
|
|
|
|
calls of transl_store_structure *)
|
|
|
|
|
|
|
|
let nat_toplevel_name id =
|
|
|
|
try match Ident.find_same id !transl_store_subst with
|
|
|
|
| Lprim(Pfield pos, [Lprim(Pgetglobal glob, [])]) -> (glob,pos)
|
|
|
|
| _ -> raise Not_found
|
|
|
|
with Not_found ->
|
|
|
|
fatal_error("Translmod.nat_toplevel_name: " ^ Ident.unique_name id)
|
|
|
|
|
1996-04-18 09:28:28 -07:00
|
|
|
let transl_store_structure glob map prims str =
|
2012-12-13 07:40:25 -08:00
|
|
|
let rec transl_store rootpath subst = function
|
1996-02-18 06:43:18 -08:00
|
|
|
[] ->
|
2007-11-06 07:16:56 -08:00
|
|
|
transl_store_subst := subst;
|
2012-05-30 07:52:37 -07:00
|
|
|
lambda_unit
|
|
|
|
| item :: rem ->
|
|
|
|
match item.str_desc with
|
2013-04-11 07:07:32 -07:00
|
|
|
| Tstr_eval (expr, _attrs) ->
|
1999-02-04 02:31:16 -08:00
|
|
|
Lsequence(subst_lambda subst (transl_exp expr),
|
2012-12-13 07:40:25 -08:00
|
|
|
transl_store rootpath subst rem)
|
2013-06-03 08:14:19 -07:00
|
|
|
| Tstr_value(rec_flag, pat_expr_list) ->
|
1999-02-04 02:31:16 -08:00
|
|
|
let ids = let_bound_idents pat_expr_list in
|
|
|
|
let lam = transl_let rec_flag pat_expr_list (store_idents ids) in
|
|
|
|
Lsequence(subst_lambda subst lam,
|
2012-12-13 07:40:25 -08:00
|
|
|
transl_store rootpath (add_idents false ids subst) rem)
|
2013-03-25 11:04:40 -07:00
|
|
|
| Tstr_primitive descr ->
|
2012-05-30 07:52:37 -07:00
|
|
|
record_primitive descr.val_val;
|
2012-12-13 07:40:25 -08:00
|
|
|
transl_store rootpath subst rem
|
2012-05-30 07:52:37 -07:00
|
|
|
| Tstr_type(decls) ->
|
2012-12-13 07:40:25 -08:00
|
|
|
transl_store rootpath subst rem
|
2013-03-25 11:42:45 -07:00
|
|
|
| Tstr_exception decl ->
|
|
|
|
let id = decl.cd_id in
|
|
|
|
let lam = transl_exception (field_path rootpath id) decl in
|
1999-02-04 02:31:16 -08:00
|
|
|
Lsequence(Llet(Strict, id, lam, store_ident id),
|
2012-12-13 07:40:25 -08:00
|
|
|
transl_store rootpath (add_ident false id subst) rem)
|
2013-03-25 07:16:07 -07:00
|
|
|
| Tstr_exn_rebind( id, _, path, _, _) ->
|
2013-10-02 01:34:01 -07:00
|
|
|
let lam = subst_lambda subst (transl_ident_path item.str_env path) in
|
2000-03-12 05:10:29 -08:00
|
|
|
Lsequence(Llet(Strict, id, lam, store_ident id),
|
2012-12-13 07:40:25 -08:00
|
|
|
transl_store rootpath (add_ident false id subst) rem)
|
2013-03-26 01:09:26 -07:00
|
|
|
| Tstr_module{mb_id=id; mb_expr={mod_desc = Tmod_structure str}} ->
|
2012-12-13 07:40:25 -08:00
|
|
|
let lam = transl_store (field_path rootpath id) subst str.str_items in
|
|
|
|
(* Careful: see next case *)
|
|
|
|
let subst = !transl_store_subst in
|
|
|
|
Lsequence(lam,
|
2013-03-09 14:38:52 -08:00
|
|
|
Llet(Strict, id,
|
|
|
|
subst_lambda subst
|
|
|
|
(Lprim(Pmakeblock(0, Immutable),
|
|
|
|
List.map (fun id -> Lvar id)
|
|
|
|
(defined_idents str.str_items))),
|
|
|
|
Lsequence(store_ident id,
|
|
|
|
transl_store rootpath (add_ident true id subst)
|
|
|
|
rem)))
|
2013-03-26 01:09:26 -07:00
|
|
|
| Tstr_module{mb_id=id; mb_expr=modl} ->
|
2013-09-29 04:49:07 -07:00
|
|
|
let lam = transl_module Tcoerce_none (field_path rootpath id) modl in
|
1999-02-25 06:02:44 -08:00
|
|
|
(* Careful: the module value stored in the global may be different
|
|
|
|
from the local module value, in case a coercion is applied.
|
|
|
|
If so, keep using the local module value (id) in the remainder of
|
|
|
|
the compilation unit (add_ident true returns subst unchanged).
|
|
|
|
If not, we can use the value from the global
|
|
|
|
(add_ident true adds id -> Pgetglobal... to subst). *)
|
|
|
|
Llet(Strict, id, subst_lambda subst lam,
|
2013-03-09 14:38:52 -08:00
|
|
|
Lsequence(store_ident id,
|
|
|
|
transl_store rootpath (add_ident true id subst) rem))
|
2012-05-30 07:52:37 -07:00
|
|
|
| Tstr_recmodule bindings ->
|
2013-03-26 01:09:26 -07:00
|
|
|
let ids = List.map (fun mb -> mb.mb_id) bindings in
|
2003-06-19 08:53:53 -07:00
|
|
|
compile_recmodule
|
|
|
|
(fun id modl ->
|
|
|
|
subst_lambda subst
|
|
|
|
(transl_module Tcoerce_none
|
2012-12-13 07:40:25 -08:00
|
|
|
(field_path rootpath id) modl))
|
2003-06-19 08:53:53 -07:00
|
|
|
bindings
|
|
|
|
(Lsequence(store_idents ids,
|
2012-12-13 07:40:25 -08:00
|
|
|
transl_store rootpath (add_idents true ids subst) rem))
|
2012-05-30 07:52:37 -07:00
|
|
|
| Tstr_class cl_list ->
|
|
|
|
let ids = List.map (fun (ci, _, _) -> ci.ci_id_class) cl_list in
|
1999-02-04 02:31:16 -08:00
|
|
|
let lam =
|
|
|
|
Lletrec(List.map
|
2012-05-30 07:52:37 -07:00
|
|
|
(fun (ci, meths, vf) ->
|
|
|
|
let id = ci.ci_id_class in
|
|
|
|
let cl = ci.ci_expr in
|
|
|
|
(id, transl_class ids id meths cl vf))
|
1999-02-04 02:31:16 -08:00
|
|
|
cl_list,
|
|
|
|
store_idents ids) in
|
|
|
|
Lsequence(subst_lambda subst lam,
|
2012-12-13 07:40:25 -08:00
|
|
|
transl_store rootpath (add_idents false ids subst) rem)
|
2013-07-22 10:03:39 -07:00
|
|
|
| Tstr_include(modl, sg, _attrs) ->
|
2013-07-17 08:25:47 -07:00
|
|
|
let ids = bound_value_identifiers sg in
|
2000-12-01 01:35:00 -08:00
|
|
|
let mid = Ident.create "include" in
|
|
|
|
let rec store_idents pos = function
|
2012-12-13 07:40:25 -08:00
|
|
|
[] -> transl_store rootpath (add_idents true ids subst) rem
|
2000-12-01 01:35:00 -08:00
|
|
|
| id :: idl ->
|
|
|
|
Llet(Alias, id, Lprim(Pfield pos, [Lvar mid]),
|
|
|
|
Lsequence(store_ident id, store_idents (pos + 1) idl)) in
|
2002-06-17 06:48:55 -07:00
|
|
|
Llet(Strict, mid,
|
|
|
|
subst_lambda subst (transl_module Tcoerce_none None modl),
|
2000-12-01 01:35:00 -08:00
|
|
|
store_idents 0 ids)
|
2013-03-25 07:16:07 -07:00
|
|
|
| Tstr_modtype _
|
|
|
|
| Tstr_open _
|
|
|
|
| Tstr_class_type _
|
|
|
|
| Tstr_attribute _ ->
|
|
|
|
transl_store rootpath subst rem
|
1996-04-18 09:28:28 -07:00
|
|
|
|
1999-02-04 02:31:16 -08:00
|
|
|
and store_ident id =
|
1996-04-18 09:28:28 -07:00
|
|
|
try
|
|
|
|
let (pos, cc) = Ident.find_same id map in
|
2013-10-02 01:34:01 -07:00
|
|
|
let init_val = apply_coercion Alias cc (Lvar id) in
|
1999-02-04 02:31:16 -08:00
|
|
|
Lprim(Psetfield(pos, false), [Lprim(Pgetglobal glob, []); init_val])
|
1996-04-18 09:28:28 -07:00
|
|
|
with Not_found ->
|
1999-02-25 06:02:44 -08:00
|
|
|
fatal_error("Translmod.store_ident: " ^ Ident.unique_name id)
|
1996-04-18 09:28:28 -07:00
|
|
|
|
1999-02-04 02:31:16 -08:00
|
|
|
and store_idents idlist =
|
|
|
|
make_sequence store_ident idlist
|
|
|
|
|
1999-02-25 06:02:44 -08:00
|
|
|
and add_ident may_coerce id subst =
|
1999-02-04 02:31:16 -08:00
|
|
|
try
|
|
|
|
let (pos, cc) = Ident.find_same id map in
|
1999-02-25 06:02:44 -08:00
|
|
|
match cc with
|
|
|
|
Tcoerce_none ->
|
|
|
|
Ident.add id (Lprim(Pfield pos, [Lprim(Pgetglobal glob, [])])) subst
|
|
|
|
| _ ->
|
|
|
|
if may_coerce then subst else assert false
|
1999-02-04 02:31:16 -08:00
|
|
|
with Not_found ->
|
1999-02-25 06:02:44 -08:00
|
|
|
assert false
|
1999-02-04 02:31:16 -08:00
|
|
|
|
2000-12-01 01:35:00 -08:00
|
|
|
and add_idents may_coerce idlist subst =
|
|
|
|
List.fold_right (add_ident may_coerce) idlist subst
|
1996-04-18 09:28:28 -07:00
|
|
|
|
|
|
|
and store_primitive (pos, prim) cont =
|
|
|
|
Lsequence(Lprim(Psetfield(pos, false),
|
2012-08-21 00:12:04 -07:00
|
|
|
[Lprim(Pgetglobal glob, []);
|
|
|
|
transl_primitive Location.none prim]),
|
1996-04-18 09:28:28 -07:00
|
|
|
cont)
|
1996-02-18 06:43:18 -08:00
|
|
|
|
2013-03-09 14:38:52 -08:00
|
|
|
in List.fold_right store_primitive prims
|
|
|
|
(transl_store (global_path glob) !transl_store_subst str)
|
1996-02-18 06:43:18 -08:00
|
|
|
|
1999-02-04 02:31:16 -08:00
|
|
|
(* Transform a coercion and the list of value identifiers defined by
|
|
|
|
a toplevel structure into a table [id -> (pos, coercion)],
|
|
|
|
with [pos] being the position in the global block where the value of
|
|
|
|
[id] must be stored, and [coercion] the coercion to be applied to it.
|
1996-04-18 09:28:28 -07:00
|
|
|
A given identifier may appear several times
|
|
|
|
in the coercion (if it occurs several times in the signature); remember
|
|
|
|
to assign it the position of its last occurrence.
|
1999-02-04 02:31:16 -08:00
|
|
|
Identifiers that are not exported are assigned positions at the
|
|
|
|
end of the block (beyond the positions of all exported idents).
|
|
|
|
Also compute the total size of the global block,
|
|
|
|
and the list of all primitives exported as values. *)
|
1996-02-18 06:43:18 -08:00
|
|
|
|
2012-12-13 07:40:25 -08:00
|
|
|
let build_ident_map restr idlist more_ids =
|
1999-02-04 02:31:16 -08:00
|
|
|
let rec natural_map pos map prims = function
|
|
|
|
[] ->
|
|
|
|
(map, prims, pos)
|
|
|
|
| id :: rem ->
|
|
|
|
natural_map (pos+1) (Ident.add id (pos, Tcoerce_none) map) prims rem in
|
2012-12-13 07:40:25 -08:00
|
|
|
let (map, prims, pos) =
|
|
|
|
match restr with
|
2013-03-09 14:38:52 -08:00
|
|
|
Tcoerce_none ->
|
|
|
|
natural_map 0 Ident.empty [] idlist
|
2013-09-30 04:35:15 -07:00
|
|
|
| Tcoerce_structure (pos_cc_list, _id_pos_list) ->
|
|
|
|
(* ignore _id_pos_list as the ids are already bound *)
|
2013-03-09 14:38:52 -08:00
|
|
|
let idarray = Array.of_list idlist in
|
|
|
|
let rec export_map pos map prims undef = function
|
1996-04-18 09:28:28 -07:00
|
|
|
[] ->
|
1999-02-04 02:31:16 -08:00
|
|
|
natural_map pos map prims undef
|
2013-03-09 14:38:52 -08:00
|
|
|
| (source_pos, Tcoerce_primitive p) :: rem ->
|
2012-12-13 07:40:25 -08:00
|
|
|
export_map (pos + 1) map ((pos, p) :: prims) undef rem
|
2013-03-09 14:38:52 -08:00
|
|
|
| (source_pos, cc) :: rem ->
|
2012-12-13 07:40:25 -08:00
|
|
|
let id = idarray.(source_pos) in
|
|
|
|
export_map (pos + 1) (Ident.add id (pos, cc) map)
|
|
|
|
prims (list_remove id undef) rem
|
2013-03-09 14:38:52 -08:00
|
|
|
in export_map 0 Ident.empty [] idlist pos_cc_list
|
2012-12-13 07:40:25 -08:00
|
|
|
| _ ->
|
2013-03-09 14:38:52 -08:00
|
|
|
fatal_error "Translmod.build_ident_map"
|
2012-12-13 07:40:25 -08:00
|
|
|
in
|
|
|
|
natural_map pos map prims more_ids
|
1999-02-04 02:31:16 -08:00
|
|
|
|
2008-01-11 08:13:18 -08:00
|
|
|
(* Compile an implementation using transl_store_structure
|
1996-02-18 06:43:18 -08:00
|
|
|
(for the native-code compiler). *)
|
|
|
|
|
2012-05-30 07:52:37 -07:00
|
|
|
let transl_store_gen module_name ({ str_items = str }, restr) topl =
|
1996-04-22 04:15:41 -07:00
|
|
|
reset_labels ();
|
1996-02-18 06:43:18 -08:00
|
|
|
primitive_declarations := [];
|
1996-04-22 04:15:41 -07:00
|
|
|
let module_id = Ident.create_persistent module_name in
|
2013-03-09 14:38:52 -08:00
|
|
|
let (map, prims, size) =
|
|
|
|
build_ident_map restr (defined_idents str) (more_idents str) in
|
2007-11-06 07:16:56 -08:00
|
|
|
let f = function
|
2013-04-11 07:07:32 -07:00
|
|
|
| [ { str_desc = Tstr_eval (expr, _attrs) } ] when topl ->
|
2008-01-11 08:13:18 -08:00
|
|
|
assert (size = 0);
|
|
|
|
subst_lambda !transl_store_subst (transl_exp expr)
|
2007-11-06 07:16:56 -08:00
|
|
|
| str -> transl_store_structure module_id map prims str in
|
|
|
|
transl_store_label_init module_id size f str
|
2004-05-26 04:10:52 -07:00
|
|
|
(*size, transl_label_init (transl_store_structure module_id map prims str)*)
|
1996-02-18 06:43:18 -08:00
|
|
|
|
2007-11-06 07:16:56 -08:00
|
|
|
let transl_store_phrases module_name str =
|
|
|
|
transl_store_gen module_name (str,Tcoerce_none) true
|
|
|
|
|
|
|
|
let transl_store_implementation module_name (str, restr) =
|
|
|
|
let s = !transl_store_subst in
|
|
|
|
transl_store_subst := Ident.empty;
|
|
|
|
let r = transl_store_gen module_name (str, restr) false in
|
|
|
|
transl_store_subst := s;
|
|
|
|
r
|
|
|
|
|
1995-05-04 03:15:53 -07:00
|
|
|
(* Compile a toplevel phrase *)
|
|
|
|
|
2000-05-16 09:19:04 -07:00
|
|
|
let toploop_ident = Ident.create_persistent "Toploop"
|
|
|
|
let toploop_getvalue_pos = 0 (* position of getvalue in module Toploop *)
|
|
|
|
let toploop_setvalue_pos = 1 (* position of setvalue in module Toploop *)
|
|
|
|
|
2000-06-13 00:00:14 -07:00
|
|
|
let aliased_idents = ref Ident.empty
|
2000-06-12 07:22:37 -07:00
|
|
|
|
2003-05-12 02:10:18 -07:00
|
|
|
let set_toplevel_unique_name id =
|
|
|
|
aliased_idents :=
|
|
|
|
Ident.add id (Ident.unique_toplevel_name id) !aliased_idents
|
2000-06-12 07:22:37 -07:00
|
|
|
|
|
|
|
let toplevel_name id =
|
2000-06-13 00:00:14 -07:00
|
|
|
try Ident.find_same id !aliased_idents
|
2000-06-12 07:22:37 -07:00
|
|
|
with Not_found -> Ident.name id
|
|
|
|
|
2000-05-16 09:19:04 -07:00
|
|
|
let toploop_getvalue id =
|
|
|
|
Lapply(Lprim(Pfield toploop_getvalue_pos,
|
|
|
|
[Lprim(Pgetglobal toploop_ident, [])]),
|
2013-03-26 04:17:17 -07:00
|
|
|
[Lconst(Const_base(Const_string (toplevel_name id, None)))],
|
2007-05-16 01:21:41 -07:00
|
|
|
Location.none)
|
2000-05-16 09:19:04 -07:00
|
|
|
|
|
|
|
let toploop_setvalue id lam =
|
|
|
|
Lapply(Lprim(Pfield toploop_setvalue_pos,
|
|
|
|
[Lprim(Pgetglobal toploop_ident, [])]),
|
2013-03-26 04:17:17 -07:00
|
|
|
[Lconst(Const_base(Const_string (toplevel_name id, None))); lam],
|
2007-05-16 01:21:41 -07:00
|
|
|
Location.none)
|
2000-05-16 09:19:04 -07:00
|
|
|
|
|
|
|
let toploop_setvalue_id id = toploop_setvalue id (Lvar id)
|
|
|
|
|
|
|
|
let close_toplevel_term lam =
|
|
|
|
IdentSet.fold (fun id l -> Llet(Strict, id, toploop_getvalue id, l))
|
|
|
|
(free_variables lam) lam
|
|
|
|
|
2012-05-30 07:52:37 -07:00
|
|
|
let transl_toplevel_item item =
|
|
|
|
match item.str_desc with
|
2013-04-11 07:07:32 -07:00
|
|
|
Tstr_eval (expr, _attrs) ->
|
1995-12-15 02:18:29 -08:00
|
|
|
transl_exp expr
|
2013-06-03 08:14:19 -07:00
|
|
|
| Tstr_value(rec_flag, pat_expr_list) ->
|
1995-05-04 03:15:53 -07:00
|
|
|
let idents = let_bound_idents pat_expr_list in
|
2000-05-16 09:19:04 -07:00
|
|
|
transl_let rec_flag pat_expr_list
|
|
|
|
(make_sequence toploop_setvalue_id idents)
|
2013-03-25 11:42:45 -07:00
|
|
|
| Tstr_exception decl ->
|
|
|
|
toploop_setvalue decl.cd_id (transl_exception None decl)
|
2013-03-25 07:16:07 -07:00
|
|
|
| Tstr_exn_rebind(id, _, path, _, _) ->
|
2013-10-02 01:34:01 -07:00
|
|
|
toploop_setvalue id (transl_ident_path item.str_env path)
|
2013-03-26 01:09:26 -07:00
|
|
|
| Tstr_module {mb_id=id; mb_expr=modl} ->
|
2003-05-12 02:10:18 -07:00
|
|
|
(* we need to use the unique name for the module because of issues
|
|
|
|
with "open" (PR#1672) *)
|
|
|
|
set_toplevel_unique_name id;
|
2013-09-29 04:49:07 -07:00
|
|
|
let lam = transl_module Tcoerce_none (Some(Pident id)) modl in
|
2013-09-29 00:22:34 -07:00
|
|
|
toploop_setvalue id lam
|
2003-06-19 08:53:53 -07:00
|
|
|
| Tstr_recmodule bindings ->
|
2013-03-26 01:09:26 -07:00
|
|
|
let idents = List.map (fun mb -> mb.mb_id) bindings in
|
2003-06-19 08:53:53 -07:00
|
|
|
compile_recmodule
|
|
|
|
(fun id modl -> transl_module Tcoerce_none (Some(Pident id)) modl)
|
|
|
|
bindings
|
|
|
|
(make_sequence toploop_setvalue_id idents)
|
1996-04-22 04:15:41 -07:00
|
|
|
| Tstr_class cl_list ->
|
2003-05-12 02:10:18 -07:00
|
|
|
(* we need to use unique names for the classes because there might
|
|
|
|
be a value named identically *)
|
2012-05-30 07:52:37 -07:00
|
|
|
let ids = List.map (fun (ci, _, _) -> ci.ci_id_class) cl_list in
|
2003-05-12 02:10:18 -07:00
|
|
|
List.iter set_toplevel_unique_name ids;
|
2000-05-16 09:19:04 -07:00
|
|
|
Lletrec(List.map
|
2012-05-30 07:52:37 -07:00
|
|
|
(fun (ci, meths, vf) ->
|
|
|
|
let id = ci.ci_id_class in
|
|
|
|
let cl = ci.ci_expr in
|
|
|
|
(id, transl_class ids id meths cl vf))
|
2000-05-16 09:19:04 -07:00
|
|
|
cl_list,
|
|
|
|
make_sequence
|
2012-05-30 07:52:37 -07:00
|
|
|
(fun (ci, _, _) -> toploop_setvalue_id ci.ci_id_class)
|
2000-05-16 09:19:04 -07:00
|
|
|
cl_list)
|
2013-07-22 10:03:39 -07:00
|
|
|
| Tstr_include(modl, sg, _attrs) ->
|
2013-07-17 08:25:47 -07:00
|
|
|
let ids = bound_value_identifiers sg in
|
2000-12-01 01:35:00 -08:00
|
|
|
let mid = Ident.create "include" in
|
|
|
|
let rec set_idents pos = function
|
|
|
|
[] ->
|
|
|
|
lambda_unit
|
|
|
|
| id :: ids ->
|
|
|
|
Lsequence(toploop_setvalue id (Lprim(Pfield pos, [Lvar mid])),
|
|
|
|
set_idents (pos + 1) ids) in
|
|
|
|
Llet(Strict, mid, transl_module Tcoerce_none None modl, set_idents 0 ids)
|
2013-03-25 07:16:07 -07:00
|
|
|
| Tstr_modtype _
|
|
|
|
| Tstr_open _
|
|
|
|
| Tstr_primitive _
|
|
|
|
| Tstr_type _
|
|
|
|
| Tstr_class_type _
|
|
|
|
| Tstr_attribute _ ->
|
|
|
|
lambda_unit
|
1995-05-04 03:15:53 -07:00
|
|
|
|
2000-06-04 08:13:42 -07:00
|
|
|
let transl_toplevel_item_and_close itm =
|
|
|
|
close_toplevel_term (transl_label_init (transl_toplevel_item itm))
|
|
|
|
|
1995-05-04 03:15:53 -07:00
|
|
|
let transl_toplevel_definition str =
|
1996-04-22 04:15:41 -07:00
|
|
|
reset_labels ();
|
2012-05-30 07:52:37 -07:00
|
|
|
make_sequence transl_toplevel_item_and_close str.str_items
|
2003-03-06 07:59:55 -08:00
|
|
|
|
|
|
|
(* Compile the initialization code for a packed library *)
|
|
|
|
|
2004-04-09 06:32:28 -07:00
|
|
|
let get_component = function
|
|
|
|
None -> Lconst const_unit
|
2008-01-11 08:13:18 -08:00
|
|
|
| Some id -> Lprim(Pgetglobal id, [])
|
2004-04-09 06:32:28 -07:00
|
|
|
|
2003-03-06 07:59:55 -08:00
|
|
|
let transl_package component_names target_name coercion =
|
|
|
|
let components =
|
|
|
|
match coercion with
|
|
|
|
Tcoerce_none ->
|
2004-04-09 06:32:28 -07:00
|
|
|
List.map get_component component_names
|
2013-09-30 04:35:15 -07:00
|
|
|
| Tcoerce_structure (pos_cc_list, id_pos_list) ->
|
|
|
|
(* ignore id_pos_list as the ids are already bound *)
|
2003-03-06 07:59:55 -08:00
|
|
|
let g = Array.of_list component_names in
|
|
|
|
List.map
|
2013-10-02 01:34:01 -07:00
|
|
|
(fun (pos, cc) -> apply_coercion Strict cc (get_component g.(pos)))
|
2003-03-06 07:59:55 -08:00
|
|
|
pos_cc_list
|
|
|
|
| _ ->
|
|
|
|
assert false in
|
|
|
|
Lprim(Psetglobal target_name, [Lprim(Pmakeblock(0, Immutable), components)])
|
|
|
|
|
|
|
|
let transl_store_package component_names target_name coercion =
|
|
|
|
let rec make_sequence fn pos arg =
|
|
|
|
match arg with
|
|
|
|
[] -> lambda_unit
|
|
|
|
| hd :: tl -> Lsequence(fn pos hd, make_sequence fn (pos + 1) tl) in
|
|
|
|
match coercion with
|
|
|
|
Tcoerce_none ->
|
|
|
|
(List.length component_names,
|
|
|
|
make_sequence
|
|
|
|
(fun pos id ->
|
|
|
|
Lprim(Psetfield(pos, false),
|
|
|
|
[Lprim(Pgetglobal target_name, []);
|
2004-04-09 06:32:28 -07:00
|
|
|
get_component id]))
|
2003-03-06 07:59:55 -08:00
|
|
|
0 component_names)
|
2013-09-30 04:35:15 -07:00
|
|
|
| Tcoerce_structure (pos_cc_list, id_pos_list) ->
|
|
|
|
(* ignore id_pos_list as the ids are already bound *)
|
2003-03-06 07:59:55 -08:00
|
|
|
let id = Array.of_list component_names in
|
|
|
|
(List.length pos_cc_list,
|
|
|
|
make_sequence
|
|
|
|
(fun dst (src, cc) ->
|
|
|
|
Lprim(Psetfield(dst, false),
|
|
|
|
[Lprim(Pgetglobal target_name, []);
|
2013-10-02 01:34:01 -07:00
|
|
|
apply_coercion Strict cc (get_component id.(src))]))
|
2003-03-06 07:59:55 -08:00
|
|
|
0 pos_cc_list)
|
|
|
|
| _ -> assert false
|
2003-06-19 08:53:53 -07:00
|
|
|
|
|
|
|
(* Error report *)
|
|
|
|
|
|
|
|
open Format
|
|
|
|
|
|
|
|
let report_error ppf = function
|
|
|
|
Circular_dependency id ->
|
|
|
|
fprintf ppf
|
2013-03-09 14:38:52 -08:00
|
|
|
"@[Cannot safely evaluate the definition@ \
|
|
|
|
of the recursively-defined module %a@]"
|
2003-06-19 08:53:53 -07:00
|
|
|
Printtyp.ident id
|
2013-09-12 07:24:27 -07:00
|
|
|
|
|
|
|
let () =
|
|
|
|
Location.register_error_of_exn
|
|
|
|
(function
|
|
|
|
| Error (loc, err) ->
|
|
|
|
Some (Location.error_of_printer loc report_error err)
|
|
|
|
| _ ->
|
|
|
|
None
|
|
|
|
)
|