1995-08-09 08:06:35 -07:00
|
|
|
(***********************************************************************)
|
|
|
|
(* *)
|
1996-04-30 07:53:58 -07:00
|
|
|
(* Objective Caml *)
|
1995-08-09 08:06:35 -07:00
|
|
|
(* *)
|
1996-04-29 06:24:25 -07:00
|
|
|
(* Xavier Leroy and Jerome Vouillon, projet Cristal, INRIA Rocquencourt*)
|
1995-08-09 08:06:35 -07:00
|
|
|
(* *)
|
1996-04-30 07:53:58 -07:00
|
|
|
(* Copyright 1996 Institut National de Recherche en Informatique et *)
|
1995-08-09 08:06:35 -07:00
|
|
|
(* Automatique. Distributed only by permission. *)
|
|
|
|
(* *)
|
|
|
|
(***********************************************************************)
|
|
|
|
|
|
|
|
(* $Id$ *)
|
|
|
|
|
1995-05-04 03:15:53 -07:00
|
|
|
(* Operations on core types *)
|
|
|
|
|
|
|
|
open Misc
|
1996-04-22 04:15:41 -07:00
|
|
|
open Asttypes
|
1996-09-23 04:33:27 -07:00
|
|
|
open Types
|
1995-05-04 03:15:53 -07:00
|
|
|
|
1997-01-20 09:11:47 -08:00
|
|
|
(******* Notes
|
|
|
|
|
|
|
|
- As much sharing as possible should be kept : it makes types
|
|
|
|
smaller and better abbreviated.
|
|
|
|
When necessary, some sharing can be lost. Types will still be
|
|
|
|
printed correctly (XXX a faire...), and types defined for a class
|
|
|
|
do not depend on sharing thanks to constrained abbreviations (XXX
|
|
|
|
a faire...).
|
|
|
|
- All nodes of a type must have a level : that way, one know
|
|
|
|
whether a node must be duplicated or not when instantiating a
|
|
|
|
type.
|
|
|
|
- Levels of a type must be decreasing.
|
|
|
|
- The level of a type constructor must be superior to the binding
|
|
|
|
time of its path.
|
|
|
|
|
|
|
|
*)
|
|
|
|
|
|
|
|
(****** A faire
|
|
|
|
|
|
|
|
- Revoir affichage des types.
|
|
|
|
- Abreviations avec contraintes.
|
|
|
|
- Revoir [copy].
|
|
|
|
- Types recursifs sans limitation.
|
|
|
|
- #-type implementes comme de vraies abreviations.
|
|
|
|
- Effacer les abreviations memorisees plus tot ?
|
|
|
|
|
|
|
|
*)
|
|
|
|
|
1996-05-26 06:42:34 -07:00
|
|
|
exception Subtype of
|
|
|
|
(type_expr * type_expr) list * (type_expr * type_expr) list
|
1995-05-04 03:15:53 -07:00
|
|
|
|
|
|
|
let current_level = ref 0
|
1996-04-22 04:15:41 -07:00
|
|
|
let global_level = ref 1
|
1995-05-04 03:15:53 -07:00
|
|
|
let generic_level = (-1)
|
|
|
|
|
1996-07-15 09:35:35 -07:00
|
|
|
let init_def level = current_level := level
|
1995-05-04 03:15:53 -07:00
|
|
|
let begin_def () = incr current_level
|
1995-12-22 02:54:36 -08:00
|
|
|
let end_def () = decr current_level
|
1995-05-04 03:15:53 -07:00
|
|
|
|
1996-04-22 04:15:41 -07:00
|
|
|
let reset_global_level () =
|
|
|
|
global_level := !current_level + 1
|
1995-05-04 03:15:53 -07:00
|
|
|
|
1996-04-22 04:15:41 -07:00
|
|
|
let newty desc = { desc = desc; level = !current_level }
|
|
|
|
let new_global_ty desc = { desc = desc; level = !global_level }
|
|
|
|
let newgenty desc = { desc = desc; level = generic_level }
|
|
|
|
let newvar () = { desc = Tvar; level = !current_level }
|
|
|
|
let new_global_var () = new_global_ty Tvar
|
|
|
|
let new_gen_var () = newgenty Tvar
|
|
|
|
let newobj fields = newty (Tobject (fields, ref None))
|
1995-10-31 07:58:31 -08:00
|
|
|
|
1995-05-04 03:15:53 -07:00
|
|
|
let rec repr = function
|
1996-04-22 04:15:41 -07:00
|
|
|
{desc = Tlink t'} as t ->
|
|
|
|
let r = repr t' in
|
|
|
|
if r != t' then t.desc <- Tlink r;
|
1995-05-04 03:15:53 -07:00
|
|
|
r
|
|
|
|
| t -> t
|
|
|
|
|
1996-04-22 04:15:41 -07:00
|
|
|
let none = newty (Ttuple []) (* Clearly ill-formed type *)
|
|
|
|
|
|
|
|
(* --- *)
|
|
|
|
|
1997-01-20 09:11:47 -08:00
|
|
|
(**** Object field manipulation. ****)
|
|
|
|
|
1996-04-22 04:15:41 -07:00
|
|
|
let flatten_fields ty =
|
|
|
|
let rec flatten l ty =
|
|
|
|
let ty = repr ty in
|
|
|
|
match ty.desc with
|
|
|
|
Tfield(s, ty1, ty2) ->
|
|
|
|
flatten ((s, ty1)::l) ty2
|
|
|
|
| Tvar | Tnil ->
|
|
|
|
(l, ty)
|
|
|
|
| _ ->
|
|
|
|
fatal_error "Ctype.flatten_fields"
|
|
|
|
in
|
|
|
|
let (l, r) = flatten [] ty in
|
|
|
|
(List.rev l, r)
|
|
|
|
|
|
|
|
let build_fields =
|
|
|
|
List.fold_right
|
|
|
|
(fun (s, ty1) ty2 ->
|
|
|
|
{desc = Tfield(s, ty1, ty2);
|
|
|
|
level = ty2.level})
|
|
|
|
|
|
|
|
let associate_fields fields1 fields2 =
|
|
|
|
let rec associate p s s' =
|
|
|
|
function
|
|
|
|
(l, []) ->
|
|
|
|
(List.rev p, (List.rev s) @ l, List.rev s')
|
|
|
|
| ([], l') ->
|
|
|
|
(List.rev p, List.rev s, (List.rev s') @ l')
|
|
|
|
| (((n, t)::r as l), ((n', t')::r' as l')) ->
|
1996-05-16 09:10:16 -07:00
|
|
|
if n = n' then
|
1996-04-22 04:15:41 -07:00
|
|
|
associate ((t, t')::p) s s' (r, r')
|
1996-05-16 09:10:16 -07:00
|
|
|
else if n < n' then
|
1996-04-22 04:15:41 -07:00
|
|
|
associate p ((n, t)::s) s' (r, l')
|
|
|
|
else
|
|
|
|
associate p s ((n', t')::s') (l, r')
|
1996-05-16 09:10:16 -07:00
|
|
|
in let sort = Sort.list (fun (n, _) (n', _) -> n < n') in
|
1996-04-22 04:15:41 -07:00
|
|
|
associate [] [] [] (sort fields1, sort fields2)
|
|
|
|
|
1997-01-20 09:11:47 -08:00
|
|
|
(**** Check whether an object is open ****)
|
1996-04-22 04:15:41 -07:00
|
|
|
|
1997-01-20 09:11:47 -08:00
|
|
|
(* XXX Faudra penser a eventuellement expanser l'abreviation *)
|
|
|
|
let rec opened_object ty =
|
1996-04-22 04:15:41 -07:00
|
|
|
match (repr ty).desc with
|
1997-01-20 09:11:47 -08:00
|
|
|
Tobject (t, _) -> opened_object t
|
|
|
|
| Tfield(_, _, t) -> opened_object t
|
1996-04-22 04:15:41 -07:00
|
|
|
| Tvar -> true
|
1997-01-20 09:11:47 -08:00
|
|
|
| _ -> false
|
1996-04-22 04:15:41 -07:00
|
|
|
|
1997-01-20 09:11:47 -08:00
|
|
|
(**** Type generalization ****)
|
1995-11-16 05:27:53 -08:00
|
|
|
|
1997-01-20 09:11:47 -08:00
|
|
|
(* XXX Probablement pas le bon endroit pour effacer l'abreviation *)
|
1995-05-04 03:15:53 -07:00
|
|
|
let rec generalize ty =
|
1996-04-22 04:15:41 -07:00
|
|
|
let ty = repr ty in
|
|
|
|
if ty.level > !current_level then begin
|
|
|
|
ty.level <- generic_level;
|
1997-01-20 09:11:47 -08:00
|
|
|
begin match ty.desc with
|
|
|
|
Tconstr(_, tl, ab) -> ab := []
|
|
|
|
| _ -> ()
|
|
|
|
end;
|
|
|
|
iter_type_expr generalize ty
|
1996-04-22 04:15:41 -07:00
|
|
|
end
|
1995-05-04 03:15:53 -07:00
|
|
|
|
|
|
|
let rec make_nongen ty =
|
1996-04-22 04:15:41 -07:00
|
|
|
let ty = repr ty in
|
|
|
|
if ty.level > !current_level then begin
|
|
|
|
ty.level <- !current_level;
|
1997-01-20 09:11:47 -08:00
|
|
|
iter_type_expr make_nongen ty
|
1996-04-22 04:15:41 -07:00
|
|
|
end
|
|
|
|
|
1997-01-20 09:11:47 -08:00
|
|
|
(**** Remove abbreviations from generalized types ****)
|
1996-04-22 04:15:41 -07:00
|
|
|
|
1997-01-20 09:11:47 -08:00
|
|
|
(* XXX Plutot ne jamais laisser trainer d'abbrev ? *)
|
1996-04-22 04:15:41 -07:00
|
|
|
let visited = ref ([] : type_expr list)
|
|
|
|
|
|
|
|
let remove_abbrev ty =
|
|
|
|
let rec remove ty =
|
|
|
|
let ty = repr ty in
|
|
|
|
if ty.level = generic_level & not (List.memq ty !visited) then begin
|
|
|
|
visited := ty :: !visited;
|
|
|
|
match ty.desc with
|
|
|
|
Tvar -> ()
|
|
|
|
| Tarrow(t1, t2) -> remove t1; remove t2
|
|
|
|
| Ttuple tl -> List.iter remove tl
|
|
|
|
| Tconstr(_, tl, ab) -> ab := []; List.iter remove tl
|
|
|
|
| Tobject(f, {contents = Some (_, p)})
|
|
|
|
-> remove f; List.iter remove p
|
|
|
|
| Tobject(f, _) -> remove f
|
|
|
|
| Tfield(_, t1, t2) -> remove t1; remove t2
|
|
|
|
| Tnil -> ()
|
|
|
|
| Tlink _ -> fatal_error "Ctype.remove_abbrev"
|
|
|
|
end
|
|
|
|
in
|
|
|
|
visited := []; remove ty; visited := []
|
|
|
|
|
1995-05-04 03:15:53 -07:00
|
|
|
|
1997-01-20 09:11:47 -08:00
|
|
|
(*******************)
|
|
|
|
(* Instantiation *)
|
|
|
|
(*******************)
|
|
|
|
|
|
|
|
(* XXX HUGE simplification ? *)
|
1995-11-16 05:27:53 -08:00
|
|
|
|
1996-04-22 04:15:41 -07:00
|
|
|
type 'a visited = Zero | One | Many of 'a
|
|
|
|
|
1995-05-04 03:15:53 -07:00
|
|
|
let inst_subst = ref ([] : (type_expr * type_expr) list)
|
|
|
|
|
1996-04-22 04:15:41 -07:00
|
|
|
let rec copy_rec abbrev visited ty =
|
|
|
|
let ty = repr ty in
|
|
|
|
if ty.level <> generic_level then ty else
|
|
|
|
try
|
|
|
|
match List.assq ty visited with
|
|
|
|
{contents = Zero} as v ->
|
|
|
|
let t = newvar () in
|
|
|
|
v := Many t;
|
|
|
|
let ty' = copy_rec_2 abbrev visited ty v in
|
|
|
|
t.desc <- ty'.desc;
|
|
|
|
t
|
|
|
|
| {contents = One} as v ->
|
|
|
|
let t = newvar () in
|
|
|
|
v := Many t;
|
|
|
|
t
|
|
|
|
| {contents = Many t} ->
|
|
|
|
t
|
|
|
|
with Not_found ->
|
|
|
|
let v = ref One in
|
|
|
|
let ty' = copy_rec_2 abbrev ((ty, v)::visited) ty v in
|
|
|
|
match v with
|
|
|
|
{contents = Many t} ->
|
|
|
|
t.desc <- ty'.desc;
|
|
|
|
t
|
|
|
|
| _ ->
|
|
|
|
ty'
|
|
|
|
|
|
|
|
and copy_rec_2 abbrev visited ty v =
|
|
|
|
match ty.desc with
|
|
|
|
Tvar ->
|
|
|
|
begin try List.assq ty !inst_subst with Not_found ->
|
|
|
|
let ty' = newvar () in
|
|
|
|
inst_subst := (ty, ty') :: !inst_subst;
|
|
|
|
ty'
|
|
|
|
end
|
|
|
|
| Tarrow (t1, t2) ->
|
|
|
|
newty (Tarrow (copy_rec abbrev visited t1,
|
|
|
|
copy_rec abbrev visited t2))
|
|
|
|
| Ttuple tl ->
|
|
|
|
newty (Ttuple (List.map (copy_rec abbrev visited) tl))
|
|
|
|
| Tconstr (p, [], _) ->
|
|
|
|
newty (Tconstr (p, [], ref abbrev))
|
|
|
|
| Tconstr (p, tl, _) ->
|
|
|
|
newty (Tconstr (p, List.map (copy_rec abbrev visited) tl,
|
|
|
|
ref abbrev))
|
|
|
|
| Tobject (t1, {contents = name}) ->
|
|
|
|
let ty' () =
|
|
|
|
let name' =
|
|
|
|
match name with
|
|
|
|
None ->
|
|
|
|
None
|
|
|
|
| Some (p, tl) ->
|
|
|
|
Some (p, List.map (copy_rec abbrev visited) tl)
|
|
|
|
in
|
|
|
|
newty (Tobject (copy_rec abbrev visited t1, ref name'))
|
|
|
|
in
|
|
|
|
if opened_object ty then
|
1995-05-04 03:15:53 -07:00
|
|
|
try
|
1996-04-22 04:15:41 -07:00
|
|
|
List.assq ty !inst_subst
|
1995-05-04 03:15:53 -07:00
|
|
|
with Not_found ->
|
1996-04-22 04:15:41 -07:00
|
|
|
if v = ref One then begin
|
|
|
|
let t = newvar () in
|
|
|
|
v := Many t;
|
|
|
|
inst_subst := (ty, t):: !inst_subst
|
|
|
|
end;
|
|
|
|
ty' ()
|
|
|
|
else
|
|
|
|
ty' ()
|
|
|
|
| Tfield (label, t1, t2) ->
|
|
|
|
newty (Tfield (label, copy_rec abbrev visited t1,
|
|
|
|
copy_rec abbrev visited t2))
|
|
|
|
| Tnil ->
|
|
|
|
newty Tnil
|
|
|
|
| Tlink _ ->
|
|
|
|
fatal_error "Ctype.copy_rec"
|
|
|
|
|
|
|
|
let copy ty = copy_rec [] [] ty
|
|
|
|
let subst abbrev ty = copy_rec abbrev [] ty
|
|
|
|
let copy_parameterized params ty = copy_rec [] params ty
|
1995-05-04 03:15:53 -07:00
|
|
|
|
|
|
|
let instance sch =
|
|
|
|
inst_subst := [];
|
|
|
|
let ty = copy sch in
|
|
|
|
inst_subst := [];
|
|
|
|
ty
|
|
|
|
|
|
|
|
let instance_constructor cstr =
|
|
|
|
inst_subst := [];
|
|
|
|
let ty_res = copy cstr.cstr_res in
|
|
|
|
let ty_args = List.map copy cstr.cstr_args in
|
|
|
|
inst_subst := [];
|
|
|
|
(ty_args, ty_res)
|
|
|
|
|
|
|
|
let instance_label lbl =
|
|
|
|
inst_subst := [];
|
|
|
|
let ty_res = copy lbl.lbl_res in
|
|
|
|
let ty_arg = copy lbl.lbl_arg in
|
|
|
|
inst_subst := [];
|
|
|
|
(ty_arg, ty_res)
|
|
|
|
|
1996-04-22 04:15:41 -07:00
|
|
|
let substitute abbrev params args body =
|
1995-07-02 09:50:08 -07:00
|
|
|
inst_subst := List.combine params args;
|
1996-04-22 04:15:41 -07:00
|
|
|
let ty = subst abbrev body in
|
1995-05-04 03:15:53 -07:00
|
|
|
inst_subst := [];
|
|
|
|
ty
|
|
|
|
|
1996-04-22 04:15:41 -07:00
|
|
|
let instance_parameterized_type sch_args sch =
|
|
|
|
inst_subst := [];
|
|
|
|
let params = List.map (function p -> (repr p, ref Zero)) sch_args in
|
|
|
|
let ty_args = List.map (copy_parameterized params) sch_args in
|
|
|
|
let ty = copy_parameterized params sch in
|
|
|
|
inst_subst := [];
|
|
|
|
(ty_args, ty)
|
|
|
|
|
|
|
|
let instance_parameterized_type_2 sch_args sch_lst sch =
|
|
|
|
inst_subst := [];
|
|
|
|
let params = List.map (function p -> (repr p, ref Zero)) sch_args in
|
|
|
|
let ty_args = List.map (copy_parameterized params) sch_args in
|
|
|
|
let ty_lst = List.map (copy_parameterized params) sch_lst in
|
|
|
|
let ty = copy_parameterized params sch in
|
|
|
|
inst_subst := [];
|
|
|
|
(ty_args, ty_lst, ty)
|
|
|
|
|
|
|
|
let instance_class cl =
|
|
|
|
inst_subst := [];
|
|
|
|
let params0 = List.map (function p -> (repr p, ref Zero)) cl.cty_params in
|
|
|
|
let params = List.map (copy_parameterized params0) cl.cty_params in
|
|
|
|
let args = List.map (copy_parameterized params0) cl.cty_args in
|
|
|
|
let vars =
|
|
|
|
Vars.fold
|
|
|
|
(fun lab (mut, ty) ->
|
|
|
|
Vars.add lab (mut, copy_parameterized params0 ty))
|
|
|
|
cl.cty_vars
|
|
|
|
Vars.empty in
|
|
|
|
let self = copy_parameterized params0 cl.cty_self in
|
|
|
|
inst_subst := [];
|
|
|
|
(params, args, vars, self)
|
|
|
|
|
1997-01-20 09:11:47 -08:00
|
|
|
(*****************)
|
|
|
|
(* Unification *)
|
|
|
|
(*****************)
|
|
|
|
|
|
|
|
|
|
|
|
(**** Unification errors ****)
|
|
|
|
|
|
|
|
exception Unify of (type_expr * type_expr) list
|
|
|
|
|
|
|
|
(**** Lower the levels of a type ****)
|
1995-11-16 05:27:53 -08:00
|
|
|
|
1996-04-22 04:15:41 -07:00
|
|
|
let rec update_level level ty =
|
1997-01-20 09:11:47 -08:00
|
|
|
let ty = repr ty in
|
1996-04-22 04:15:41 -07:00
|
|
|
if ty.level > level then begin
|
|
|
|
ty.level <- level;
|
1997-01-20 09:11:47 -08:00
|
|
|
begin match ty.desc with
|
|
|
|
Tconstr(p, tl, _) when level < Path.binding_time p -> raise (Unify [])
|
|
|
|
| _ -> ()
|
|
|
|
end;
|
|
|
|
iter_type_expr (update_level level) ty
|
1996-04-22 04:15:41 -07:00
|
|
|
end
|
|
|
|
|
1997-01-20 09:11:47 -08:00
|
|
|
(**** Abbreviation expansion ****)
|
|
|
|
|
1995-05-04 03:15:53 -07:00
|
|
|
exception Cannot_expand
|
|
|
|
|
1997-01-20 09:11:47 -08:00
|
|
|
(* Search whether the abbreviation has been memorized. *)
|
1996-04-22 04:15:41 -07:00
|
|
|
let rec find_expans p1 =
|
|
|
|
function
|
|
|
|
[] ->
|
|
|
|
None
|
|
|
|
| (p2, ty)::l ->
|
|
|
|
if Path.same p1 p2 then
|
|
|
|
Some ty
|
|
|
|
else
|
|
|
|
find_expans p1 l
|
|
|
|
|
1997-01-20 09:11:47 -08:00
|
|
|
(* Expand an abbreviation.
|
|
|
|
The expansion is memorized. *)
|
1996-04-22 04:15:41 -07:00
|
|
|
let expand_abbrev env path args abbrev level =
|
|
|
|
match find_expans path !abbrev with
|
|
|
|
Some ty ->
|
|
|
|
update_level level ty;
|
|
|
|
ty
|
|
|
|
| None ->
|
1996-10-01 02:47:18 -07:00
|
|
|
let decl =
|
|
|
|
try Env.find_type path env with Not_found -> raise Cannot_expand in
|
|
|
|
match decl.type_manifest with
|
|
|
|
Some body ->
|
|
|
|
let v = newvar () in
|
|
|
|
abbrev := (path, v)::!abbrev;
|
|
|
|
let old_level = !current_level in
|
|
|
|
current_level := level;
|
|
|
|
let ty = substitute !abbrev decl.type_params args body in
|
|
|
|
current_level := old_level;
|
|
|
|
v.desc <- Tlink ty;
|
|
|
|
ty
|
|
|
|
| _ ->
|
|
|
|
raise Cannot_expand
|
1996-04-22 04:15:41 -07:00
|
|
|
|
1997-01-20 09:11:47 -08:00
|
|
|
(* Recursively expand the root of a type. *)
|
1996-05-20 09:43:29 -07:00
|
|
|
let rec expand_root env ty =
|
|
|
|
let ty = repr ty in
|
|
|
|
match ty.desc with
|
|
|
|
Tconstr(p, tl, abbrev) ->
|
|
|
|
begin try
|
|
|
|
expand_root env (expand_abbrev env p tl (ref !abbrev) ty.level)
|
|
|
|
with Cannot_expand ->
|
|
|
|
ty
|
|
|
|
end
|
|
|
|
| _ ->
|
|
|
|
ty
|
|
|
|
|
1997-01-20 09:11:47 -08:00
|
|
|
(* Recursively expand the root of a type.
|
|
|
|
Also expand #-types. *)
|
|
|
|
(* XXX This is a hack ! *)
|
1996-05-20 09:43:29 -07:00
|
|
|
let rec full_expand env ty =
|
|
|
|
let ty = repr (expand_root env ty) in
|
|
|
|
match ty.desc with
|
1996-05-26 06:42:34 -07:00
|
|
|
Tobject (fi, {contents = Some (_, v::_)}) when (repr v).desc = Tvar ->
|
1996-05-20 09:43:29 -07:00
|
|
|
{ desc = Tobject (fi, ref None); level = ty.level }
|
|
|
|
| _ ->
|
|
|
|
ty
|
|
|
|
|
1997-01-20 09:11:47 -08:00
|
|
|
(* Check whether the abbreviation expands to a well-defined type.
|
|
|
|
During the typing of a class, abbreviations for correspondings
|
|
|
|
types expand to non-generic types. *)
|
1996-04-22 04:15:41 -07:00
|
|
|
let generic_abbrev env path =
|
1995-11-03 05:23:03 -08:00
|
|
|
try
|
|
|
|
let decl = Env.find_type path env in
|
|
|
|
match decl.type_manifest with
|
1996-04-22 04:15:41 -07:00
|
|
|
Some body ->
|
|
|
|
body.level = generic_level
|
|
|
|
| _ ->
|
|
|
|
false
|
|
|
|
with
|
|
|
|
Not_found ->
|
|
|
|
false
|
1995-05-04 03:15:53 -07:00
|
|
|
|
1997-01-20 09:11:47 -08:00
|
|
|
(**** Occur check ****)
|
1996-10-28 09:51:55 -08:00
|
|
|
|
1997-01-20 09:11:47 -08:00
|
|
|
(* XXX A supprimer *)
|
1996-04-22 04:15:41 -07:00
|
|
|
let occur env ty0 ty =
|
|
|
|
let visited = ref ([] : type_expr list) in
|
|
|
|
let rec occur_rec ty =
|
1996-06-10 04:26:54 -07:00
|
|
|
let ty = repr ty in
|
|
|
|
if ty == ty0 then raise (Unify []);
|
1996-04-22 04:15:41 -07:00
|
|
|
match ty.desc with
|
1996-07-15 09:35:35 -07:00
|
|
|
Tvar ->
|
1996-04-22 04:15:41 -07:00
|
|
|
()
|
|
|
|
| Tarrow(t1, t2) ->
|
|
|
|
occur_rec t1; occur_rec t2
|
|
|
|
| Ttuple tl ->
|
|
|
|
List.iter occur_rec tl
|
1996-07-15 09:35:35 -07:00
|
|
|
| Tconstr(p, [], abbrev) ->
|
1996-10-28 09:51:55 -08:00
|
|
|
()
|
1996-04-22 04:15:41 -07:00
|
|
|
| Tconstr(p, tl, abbrev) ->
|
|
|
|
if not (List.memq ty !visited) then begin
|
|
|
|
visited := ty :: !visited;
|
1996-10-28 09:51:55 -08:00
|
|
|
try List.iter occur_rec tl with Unify _ ->
|
|
|
|
try
|
|
|
|
let ty' = expand_abbrev env p tl abbrev ty.level in
|
1996-07-15 09:35:35 -07:00
|
|
|
occur_rec ty'
|
1996-10-28 09:51:55 -08:00
|
|
|
with Cannot_expand -> ()
|
1996-04-22 04:15:41 -07:00
|
|
|
end
|
1997-01-20 09:11:47 -08:00
|
|
|
| Tobject (_, _) | Tfield (_, _, _) | Tnil ->
|
1996-04-22 04:15:41 -07:00
|
|
|
()
|
1997-01-20 09:11:47 -08:00
|
|
|
| Tlink _ ->
|
1996-04-22 04:15:41 -07:00
|
|
|
fatal_error "Ctype.occur"
|
|
|
|
in
|
|
|
|
occur_rec ty
|
|
|
|
|
1997-01-20 09:11:47 -08:00
|
|
|
(**** Transform error trace ****)
|
|
|
|
|
|
|
|
let expand_trace env trace =
|
|
|
|
List.fold_right
|
|
|
|
(fun (t1, t2) rem ->
|
|
|
|
(repr t1, full_expand env t1)::(repr t2, full_expand env t2)::rem)
|
|
|
|
trace []
|
|
|
|
|
|
|
|
let rec filter_trace =
|
|
|
|
function
|
|
|
|
(t1, t1')::(t2, t2')::rem ->
|
|
|
|
let rem' = filter_trace rem in
|
|
|
|
if (t1 == t1') & (t2 == t2') then
|
|
|
|
rem'
|
|
|
|
else
|
|
|
|
(t1, t1')::(t2, t2')::rem
|
|
|
|
| _ ->
|
|
|
|
[]
|
|
|
|
|
|
|
|
(**** Unification ****)
|
|
|
|
|
1996-04-22 04:15:41 -07:00
|
|
|
let rec unify_rec env a1 a2 t1 t2 = (* Variables and abbreviations *)
|
|
|
|
if t1 == t2 then () else
|
1997-01-20 09:11:47 -08:00
|
|
|
let t1 = repr t1 in
|
|
|
|
let t2 = repr t2 in
|
1996-04-22 04:15:41 -07:00
|
|
|
if t1 == t2 then () else
|
1996-05-20 09:43:29 -07:00
|
|
|
try
|
|
|
|
match (t1.desc, t2.desc) with
|
|
|
|
(Tvar, _) ->
|
|
|
|
update_level t1.level t2;
|
|
|
|
begin match a2 with
|
1996-10-28 09:51:55 -08:00
|
|
|
None ->
|
1997-01-20 09:11:47 -08:00
|
|
|
occur env t1 t2; t1.desc <- Tlink t2
|
1996-10-28 09:51:55 -08:00
|
|
|
| Some l2 ->
|
1997-01-20 09:11:47 -08:00
|
|
|
occur env t1 l2; t1.desc <- Tlink l2
|
1996-05-20 09:43:29 -07:00
|
|
|
end
|
|
|
|
| (_, Tvar) ->
|
|
|
|
update_level t2.level t1;
|
|
|
|
begin match a1 with
|
1996-10-28 09:51:55 -08:00
|
|
|
None ->
|
1997-01-20 09:11:47 -08:00
|
|
|
occur env t2 t1; t2.desc <- Tlink t1
|
1996-10-28 09:51:55 -08:00
|
|
|
| Some l1 ->
|
1997-01-20 09:11:47 -08:00
|
|
|
occur env t2 l1; t2.desc <- Tlink l1
|
1996-05-20 09:43:29 -07:00
|
|
|
end
|
1996-10-26 08:43:02 -07:00
|
|
|
| (Tconstr (p1, tl1, abbrev1), Tconstr (p2, tl2, abbrev2))
|
|
|
|
when Path.same p1 p2 ->
|
|
|
|
begin
|
|
|
|
try
|
|
|
|
unify_core env a1 a2 t1 t2
|
|
|
|
with Unify lst ->
|
|
|
|
try
|
|
|
|
let t3 = expand_abbrev env p1 tl1 abbrev1 t1.level in
|
|
|
|
update_level t2.level t1;
|
|
|
|
unify_rec env (Some t1) a2 t3 t2
|
|
|
|
with Cannot_expand ->
|
|
|
|
try
|
|
|
|
let t3 = expand_abbrev env p2 tl2 abbrev2 t2.level in
|
|
|
|
update_level t1.level t2;
|
|
|
|
unify_rec env a1 (Some t2) t1 t3
|
|
|
|
with Cannot_expand ->
|
|
|
|
raise (Unify lst)
|
|
|
|
end
|
1996-05-20 09:43:29 -07:00
|
|
|
| (Tconstr (p1, tl1, abbrev1), Tconstr (p2, tl2, abbrev2)) ->
|
|
|
|
begin
|
|
|
|
try
|
|
|
|
let t3 = expand_abbrev env p1 tl1 abbrev1 t1.level in
|
|
|
|
update_level t2.level t1;
|
|
|
|
unify_rec env (Some t1) a2 t3 t2
|
|
|
|
with Cannot_expand ->
|
|
|
|
try
|
|
|
|
let t3 = expand_abbrev env p2 tl2 abbrev2 t2.level in
|
|
|
|
update_level t1.level t2;
|
|
|
|
unify_rec env a1 (Some t2) t1 t3
|
|
|
|
with Cannot_expand ->
|
|
|
|
raise (Unify [])
|
|
|
|
end
|
|
|
|
| (Tconstr (p1, tl1, abbrev1), _) ->
|
|
|
|
begin try
|
1996-04-22 04:15:41 -07:00
|
|
|
let t3 = expand_abbrev env p1 tl1 abbrev1 t1.level in
|
|
|
|
update_level t2.level t1;
|
|
|
|
unify_rec env (Some t1) a2 t3 t2
|
|
|
|
with Cannot_expand ->
|
1996-05-20 09:43:29 -07:00
|
|
|
unify_core env a1 a2 t1 t2
|
|
|
|
end
|
|
|
|
| (_, Tconstr (p2, tl2, abbrev2)) ->
|
|
|
|
begin try
|
1996-04-22 04:15:41 -07:00
|
|
|
let t3 = expand_abbrev env p2 tl2 abbrev2 t2.level in
|
|
|
|
update_level t1.level t2;
|
|
|
|
unify_rec env a1 (Some t2) t1 t3
|
|
|
|
with Cannot_expand ->
|
1996-05-20 09:43:29 -07:00
|
|
|
unify_core env a1 a2 t1 t2
|
|
|
|
end
|
|
|
|
| (_, _) ->
|
1996-04-22 04:15:41 -07:00
|
|
|
unify_core env a1 a2 t1 t2
|
1996-05-20 09:43:29 -07:00
|
|
|
with
|
|
|
|
Unify [] ->
|
|
|
|
raise (Unify [(t1, t2)])
|
|
|
|
| Unify (_::l) ->
|
|
|
|
raise (Unify ((t1, t2)::l))
|
1996-04-22 04:15:41 -07:00
|
|
|
|
|
|
|
and unify_core env a1 a2 t1 t2 = (* Other cases *)
|
|
|
|
let d1 = t1.desc and d2 = t2.desc in
|
|
|
|
begin match (a1, a2) with
|
|
|
|
(None, Some l2) ->
|
|
|
|
update_level t1.level t2; t1.desc <- Tlink l2
|
|
|
|
| (Some l1, None) ->
|
|
|
|
update_level t2.level t1; t2.desc <- Tlink l1
|
|
|
|
| (_, _) ->
|
1996-06-10 04:26:54 -07:00
|
|
|
update_level t1.level t2; occur env t1 t2; t1.desc <- Tlink t2
|
1996-04-22 04:15:41 -07:00
|
|
|
end;
|
|
|
|
try
|
|
|
|
match (d1, d2) with
|
|
|
|
(Tarrow (t1, u1), Tarrow (t2, u2)) ->
|
|
|
|
unify_rec env None None t1 t2; unify_rec env None None u1 u2
|
|
|
|
| (Ttuple tl1, Ttuple tl2) ->
|
|
|
|
unify_list env tl1 tl2
|
|
|
|
| (Tconstr (p1, [], _), Tconstr (p2, [], _)) (*when Path.same p1 p2*) ->
|
|
|
|
()
|
|
|
|
| (Tconstr (p1, tl1, _), Tconstr (p2, tl2, _)) (*when Path.same p1 p2*) ->
|
|
|
|
unify_list env tl1 tl2
|
|
|
|
| (Tobject (fi1, nm1), Tobject (fi2, nm2)) ->
|
1996-09-23 10:15:59 -07:00
|
|
|
unify_fields env fi1 fi2;
|
|
|
|
begin match !nm2 with
|
1996-04-22 04:15:41 -07:00
|
|
|
Some (_, va::_) when (repr va).desc = Tvar -> ()
|
|
|
|
| _ -> nm2 := !nm1
|
|
|
|
end
|
1997-01-20 09:11:47 -08:00
|
|
|
| (Tfield _, Tfield _) ->
|
|
|
|
unify_fields env t1 t2
|
|
|
|
| (Tnil, Tnil) ->
|
|
|
|
()
|
1996-04-22 04:15:41 -07:00
|
|
|
| (_, _) ->
|
1996-05-20 09:43:29 -07:00
|
|
|
raise (Unify [])
|
|
|
|
with
|
|
|
|
Unify l ->
|
|
|
|
t1.desc <- d1;
|
|
|
|
t2.desc <- d2;
|
|
|
|
raise (Unify ((t1, t2)::l))
|
|
|
|
| exn ->
|
|
|
|
t1.desc <- d1;
|
|
|
|
t2.desc <- d2;
|
|
|
|
raise exn
|
1995-05-04 03:15:53 -07:00
|
|
|
|
|
|
|
and unify_list env tl1 tl2 =
|
1996-05-31 05:27:03 -07:00
|
|
|
if List.length tl1 <> List.length tl2 then
|
|
|
|
raise (Unify []);
|
|
|
|
List.iter2 (unify_rec env None None) tl1 tl2
|
1996-04-22 04:15:41 -07:00
|
|
|
|
1997-01-20 09:11:47 -08:00
|
|
|
and unify_fields env ty1 ty2 = (* Optimization *)
|
1996-04-22 04:15:41 -07:00
|
|
|
let (fields1, rest1) = flatten_fields ty1
|
|
|
|
and (fields2, rest2) = flatten_fields ty2 in
|
|
|
|
let (pairs, miss1, miss2) = associate_fields fields1 fields2 in
|
|
|
|
let va = newvar () in
|
|
|
|
begin match rest1.desc with
|
|
|
|
Tvar ->
|
1997-01-20 09:11:47 -08:00
|
|
|
unify_rec env None None rest1 (build_fields miss2 va)
|
1996-04-22 04:15:41 -07:00
|
|
|
| Tnil ->
|
1996-05-20 09:43:29 -07:00
|
|
|
if miss2 <> [] then raise (Unify []);
|
1996-04-22 04:15:41 -07:00
|
|
|
va.desc <- Tlink {desc = Tnil; level = va.level}
|
|
|
|
| _ ->
|
|
|
|
fatal_error "Ctype.unify_fields (1)"
|
|
|
|
end;
|
|
|
|
begin match rest2.desc with
|
|
|
|
Tvar ->
|
1997-01-20 09:11:47 -08:00
|
|
|
unify_rec env None None (build_fields miss1 va) rest2
|
1996-04-22 04:15:41 -07:00
|
|
|
| Tnil ->
|
1996-05-20 09:43:29 -07:00
|
|
|
if miss1 <> [] then raise (Unify []);
|
1996-04-22 04:15:41 -07:00
|
|
|
va.desc <- Tlink {desc = Tnil; level = va.level}
|
|
|
|
| _ ->
|
|
|
|
fatal_error "Ctype.unify_fields (2)"
|
|
|
|
end;
|
|
|
|
List.iter (fun (t1, t2) -> unify_rec env None None t1 t2) pairs
|
|
|
|
|
|
|
|
let unify env ty1 ty2 =
|
1996-05-20 09:43:29 -07:00
|
|
|
try
|
|
|
|
unify_rec env None None ty1 ty2
|
|
|
|
with Unify trace ->
|
|
|
|
let trace = expand_trace env trace in
|
|
|
|
match trace with
|
|
|
|
t1::t2::rem ->
|
|
|
|
raise (Unify (t1::t2::filter_trace rem))
|
|
|
|
| _ ->
|
|
|
|
fatal_error "Ctype.unify"
|
1995-05-04 03:15:53 -07:00
|
|
|
|
1997-01-20 09:11:47 -08:00
|
|
|
(**** Special cases of unification ****)
|
|
|
|
|
|
|
|
(* Unify [t] and ['a -> 'b]. Return ['a] and ['b]. *)
|
1995-05-04 03:15:53 -07:00
|
|
|
let rec filter_arrow env t =
|
1996-04-22 04:15:41 -07:00
|
|
|
let t = repr t in
|
|
|
|
match t.desc with
|
|
|
|
Tvar ->
|
|
|
|
let t1 = newvar () and t2 = newvar () in
|
|
|
|
let t' = newty (Tarrow (t1, t2)) in
|
|
|
|
update_level t.level t';
|
|
|
|
t.desc <- Tlink t';
|
1995-05-04 03:15:53 -07:00
|
|
|
(t1, t2)
|
|
|
|
| Tarrow(t1, t2) ->
|
|
|
|
(t1, t2)
|
1996-04-22 04:15:41 -07:00
|
|
|
| Tconstr(p, tl, abbrev) ->
|
|
|
|
begin try
|
|
|
|
filter_arrow env (expand_abbrev env p tl abbrev t.level)
|
|
|
|
with Cannot_expand ->
|
1996-05-20 09:43:29 -07:00
|
|
|
raise (Unify [])
|
1996-04-22 04:15:41 -07:00
|
|
|
end
|
|
|
|
| _ ->
|
1996-05-20 09:43:29 -07:00
|
|
|
raise (Unify [])
|
1996-04-22 04:15:41 -07:00
|
|
|
|
1997-01-20 09:11:47 -08:00
|
|
|
(* Used by [filter_method]. *)
|
1996-04-22 04:15:41 -07:00
|
|
|
let rec filter_method_field name ty =
|
|
|
|
let ty = repr ty in
|
|
|
|
match ty.desc with
|
|
|
|
Tvar ->
|
|
|
|
let ty1 = newvar () and ty2 = newvar () in
|
|
|
|
let ty' = newty (Tfield (name, ty1, ty2)) in
|
|
|
|
update_level ty.level ty';
|
|
|
|
ty.desc <- Tlink ty';
|
|
|
|
ty1
|
|
|
|
| Tfield(n, ty1, ty2) ->
|
1996-05-16 09:10:16 -07:00
|
|
|
if n = name then
|
1996-04-22 04:15:41 -07:00
|
|
|
ty1
|
|
|
|
else
|
|
|
|
filter_method_field name ty2
|
|
|
|
| _ ->
|
1996-05-20 09:43:29 -07:00
|
|
|
raise (Unify [])
|
1996-04-22 04:15:41 -07:00
|
|
|
|
1997-01-20 09:11:47 -08:00
|
|
|
(* Unify [ty] and [< name : 'a; .. >]. Return ['a]. *)
|
1996-04-22 04:15:41 -07:00
|
|
|
let rec filter_method env name ty =
|
|
|
|
let ty = repr ty in
|
|
|
|
match ty.desc with
|
|
|
|
Tvar ->
|
1997-01-20 09:11:47 -08:00
|
|
|
let ty1 = newvar () in
|
1996-04-22 04:15:41 -07:00
|
|
|
let ty' = newobj ty1 in
|
|
|
|
update_level ty.level ty';
|
|
|
|
ty.desc <- Tlink ty';
|
|
|
|
filter_method_field name ty1
|
|
|
|
| Tobject(f, _) ->
|
|
|
|
filter_method_field name f
|
|
|
|
| Tconstr(p, tl, abbrev) ->
|
1995-05-04 03:15:53 -07:00
|
|
|
begin try
|
1996-04-22 04:15:41 -07:00
|
|
|
filter_method env name (expand_abbrev env p tl abbrev ty.level)
|
1995-05-04 03:15:53 -07:00
|
|
|
with Cannot_expand ->
|
1996-05-20 09:43:29 -07:00
|
|
|
raise (Unify [])
|
1995-05-04 03:15:53 -07:00
|
|
|
end
|
|
|
|
| _ ->
|
1996-05-20 09:43:29 -07:00
|
|
|
raise (Unify [])
|
1995-05-04 03:15:53 -07:00
|
|
|
|
1997-01-20 09:11:47 -08:00
|
|
|
(**** Matching between type schemes ****)
|
1995-11-16 05:27:53 -08:00
|
|
|
|
1997-01-20 09:11:47 -08:00
|
|
|
(* XXX This is not really an occur check !!! *)
|
1996-10-25 06:40:04 -07:00
|
|
|
let moregen_occur env ty0 ty =
|
1996-04-22 04:15:41 -07:00
|
|
|
let visited = ref [] in
|
|
|
|
let rec occur_rec ty =
|
1996-10-25 06:40:04 -07:00
|
|
|
let ty = repr ty in
|
1997-01-20 09:11:47 -08:00
|
|
|
if not (List.memq ty !visited) then begin
|
|
|
|
visited := ty::!visited;
|
|
|
|
begin match ty.desc with
|
|
|
|
Tvar when ty.level = generic_level & ty0.level < !current_level ->
|
|
|
|
(* ty0 has level = !current_level iff it is generic
|
|
|
|
in the original type scheme. In this case, it can be freely
|
|
|
|
instantiated. Otherwise, ty0 is not generic
|
|
|
|
and cannot be instantiated by a type that contains
|
|
|
|
generic variables. *)
|
|
|
|
raise (Unify [])
|
|
|
|
| Tconstr(p, tl, abbrev) ->
|
|
|
|
(* XXX Pourquoi expanser ? *)
|
|
|
|
begin try
|
1996-10-25 06:40:04 -07:00
|
|
|
List.iter occur_rec tl
|
|
|
|
with Unify lst ->
|
|
|
|
let ty' =
|
|
|
|
try expand_abbrev env p tl abbrev ty.level
|
|
|
|
with Cannot_expand -> raise (Unify lst) in
|
|
|
|
occur_rec ty'
|
1997-01-20 09:11:47 -08:00
|
|
|
end
|
|
|
|
| _ ->
|
|
|
|
iter_type_expr occur_rec ty
|
|
|
|
end
|
|
|
|
end
|
1996-04-22 04:15:41 -07:00
|
|
|
in
|
|
|
|
occur_rec ty
|
1995-11-16 05:27:53 -08:00
|
|
|
|
|
|
|
let rec moregen env t1 t2 =
|
1996-04-22 04:15:41 -07:00
|
|
|
if t1 == t2 then () else
|
|
|
|
let t1 = repr t1 in
|
|
|
|
let t2 = repr t2 in
|
|
|
|
if t1 == t2 then () else
|
|
|
|
let d1 = t1.desc in
|
|
|
|
try
|
|
|
|
begin match (t1.desc, t2.desc) with
|
|
|
|
(Tvar, _) ->
|
1996-05-20 09:43:29 -07:00
|
|
|
if t1.level = generic_level then raise (Unify []);
|
1996-10-25 06:40:04 -07:00
|
|
|
moregen_occur env t1 t2;
|
1996-04-22 04:15:41 -07:00
|
|
|
t1.desc <- Tlink t2
|
|
|
|
| (Tarrow(t1, u1), Tarrow(t2, u2)) ->
|
|
|
|
moregen env t1 t2; moregen env u1 u2
|
|
|
|
| (Ttuple tl1, Ttuple tl2) ->
|
|
|
|
moregen_list env tl1 tl2
|
|
|
|
| (Tconstr(p1, tl1, abbrev1), Tconstr(p2, tl2, abbrev2)) ->
|
|
|
|
if Path.same p1 p2 then begin
|
1996-10-26 08:43:02 -07:00
|
|
|
try
|
|
|
|
t1.desc <- Tlink t2;
|
|
|
|
moregen_list env tl1 tl2;
|
|
|
|
t1.desc <- d1
|
|
|
|
with Unify lst ->
|
|
|
|
t1.desc <- d1;
|
|
|
|
try
|
|
|
|
moregen env (expand_abbrev env p1 tl1 abbrev1 t1.level) t2
|
|
|
|
with Cannot_expand ->
|
|
|
|
try
|
|
|
|
moregen env t1 (expand_abbrev env p2 tl2 abbrev2 t2.level)
|
|
|
|
with Cannot_expand ->
|
|
|
|
raise (Unify lst)
|
1996-04-22 04:15:41 -07:00
|
|
|
end else begin
|
|
|
|
try
|
|
|
|
moregen env (expand_abbrev env p1 tl1 abbrev1 t1.level) t2
|
1995-05-04 03:15:53 -07:00
|
|
|
with Cannot_expand ->
|
1996-04-22 04:15:41 -07:00
|
|
|
try
|
|
|
|
moregen env t1 (expand_abbrev env p2 tl2 abbrev2 t2.level)
|
1995-05-04 03:15:53 -07:00
|
|
|
with Cannot_expand ->
|
1996-05-20 09:43:29 -07:00
|
|
|
raise (Unify [])
|
1996-04-22 04:15:41 -07:00
|
|
|
end
|
|
|
|
| (Tobject(f1, _), Tobject(f2, _)) ->
|
|
|
|
t1.desc <- Tlink t2;
|
1996-09-23 08:57:00 -07:00
|
|
|
moregen_fields env f1 f2
|
1996-04-22 04:15:41 -07:00
|
|
|
| (Tconstr(p1, tl1, abbrev1), _) ->
|
|
|
|
begin try
|
|
|
|
moregen env (expand_abbrev env p1 tl1 abbrev1 t1.level) t2
|
|
|
|
with Cannot_expand ->
|
1996-05-20 09:43:29 -07:00
|
|
|
raise (Unify [])
|
1996-04-22 04:15:41 -07:00
|
|
|
end
|
|
|
|
| (_, Tconstr(p2, tl2, abbrev2)) ->
|
|
|
|
begin try
|
|
|
|
moregen env t1 (expand_abbrev env p2 tl2 abbrev2 t2.level)
|
|
|
|
with Cannot_expand ->
|
1996-05-20 09:43:29 -07:00
|
|
|
raise (Unify [])
|
1996-04-22 04:15:41 -07:00
|
|
|
end
|
|
|
|
| (_, _) ->
|
1996-05-20 09:43:29 -07:00
|
|
|
raise (Unify [])
|
1995-05-04 03:15:53 -07:00
|
|
|
end
|
1996-04-22 04:15:41 -07:00
|
|
|
with exn ->
|
|
|
|
t1.desc <- d1;
|
|
|
|
raise exn
|
1995-05-04 03:15:53 -07:00
|
|
|
|
1995-11-16 05:27:53 -08:00
|
|
|
and moregen_list env tl1 tl2 =
|
1996-05-31 05:27:03 -07:00
|
|
|
if List.length tl1 <> List.length tl2 then
|
|
|
|
raise (Unify []);
|
|
|
|
List.iter2 (moregen env) tl1 tl2
|
1996-04-22 04:15:41 -07:00
|
|
|
|
|
|
|
and moregen_fields env ty1 ty2 =
|
|
|
|
let (fields1, rest1) = flatten_fields ty1
|
|
|
|
and (fields2, rest2) = flatten_fields ty2 in
|
|
|
|
let (pairs, miss1, miss2) = associate_fields fields1 fields2 in
|
1996-05-20 09:43:29 -07:00
|
|
|
if miss1 <> [] then raise (Unify []);
|
1996-04-22 04:15:41 -07:00
|
|
|
begin match rest1.desc with
|
|
|
|
Tvar ->
|
1996-05-20 09:43:29 -07:00
|
|
|
if rest1.level = generic_level then raise (Unify []);
|
1996-04-22 04:15:41 -07:00
|
|
|
let fi = build_fields miss2 rest2 in
|
1996-10-25 06:40:04 -07:00
|
|
|
moregen_occur env rest1 fi
|
1996-04-22 04:15:41 -07:00
|
|
|
| Tnil ->
|
1996-05-20 09:43:29 -07:00
|
|
|
if miss2 <> [] then raise (Unify []);
|
|
|
|
if rest2.desc <> Tnil then raise (Unify [])
|
1996-04-22 04:15:41 -07:00
|
|
|
| _ ->
|
|
|
|
fatal_error "moregen_fields"
|
|
|
|
end;
|
|
|
|
List.iter (fun (t1, t2) -> moregen env t1 t2) pairs
|
|
|
|
|
1995-05-04 03:15:53 -07:00
|
|
|
let moregeneral env sch1 sch2 =
|
1995-11-13 06:25:55 -08:00
|
|
|
begin_def();
|
1995-05-04 03:15:53 -07:00
|
|
|
try
|
1995-11-16 05:27:53 -08:00
|
|
|
moregen env (instance sch1) sch2;
|
1996-04-22 04:15:41 -07:00
|
|
|
remove_abbrev sch2;
|
1995-11-13 06:25:55 -08:00
|
|
|
end_def();
|
|
|
|
true
|
1996-05-20 09:43:29 -07:00
|
|
|
with Unify _ ->
|
1996-04-22 04:15:41 -07:00
|
|
|
remove_abbrev sch2;
|
1995-11-13 06:25:55 -08:00
|
|
|
end_def();
|
1995-05-04 03:15:53 -07:00
|
|
|
false
|
|
|
|
|
1997-01-20 09:11:47 -08:00
|
|
|
(**** Equivalence between parameterized types ****)
|
1995-11-16 05:27:53 -08:00
|
|
|
|
1995-05-04 03:15:53 -07:00
|
|
|
let equal env params1 ty1 params2 ty2 =
|
1996-04-22 04:15:41 -07:00
|
|
|
let subst = ref (List.combine params1 params2) in
|
|
|
|
let type_pairs = ref [] in
|
1995-05-04 03:15:53 -07:00
|
|
|
let rec eqtype t1 t2 =
|
|
|
|
let t1 = repr t1 in
|
|
|
|
let t2 = repr t2 in
|
1996-04-22 04:15:41 -07:00
|
|
|
match (t1.desc, t2.desc) with
|
|
|
|
(Tvar, Tvar) ->
|
1995-05-04 03:15:53 -07:00
|
|
|
begin try
|
1996-04-22 04:15:41 -07:00
|
|
|
List.assq t1 !subst == t2
|
1995-05-04 03:15:53 -07:00
|
|
|
with Not_found ->
|
1996-04-22 04:15:41 -07:00
|
|
|
subst := (t1, t2) :: !subst;
|
|
|
|
true
|
1995-05-04 03:15:53 -07:00
|
|
|
end
|
|
|
|
| (Tarrow(t1, u1), Tarrow(t2, u2)) ->
|
|
|
|
eqtype t1 t2 & eqtype u1 u2
|
|
|
|
| (Ttuple tl1, Ttuple tl2) ->
|
|
|
|
eqtype_list tl1 tl2
|
1996-04-22 04:15:41 -07:00
|
|
|
| (Tconstr(p1, tl1, abbrev1), Tconstr(p2, tl2, abbrev2)) ->
|
|
|
|
List.exists (function (t1', t2') -> t1 == t1' & t2 == t2') !type_pairs
|
|
|
|
or begin
|
|
|
|
type_pairs := (t1, t2) :: !type_pairs;
|
|
|
|
if Path.same p1 p2 then
|
|
|
|
eqtype_list tl1 tl2
|
|
|
|
else begin
|
|
|
|
try
|
|
|
|
eqtype (expand_abbrev env p1 tl1 abbrev1 t1.level) t2
|
|
|
|
with Cannot_expand ->
|
|
|
|
try
|
|
|
|
eqtype t1 (expand_abbrev env p2 tl2 abbrev2 t2.level)
|
|
|
|
with Cannot_expand ->
|
|
|
|
false
|
|
|
|
end
|
|
|
|
end
|
|
|
|
| (Tobject (f1, _), Tobject (f2, _)) ->
|
|
|
|
List.exists (function (t1', t2') -> t1 == t1' & t2 == t2') !type_pairs
|
|
|
|
or begin
|
|
|
|
type_pairs := (t1, t2) :: !type_pairs;
|
|
|
|
eqtype_fields f1 f2
|
1995-05-04 03:15:53 -07:00
|
|
|
end
|
1996-04-22 04:15:41 -07:00
|
|
|
| (Tconstr(p1, tl1, abbrev1), _) ->
|
1995-05-04 03:15:53 -07:00
|
|
|
begin try
|
1996-04-22 04:15:41 -07:00
|
|
|
eqtype (expand_abbrev env p1 tl1 abbrev1 t1.level) t2
|
1995-05-04 03:15:53 -07:00
|
|
|
with Cannot_expand ->
|
|
|
|
false
|
|
|
|
end
|
1996-04-22 04:15:41 -07:00
|
|
|
| (_, Tconstr(p2, tl2, abbrev2)) ->
|
1995-05-04 03:15:53 -07:00
|
|
|
begin try
|
1996-04-22 04:15:41 -07:00
|
|
|
eqtype t1 (expand_abbrev env p2 tl2 abbrev2 t2.level)
|
1995-05-04 03:15:53 -07:00
|
|
|
with Cannot_expand ->
|
|
|
|
false
|
|
|
|
end
|
1996-04-22 04:15:41 -07:00
|
|
|
| (Tnil, Tnil) ->
|
|
|
|
true
|
1995-05-04 03:15:53 -07:00
|
|
|
| (_, _) ->
|
|
|
|
false
|
|
|
|
and eqtype_list tl1 tl2 =
|
|
|
|
match (tl1, tl2) with
|
|
|
|
([], []) -> true
|
|
|
|
| (t1::r1, t2::r2) -> eqtype t1 t2 & eqtype_list r1 r2
|
|
|
|
| (_, _) -> false
|
1996-04-22 04:15:41 -07:00
|
|
|
and eqtype_fields ty1 ty2 =
|
|
|
|
let (fields1, rest1) = flatten_fields ty1
|
|
|
|
and (fields2, rest2) = flatten_fields ty2 in
|
|
|
|
List.length fields1 = List.length fields2
|
|
|
|
&
|
|
|
|
eqtype rest1 rest2
|
|
|
|
&
|
|
|
|
List.for_all
|
|
|
|
(function (label, t) ->
|
|
|
|
List.exists
|
1996-05-16 09:10:16 -07:00
|
|
|
(function (label', t') -> (label = label') & (eqtype t t'))
|
1996-04-22 04:15:41 -07:00
|
|
|
fields2)
|
|
|
|
fields1
|
1995-05-04 03:15:53 -07:00
|
|
|
in
|
1996-04-22 04:15:41 -07:00
|
|
|
let eq = eqtype ty1 ty2 in
|
|
|
|
remove_abbrev ty1; remove_abbrev ty2;
|
|
|
|
eq
|
1995-05-04 03:15:53 -07:00
|
|
|
|
1997-01-20 09:11:47 -08:00
|
|
|
(***************)
|
|
|
|
(* Subtyping *)
|
|
|
|
(***************)
|
|
|
|
|
|
|
|
|
|
|
|
(**** Build a subtype for a given type. ****)
|
1996-04-22 04:15:41 -07:00
|
|
|
|
1996-05-28 07:30:52 -07:00
|
|
|
let subtypes = ref []
|
1995-05-04 03:15:53 -07:00
|
|
|
|
1997-01-20 09:11:47 -08:00
|
|
|
let rec build_subtype env t =
|
|
|
|
let t = repr t in
|
1996-04-22 04:15:41 -07:00
|
|
|
match t.desc with
|
1997-01-20 09:11:47 -08:00
|
|
|
Tlink t' -> (* Redundant ! *)
|
|
|
|
build_subtype env t'
|
1996-04-22 04:15:41 -07:00
|
|
|
| Tvar ->
|
|
|
|
(t, false)
|
1995-05-04 03:15:53 -07:00
|
|
|
| Tarrow(t1, t2) ->
|
1996-10-27 01:43:07 -08:00
|
|
|
let (t1', c1) = (t1, false) in
|
1997-01-20 09:11:47 -08:00
|
|
|
let (t2', c2) = build_subtype env t2 in
|
1996-04-22 04:15:41 -07:00
|
|
|
if c1 or c2 then (new_global_ty (Tarrow(t1', t2')), true)
|
|
|
|
else (t, false)
|
|
|
|
| Ttuple tlist ->
|
|
|
|
let (tlist', clist) =
|
1997-01-20 09:11:47 -08:00
|
|
|
List.split (List.map (build_subtype env) tlist)
|
1996-04-22 04:15:41 -07:00
|
|
|
in
|
|
|
|
if List.exists (function c -> c) clist then
|
|
|
|
(new_global_ty (Ttuple tlist'), true)
|
|
|
|
else (t, false)
|
|
|
|
| Tconstr(p, tl, abbrev) ->
|
|
|
|
if generic_abbrev env p then begin
|
|
|
|
let t' = expand_abbrev env p tl abbrev t.level in
|
1997-01-20 09:11:47 -08:00
|
|
|
let (t'', c) = build_subtype env t' in
|
1996-04-22 04:15:41 -07:00
|
|
|
if c then (t'', true)
|
|
|
|
else (t, false)
|
1995-05-04 03:15:53 -07:00
|
|
|
end else
|
1996-04-22 04:15:41 -07:00
|
|
|
(t, false)
|
|
|
|
| Tobject (t1, _) ->
|
1997-01-20 09:11:47 -08:00
|
|
|
if opened_object t1 then
|
1996-04-22 04:15:41 -07:00
|
|
|
(t, false)
|
1996-05-28 07:30:52 -07:00
|
|
|
else
|
|
|
|
(begin try
|
|
|
|
List.assq t !subtypes
|
|
|
|
with Not_found ->
|
|
|
|
let t' = new_global_var () in
|
|
|
|
subtypes := (t, t')::!subtypes;
|
1997-01-20 09:11:47 -08:00
|
|
|
let (t1', _) = build_subtype env t1 in
|
1996-05-28 07:30:52 -07:00
|
|
|
t'.desc <- Tobject (t1', ref None);
|
|
|
|
t'
|
|
|
|
end,
|
|
|
|
true)
|
1996-04-22 04:15:41 -07:00
|
|
|
| Tfield(s, t1, t2) ->
|
1997-01-20 09:11:47 -08:00
|
|
|
let (t1', _) = build_subtype env t1 in
|
|
|
|
let (t2', _) = build_subtype env t2 in
|
1996-04-22 04:15:41 -07:00
|
|
|
(new_global_ty (Tfield(s, t1', t2')), true)
|
|
|
|
| Tnil ->
|
|
|
|
let v = new_global_var () in
|
|
|
|
(v, true)
|
1995-05-04 03:15:53 -07:00
|
|
|
|
1997-01-20 09:11:47 -08:00
|
|
|
let enlarge_type env ty =
|
1996-10-27 01:43:07 -08:00
|
|
|
subtypes := [];
|
1997-01-20 09:11:47 -08:00
|
|
|
let (ty', _) = build_subtype env ty in
|
1996-10-27 01:43:07 -08:00
|
|
|
subtypes := [];
|
1996-05-28 07:30:52 -07:00
|
|
|
ty'
|
1996-04-22 04:15:41 -07:00
|
|
|
|
1997-01-20 09:11:47 -08:00
|
|
|
(**** Check that a type is a subtype of another type. ****)
|
|
|
|
|
1996-04-22 04:15:41 -07:00
|
|
|
let subtypes = ref [];;
|
|
|
|
|
1997-01-20 09:11:47 -08:00
|
|
|
let subtype_error env trace =
|
|
|
|
raise (Subtype (expand_trace env (List.rev trace), []))
|
1996-10-26 12:39:26 -07:00
|
|
|
|
1997-01-20 09:11:47 -08:00
|
|
|
let rec subtype_rec env trace t1 t2 =
|
|
|
|
let t1 = repr t1 in
|
|
|
|
let t2 = repr t2 in
|
|
|
|
if t1 == t2 then [] else
|
|
|
|
if List.exists (fun (t1', t2') -> t1 == t1' & t2 == t2') !subtypes then
|
|
|
|
[]
|
|
|
|
else begin
|
|
|
|
subtypes := (t1, t2) :: !subtypes;
|
1996-04-22 04:15:41 -07:00
|
|
|
match (t1.desc, t2.desc) with
|
1997-01-20 09:11:47 -08:00
|
|
|
(Tvar, _) | (_, Tvar) ->
|
|
|
|
[(trace, t1, t2)]
|
1996-04-22 04:15:41 -07:00
|
|
|
| (Tarrow(t1, u1), Tarrow(t2, u2)) ->
|
1997-01-20 09:11:47 -08:00
|
|
|
(subtype_rec env ((t2, t1)::trace) t2 t1) @
|
|
|
|
(subtype_rec env ((u1, u2)::trace) u1 u2)
|
1996-04-22 04:15:41 -07:00
|
|
|
| (Ttuple tl1, Ttuple tl2) ->
|
1997-01-20 09:11:47 -08:00
|
|
|
subtype_list env trace tl1 tl2
|
1996-04-22 04:15:41 -07:00
|
|
|
| (Tconstr(p1, tl1, abbrev1), Tconstr(p2, tl2, abbrev2)) ->
|
1997-01-20 09:11:47 -08:00
|
|
|
if generic_abbrev env p1 then
|
|
|
|
subtype_rec env trace
|
|
|
|
(expand_abbrev env p1 tl1 abbrev1 t1.level) t2
|
|
|
|
else if generic_abbrev env p2 then
|
|
|
|
subtype_rec env trace t1
|
|
|
|
(expand_abbrev env p2 tl2 abbrev2 t2.level)
|
|
|
|
else
|
|
|
|
[(trace, t1, t2)]
|
1996-05-26 06:42:34 -07:00
|
|
|
| (Tconstr(p1, tl1, abbrev1), _) ->
|
1997-01-20 09:11:47 -08:00
|
|
|
if generic_abbrev env p1 then
|
|
|
|
subtype_rec env trace
|
|
|
|
(expand_abbrev env p1 tl1 abbrev1 t1.level) t2
|
|
|
|
else
|
|
|
|
[(trace, t1, t2)]
|
1996-05-26 06:42:34 -07:00
|
|
|
| (_, Tconstr(p2, tl2, abbrev2)) ->
|
1997-01-20 09:11:47 -08:00
|
|
|
if generic_abbrev env p2 then
|
|
|
|
subtype_rec env trace t1
|
|
|
|
(expand_abbrev env p2 tl2 abbrev2 t2.level)
|
|
|
|
else
|
|
|
|
[(trace, t1, t2)]
|
1996-04-22 04:15:41 -07:00
|
|
|
| (Tobject (f1, _), Tobject (f2, _)) ->
|
1997-01-20 09:11:47 -08:00
|
|
|
if opened_object f1 & opened_object f2 then
|
|
|
|
[(trace, t1, t2)]
|
|
|
|
else
|
|
|
|
subtype_fields env trace f1 f2
|
1996-04-22 04:15:41 -07:00
|
|
|
| (_, _) ->
|
1997-01-20 09:11:47 -08:00
|
|
|
subtype_error env trace
|
|
|
|
end
|
1996-04-22 04:15:41 -07:00
|
|
|
|
1997-01-20 09:11:47 -08:00
|
|
|
and subtype_list env trace tl1 tl2 =
|
1996-05-31 05:27:03 -07:00
|
|
|
if List.length tl1 <> List.length tl2 then
|
1997-01-20 09:11:47 -08:00
|
|
|
subtype_error env trace;
|
|
|
|
List.fold_left2
|
|
|
|
(fun cstrs t1 t2 -> cstrs @ (subtype_rec env ((t1, t2)::trace) t1 t2))
|
|
|
|
[] tl1 tl2
|
1996-04-22 04:15:41 -07:00
|
|
|
|
1997-01-20 09:11:47 -08:00
|
|
|
and subtype_fields env trace ty1 ty2 =
|
1996-04-22 04:15:41 -07:00
|
|
|
let (fields1, rest1) = flatten_fields ty1 in
|
|
|
|
let (fields2, rest2) = flatten_fields ty2 in
|
|
|
|
let (pairs, miss1, miss2) = associate_fields fields1 fields2 in
|
|
|
|
begin match rest1.desc with
|
|
|
|
Tvar ->
|
1997-01-20 09:11:47 -08:00
|
|
|
[(trace, rest1, build_fields miss2 (newvar ()))]
|
|
|
|
| Tnil -> if miss2 = [] then [] else subtype_error env trace
|
1996-04-22 04:15:41 -07:00
|
|
|
| _ -> fatal_error "Ctype.subtype_fields (1)"
|
1997-01-20 09:11:47 -08:00
|
|
|
end
|
|
|
|
@
|
1996-04-22 04:15:41 -07:00
|
|
|
begin match rest2.desc with
|
|
|
|
Tvar ->
|
1997-01-20 09:11:47 -08:00
|
|
|
[(trace, build_fields miss1 (rest1), rest2)]
|
|
|
|
| Tnil -> []
|
1996-04-22 04:15:41 -07:00
|
|
|
| _ -> fatal_error "Ctype.subtype_fields (2)"
|
1997-01-20 09:11:47 -08:00
|
|
|
end
|
|
|
|
@
|
|
|
|
(List.fold_left
|
|
|
|
(fun cstrs (t1, t2) ->
|
|
|
|
cstrs @ (subtype_rec env ((t1, t2)::trace) t1 t2))
|
|
|
|
[] pairs)
|
|
|
|
|
|
|
|
(* XXX Supporte les types recursifs sans limitation *)
|
|
|
|
let subtype env ty1 ty2 =
|
1996-04-22 04:15:41 -07:00
|
|
|
subtypes := [];
|
1997-01-20 09:11:47 -08:00
|
|
|
(* Build constraint set. *)
|
|
|
|
let cstrs = subtype_rec env [(ty1, ty2)] ty1 ty2 in
|
|
|
|
(* Enforce constraints. *)
|
|
|
|
function () ->
|
|
|
|
List.iter
|
|
|
|
(function (trace0, t1, t2) ->
|
|
|
|
try unify env t1 t2 with Unify trace ->
|
|
|
|
raise (Subtype (expand_trace env (List.rev trace0),
|
|
|
|
List.tl (List.tl trace))))
|
|
|
|
cstrs;
|
|
|
|
subtypes := []
|
|
|
|
|
|
|
|
(**** Remove dependencies ****)
|
1996-04-22 04:15:41 -07:00
|
|
|
|
|
|
|
let inst_subst = ref ([] : (type_expr * type_expr) list)
|
|
|
|
|
|
|
|
let rec nondep_type_rec env id ty =
|
|
|
|
let ty = repr ty in
|
|
|
|
if ty.desc = Tvar then ty else
|
|
|
|
try List.assq ty !inst_subst with Not_found ->
|
|
|
|
let ty' = new_gen_var () in
|
|
|
|
inst_subst := (ty, ty') :: !inst_subst;
|
|
|
|
ty'.desc <-
|
|
|
|
begin match ty.desc with
|
|
|
|
Tvar ->
|
|
|
|
Tvar
|
|
|
|
| Tarrow(t1, t2) ->
|
|
|
|
Tarrow(nondep_type_rec env id t1, nondep_type_rec env id t2)
|
|
|
|
| Ttuple tl ->
|
|
|
|
Ttuple(List.map (nondep_type_rec env id) tl)
|
|
|
|
| Tconstr(p, tl, abbrev) ->
|
|
|
|
if Path.isfree id p then
|
|
|
|
begin try
|
|
|
|
(nondep_type_rec env id
|
|
|
|
(expand_abbrev env p tl (ref !abbrev) ty.level)).desc
|
|
|
|
with Cannot_expand ->
|
|
|
|
raise Not_found
|
|
|
|
end
|
|
|
|
else
|
|
|
|
Tconstr(p, List.map (nondep_type_rec env id) tl, ref [])
|
|
|
|
| Tobject (t1, name) ->
|
|
|
|
Tobject (nondep_type_rec env id t1,
|
|
|
|
ref (match !name with
|
|
|
|
None -> None
|
|
|
|
| Some (p, tl) ->
|
|
|
|
if Path.isfree id p then None
|
|
|
|
else Some (p, List.map (nondep_type_rec env id) tl)))
|
|
|
|
| Tfield(label, t1, t2) ->
|
|
|
|
Tfield(label, nondep_type_rec env id t1, nondep_type_rec env id t2)
|
|
|
|
| Tnil ->
|
|
|
|
Tnil
|
|
|
|
| Tlink _ ->
|
|
|
|
fatal_error "Ctype.nondep_type"
|
|
|
|
end;
|
|
|
|
ty'
|
|
|
|
|
|
|
|
let nondep_type env id ty =
|
|
|
|
inst_subst := [];
|
|
|
|
let ty' = nondep_type_rec env id ty in
|
|
|
|
inst_subst := [];
|
|
|
|
ty'
|
|
|
|
|
|
|
|
let nondep_class_type env id decl =
|
|
|
|
inst_subst := [];
|
|
|
|
let decl =
|
|
|
|
{ cty_params = List.map (nondep_type_rec env id) decl.cty_params;
|
|
|
|
cty_args = List.map (nondep_type_rec env id) decl.cty_args;
|
|
|
|
cty_vars =
|
|
|
|
Vars.fold (fun l (m, t) -> Vars.add l (m, nondep_type_rec env id t))
|
|
|
|
decl.cty_vars Vars.empty;
|
|
|
|
cty_self = nondep_type_rec env id decl.cty_self;
|
|
|
|
cty_concr = decl.cty_concr;
|
|
|
|
cty_new =
|
|
|
|
begin match decl.cty_new with
|
|
|
|
None -> None
|
|
|
|
| Some ty -> Some (nondep_type_rec env id ty)
|
|
|
|
end }
|
|
|
|
in
|
|
|
|
inst_subst := [];
|
|
|
|
decl
|
|
|
|
|
1997-01-20 09:11:47 -08:00
|
|
|
(**** Type pruning ****)
|
1996-04-22 04:15:41 -07:00
|
|
|
|
|
|
|
let inst_subst = ref ([] : (type_expr * type_expr) list)
|
|
|
|
|
|
|
|
let rec prune_rec top cstr ty =
|
|
|
|
let ty = repr ty in
|
|
|
|
try List.assq ty (if top then [] else cstr) with Not_found ->
|
|
|
|
match ty.desc with
|
|
|
|
Tvar ->
|
|
|
|
if ty.level = generic_level then
|
|
|
|
begin try
|
|
|
|
List.assq ty !inst_subst
|
|
|
|
with Not_found ->
|
|
|
|
let ty' = newvar() in
|
|
|
|
inst_subst := (ty, ty') :: !inst_subst;
|
|
|
|
ty'
|
|
|
|
end
|
|
|
|
else
|
|
|
|
ty
|
|
|
|
| Tarrow(t1, t2) ->
|
|
|
|
newty (Tarrow(prune_rec false cstr t1, prune_rec false cstr t2))
|
1995-05-04 03:15:53 -07:00
|
|
|
| Ttuple tl ->
|
1996-04-22 04:15:41 -07:00
|
|
|
newty (Ttuple(List.map (prune_rec false cstr) tl))
|
|
|
|
| Tconstr(p, tl, _) ->
|
|
|
|
begin try
|
|
|
|
List.assq ty !inst_subst
|
|
|
|
with Not_found ->
|
|
|
|
let ty' = newvar() in
|
|
|
|
inst_subst := (ty, ty') :: !inst_subst;
|
|
|
|
let ty'' =
|
|
|
|
newty (Tconstr(p, List.map (prune_rec false cstr) tl, ref []))
|
|
|
|
in
|
|
|
|
ty'.desc <- Tlink ty'';
|
|
|
|
ty''
|
1995-10-19 09:28:44 -07:00
|
|
|
end
|
1996-04-22 04:15:41 -07:00
|
|
|
| Tobject (t1, name) ->
|
1995-10-19 09:28:44 -07:00
|
|
|
begin try
|
1996-04-22 04:15:41 -07:00
|
|
|
List.assq ty !inst_subst
|
|
|
|
with Not_found ->
|
|
|
|
let ty' = newvar() in
|
|
|
|
inst_subst := (ty, ty') :: !inst_subst;
|
|
|
|
let ty'' = newty
|
|
|
|
(Tobject (prune_rec false cstr t1,
|
|
|
|
ref (match !name with
|
|
|
|
None -> None
|
|
|
|
| Some (p, tl) ->
|
|
|
|
Some (p, List.map (prune_rec false cstr) tl))))
|
|
|
|
in
|
|
|
|
ty'.desc <- Tlink ty'';
|
|
|
|
ty''
|
|
|
|
end
|
|
|
|
| Tfield(label, t1, t2) ->
|
|
|
|
newty (Tfield(label, prune_rec false cstr t1, prune_rec false cstr t2))
|
|
|
|
| Tnil ->
|
|
|
|
newty Tnil
|
|
|
|
| Tlink _ ->
|
|
|
|
fatal_error "Ctype.prune_rec"
|
|
|
|
|
|
|
|
let prune_cstr cstr (old_cstr, new_cstr) ((ty, v) as c) =
|
|
|
|
let c' =
|
|
|
|
try (v, List.assq ty old_cstr) with Not_found ->
|
|
|
|
match ty.desc with
|
|
|
|
Tvar ->
|
|
|
|
(v, v)
|
|
|
|
| _ ->
|
|
|
|
(v, prune_rec true cstr ty)
|
|
|
|
in
|
|
|
|
(c :: old_cstr, c' :: new_cstr)
|
|
|
|
|
|
|
|
let prune ty leaves =
|
|
|
|
inst_subst := [];
|
|
|
|
let cstr = List.map (fun leaf -> (repr leaf, newvar ())) leaves in
|
|
|
|
let new_ty = prune_rec true cstr ty in
|
|
|
|
inst_subst := [];
|
|
|
|
(new_ty, List.map (fun (ty, v) -> (v, ty)) cstr)
|
|
|
|
|
|
|
|
let prune_class_type cl =
|
|
|
|
inst_subst := [];
|
|
|
|
let cstr = List.map (fun leaf -> (repr leaf, newvar ())) cl.cty_params in
|
|
|
|
let args = List.map (prune_rec false cstr) cl.cty_args in
|
|
|
|
let vars =
|
|
|
|
Vars.fold
|
|
|
|
(fun lab (mut, ty) -> Vars.add lab (mut, prune_rec false cstr ty))
|
|
|
|
cl.cty_vars Vars.empty in
|
|
|
|
let self = prune_rec true cstr cl.cty_self in
|
|
|
|
let (_, cstr) = List.fold_left (prune_cstr cstr) ([], []) cstr in
|
|
|
|
inst_subst := [];
|
|
|
|
(List.rev cstr, args, vars, self)
|
|
|
|
|
|
|
|
(* --- *)
|
|
|
|
|
|
|
|
let rec row_variable ty =
|
|
|
|
let ty = repr ty in
|
|
|
|
match ty.desc with
|
|
|
|
Tfield (_, _, ty) -> row_variable ty
|
|
|
|
| Tvar -> ty
|
|
|
|
| Tnil -> raise Not_found
|
|
|
|
| _ -> fatal_error "Ctype.row_variable"
|
|
|
|
|
|
|
|
let close_object ty =
|
|
|
|
let rec close ty =
|
|
|
|
let ty = repr ty in
|
|
|
|
match ty.desc with
|
|
|
|
Tvar ->
|
|
|
|
ty.desc <- Tlink {desc = Tnil; level = ty.level}
|
|
|
|
| Tfield(_, _, ty') -> close ty'
|
|
|
|
| Tnil -> ()
|
|
|
|
| _ -> fatal_error "Ctype.close_object (1)"
|
|
|
|
in
|
|
|
|
match (repr ty).desc with
|
|
|
|
Tobject (ty, _) -> close ty
|
|
|
|
| Tconstr (_, _, _) -> () (* Already closed *)
|
|
|
|
| _ -> fatal_error "Ctype.close_object (2)"
|
|
|
|
|
|
|
|
|
|
|
|
let set_object_name ty params id =
|
|
|
|
match (repr ty).desc with
|
|
|
|
Tobject (fi, nm) ->
|
|
|
|
begin try
|
|
|
|
nm := Some (Path.Pident id, (row_variable fi)::params)
|
|
|
|
with Not_found ->
|
|
|
|
()
|
|
|
|
end
|
|
|
|
| Tconstr (_, _, _) ->
|
|
|
|
()
|
|
|
|
| _ ->
|
|
|
|
fatal_error "Ctype.set_object_name"
|
|
|
|
|
|
|
|
let remove_object_name ty =
|
|
|
|
match (repr ty).desc with
|
|
|
|
Tobject (_, nm) -> nm := None
|
|
|
|
| Tconstr (_, _, _) -> ()
|
|
|
|
| _ -> fatal_error "Ctype.remove_object_name"
|
|
|
|
|
1997-01-20 09:11:47 -08:00
|
|
|
(**** Abbreviation correctness ****)
|
1996-04-22 04:15:41 -07:00
|
|
|
|
|
|
|
exception Nonlinear_abbrev
|
|
|
|
exception Recursive_abbrev
|
|
|
|
|
1996-09-21 05:02:42 -07:00
|
|
|
let rec non_recursive_abbrev env path constrs ty =
|
|
|
|
let ty = repr ty in
|
|
|
|
match ty.desc with
|
|
|
|
Tarrow (ty1, ty2) ->
|
|
|
|
non_recursive_abbrev env path constrs ty1;
|
|
|
|
non_recursive_abbrev env path constrs ty2
|
|
|
|
| Ttuple tl ->
|
|
|
|
List.iter (non_recursive_abbrev env path constrs) tl
|
|
|
|
| Tconstr(p, args, abbrev) ->
|
|
|
|
if Path.same path p then
|
|
|
|
raise Recursive_abbrev
|
|
|
|
else begin
|
|
|
|
begin try
|
|
|
|
let ty' = expand_abbrev env p args abbrev ty.level in
|
|
|
|
if List.memq ty' constrs then () else
|
|
|
|
non_recursive_abbrev env path (ty'::constrs) ty'
|
|
|
|
with Cannot_expand ->
|
|
|
|
()
|
|
|
|
end
|
|
|
|
end
|
|
|
|
| _ (* Tvar | Tobject (_, _) | Tfield (_, _, _) | Tnil *) ->
|
|
|
|
()
|
|
|
|
|
1996-09-20 14:29:50 -07:00
|
|
|
let rec path_assoc x =
|
|
|
|
function
|
|
|
|
[] -> raise Not_found
|
|
|
|
| (a,b)::l -> if Path.same a x then b else path_assoc x l
|
|
|
|
|
|
|
|
let visited_abbrevs = ref []
|
|
|
|
|
|
|
|
let visited_abbrev p args =
|
|
|
|
try
|
|
|
|
let slot = path_assoc p !visited_abbrevs in
|
|
|
|
if
|
|
|
|
List.exists
|
|
|
|
(function args' ->
|
|
|
|
List.for_all2 (fun ty ty' -> repr ty == ty') args args')
|
|
|
|
!slot
|
|
|
|
then
|
|
|
|
true
|
|
|
|
else begin
|
|
|
|
slot := (List.map repr args)::!slot;
|
|
|
|
false
|
|
|
|
end
|
|
|
|
with Not_found ->
|
|
|
|
visited_abbrevs := (p, ref [args])::!visited_abbrevs;
|
|
|
|
false
|
|
|
|
|
1996-09-21 05:02:42 -07:00
|
|
|
let rec linear_abbrev env path params visited ty =
|
1996-04-22 04:15:41 -07:00
|
|
|
let ty = repr ty in
|
|
|
|
match ty.desc with
|
1996-09-20 14:29:50 -07:00
|
|
|
Tarrow (ty1, ty2) ->
|
1996-09-21 05:02:42 -07:00
|
|
|
linear_abbrev env path params visited ty1;
|
|
|
|
linear_abbrev env path params visited ty2
|
1996-04-22 04:15:41 -07:00
|
|
|
| Ttuple tl ->
|
1996-09-21 05:02:42 -07:00
|
|
|
List.iter (linear_abbrev env path params visited) tl
|
1996-04-22 04:15:41 -07:00
|
|
|
| Tconstr(p, args, abbrev) ->
|
|
|
|
if Path.same p path then begin
|
|
|
|
if
|
|
|
|
List.exists (fun (ty1, ty2) -> repr ty1 != repr ty2)
|
|
|
|
(List.combine params args)
|
|
|
|
then
|
|
|
|
raise Nonlinear_abbrev
|
|
|
|
end else begin
|
1996-09-20 14:29:50 -07:00
|
|
|
try
|
|
|
|
let ty' = expand_abbrev env p args abbrev ty.level in
|
|
|
|
if not (visited_abbrev p args) then
|
1996-09-21 05:02:42 -07:00
|
|
|
linear_abbrev env path params visited ty'
|
1996-09-20 14:29:50 -07:00
|
|
|
with Cannot_expand ->
|
|
|
|
if not (List.memq ty visited) then begin
|
|
|
|
List.iter
|
1996-09-21 05:02:42 -07:00
|
|
|
(linear_abbrev env path params (ty::visited))
|
1996-09-20 14:29:50 -07:00
|
|
|
args
|
|
|
|
end
|
1996-04-22 04:15:41 -07:00
|
|
|
end
|
|
|
|
| Tobject (ty', _) ->
|
1996-09-20 14:29:50 -07:00
|
|
|
if not (List.memq ty visited) then
|
1996-09-21 05:02:42 -07:00
|
|
|
linear_abbrev env path params (ty::visited) ty'
|
1996-04-22 04:15:41 -07:00
|
|
|
| Tfield(_, ty1, ty2) ->
|
1996-09-21 05:02:42 -07:00
|
|
|
linear_abbrev env path params visited ty1;
|
|
|
|
linear_abbrev env path params visited ty2
|
1996-09-20 14:29:50 -07:00
|
|
|
| _ (* Tvar | Tnil *) ->
|
|
|
|
()
|
|
|
|
|
1996-04-22 04:15:41 -07:00
|
|
|
let correct_abbrev env ident params ty =
|
|
|
|
let path = Path.Pident ident in
|
1996-09-20 14:29:50 -07:00
|
|
|
non_recursive_abbrev env path [] ty;
|
|
|
|
if params <> [] then begin
|
|
|
|
visited_abbrevs := [];
|
1996-09-21 05:02:42 -07:00
|
|
|
linear_abbrev env path params [] ty;
|
1996-09-20 14:29:50 -07:00
|
|
|
visited_abbrevs := []
|
|
|
|
end;
|
|
|
|
remove_abbrev ty
|
1995-05-04 03:15:53 -07:00
|
|
|
|
1997-01-20 09:11:47 -08:00
|
|
|
(**** Miscellaneous ****)
|
1995-11-16 05:27:53 -08:00
|
|
|
|
1996-04-22 04:15:41 -07:00
|
|
|
let unroll_abbrev id tl ty =
|
|
|
|
let ty = repr ty in
|
|
|
|
match ty.desc with
|
|
|
|
Tobject (fi, nm) ->
|
|
|
|
ty.desc <-
|
|
|
|
Tlink {desc = Tconstr (Path.Pident id, tl, ref []);
|
|
|
|
level = generic_level};
|
|
|
|
{desc = Tobject (fi, nm); level = ty.level}
|
|
|
|
| _ ->
|
|
|
|
ty
|
|
|
|
|
1996-05-26 06:42:34 -07:00
|
|
|
type closed_schema_result = Var of type_expr | Row_var of type_expr
|
|
|
|
exception Failed of closed_schema_result
|
|
|
|
|
1996-07-15 09:35:35 -07:00
|
|
|
let visited = ref []
|
|
|
|
|
1996-05-26 06:42:34 -07:00
|
|
|
let rec closed_schema_rec ty =
|
|
|
|
let ty = repr ty in
|
1997-01-20 09:11:47 -08:00
|
|
|
if not (List.memq ty !visited) then begin
|
|
|
|
visited := ty::!visited;
|
|
|
|
match ty.desc with
|
|
|
|
Tvar when ty.level != generic_level -> raise (Failed (Var ty))
|
|
|
|
| Tobject(f, {contents = Some (_, p)}) ->
|
1996-05-26 06:42:34 -07:00
|
|
|
begin try closed_schema_rec f with
|
|
|
|
Failed (Row_var v) -> raise (Failed (Var v))
|
|
|
|
| Failed (Var v) -> raise (Failed (Row_var v))
|
|
|
|
end;
|
|
|
|
List.iter closed_schema_rec p
|
1997-01-20 09:11:47 -08:00
|
|
|
| Tobject(f, _) ->
|
|
|
|
begin try closed_schema_rec f with
|
1996-05-26 06:42:34 -07:00
|
|
|
Failed (Row_var v) -> raise (Failed (Var v))
|
|
|
|
| Failed (Var v) -> raise (Failed (Row_var v))
|
1997-01-20 09:11:47 -08:00
|
|
|
end
|
|
|
|
| Tfield(_, t1, t2) ->
|
|
|
|
begin try
|
|
|
|
closed_schema_rec t1
|
|
|
|
with
|
|
|
|
Failed (Row_var v) -> raise (Failed (Var v))
|
|
|
|
| Failed (Var v) -> raise (Failed (Row_var v))
|
|
|
|
end;
|
|
|
|
closed_schema_rec t2
|
|
|
|
| _ ->
|
|
|
|
iter_type_expr closed_schema_rec ty
|
|
|
|
end
|
1996-05-26 06:42:34 -07:00
|
|
|
|
|
|
|
let closed_schema ty =
|
|
|
|
visited := [];
|
|
|
|
try
|
|
|
|
closed_schema_rec ty;
|
|
|
|
visited := [];
|
|
|
|
true
|
|
|
|
with Failed _ ->
|
|
|
|
visited := [];
|
|
|
|
false
|
|
|
|
|
|
|
|
let closed_schema_verbose ty =
|
|
|
|
visited := [];
|
|
|
|
try
|
|
|
|
closed_schema_rec ty;
|
|
|
|
visited := [];
|
|
|
|
None
|
|
|
|
with Failed status ->
|
|
|
|
visited := [];
|
|
|
|
Some status
|
|
|
|
|
1995-05-04 03:15:53 -07:00
|
|
|
let is_generic ty =
|
1996-04-22 04:15:41 -07:00
|
|
|
let ty = repr ty in
|
|
|
|
match ty.desc with
|
|
|
|
Tvar -> ty.level = generic_level
|
1995-05-04 03:15:53 -07:00
|
|
|
| _ -> fatal_error "Ctype.is_generic"
|
|
|
|
|
|
|
|
let rec arity ty =
|
1996-04-22 04:15:41 -07:00
|
|
|
match (repr ty).desc with
|
1995-05-04 03:15:53 -07:00
|
|
|
Tarrow(t1, t2) -> 1 + arity t2
|
|
|
|
| _ -> 0
|