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-02-20 12:39:02 -08:00
|
|
|
|
(*
|
|
|
|
|
General notes
|
|
|
|
|
=============
|
1997-01-20 09:11:47 -08:00
|
|
|
|
- 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
|
1997-02-20 12:39:02 -08:00
|
|
|
|
printed correctly (XXX TO DO...), and types defined by a class do
|
|
|
|
|
not depend on sharing thanks to constrained abbreviations. (Of
|
|
|
|
|
course, typing will still be correct.)
|
|
|
|
|
- All nodes of a type have a level : that way, one know whether a
|
|
|
|
|
node need to be duplicated or not when instantiating a type.
|
1997-03-07 14:44:02 -08:00
|
|
|
|
- Levels of a type are decreasing (generic level being considered
|
|
|
|
|
as greatest).
|
1997-02-20 12:39:02 -08:00
|
|
|
|
- The level of a type constructor is superior to the binding
|
1997-01-20 09:11:47 -08:00
|
|
|
|
time of its path.
|
1997-03-08 14:05:39 -08:00
|
|
|
|
- Recursive types without limitation should be handled (even if
|
|
|
|
|
there is still an occur check.
|
1997-01-20 09:11:47 -08:00
|
|
|
|
*)
|
|
|
|
|
|
1997-02-20 12:39:02 -08:00
|
|
|
|
(*
|
|
|
|
|
A faire
|
|
|
|
|
=======
|
1997-03-08 14:05:39 -08:00
|
|
|
|
- XXX Se debarasser de [Ident.identify] (utiliser plutot des substitutions).
|
1997-01-20 09:11:47 -08:00
|
|
|
|
- Revoir affichage des types.
|
|
|
|
|
- Types recursifs sans limitation.
|
1997-02-20 12:39:02 -08:00
|
|
|
|
- Etendre la portee d'un alias [... as 'a] a tout le type englobant.
|
1997-01-20 09:11:47 -08:00
|
|
|
|
- #-type implementes comme de vraies abreviations.
|
1997-01-23 04:46:46 -08:00
|
|
|
|
- Deplacer Ctype.repr dans Types ?
|
1997-02-20 12:39:02 -08:00
|
|
|
|
- Niveaux plus fins pour les identificateurs :
|
|
|
|
|
Champ [global] renomme en [level];
|
|
|
|
|
Niveau -1 : global
|
|
|
|
|
0 : module toplevel
|
|
|
|
|
1 : module contenu dans module toplevel
|
|
|
|
|
...
|
|
|
|
|
En fait, incrementer le niveau a chaque fois que l'on rentre dans
|
|
|
|
|
un module.
|
|
|
|
|
|
|
|
|
|
3 4 6
|
|
|
|
|
\ / /
|
|
|
|
|
1 2 5
|
|
|
|
|
\|/
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
|
[Subst] doit ecreter les niveaux (pour qu'un variable non
|
|
|
|
|
generalisable dans un module de niveau 2 ne se retrouve pas
|
|
|
|
|
generalisable lorsque l'on l'utilise au niveau 0).
|
|
|
|
|
|
|
|
|
|
- Traitement de la trace de l'unification separe de la fonction
|
|
|
|
|
[unify].
|
1997-01-20 09:11:47 -08:00
|
|
|
|
*)
|
|
|
|
|
|
1997-01-21 05:38:42 -08:00
|
|
|
|
(**** Errors ****)
|
|
|
|
|
|
|
|
|
|
exception Unify of (type_expr * type_expr) list
|
|
|
|
|
|
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
|
|
|
|
|
1997-01-23 04:46:46 -08:00
|
|
|
|
exception Cannot_expand
|
|
|
|
|
|
1997-03-08 14:05:39 -08:00
|
|
|
|
exception Recursive_abbrev
|
|
|
|
|
|
1997-01-21 05:38:42 -08:00
|
|
|
|
(**** Type level management ****)
|
|
|
|
|
|
|
|
|
|
let generic_level = (-1)
|
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
|
|
|
|
|
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
|
|
|
|
|
1997-03-08 14:05:39 -08:00
|
|
|
|
(* Used to mark a type during a traversal. *)
|
|
|
|
|
let lowest_level = generic_level
|
|
|
|
|
let pivot_level = 2 * lowest_level - 1
|
|
|
|
|
(* pivot_level - lowest_level < lowest_level *)
|
|
|
|
|
|
1997-01-21 05:38:42 -08:00
|
|
|
|
(**** Some type creators ****)
|
|
|
|
|
|
1997-03-08 14:05:39 -08:00
|
|
|
|
let newty desc = { desc = desc; level = !current_level }
|
1996-04-22 04:15:41 -07:00
|
|
|
|
let newgenty desc = { desc = desc; level = generic_level }
|
1997-03-08 14:05:39 -08:00
|
|
|
|
let new_global_ty desc = { desc = desc; level = !global_level }
|
1997-01-21 05:38:42 -08:00
|
|
|
|
|
1996-04-22 04:15:41 -07:00
|
|
|
|
let newvar () = { desc = Tvar; level = !current_level }
|
1997-03-08 14:05:39 -08:00
|
|
|
|
let newgenvar () = newgenty Tvar
|
1997-01-21 05:38:42 -08:00
|
|
|
|
let new_global_var () = new_global_ty Tvar
|
1997-03-09 08:52:49 -08:00
|
|
|
|
let newmarkedvar () = { desc = Tvar; level = pivot_level - generic_level }
|
1997-01-21 05:38:42 -08:00
|
|
|
|
|
1997-03-08 14:05:39 -08:00
|
|
|
|
let newobj fields = newty (Tobject (fields, ref None))
|
|
|
|
|
|
1997-01-21 05:38:42 -08:00
|
|
|
|
let none = newty (Ttuple []) (* Clearly ill-formed type *)
|
|
|
|
|
|
|
|
|
|
(**** Representative of a type ****)
|
|
|
|
|
|
|
|
|
|
let rec repr =
|
|
|
|
|
function
|
1997-03-07 14:44:02 -08:00
|
|
|
|
{desc = Tlink t'} ->
|
|
|
|
|
(*
|
|
|
|
|
We do no path compression. Path compression does not seem to
|
|
|
|
|
improve notably efficiency, and it prevents from changing a
|
|
|
|
|
[Tlink] into another type (for instance, for undoing a
|
|
|
|
|
unification).
|
|
|
|
|
*)
|
|
|
|
|
repr t'
|
1995-05-04 03:15:53 -07:00
|
|
|
|
| t -> t
|
|
|
|
|
|
1996-04-22 04:15:41 -07:00
|
|
|
|
|
1997-03-09 08:52:49 -08:00
|
|
|
|
(**********************************)
|
|
|
|
|
(* Utilities for type traversal *)
|
|
|
|
|
(**********************************)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let saved_desc = ref []
|
|
|
|
|
(* Saved association of generic nodes with their description. *)
|
|
|
|
|
|
|
|
|
|
(* Restored type descriptions *)
|
|
|
|
|
let cleanup_types () =
|
|
|
|
|
List.iter (fun (ty, desc) -> ty.desc <- desc) !saved_desc;
|
|
|
|
|
saved_desc := []
|
|
|
|
|
|
|
|
|
|
(* Remove marks from a type. *)
|
|
|
|
|
let rec unmark_type ty =
|
|
|
|
|
let ty = repr ty in
|
|
|
|
|
if ty.level < lowest_level then begin
|
|
|
|
|
ty.level <- pivot_level - ty.level;
|
|
|
|
|
iter_type_expr unmark_type ty
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
1997-01-21 05:38:42 -08:00
|
|
|
|
(**********************************************)
|
|
|
|
|
(* Miscellaneous operations on object types *)
|
|
|
|
|
(**********************************************)
|
|
|
|
|
|
1996-04-22 04:15:41 -07:00
|
|
|
|
|
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
|
|
|
|
|
| _ ->
|
1997-03-07 14:44:02 -08:00
|
|
|
|
(l, ty)
|
1996-04-22 04:15:41 -07:00
|
|
|
|
in
|
|
|
|
|
let (l, r) = flatten [] ty in
|
|
|
|
|
(List.rev l, r)
|
|
|
|
|
|
|
|
|
|
let build_fields =
|
1997-03-08 14:05:39 -08:00
|
|
|
|
List.fold_right (fun (s, ty1) ty2 -> newty (Tfield(s, ty1, ty2)))
|
1996-04-22 04:15:41 -07:00
|
|
|
|
|
|
|
|
|
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')
|
1997-01-23 04:46:46 -08:00
|
|
|
|
| ((n, t)::r, (n', t')::r') when n = n' ->
|
|
|
|
|
associate ((t, t')::p) s s' (r, r')
|
|
|
|
|
| ((n, t)::r, ((n', t')::_ as l')) when n < n' ->
|
|
|
|
|
associate p ((n, t)::s) s' (r, l')
|
|
|
|
|
| (((n, t)::r as l), (n', t')::r') (* when n > n' *) ->
|
|
|
|
|
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-03-08 14:05:39 -08:00
|
|
|
|
(* +++ Il faudra penser a eventuellement expanser l'abreviation *)
|
1997-01-20 09:11:47 -08:00
|
|
|
|
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-21 05:38:42 -08:00
|
|
|
|
(**** Close an object ****)
|
|
|
|
|
|
|
|
|
|
let close_object ty =
|
|
|
|
|
let rec close ty =
|
|
|
|
|
let ty = repr ty in
|
|
|
|
|
match ty.desc with
|
1997-01-23 04:46:46 -08:00
|
|
|
|
Tvar -> ty.desc <- Tlink {desc = Tnil; level = ty.level}
|
1997-01-21 05:38:42 -08:00
|
|
|
|
| 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)"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(**** Object name manipulation ****)
|
1997-03-08 14:05:39 -08:00
|
|
|
|
(* +++ Bientot obsolete *)
|
1997-01-21 05:38:42 -08:00
|
|
|
|
|
|
|
|
|
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 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-23 04:46:46 -08:00
|
|
|
|
|
|
|
|
|
(*****************************)
|
|
|
|
|
(* Type level manipulation *)
|
|
|
|
|
(*****************************)
|
|
|
|
|
|
1997-02-20 12:39:02 -08:00
|
|
|
|
(*
|
|
|
|
|
It would be a bit more efficient to remove abbreviation expansions
|
|
|
|
|
rather than generalizing them: these expansions will usually not be
|
|
|
|
|
used anymore. However, this is not possible in the general case, as
|
|
|
|
|
[expand_abbrev] (via [subst]) requires these expansions to be
|
|
|
|
|
preserved. Does it worth duplicating this code ?
|
|
|
|
|
*)
|
1995-05-04 03:15:53 -07:00
|
|
|
|
let rec generalize ty =
|
1997-01-24 12:54:56 -08:00
|
|
|
|
let ty = repr ty in
|
|
|
|
|
if ty.level > !current_level then begin
|
|
|
|
|
ty.level <- generic_level;
|
|
|
|
|
begin match ty.desc with
|
|
|
|
|
Tconstr (_, _, abbrev) ->
|
|
|
|
|
generalize_expans !abbrev
|
|
|
|
|
| _ -> ()
|
|
|
|
|
end;
|
1997-02-20 12:39:02 -08:00
|
|
|
|
iter_type_expr generalize ty
|
1997-01-24 12:54:56 -08:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
and generalize_expans =
|
|
|
|
|
function
|
|
|
|
|
Mnil -> ()
|
1997-02-20 12:39:02 -08:00
|
|
|
|
| Mcons(_, ty, rem) -> generalize ty; generalize_expans rem
|
1997-01-24 12:54:56 -08:00
|
|
|
|
| Mlink rem -> generalize_expans !rem
|
|
|
|
|
|
1997-02-20 12:39:02 -08:00
|
|
|
|
(*
|
|
|
|
|
Lower in-place the level of a generic type. That way, [subst] can
|
|
|
|
|
do "unification" on generic types.
|
|
|
|
|
*)
|
1997-01-24 12:54:56 -08:00
|
|
|
|
let rec ungeneralize ty =
|
|
|
|
|
let ty = repr ty in
|
|
|
|
|
if ty.level = generic_level then begin
|
|
|
|
|
ty.level <- !current_level;
|
|
|
|
|
begin match ty.desc with
|
|
|
|
|
Tconstr (_, _, abbrev) ->
|
|
|
|
|
ungeneralize_expans !abbrev
|
|
|
|
|
| _ -> ()
|
|
|
|
|
end;
|
|
|
|
|
iter_type_expr ungeneralize ty
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
and ungeneralize_expans =
|
|
|
|
|
function
|
|
|
|
|
Mnil -> ()
|
|
|
|
|
| Mcons(_, ty, rem) -> ungeneralize ty; ungeneralize_expans rem
|
|
|
|
|
| Mlink rem -> ungeneralize_expans !rem
|
|
|
|
|
|
|
|
|
|
let expand_abbrev' = (* Forward declaration *)
|
|
|
|
|
ref (fun env path args abbrev level -> raise Cannot_expand)
|
1997-01-23 04:46:46 -08:00
|
|
|
|
|
1997-02-20 12:39:02 -08:00
|
|
|
|
(*
|
1997-03-07 14:44:02 -08:00
|
|
|
|
Lower the levels of a type (assume [level] is not
|
|
|
|
|
[generic_level]).
|
|
|
|
|
*)
|
|
|
|
|
(*
|
|
|
|
|
The level of a type constructor must be greater than its binding
|
1997-02-20 12:39:02 -08:00
|
|
|
|
time. That way, a type constructor cannot escape the scope of its
|
|
|
|
|
definition, as would be the case in
|
|
|
|
|
let x = ref []
|
|
|
|
|
module M = struct type t let _ = (x : t list ref) end
|
1997-03-07 14:44:02 -08:00
|
|
|
|
(without this constraint, the type system would even be unsafe.)
|
1997-02-20 12:39:02 -08:00
|
|
|
|
*)
|
1997-01-23 04:46:46 -08:00
|
|
|
|
let rec update_level env level ty =
|
1996-04-22 04:15:41 -07:00
|
|
|
|
let ty = repr ty in
|
1997-01-21 05:38:42 -08:00
|
|
|
|
if ty.level > level then begin
|
1997-03-07 14:44:02 -08:00
|
|
|
|
let old_level = ty.level in
|
1997-01-21 05:38:42 -08:00
|
|
|
|
ty.level <- level;
|
|
|
|
|
begin match ty.desc with
|
1997-01-23 04:46:46 -08:00
|
|
|
|
Tconstr(p, tl, abbrev) when level < Path.binding_time p ->
|
1997-01-24 12:54:56 -08:00
|
|
|
|
(* Try first to replace an abbreviation by its expansion. *)
|
1997-01-23 04:46:46 -08:00
|
|
|
|
begin try
|
1997-03-07 14:44:02 -08:00
|
|
|
|
ty.desc <- Tlink (!expand_abbrev' env p tl abbrev old_level);
|
|
|
|
|
update_level env level ty
|
1997-01-23 04:46:46 -08:00
|
|
|
|
with Cannot_expand ->
|
1997-03-07 14:44:02 -08:00
|
|
|
|
(* XXX Levels should be restored... *)
|
1997-01-23 04:46:46 -08:00
|
|
|
|
raise (Unify [])
|
|
|
|
|
end
|
1997-01-24 12:54:56 -08:00
|
|
|
|
| _ ->
|
|
|
|
|
iter_type_expr (update_level env level) ty
|
1997-03-08 04:14:57 -08:00
|
|
|
|
end
|
1996-04-22 04:15:41 -07:00
|
|
|
|
end
|
|
|
|
|
|
1997-01-24 12:54:56 -08:00
|
|
|
|
(*
|
|
|
|
|
Function [update_level] will never try to expand an abbreviation in
|
1997-03-07 14:44:02 -08:00
|
|
|
|
this case ([current_level] is greater than the binding time of any
|
1997-01-24 12:54:56 -08:00
|
|
|
|
type constructor path). So, it can be called with the empty
|
|
|
|
|
environnement.
|
|
|
|
|
*)
|
1997-02-20 12:39:02 -08:00
|
|
|
|
let make_nongen ty = update_level Env.empty !current_level ty
|
1996-04-22 04:15:41 -07:00
|
|
|
|
|
1995-05-04 03:15:53 -07:00
|
|
|
|
|
1997-01-20 09:11:47 -08:00
|
|
|
|
(*******************)
|
|
|
|
|
(* Instantiation *)
|
|
|
|
|
(*******************)
|
|
|
|
|
|
1997-01-21 09:43:53 -08:00
|
|
|
|
|
1997-01-21 05:38:42 -08:00
|
|
|
|
(*
|
|
|
|
|
Generic nodes are duplicated, while non-generic nodes are left
|
|
|
|
|
as-is. The instance cannot be generic.
|
|
|
|
|
During instantiation, the description of a generic node is first
|
|
|
|
|
replaced by a link to a stub ([Tlink (newvar ())]). Once the copy
|
|
|
|
|
is made, it replaces the stub.
|
|
|
|
|
After instantiation, the description of generic node, which was
|
|
|
|
|
stored in [saved_desc], must be put back, using [cleanup_types].
|
|
|
|
|
*)
|
1995-11-16 05:27:53 -08:00
|
|
|
|
|
1997-01-21 09:43:53 -08:00
|
|
|
|
let abbreviations = ref (ref Mnil)
|
1997-01-21 05:38:42 -08:00
|
|
|
|
(* Abbreviation memorized. *)
|
|
|
|
|
|
1997-03-07 14:44:02 -08:00
|
|
|
|
let rec copy ty =
|
|
|
|
|
let ty = repr ty in
|
|
|
|
|
if ty.level <> generic_level then
|
|
|
|
|
ty
|
|
|
|
|
else begin
|
|
|
|
|
let desc = ty.desc in
|
|
|
|
|
saved_desc := (ty, desc)::!saved_desc;
|
|
|
|
|
let t = newvar () in (* Stub *)
|
|
|
|
|
ty.desc <- Tlink t;
|
|
|
|
|
t.desc <-
|
|
|
|
|
begin match desc with
|
|
|
|
|
Tvar ->
|
|
|
|
|
Tvar
|
|
|
|
|
| Tarrow (t1, t2) ->
|
|
|
|
|
Tarrow (copy t1, copy t2)
|
|
|
|
|
| Ttuple tl ->
|
|
|
|
|
Ttuple (List.map copy tl)
|
|
|
|
|
| Tconstr (p, tl, _) ->
|
|
|
|
|
(*
|
|
|
|
|
One must allocate a new reference, so that abbrevia-
|
|
|
|
|
tions belonging to different branches of a type are
|
|
|
|
|
independent.
|
|
|
|
|
Moreover, a reference containing a [Mcons] must be
|
|
|
|
|
shared, so that the memorized expansion of an abbrevi-
|
|
|
|
|
ation can be released by changing the content of just
|
|
|
|
|
one reference.
|
|
|
|
|
*)
|
|
|
|
|
Tconstr (p, List.map copy tl,
|
|
|
|
|
ref (match ! !abbreviations with
|
|
|
|
|
Mcons _ -> Mlink !abbreviations
|
|
|
|
|
| abbrev -> abbrev))
|
|
|
|
|
| Tobject (t1, {contents = name}) ->
|
|
|
|
|
let name' =
|
|
|
|
|
match name with
|
|
|
|
|
None ->
|
|
|
|
|
None
|
|
|
|
|
| Some (p, tl) ->
|
|
|
|
|
Some (p, List.map copy tl)
|
|
|
|
|
in
|
|
|
|
|
Tobject (copy t1, ref name')
|
|
|
|
|
| Tfield (label, t1, t2) ->
|
|
|
|
|
Tfield (label, copy t1, copy t2)
|
|
|
|
|
| Tnil ->
|
|
|
|
|
Tnil
|
|
|
|
|
| Tlink t -> (* Actually unused *)
|
|
|
|
|
Tlink (copy t)
|
|
|
|
|
end;
|
|
|
|
|
t
|
|
|
|
|
end
|
1996-04-22 04:15:41 -07:00
|
|
|
|
|
1997-01-21 05:38:42 -08:00
|
|
|
|
(**** Variants of instantiations ****)
|
1995-05-04 03:15:53 -07:00
|
|
|
|
|
|
|
|
|
let instance sch =
|
|
|
|
|
let ty = copy sch in
|
1997-01-21 05:38:42 -08:00
|
|
|
|
cleanup_types ();
|
1995-05-04 03:15:53 -07:00
|
|
|
|
ty
|
|
|
|
|
|
1997-02-20 12:39:02 -08:00
|
|
|
|
let instance_list schl =
|
|
|
|
|
let tyl = List.map copy schl in
|
|
|
|
|
cleanup_types ();
|
|
|
|
|
tyl
|
|
|
|
|
|
1995-05-04 03:15:53 -07:00
|
|
|
|
let instance_constructor cstr =
|
|
|
|
|
let ty_res = copy cstr.cstr_res in
|
|
|
|
|
let ty_args = List.map copy cstr.cstr_args in
|
1997-01-21 05:38:42 -08:00
|
|
|
|
cleanup_types ();
|
1995-05-04 03:15:53 -07:00
|
|
|
|
(ty_args, ty_res)
|
|
|
|
|
|
|
|
|
|
let instance_label lbl =
|
|
|
|
|
let ty_res = copy lbl.lbl_res in
|
|
|
|
|
let ty_arg = copy lbl.lbl_arg in
|
1997-01-21 05:38:42 -08:00
|
|
|
|
cleanup_types ();
|
1995-05-04 03:15:53 -07:00
|
|
|
|
(ty_arg, ty_res)
|
|
|
|
|
|
1996-04-22 04:15:41 -07:00
|
|
|
|
let instance_parameterized_type sch_args sch =
|
1997-01-21 05:38:42 -08:00
|
|
|
|
let ty_args = List.map copy sch_args in
|
|
|
|
|
let ty = copy sch in
|
|
|
|
|
cleanup_types ();
|
1996-04-22 04:15:41 -07:00
|
|
|
|
(ty_args, ty)
|
|
|
|
|
|
|
|
|
|
let instance_parameterized_type_2 sch_args sch_lst sch =
|
1997-01-21 05:38:42 -08:00
|
|
|
|
let ty_args = List.map copy sch_args in
|
|
|
|
|
let ty_lst = List.map copy sch_lst in
|
|
|
|
|
let ty = copy sch in
|
|
|
|
|
cleanup_types ();
|
1996-04-22 04:15:41 -07:00
|
|
|
|
(ty_args, ty_lst, ty)
|
|
|
|
|
|
|
|
|
|
let instance_class cl =
|
1997-01-21 05:38:42 -08:00
|
|
|
|
let params = List.map copy cl.cty_params in
|
|
|
|
|
let args = List.map copy cl.cty_args in
|
1996-04-22 04:15:41 -07:00
|
|
|
|
let vars =
|
|
|
|
|
Vars.fold
|
|
|
|
|
(fun lab (mut, ty) ->
|
1997-01-21 05:38:42 -08:00
|
|
|
|
Vars.add lab (mut, copy ty))
|
1996-04-22 04:15:41 -07:00
|
|
|
|
cl.cty_vars
|
|
|
|
|
Vars.empty in
|
1997-01-21 05:38:42 -08:00
|
|
|
|
let self = copy cl.cty_self in
|
|
|
|
|
cleanup_types ();
|
1996-04-22 04:15:41 -07:00
|
|
|
|
(params, args, vars, self)
|
|
|
|
|
|
1997-01-23 04:46:46 -08:00
|
|
|
|
(**** Instantiation with parameter substitution ****)
|
1997-01-21 05:38:42 -08:00
|
|
|
|
|
1997-02-20 12:39:02 -08:00
|
|
|
|
let unify' = (* Forward declaration *)
|
|
|
|
|
ref (fun env ty1 ty2 -> raise (Unify []))
|
|
|
|
|
|
|
|
|
|
let rec subst env level abbrev path params args body =
|
1997-01-24 12:54:56 -08:00
|
|
|
|
if level <> generic_level then begin
|
|
|
|
|
let old_level = !current_level in
|
|
|
|
|
current_level := level;
|
1997-02-20 12:39:02 -08:00
|
|
|
|
let body0 = newvar () in (* Stub *)
|
|
|
|
|
begin match path with
|
|
|
|
|
None -> ()
|
|
|
|
|
| Some path -> memorize_abbrev abbrev path body0
|
|
|
|
|
end;
|
1997-01-21 05:38:42 -08:00
|
|
|
|
abbreviations := abbrev;
|
1997-02-20 12:39:02 -08:00
|
|
|
|
let (params', body') = instance_parameterized_type params body in
|
1997-01-21 09:43:53 -08:00
|
|
|
|
abbreviations := ref Mnil;
|
1997-02-20 12:39:02 -08:00
|
|
|
|
!unify' env body0 body';
|
|
|
|
|
List.iter2 (!unify' env) params' args;
|
1997-01-24 12:54:56 -08:00
|
|
|
|
current_level := old_level;
|
1997-02-20 12:39:02 -08:00
|
|
|
|
body'
|
1997-01-21 05:38:42 -08:00
|
|
|
|
end else begin
|
|
|
|
|
(* One cannot expand directly to a generic type. *)
|
1997-01-24 12:54:56 -08:00
|
|
|
|
begin_def ();
|
1997-02-20 12:39:02 -08:00
|
|
|
|
(*
|
|
|
|
|
Arguments cannot be generic either, as they are unified to the
|
|
|
|
|
parameters.
|
|
|
|
|
*)
|
|
|
|
|
List.iter ungeneralize args;
|
|
|
|
|
let ty = subst env !current_level abbrev path params args body in
|
1997-01-23 04:46:46 -08:00
|
|
|
|
end_def ();
|
1997-02-20 12:39:02 -08:00
|
|
|
|
generalize ty;
|
1997-03-07 14:44:02 -08:00
|
|
|
|
List.iter generalize args;
|
1997-01-21 05:38:42 -08:00
|
|
|
|
ty
|
|
|
|
|
end
|
1997-01-20 09:11:47 -08:00
|
|
|
|
|
1997-02-20 12:39:02 -08:00
|
|
|
|
(*
|
|
|
|
|
Only the shape of the type matters, not whether is is generic or
|
|
|
|
|
not. [generic_level] might be somewhat slower, but it ensures
|
|
|
|
|
invariants on types are enforced (decreasing levels.), and we don't
|
|
|
|
|
care about efficiency here.
|
|
|
|
|
*)
|
|
|
|
|
let substitute env params args body =
|
|
|
|
|
subst env generic_level (ref Mnil) None params args body
|
1997-01-20 09:11:47 -08:00
|
|
|
|
|
|
|
|
|
|
1997-01-21 05:38:42 -08:00
|
|
|
|
(****************************)
|
|
|
|
|
(* Abbreviation expansion *)
|
|
|
|
|
(****************************)
|
1997-01-20 09:11:47 -08:00
|
|
|
|
|
|
|
|
|
|
1997-01-23 04:46:46 -08:00
|
|
|
|
(* Search whether the expansion has been memorized. *)
|
1996-04-22 04:15:41 -07:00
|
|
|
|
let rec find_expans p1 =
|
|
|
|
|
function
|
1997-01-21 09:43:53 -08:00
|
|
|
|
Mnil ->
|
1996-04-22 04:15:41 -07:00
|
|
|
|
None
|
1997-01-24 12:54:56 -08:00
|
|
|
|
| Mcons (p2, ty, _) when Path.same p1 p2 ->
|
1997-01-23 04:46:46 -08:00
|
|
|
|
Some ty
|
1997-01-24 12:54:56 -08:00
|
|
|
|
| Mcons (_, _, rem) ->
|
1997-01-23 04:46:46 -08:00
|
|
|
|
find_expans p1 rem
|
1997-01-21 09:43:53 -08:00
|
|
|
|
| Mlink {contents = rem} ->
|
|
|
|
|
find_expans p1 rem
|
|
|
|
|
|
|
|
|
|
let previous_env = ref Env.empty
|
1996-04-22 04:15:41 -07:00
|
|
|
|
|
1997-01-23 04:46:46 -08:00
|
|
|
|
(* Expand an abbreviation. The expansion is memorized. *)
|
1997-03-07 14:44:02 -08:00
|
|
|
|
(*
|
|
|
|
|
Assume the level is greater than the path binding time of the
|
|
|
|
|
expanded abbreviation.
|
|
|
|
|
*)
|
1996-04-22 04:15:41 -07:00
|
|
|
|
let expand_abbrev env path args abbrev level =
|
1997-02-20 12:39:02 -08:00
|
|
|
|
(*
|
|
|
|
|
If the environnement has changed, memorized expansions might not
|
|
|
|
|
be correct anymore, and so we flush the cache. This is safe but
|
|
|
|
|
quite pessimistic: it would be enough to flush the cache at the
|
|
|
|
|
ends of structures and signatures.
|
1997-03-08 14:05:39 -08:00
|
|
|
|
+++ Do it !
|
1997-02-20 12:39:02 -08:00
|
|
|
|
*)
|
1997-01-21 09:43:53 -08:00
|
|
|
|
if env != !previous_env then begin
|
|
|
|
|
cleanup_abbrev ();
|
|
|
|
|
previous_env := env
|
|
|
|
|
end;
|
1996-04-22 04:15:41 -07:00
|
|
|
|
match find_expans path !abbrev with
|
|
|
|
|
Some ty ->
|
1997-01-23 04:46:46 -08:00
|
|
|
|
if level <> generic_level then
|
|
|
|
|
update_level env level ty;
|
1996-04-22 04:15:41 -07:00
|
|
|
|
ty
|
|
|
|
|
| None ->
|
1996-10-01 02:47:18 -07:00
|
|
|
|
let decl =
|
1997-03-07 14:44:02 -08:00
|
|
|
|
(*
|
|
|
|
|
The type constructor is always in the environnement during
|
|
|
|
|
typing. This is not true anymore at a latter stage (code
|
|
|
|
|
generation and debugger), as a non-generic type variable
|
|
|
|
|
can be instanciated afterwards to a previously undefined
|
|
|
|
|
type constructor.
|
1997-03-08 14:05:39 -08:00
|
|
|
|
(+++ actually, it is still true for the moment, due to the
|
1997-03-07 14:44:02 -08:00
|
|
|
|
strong constraint on type levels and constructor binding
|
|
|
|
|
time.)
|
|
|
|
|
(XXX except that moregeneral can bind variables to out of
|
|
|
|
|
context types...)
|
|
|
|
|
*)
|
1996-10-01 02:47:18 -07:00
|
|
|
|
try Env.find_type path env with Not_found -> raise Cannot_expand in
|
|
|
|
|
match decl.type_manifest with
|
|
|
|
|
Some body ->
|
1997-02-20 12:39:02 -08:00
|
|
|
|
subst env level abbrev (Some path) decl.type_params args body
|
|
|
|
|
| None ->
|
1996-10-01 02:47:18 -07:00
|
|
|
|
raise Cannot_expand
|
1996-04-22 04:15:41 -07:00
|
|
|
|
|
1997-01-23 04:46:46 -08:00
|
|
|
|
let _ = expand_abbrev' := expand_abbrev
|
|
|
|
|
|
1997-03-07 14:44:02 -08:00
|
|
|
|
(* Fully expand the head of a type. *)
|
|
|
|
|
let rec expand_head env ty =
|
1996-05-20 09:43:29 -07:00
|
|
|
|
let ty = repr ty in
|
|
|
|
|
match ty.desc with
|
|
|
|
|
Tconstr(p, tl, abbrev) ->
|
|
|
|
|
begin try
|
1997-03-07 14:44:02 -08:00
|
|
|
|
expand_head env (expand_abbrev env p tl abbrev ty.level)
|
1996-05-20 09:43:29 -07:00
|
|
|
|
with Cannot_expand ->
|
|
|
|
|
ty
|
|
|
|
|
end
|
|
|
|
|
| _ ->
|
|
|
|
|
ty
|
|
|
|
|
|
1997-03-07 14:44:02 -08:00
|
|
|
|
(* Recursively expand the head of a type.
|
1997-01-20 09:11:47 -08:00
|
|
|
|
Also expand #-types. *)
|
1996-05-20 09:43:29 -07:00
|
|
|
|
let rec full_expand env ty =
|
1997-03-07 14:44:02 -08:00
|
|
|
|
let ty = repr (expand_head env ty) in
|
1996-05-20 09:43:29 -07:00
|
|
|
|
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-02-20 12:39:02 -08:00
|
|
|
|
(*
|
|
|
|
|
Check whether the abbreviation expands to a well-defined type.
|
1997-01-20 09:11:47 -08:00
|
|
|
|
During the typing of a class, abbreviations for correspondings
|
1997-02-20 12:39:02 -08:00
|
|
|
|
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
|
1997-02-20 12:39:02 -08:00
|
|
|
|
Some body -> (repr body).level = generic_level
|
1997-01-23 04:46:46 -08:00
|
|
|
|
| None -> false
|
1996-04-22 04:15:41 -07:00
|
|
|
|
with
|
|
|
|
|
Not_found ->
|
|
|
|
|
false
|
1995-05-04 03:15:53 -07:00
|
|
|
|
|
1997-01-21 05:38:42 -08:00
|
|
|
|
|
|
|
|
|
(*****************)
|
|
|
|
|
(* Unification *)
|
|
|
|
|
(*****************)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1997-01-20 09:11:47 -08:00
|
|
|
|
(**** Occur check ****)
|
1996-10-28 09:51:55 -08:00
|
|
|
|
|
1997-02-20 12:39:02 -08:00
|
|
|
|
exception Occur
|
|
|
|
|
|
1997-03-08 14:05:39 -08:00
|
|
|
|
(* +++ 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 =
|
1997-02-20 12:39:02 -08:00
|
|
|
|
if ty == ty0 then raise Occur;
|
1996-04-22 04:15:41 -07:00
|
|
|
|
match ty.desc with
|
1997-03-07 14:44:02 -08:00
|
|
|
|
Tconstr(p, tl, abbrev) ->
|
1996-04-22 04:15:41 -07:00
|
|
|
|
if not (List.memq ty !visited) then begin
|
|
|
|
|
visited := ty :: !visited;
|
1997-03-07 14:44:02 -08:00
|
|
|
|
try List.iter occur_rec tl with Occur ->
|
1996-10-28 09:51:55 -08:00
|
|
|
|
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-03-07 14:44:02 -08:00
|
|
|
|
| Tobject (_, _) ->
|
1996-04-22 04:15:41 -07:00
|
|
|
|
()
|
1997-03-07 14:44:02 -08:00
|
|
|
|
| _ ->
|
|
|
|
|
iter_type_expr occur_rec ty
|
1996-04-22 04:15:41 -07:00
|
|
|
|
in
|
|
|
|
|
occur_rec ty
|
|
|
|
|
|
1997-01-20 09:11:47 -08:00
|
|
|
|
(**** Transform error trace ****)
|
1997-03-08 14:05:39 -08:00
|
|
|
|
(* +++ Move it to some other place ? *)
|
1997-01-20 09:11:47 -08:00
|
|
|
|
|
|
|
|
|
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
|
1997-02-20 12:39:02 -08:00
|
|
|
|
if (t1 == t1') & (t2 == t2')
|
|
|
|
|
then rem'
|
|
|
|
|
else (t1, t1')::(t2, t2')::rem'
|
1997-01-20 09:11:47 -08:00
|
|
|
|
| _ ->
|
|
|
|
|
[]
|
|
|
|
|
|
|
|
|
|
(**** Unification ****)
|
|
|
|
|
|
1997-03-07 14:44:02 -08:00
|
|
|
|
(* Return whether [t0] occurs in [ty]. Objects are also traversed. *)
|
1997-02-20 12:39:02 -08:00
|
|
|
|
let deep_occur t0 ty =
|
|
|
|
|
let rec occur_rec ty =
|
|
|
|
|
let ty = repr ty in
|
1997-03-08 14:05:39 -08:00
|
|
|
|
if ty.level >= lowest_level then begin
|
1997-02-20 12:39:02 -08:00
|
|
|
|
if ty == t0 then raise Occur;
|
1997-03-08 14:05:39 -08:00
|
|
|
|
ty.level <- pivot_level - ty.level;
|
1997-02-20 12:39:02 -08:00
|
|
|
|
iter_type_expr occur_rec ty
|
|
|
|
|
end
|
|
|
|
|
in
|
|
|
|
|
try
|
1997-03-07 14:44:02 -08:00
|
|
|
|
occur_rec ty; unmark_type ty; false
|
1997-02-20 12:39:02 -08:00
|
|
|
|
with Occur ->
|
1997-03-07 14:44:02 -08:00
|
|
|
|
unmark_type ty; true
|
1997-02-20 12:39:02 -08:00
|
|
|
|
|
|
|
|
|
(*
|
|
|
|
|
1. When unifying two non-abbreviated types, one type is made a link
|
|
|
|
|
to the other. When unifying an abbreviated type with a
|
|
|
|
|
non-abbreviated type, the non-abbreviated type is made a link to
|
|
|
|
|
the other one. When unifying to abbreviated types, these two
|
|
|
|
|
types are kept distincts, but they are made to (temporally)
|
|
|
|
|
expand to the same type.
|
|
|
|
|
2. Abbreviations with at least one parameter are systematically
|
|
|
|
|
expanded. The overhead does not seem to high, and that way
|
|
|
|
|
abbreviations where some parameters does not appear in the
|
|
|
|
|
expansion, such as ['a t = int], are correctly handled. In
|
|
|
|
|
particular, for this example, unifying ['a t] with ['b t] keeps
|
|
|
|
|
['a] and ['b] distincts. (Is it really important ?)
|
|
|
|
|
3. Unifying an abbreviation ['a t = 'a] with ['a] should not yield
|
|
|
|
|
['a t as 'a]. Indeed, the type variable would otherwise be lost.
|
|
|
|
|
This problem occurs for abbreviations expanding to a type
|
|
|
|
|
variable, but also to many other constrained abbreviations (for
|
|
|
|
|
instance, [(< x : 'a > -> unit) t = <x : 'a>]). The solution is
|
|
|
|
|
that, if an abbreviation is unified with some subpart of its
|
|
|
|
|
parameters, then the parameter actually does not get
|
|
|
|
|
abbreviated. It would be possible to check whether some
|
|
|
|
|
information is indeed lost, but it probably does not worth it.
|
|
|
|
|
*)
|
|
|
|
|
let rec unify env t1 t2 =
|
|
|
|
|
(* First step: special cases (optimizations) *)
|
1996-04-22 04:15:41 -07:00
|
|
|
|
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
|
1997-02-20 12:39:02 -08:00
|
|
|
|
|
1996-05-20 09:43:29 -07:00
|
|
|
|
try
|
|
|
|
|
match (t1.desc, t2.desc) with
|
1997-02-20 12:39:02 -08:00
|
|
|
|
(Tvar, Tconstr _) when deep_occur t1 t2 ->
|
|
|
|
|
unify2 env t1 t2
|
|
|
|
|
| (Tconstr _, Tvar) when deep_occur t2 t1 ->
|
|
|
|
|
unify2 env t1 t2
|
|
|
|
|
| (Tvar, _) ->
|
|
|
|
|
begin try occur env t1 t2 with Occur ->
|
|
|
|
|
raise (Unify [])
|
|
|
|
|
end;
|
|
|
|
|
update_level env t1.level t2;
|
|
|
|
|
t1.desc <- Tlink t2
|
1996-05-20 09:43:29 -07:00
|
|
|
|
| (_, Tvar) ->
|
1997-02-20 12:39:02 -08:00
|
|
|
|
begin try occur env t2 t1 with Occur ->
|
|
|
|
|
raise (Unify [])
|
|
|
|
|
end;
|
|
|
|
|
update_level env t2.level t1;
|
|
|
|
|
t2.desc <- Tlink t1
|
|
|
|
|
| (Tconstr (p1, [], _), Tconstr (p2, [], _)) when Path.same p1 p2 ->
|
|
|
|
|
update_level env t1.level t2;
|
|
|
|
|
t1.desc <- Tlink t2
|
|
|
|
|
| _ ->
|
|
|
|
|
unify2 env t1 t2
|
|
|
|
|
with Unify trace ->
|
|
|
|
|
raise (Unify ((t1, t2)::trace))
|
|
|
|
|
|
|
|
|
|
and unify2 env t1 t2 =
|
|
|
|
|
(* Second step: expansion of abbreviations *)
|
1997-03-07 14:44:02 -08:00
|
|
|
|
let t1' = expand_head env t1 in
|
|
|
|
|
let t2' = expand_head env t2 in
|
1997-02-20 12:39:02 -08:00
|
|
|
|
if t1' == t2' then () else
|
|
|
|
|
|
|
|
|
|
if (t1 == t1') || (t2 != t2') then
|
|
|
|
|
unify3 env t1 t1' t2 t2'
|
|
|
|
|
else
|
|
|
|
|
try unify3 env t2 t2' t1 t1' with Unify trace ->
|
|
|
|
|
raise (Unify (List.map (fun (x, y) -> (y, x)) trace))
|
|
|
|
|
|
|
|
|
|
and unify3 env t1 t1' t2 t2' =
|
|
|
|
|
(* Third step: truly unification *)
|
|
|
|
|
(* Assumes either [t1 == t1'] or [t2 != t2'] *)
|
|
|
|
|
let d1 = t1'.desc and d2 = t2'.desc in
|
|
|
|
|
|
|
|
|
|
if (t2 != t2') && (deep_occur t1' t2) then begin
|
|
|
|
|
(* See point 3. *)
|
|
|
|
|
update_level env t1'.level t2';
|
|
|
|
|
t1'.desc <- Tlink t2'
|
|
|
|
|
end else begin
|
|
|
|
|
update_level env t1'.level t2;
|
|
|
|
|
t1'.desc <- Tlink t2
|
1996-04-22 04:15:41 -07:00
|
|
|
|
end;
|
1997-02-20 12:39:02 -08:00
|
|
|
|
|
1996-04-22 04:15:41 -07:00
|
|
|
|
try
|
1997-02-20 12:39:02 -08:00
|
|
|
|
begin match (d1, d2) with
|
|
|
|
|
(Tvar, _) ->
|
|
|
|
|
begin try occur env t1' t2 with Occur ->
|
|
|
|
|
raise (Unify [])
|
|
|
|
|
end
|
|
|
|
|
| (_, Tvar) ->
|
|
|
|
|
begin try occur env t2' (newty d1) with Occur ->
|
|
|
|
|
raise (Unify [])
|
|
|
|
|
end;
|
|
|
|
|
if t1 == t1' then begin
|
|
|
|
|
(* The variable must be instantiated... *)
|
|
|
|
|
let ty = {desc = d1; level = t1'.level} in
|
|
|
|
|
update_level env t2'.level ty;
|
|
|
|
|
t2'.desc <- Tlink ty
|
|
|
|
|
end else begin
|
|
|
|
|
t1'.desc <- d1;
|
|
|
|
|
update_level env t2'.level t1;
|
|
|
|
|
t2'.desc <- Tlink t1
|
|
|
|
|
end
|
|
|
|
|
| (Tarrow (t1, u1), Tarrow (t2, u2)) ->
|
|
|
|
|
unify env t1 t2; unify env u1 u2
|
1996-04-22 04:15:41 -07:00
|
|
|
|
| (Ttuple tl1, Ttuple tl2) ->
|
|
|
|
|
unify_list env tl1 tl2
|
1997-02-20 12:39:02 -08:00
|
|
|
|
| (Tconstr (p1, tl1, _), Tconstr (p2, tl2, _)) when Path.same p1 p2 ->
|
1996-04-22 04:15:41 -07:00
|
|
|
|
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-03-08 14:05:39 -08:00
|
|
|
|
| (Tfield _, Tfield _) -> (* Actually unused *)
|
1997-01-20 09:11:47 -08:00
|
|
|
|
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 [])
|
1997-03-08 04:14:57 -08:00
|
|
|
|
end
|
1997-02-20 12:39:02 -08:00
|
|
|
|
(*
|
|
|
|
|
(*
|
|
|
|
|
Can only be done afterwards, once the row variable has
|
|
|
|
|
(possibly) been instantiated.
|
|
|
|
|
*)
|
|
|
|
|
if t1 != t1' (* && t2 != t2' *) then begin
|
|
|
|
|
match (t1.desc, t2.desc) with
|
|
|
|
|
(Tconstr (p, ty::_, _), _)
|
|
|
|
|
when ((repr ty).desc != Tvar)
|
|
|
|
|
&& weak_abbrev p
|
|
|
|
|
&& not (deep_occur t1 t2) ->
|
|
|
|
|
update_level env t1.level t2;
|
|
|
|
|
t1.desc <- Tlink t2
|
|
|
|
|
| (_, Tconstr (p, ty::_, _))
|
|
|
|
|
when ((repr ty).desc != Tvar)
|
|
|
|
|
&& weak_abbrev p
|
|
|
|
|
&& not (deep_occur t2 t1) ->
|
|
|
|
|
update_level env t2.level t1;
|
|
|
|
|
t2.desc <- Tlink t1;
|
|
|
|
|
t1'.desc <- Tlink t2'
|
|
|
|
|
| _ ->
|
|
|
|
|
()
|
|
|
|
|
end
|
|
|
|
|
*)
|
|
|
|
|
with Unify trace ->
|
|
|
|
|
t1'.desc <- d1;
|
|
|
|
|
raise (Unify trace)
|
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 []);
|
1997-02-20 12:39:02 -08:00
|
|
|
|
List.iter2 (unify env) 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
|
1997-02-20 12:39:02 -08:00
|
|
|
|
unify env rest1 (build_fields miss2 va);
|
|
|
|
|
unify env (build_fields miss1 va) rest2;
|
|
|
|
|
List.iter (fun (t1, t2) -> unify env t1 t2) pairs
|
1996-04-22 04:15:41 -07:00
|
|
|
|
|
|
|
|
|
let unify env ty1 ty2 =
|
1996-05-20 09:43:29 -07:00
|
|
|
|
try
|
1997-02-20 12:39:02 -08:00
|
|
|
|
unify env ty1 ty2
|
1996-05-20 09:43:29 -07:00
|
|
|
|
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-02-20 12:39:02 -08:00
|
|
|
|
let _ = unify' := unify
|
|
|
|
|
|
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
|
1997-01-23 04:46:46 -08:00
|
|
|
|
update_level env t.level t';
|
1996-04-22 04:15:41 -07:00
|
|
|
|
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]. *)
|
1997-01-23 04:46:46 -08:00
|
|
|
|
let rec filter_method_field env name ty =
|
1996-04-22 04:15:41 -07:00
|
|
|
|
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
|
1997-01-23 04:46:46 -08:00
|
|
|
|
update_level env ty.level ty';
|
1996-04-22 04:15:41 -07:00
|
|
|
|
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
|
1997-01-23 04:46:46 -08:00
|
|
|
|
filter_method_field env name ty2
|
1996-04-22 04:15:41 -07:00
|
|
|
|
| _ ->
|
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
|
1997-01-23 04:46:46 -08:00
|
|
|
|
update_level env ty.level ty';
|
1996-04-22 04:15:41 -07:00
|
|
|
|
ty.desc <- Tlink ty';
|
1997-01-23 04:46:46 -08:00
|
|
|
|
filter_method_field env name ty1
|
1996-04-22 04:15:41 -07:00
|
|
|
|
| Tobject(f, _) ->
|
1997-01-23 04:46:46 -08:00
|
|
|
|
filter_method_field env name f
|
1996-04-22 04:15:41 -07:00
|
|
|
|
| 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-21 05:38:42 -08:00
|
|
|
|
|
|
|
|
|
(***********************************)
|
|
|
|
|
(* Matching between type schemes *)
|
|
|
|
|
(***********************************)
|
|
|
|
|
|
1997-03-08 14:05:39 -08:00
|
|
|
|
(*
|
|
|
|
|
Levels:
|
|
|
|
|
!current_level : generic variables from the pattern
|
|
|
|
|
!current_level - 1 : generic variables from the subject
|
|
|
|
|
|
|
|
|
|
A generic variable from the subject cannot be instantiated, and its
|
|
|
|
|
level must remain unchanged. A generic variable from the pattern
|
|
|
|
|
can be instantiated to anything.
|
|
|
|
|
|
|
|
|
|
Usually, the subject is given by the user, and the pattern is
|
|
|
|
|
unimportant. So, no need to propagate abbreviations.
|
|
|
|
|
*)
|
1995-11-16 05:27:53 -08:00
|
|
|
|
|
1997-03-08 14:05:39 -08:00
|
|
|
|
(*
|
|
|
|
|
Update the level of [ty]. Check that the levels of generic variables
|
|
|
|
|
from the subject are not lowered.
|
|
|
|
|
*)
|
|
|
|
|
let moregen_occur env level ty =
|
1996-04-22 04:15:41 -07:00
|
|
|
|
let rec occur_rec ty =
|
1996-10-25 06:40:04 -07:00
|
|
|
|
let ty = repr ty in
|
1997-03-08 14:05:39 -08:00
|
|
|
|
if ty.level >= !current_level - 1 then begin
|
|
|
|
|
if (ty.desc = Tvar) && (ty.level = !current_level - 1) then
|
|
|
|
|
raise Occur;
|
|
|
|
|
ty.level <- pivot_level - ty.level;
|
1997-03-07 14:44:02 -08:00
|
|
|
|
iter_type_expr occur_rec ty
|
1997-01-20 09:11:47 -08:00
|
|
|
|
end
|
1996-04-22 04:15:41 -07:00
|
|
|
|
in
|
1997-03-08 14:05:39 -08:00
|
|
|
|
if level < !current_level - 1 then begin
|
|
|
|
|
begin try
|
|
|
|
|
occur_rec ty; unmark_type ty
|
|
|
|
|
with Occur ->
|
|
|
|
|
unmark_type ty; raise (Unify [])
|
|
|
|
|
end;
|
|
|
|
|
update_level env level ty
|
|
|
|
|
end
|
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
|
1997-03-08 14:05:39 -08:00
|
|
|
|
let d2 = ref t2.desc in
|
|
|
|
|
moregen_occur env t1.level t2;
|
|
|
|
|
(* Ensure termination *)
|
|
|
|
|
t2.desc <- Tlink t1;
|
1996-04-22 04:15:41 -07:00
|
|
|
|
try
|
1997-03-08 14:05:39 -08:00
|
|
|
|
begin match (t1.desc, !d2) with
|
|
|
|
|
(Tvar, _) when t1.level <> !current_level - 1 ->
|
|
|
|
|
t2.desc <- !d2;
|
|
|
|
|
moregen_occur env t1.level t2;
|
|
|
|
|
t1.desc <- Tlink t2
|
|
|
|
|
| (_, Tvar) when t2.level <> !current_level - 1 ->
|
|
|
|
|
moregen_occur env t2.level t1;
|
|
|
|
|
d2 := Tlink t1
|
1996-04-22 04:15:41 -07:00
|
|
|
|
| (Tarrow(t1, u1), Tarrow(t2, u2)) ->
|
|
|
|
|
moregen env t1 t2; moregen env u1 u2
|
|
|
|
|
| (Ttuple tl1, Ttuple tl2) ->
|
|
|
|
|
moregen_list env tl1 tl2
|
1997-03-08 14:05:39 -08:00
|
|
|
|
| (Tconstr(p1, tl1, abbrev1), Tconstr(p2, tl2, abbrev2))
|
|
|
|
|
when Path.same p1 p2 ->
|
|
|
|
|
begin try
|
1997-03-09 08:52:49 -08:00
|
|
|
|
moregen_list env tl1 tl2
|
1997-03-08 14:05:39 -08:00
|
|
|
|
with Unify _ ->
|
|
|
|
|
try
|
|
|
|
|
moregen env t1 (expand_abbrev env p2 tl2 abbrev2 t2.level)
|
|
|
|
|
with Cannot_expand ->
|
|
|
|
|
t2.desc <- !d2;
|
|
|
|
|
try
|
|
|
|
|
moregen env (expand_abbrev env p1 tl1 abbrev1 t1.level) t2
|
|
|
|
|
with Cannot_expand ->
|
|
|
|
|
raise (Unify [])
|
|
|
|
|
end
|
1996-04-22 04:15:41 -07:00
|
|
|
|
| (Tconstr(p1, tl1, abbrev1), Tconstr(p2, tl2, abbrev2)) ->
|
1997-03-08 14:05:39 -08:00
|
|
|
|
begin 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 [])
|
1996-04-22 04:15:41 -07:00
|
|
|
|
end
|
|
|
|
|
| (Tobject(f1, _), Tobject(f2, _)) ->
|
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), _) ->
|
1997-03-08 14:05:39 -08:00
|
|
|
|
t2.desc <- !d2;
|
1996-04-22 04:15:41 -07:00
|
|
|
|
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
|
1997-03-08 14:05:39 -08:00
|
|
|
|
| (Tfield _, Tfield _) -> (* Actually unused *)
|
|
|
|
|
t2.desc <- !d2;
|
|
|
|
|
moregen_fields env t1 t2
|
|
|
|
|
| (Tnil, Tnil) ->
|
|
|
|
|
()
|
1996-04-22 04:15:41 -07:00
|
|
|
|
| (_, _) ->
|
1996-05-20 09:43:29 -07:00
|
|
|
|
raise (Unify [])
|
1997-03-08 14:05:39 -08:00
|
|
|
|
end;
|
|
|
|
|
t2.desc <- !d2
|
1996-04-22 04:15:41 -07:00
|
|
|
|
with exn ->
|
1997-03-08 14:05:39 -08:00
|
|
|
|
t2.desc <- !d2;
|
1996-04-22 04:15:41 -07:00
|
|
|
|
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
|
1997-03-08 14:05:39 -08:00
|
|
|
|
let va = newvar () in
|
|
|
|
|
moregen env (build_fields miss1 va) rest2;
|
|
|
|
|
moregen env rest1 (build_fields miss2 va);
|
1996-04-22 04:15:41 -07:00
|
|
|
|
List.iter (fun (t1, t2) -> moregen env t1 t2) pairs
|
|
|
|
|
|
1995-05-04 03:15:53 -07:00
|
|
|
|
let moregeneral env sch1 sch2 =
|
1997-03-08 14:05:39 -08:00
|
|
|
|
begin_def ();
|
|
|
|
|
let ty2 = instance sch2 in
|
|
|
|
|
begin_def ();
|
|
|
|
|
let ty1 = instance sch1 in
|
1995-05-04 03:15:53 -07:00
|
|
|
|
try
|
1997-03-08 14:05:39 -08:00
|
|
|
|
moregen env ty1 ty2;
|
|
|
|
|
end_def ();
|
|
|
|
|
end_def ();
|
1995-11-13 06:25:55 -08:00
|
|
|
|
true
|
1996-05-20 09:43:29 -07:00
|
|
|
|
with Unify _ ->
|
1997-03-08 14:05:39 -08:00
|
|
|
|
end_def ();
|
|
|
|
|
end_def ();
|
1995-05-04 03:15:53 -07:00
|
|
|
|
false
|
|
|
|
|
|
1997-01-21 05:38:42 -08:00
|
|
|
|
|
|
|
|
|
(*********************************************)
|
|
|
|
|
(* Equivalence between parameterized types *)
|
|
|
|
|
(*********************************************)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(* XXX A voir... *)
|
1995-11-16 05:27:53 -08:00
|
|
|
|
|
1997-02-20 12:39:02 -08:00
|
|
|
|
(* Deux modes : avec ou sans subtitution *)
|
|
|
|
|
(* Equalite de deux listes de types : *)
|
|
|
|
|
(* [Ctype.equal env rename tyl1 tyl2] *)
|
|
|
|
|
|
|
|
|
|
let equal env rename tyl1 tyl2 =
|
|
|
|
|
let subst = ref [] in
|
1996-04-22 04:15:41 -07:00
|
|
|
|
let type_pairs = ref [] in
|
1997-03-09 08:52:49 -08:00
|
|
|
|
|
1995-05-04 03:15:53 -07:00
|
|
|
|
let rec eqtype t1 t2 =
|
|
|
|
|
let t1 = repr t1 in
|
|
|
|
|
let t2 = repr t2 in
|
1997-02-20 12:39:02 -08:00
|
|
|
|
List.exists (function (t1', t2') -> t1 == t1' & t2 == t2') !type_pairs
|
1997-03-09 08:52:49 -08:00
|
|
|
|
(* XXX Possibly slow... *)
|
1997-02-20 12:39:02 -08:00
|
|
|
|
||
|
|
|
|
|
begin
|
|
|
|
|
type_pairs := (t1, t2) :: !type_pairs;
|
|
|
|
|
match (t1.desc, t2.desc) with
|
|
|
|
|
(Tvar, Tvar) ->
|
|
|
|
|
if rename then begin
|
|
|
|
|
try
|
|
|
|
|
List.assq t1 !subst == t2
|
|
|
|
|
with Not_found ->
|
|
|
|
|
subst := (t1, t2) :: !subst;
|
|
|
|
|
true
|
|
|
|
|
end else
|
|
|
|
|
t1 == t2
|
|
|
|
|
| (Tarrow(t1, u1), Tarrow(t2, u2)) ->
|
|
|
|
|
eqtype t1 t2 & eqtype u1 u2
|
|
|
|
|
| (Ttuple tl1, Ttuple tl2) ->
|
|
|
|
|
eqtype_list tl1 tl2
|
|
|
|
|
| (Tconstr(p1, tl1, abbrev1), Tconstr(p2, tl2, abbrev2)) ->
|
|
|
|
|
(Path.same p1 p2 && eqtype_list tl1 tl2)
|
|
|
|
|
||
|
|
|
|
|
begin
|
1996-04-22 04:15:41 -07:00
|
|
|
|
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
|
1997-02-20 12:39:02 -08:00
|
|
|
|
| (Tobject (f1, _), Tobject (f2, _)) ->
|
1996-04-22 04:15:41 -07:00
|
|
|
|
eqtype_fields f1 f2
|
1997-02-20 12:39:02 -08:00
|
|
|
|
| (Tconstr(p1, tl1, abbrev1), _) ->
|
|
|
|
|
begin try
|
|
|
|
|
eqtype (expand_abbrev env p1 tl1 abbrev1 t1.level) t2
|
|
|
|
|
with Cannot_expand ->
|
|
|
|
|
false
|
|
|
|
|
end
|
|
|
|
|
| (_, Tconstr(p2, tl2, abbrev2)) ->
|
|
|
|
|
begin try
|
|
|
|
|
eqtype t1 (expand_abbrev env p2 tl2 abbrev2 t2.level)
|
|
|
|
|
with Cannot_expand ->
|
|
|
|
|
false
|
|
|
|
|
end
|
|
|
|
|
| (Tfield _, Tfield _) ->
|
|
|
|
|
eqtype_fields t1 t2
|
|
|
|
|
| (Tnil, Tnil) ->
|
|
|
|
|
true
|
|
|
|
|
| (_, _) ->
|
1995-05-04 03:15:53 -07:00
|
|
|
|
false
|
1997-02-20 12:39:02 -08:00
|
|
|
|
end
|
1997-03-09 08:52:49 -08:00
|
|
|
|
|
1995-05-04 03:15:53 -07:00
|
|
|
|
and eqtype_list tl1 tl2 =
|
1997-03-09 08:52:49 -08:00
|
|
|
|
List.length tl1 = List.length tl2
|
|
|
|
|
&&
|
|
|
|
|
List.for_all2 eqtype tl1 tl2
|
|
|
|
|
|
1997-01-23 04:46:46 -08:00
|
|
|
|
and eqtype_fields ty1 ty2 = (* Optimization *)
|
1996-04-22 04:15:41 -07:00
|
|
|
|
let (fields1, rest1) = flatten_fields ty1
|
|
|
|
|
and (fields2, rest2) = flatten_fields ty2 in
|
1997-02-20 12:39:02 -08:00
|
|
|
|
let (pairs, miss1, miss2) = associate_fields fields1 fields2 in
|
1996-04-22 04:15:41 -07:00
|
|
|
|
eqtype rest1 rest2
|
1997-02-20 12:39:02 -08:00
|
|
|
|
&&
|
1997-03-09 08:52:49 -08:00
|
|
|
|
(miss1 = []) && (miss2 = [])
|
1997-02-20 12:39:02 -08:00
|
|
|
|
&&
|
|
|
|
|
List.for_all (function (t1, t2) -> eqtype t1 t2) pairs
|
1995-05-04 03:15:53 -07:00
|
|
|
|
in
|
1997-03-09 08:52:49 -08:00
|
|
|
|
eqtype_list tyl1 tyl2
|
1995-05-04 03:15:53 -07:00
|
|
|
|
|
1997-01-21 05:38:42 -08:00
|
|
|
|
|
1997-01-20 09:11:47 -08:00
|
|
|
|
(***************)
|
|
|
|
|
(* Subtyping *)
|
|
|
|
|
(***************)
|
|
|
|
|
|
|
|
|
|
|
1997-01-21 05:38:42 -08:00
|
|
|
|
(**** Build a subtype of 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-21 05:38:42 -08:00
|
|
|
|
(* XXX Types r<>cursifs ? *)
|
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)
|
1997-01-23 04:46:46 -08:00
|
|
|
|
| Tconstr(p, tl, abbrev) when generic_abbrev env p ->
|
|
|
|
|
let t' = expand_abbrev env p tl abbrev t.level in
|
|
|
|
|
let (t'', c) = build_subtype env t' in
|
|
|
|
|
if c then (t'', true)
|
|
|
|
|
else (t, false)
|
1996-04-22 04:15:41 -07:00
|
|
|
|
| Tconstr(p, tl, abbrev) ->
|
1997-01-23 04:46:46 -08:00
|
|
|
|
(t, false)
|
|
|
|
|
| Tobject (t1, _) when opened_object t1 ->
|
|
|
|
|
(t, false)
|
1996-04-22 04:15:41 -07:00
|
|
|
|
| Tobject (t1, _) ->
|
1997-01-23 04:46:46 -08:00
|
|
|
|
(begin try
|
|
|
|
|
List.assq t !subtypes
|
|
|
|
|
with Not_found ->
|
|
|
|
|
let t' = new_global_var () in
|
|
|
|
|
subtypes := (t, t')::!subtypes;
|
|
|
|
|
let (t1', _) = build_subtype env t1 in
|
|
|
|
|
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-21 05:38:42 -08:00
|
|
|
|
(**** Check whether a type is a subtype of another type. ****)
|
1997-01-20 09:11:47 -08:00
|
|
|
|
|
1997-01-21 09:43:53 -08:00
|
|
|
|
(*
|
1997-01-23 04:46:46 -08:00
|
|
|
|
During the traversal, a trace of visited types is maintained. It
|
|
|
|
|
is printed in case of error.
|
1997-01-21 09:43:53 -08:00
|
|
|
|
Constraints (pairs of types that must be equals) are accumulated
|
|
|
|
|
rather than being enforced straight. Indeed, the result would
|
|
|
|
|
otherwise depend on the order in which these constraints are
|
|
|
|
|
enforced.
|
|
|
|
|
A function enforcing these constraints is returned. That way, type
|
|
|
|
|
variables can be bound to their actual values before this function
|
1997-01-23 04:46:46 -08:00
|
|
|
|
is called (see Typecore).
|
|
|
|
|
Only well-defined abbreviations are expanded (hence the tests
|
|
|
|
|
[generic_abbrev ...]).
|
1997-01-21 09:43:53 -08:00
|
|
|
|
*)
|
|
|
|
|
|
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
|
1997-03-09 08:52:49 -08:00
|
|
|
|
(* XXX Possibly slow *)
|
1997-01-20 09:11:47 -08:00
|
|
|
|
[]
|
|
|
|
|
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
|
1997-01-23 04:46:46 -08:00
|
|
|
|
| (Tconstr(p1, tl1, abbrev1), Tconstr _) when generic_abbrev env p1 ->
|
|
|
|
|
subtype_rec env trace (expand_abbrev env p1 tl1 abbrev1 t1.level) t2
|
|
|
|
|
| (Tconstr _, Tconstr(p2, tl2, abbrev2)) when generic_abbrev env p2 ->
|
|
|
|
|
subtype_rec env trace t1 (expand_abbrev env p2 tl2 abbrev2 t2.level)
|
|
|
|
|
| (Tconstr _, Tconstr _) ->
|
|
|
|
|
[(trace, t1, t2)]
|
|
|
|
|
| (Tconstr(p1, tl1, abbrev1), _) when generic_abbrev env p1 ->
|
|
|
|
|
subtype_rec env trace (expand_abbrev env p1 tl1 abbrev1 t1.level) t2
|
|
|
|
|
| (_, Tconstr (p2, tl2, abbrev2)) when generic_abbrev env p2 ->
|
|
|
|
|
subtype_rec env trace t1 (expand_abbrev env p2 tl2 abbrev2 t2.level)
|
|
|
|
|
| (Tobject (f1, _), Tobject (f2, _))
|
|
|
|
|
when opened_object f1 & opened_object f2 ->
|
|
|
|
|
(* Same row variable implies same object. *)
|
|
|
|
|
[(trace, t1, t2)]
|
1996-04-22 04:15:41 -07:00
|
|
|
|
| (Tobject (f1, _), Tobject (f2, _)) ->
|
1997-01-23 04:46:46 -08:00
|
|
|
|
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
|
1997-03-07 14:44:02 -08:00
|
|
|
|
[(trace, rest1, build_fields miss2 (newvar ()))]
|
1997-01-20 09:11:47 -08:00
|
|
|
|
@
|
1997-03-07 14:44:02 -08:00
|
|
|
|
begin match rest2.desc with
|
|
|
|
|
Tnil -> []
|
|
|
|
|
| _ -> [(trace, build_fields miss1 rest1, rest2)]
|
|
|
|
|
end
|
1997-01-20 09:11:47 -08:00
|
|
|
|
@
|
|
|
|
|
(List.fold_left
|
1997-01-23 04:46:46 -08:00
|
|
|
|
(fun cstrs (t1, t2) -> cstrs @ (subtype_rec env ((t1, t2)::trace) t1 t2))
|
1997-01-20 09:11:47 -08:00
|
|
|
|
[] pairs)
|
|
|
|
|
|
|
|
|
|
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 := []
|
|
|
|
|
|
1997-01-21 05:38:42 -08:00
|
|
|
|
|
1997-03-09 08:52:49 -08:00
|
|
|
|
(*******************)
|
|
|
|
|
(* Miscellaneous *)
|
|
|
|
|
(*******************)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let unalias ty =
|
|
|
|
|
let ty = repr ty in
|
|
|
|
|
match ty.desc with
|
|
|
|
|
Tvar ->
|
|
|
|
|
ty
|
|
|
|
|
| _ ->
|
|
|
|
|
{desc = ty.desc; level = ty.level}
|
|
|
|
|
|
|
|
|
|
let unroll_abbrev id tl ty =
|
|
|
|
|
let ty = repr ty in
|
|
|
|
|
match ty.desc with
|
|
|
|
|
Tvar ->
|
|
|
|
|
ty
|
|
|
|
|
| _ ->
|
|
|
|
|
let ty' = {desc = ty.desc; level = ty.level} in
|
|
|
|
|
ty.desc <- Tlink {desc = Tconstr (Path.Pident id, tl, ref Mnil);
|
|
|
|
|
level = ty.level};
|
|
|
|
|
ty'
|
|
|
|
|
|
|
|
|
|
(* Return the arity (as for curried functions) of the given type. *)
|
|
|
|
|
let rec arity ty =
|
|
|
|
|
match (repr ty).desc with
|
|
|
|
|
Tarrow(t1, t2) -> 1 + arity t2
|
|
|
|
|
| _ -> 0
|
|
|
|
|
|
|
|
|
|
|
1997-01-21 05:38:42 -08:00
|
|
|
|
(*************************)
|
|
|
|
|
(* Remove dependencies *)
|
|
|
|
|
(*************************)
|
|
|
|
|
|
1996-04-22 04:15:41 -07:00
|
|
|
|
|
1997-01-24 12:54:56 -08:00
|
|
|
|
(* XXX Petit probleme... (deroulement) *)
|
|
|
|
|
(* module F(X : sig type t end) = struct type t = X.t end;; *)
|
|
|
|
|
(* module M = F(struct type t = <x : t> end);; *)
|
|
|
|
|
(* -> module M : sig type t = < x : < x : 'a > as 'a > end *)
|
1997-03-09 08:52:49 -08:00
|
|
|
|
|
|
|
|
|
(*
|
|
|
|
|
Variables are left unchanged. Other type nodes are duplicated, with
|
|
|
|
|
levels set to generic level.
|
|
|
|
|
During copying, the description of a (non-variable) node is first
|
|
|
|
|
replaced by a link to a marked stub ([Tlink (newmarkedvar
|
|
|
|
|
())]). The mark allows to differentiate the original type from the
|
|
|
|
|
copy. Once the copy is made, it replaces the stub.
|
|
|
|
|
After copying, the description of node, which was stored in
|
|
|
|
|
[saved_desc], must be put back, using [cleanup_types], and the
|
|
|
|
|
marks on the copy must be removed.
|
|
|
|
|
*)
|
|
|
|
|
|
1996-04-22 04:15:41 -07:00
|
|
|
|
let rec nondep_type_rec env id ty =
|
|
|
|
|
let ty = repr ty in
|
1997-03-09 08:52:49 -08:00
|
|
|
|
if (ty.desc = Tvar) || (ty.level < lowest_level) then
|
|
|
|
|
ty
|
|
|
|
|
else begin
|
|
|
|
|
let desc = ty.desc in
|
|
|
|
|
saved_desc := (ty, desc)::!saved_desc;
|
|
|
|
|
let ty' = newmarkedvar () in (* Stub *)
|
|
|
|
|
ty.desc <- Tlink ty';
|
1996-04-22 04:15:41 -07:00
|
|
|
|
ty'.desc <-
|
1997-03-09 08:52:49 -08:00
|
|
|
|
begin match desc with
|
1996-04-22 04:15:41 -07:00
|
|
|
|
Tvar ->
|
1997-03-09 08:52:49 -08:00
|
|
|
|
fatal_error "Ctype.nondep_type_rec"
|
1996-04-22 04:15:41 -07:00
|
|
|
|
| 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
|
1997-03-09 08:52:49 -08:00
|
|
|
|
Tlink (nondep_type_rec env id
|
|
|
|
|
(expand_abbrev env p tl abbrev ty.level))
|
|
|
|
|
(*
|
|
|
|
|
The [Tlink] is important. The expanded type may be a
|
|
|
|
|
variable, or may not be completely copied yet
|
|
|
|
|
(recursive type), so one cannot just take its
|
|
|
|
|
description.
|
|
|
|
|
*)
|
1996-04-22 04:15:41 -07:00
|
|
|
|
with Cannot_expand ->
|
|
|
|
|
raise Not_found
|
|
|
|
|
end
|
|
|
|
|
else
|
1997-01-21 09:43:53 -08:00
|
|
|
|
Tconstr(p, List.map (nondep_type_rec env id) tl, ref Mnil)
|
1996-04-22 04:15:41 -07:00
|
|
|
|
| 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)))
|
1997-03-09 08:52:49 -08:00
|
|
|
|
| Tfield(label, t1, t2) ->
|
|
|
|
|
Tfield(label, nondep_type_rec env id t1, nondep_type_rec env id t2)
|
|
|
|
|
| Tnil ->
|
|
|
|
|
Tnil
|
|
|
|
|
| Tlink ty -> (* Actually unused *)
|
|
|
|
|
Tlink(nondep_type_rec env id ty)
|
|
|
|
|
end;
|
|
|
|
|
ty'
|
|
|
|
|
end
|
1996-04-22 04:15:41 -07:00
|
|
|
|
|
|
|
|
|
let nondep_type env id ty =
|
1997-03-09 08:52:49 -08:00
|
|
|
|
try
|
|
|
|
|
let ty' = nondep_type_rec env id ty in
|
|
|
|
|
cleanup_types ();
|
|
|
|
|
unmark_type ty';
|
|
|
|
|
ty'
|
|
|
|
|
with Not_found ->
|
|
|
|
|
cleanup_types ();
|
|
|
|
|
raise Not_found
|
|
|
|
|
|
1997-03-09 10:42:51 -08:00
|
|
|
|
(* Preserve sharing inside type declarations. *)
|
1997-03-09 08:52:49 -08:00
|
|
|
|
let nondep_type_decl env mid id is_covariant decl =
|
|
|
|
|
try
|
|
|
|
|
let params = List.map (nondep_type_rec env mid) decl.type_params in
|
|
|
|
|
let decl =
|
|
|
|
|
{ type_params = params;
|
|
|
|
|
type_arity = decl.type_arity;
|
|
|
|
|
type_kind =
|
|
|
|
|
begin try
|
|
|
|
|
match decl.type_kind with
|
|
|
|
|
Type_abstract ->
|
|
|
|
|
Type_abstract
|
|
|
|
|
| Type_variant cstrs ->
|
|
|
|
|
Type_variant(List.map
|
|
|
|
|
(fun (c, tl) -> (c, List.map (nondep_type_rec env mid) tl))
|
|
|
|
|
cstrs)
|
|
|
|
|
| Type_record lbls ->
|
|
|
|
|
Type_record(List.map
|
|
|
|
|
(fun (c, mut, t) -> (c, mut, nondep_type_rec env mid t))
|
|
|
|
|
lbls)
|
|
|
|
|
with Not_found when is_covariant ->
|
|
|
|
|
Type_abstract
|
|
|
|
|
end;
|
|
|
|
|
type_manifest =
|
|
|
|
|
begin try
|
|
|
|
|
match decl.type_manifest with
|
|
|
|
|
None -> None
|
|
|
|
|
| Some ty ->
|
|
|
|
|
Some (unroll_abbrev id params (nondep_type_rec env mid ty))
|
|
|
|
|
with Not_found when is_covariant ->
|
|
|
|
|
None
|
|
|
|
|
end }
|
|
|
|
|
in
|
|
|
|
|
cleanup_types ();
|
1997-03-09 10:42:51 -08:00
|
|
|
|
List.iter unmark_type decl.type_params;
|
1997-03-09 08:52:49 -08:00
|
|
|
|
begin match decl.type_kind with
|
|
|
|
|
Type_abstract -> ()
|
|
|
|
|
| Type_variant cstrs ->
|
|
|
|
|
List.iter (fun (c, tl) -> List.iter unmark_type tl) cstrs
|
|
|
|
|
| Type_record lbls ->
|
|
|
|
|
List.iter (fun (c, mut, t) -> unmark_type t) lbls
|
|
|
|
|
end;
|
|
|
|
|
begin match decl.type_manifest with
|
|
|
|
|
None -> ()
|
|
|
|
|
| Some ty -> unmark_type ty
|
|
|
|
|
end;
|
|
|
|
|
decl
|
|
|
|
|
with Not_found ->
|
|
|
|
|
cleanup_types ();
|
|
|
|
|
raise Not_found
|
1996-04-22 04:15:41 -07:00
|
|
|
|
|
1997-03-09 10:42:51 -08:00
|
|
|
|
(* Preserve sharing inside class types. *)
|
1996-04-22 04:15:41 -07:00
|
|
|
|
let nondep_class_type env id decl =
|
1997-03-09 08:52:49 -08:00
|
|
|
|
try
|
|
|
|
|
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
|
|
|
|
|
cleanup_types ();
|
|
|
|
|
List.iter unmark_type decl.cty_params;
|
|
|
|
|
List.iter unmark_type decl.cty_args;
|
|
|
|
|
Vars.iter (fun l (m, t) -> unmark_type t) decl.cty_vars;
|
|
|
|
|
unmark_type decl.cty_self;
|
|
|
|
|
begin match decl.cty_new with
|
|
|
|
|
None -> ()
|
|
|
|
|
| Some ty -> unmark_type ty
|
|
|
|
|
end;
|
|
|
|
|
decl
|
|
|
|
|
with Not_found ->
|
|
|
|
|
cleanup_types ();
|
|
|
|
|
raise Not_found
|
1997-01-21 05:38:42 -08:00
|
|
|
|
|
|
|
|
|
(******************************)
|
|
|
|
|
(* Abbreviation correctness *)
|
|
|
|
|
(******************************)
|
1996-04-22 04:15:41 -07:00
|
|
|
|
|
|
|
|
|
|
1997-03-08 14:05:39 -08:00
|
|
|
|
(* +++ A supprimer... (occur-check) *)
|
|
|
|
|
|
|
|
|
|
let marked_types = ref []
|
1996-04-22 04:15:41 -07:00
|
|
|
|
|
1997-03-08 14:05:39 -08:00
|
|
|
|
let rec non_recursive_abbrev env path ty =
|
1996-09-21 05:02:42 -07:00
|
|
|
|
let ty = repr ty in
|
1997-03-08 14:05:39 -08:00
|
|
|
|
if ty.level >= lowest_level then begin
|
|
|
|
|
let level = ty.level in
|
|
|
|
|
ty.level <- pivot_level - level;
|
|
|
|
|
match ty.desc with
|
|
|
|
|
Tconstr(p, _, _) when Path.same path p ->
|
1996-09-21 05:02:42 -07:00
|
|
|
|
raise Recursive_abbrev
|
1997-03-08 14:05:39 -08:00
|
|
|
|
| Tconstr(p, args, abbrev) ->
|
1996-09-21 05:02:42 -07:00
|
|
|
|
begin try
|
1997-03-08 14:05:39 -08:00
|
|
|
|
let ty' = repr (expand_abbrev env p args abbrev level) in
|
|
|
|
|
if ty'.level >= lowest_level then begin
|
|
|
|
|
marked_types := ty' :: !marked_types;
|
|
|
|
|
non_recursive_abbrev env path ty'
|
|
|
|
|
end
|
|
|
|
|
with Cannot_expand -> () end
|
|
|
|
|
| Tobject (_, _) ->
|
|
|
|
|
()
|
|
|
|
|
| _ ->
|
|
|
|
|
iter_type_expr (non_recursive_abbrev env path) ty
|
|
|
|
|
end
|
1996-09-21 05:02:42 -07:00
|
|
|
|
|
1996-04-22 04:15:41 -07:00
|
|
|
|
let correct_abbrev env ident params ty =
|
1997-03-08 14:05:39 -08:00
|
|
|
|
marked_types := [ty];
|
|
|
|
|
non_recursive_abbrev env (Path.Pident ident) ty;
|
|
|
|
|
List.iter unmark_type !marked_types;
|
|
|
|
|
marked_types := []
|
1997-01-21 09:43:53 -08:00
|
|
|
|
|
|
|
|
|
|
1997-03-07 14:44:02 -08:00
|
|
|
|
(**************************************)
|
|
|
|
|
(* Check genericity of type schemes *)
|
|
|
|
|
(**************************************)
|
1997-02-20 12:39:02 -08:00
|
|
|
|
|
1996-04-22 04:15:41 -07:00
|
|
|
|
|
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
|
|
|
|
|
|
1997-03-07 14:44:02 -08:00
|
|
|
|
let rec closed_schema_rec fullgen row ty =
|
1996-05-26 06:42:34 -07:00
|
|
|
|
let ty = repr ty in
|
1997-03-08 14:05:39 -08:00
|
|
|
|
if ty.level >= lowest_level then begin
|
1997-03-07 14:44:02 -08:00
|
|
|
|
let level = ty.level in
|
|
|
|
|
if fullgen then
|
1997-03-08 14:05:39 -08:00
|
|
|
|
ty.level <- pivot_level - generic_level (* Generalize type *)
|
1997-03-07 14:44:02 -08:00
|
|
|
|
else
|
1997-03-08 14:05:39 -08:00
|
|
|
|
ty.level <- pivot_level - level;
|
1997-01-20 09:11:47 -08:00
|
|
|
|
match ty.desc with
|
1997-03-07 14:44:02 -08:00
|
|
|
|
Tvar when level != generic_level ->
|
|
|
|
|
raise (Failed (if row then Row_var ty else Var ty))
|
1997-01-20 09:11:47 -08:00
|
|
|
|
| Tobject(f, {contents = Some (_, p)}) ->
|
1997-03-07 14:44:02 -08:00
|
|
|
|
closed_schema_rec fullgen true f;
|
|
|
|
|
List.iter (closed_schema_rec fullgen false) p
|
1997-01-20 09:11:47 -08:00
|
|
|
|
| Tobject(f, _) ->
|
1997-03-07 14:44:02 -08:00
|
|
|
|
closed_schema_rec fullgen true f
|
1997-01-20 09:11:47 -08:00
|
|
|
|
| Tfield(_, t1, t2) ->
|
1997-03-07 14:44:02 -08:00
|
|
|
|
closed_schema_rec fullgen false t1;
|
|
|
|
|
closed_schema_rec fullgen true t2
|
1997-01-20 09:11:47 -08:00
|
|
|
|
| _ ->
|
1997-03-07 14:44:02 -08:00
|
|
|
|
iter_type_expr (closed_schema_rec fullgen false) ty
|
1997-01-20 09:11:47 -08:00
|
|
|
|
end
|
1996-05-26 06:42:34 -07:00
|
|
|
|
|
1997-03-07 14:44:02 -08:00
|
|
|
|
(*
|
|
|
|
|
Return whether all variables of type [ty] are generic. The type is
|
|
|
|
|
also generalized if [fullgen] is true.
|
|
|
|
|
A file interface should be fully generic. On the other hand, class
|
|
|
|
|
abbreviation expansion cannot be made fully generic (this could
|
|
|
|
|
break type level invariant).
|
|
|
|
|
*)
|
|
|
|
|
let closed_schema fullgen ty =
|
1996-05-26 06:42:34 -07:00
|
|
|
|
try
|
1997-03-07 14:44:02 -08:00
|
|
|
|
closed_schema_rec fullgen false ty;
|
|
|
|
|
unmark_type ty;
|
1996-05-26 06:42:34 -07:00
|
|
|
|
true
|
|
|
|
|
with Failed _ ->
|
1997-03-07 14:44:02 -08:00
|
|
|
|
unmark_type ty;
|
1996-05-26 06:42:34 -07:00
|
|
|
|
false
|
|
|
|
|
|
1997-03-07 14:44:02 -08:00
|
|
|
|
(*
|
|
|
|
|
Check that all variables of type [ty] are generic. If this is not
|
|
|
|
|
the case, the non-generic variable is returned. The type is never
|
|
|
|
|
generalized.
|
|
|
|
|
*)
|
1996-05-26 06:42:34 -07:00
|
|
|
|
let closed_schema_verbose ty =
|
|
|
|
|
try
|
1997-03-07 14:44:02 -08:00
|
|
|
|
closed_schema_rec false false ty;
|
|
|
|
|
unmark_type ty;
|
1996-05-26 06:42:34 -07:00
|
|
|
|
None
|
|
|
|
|
with Failed status ->
|
1997-03-07 14:44:02 -08:00
|
|
|
|
unmark_type ty;
|
1996-05-26 06:42:34 -07:00
|
|
|
|
Some status
|