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
|
|
|
(* *)
|
1997-02-20 12:39:02 -08: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 *)
|
1999-11-17 10:59:06 -08:00
|
|
|
(* en Automatique. All rights reserved. This file is distributed *)
|
|
|
|
(* under the terms of the Q Public License version 1.0. *)
|
1995-08-09 08:06:35 -07:00
|
|
|
(* *)
|
|
|
|
(***********************************************************************)
|
|
|
|
|
|
|
|
(* $Id$ *)
|
|
|
|
|
1997-02-20 12:39:02 -08:00
|
|
|
(**** Typing of type definitions ****)
|
1995-05-04 03:15:53 -07:00
|
|
|
|
1997-02-20 12:39:02 -08:00
|
|
|
open Misc
|
2000-09-06 03:21:07 -07:00
|
|
|
open Asttypes
|
1995-05-04 03:15:53 -07:00
|
|
|
open Parsetree
|
2000-06-05 05:18:30 -07:00
|
|
|
open Primitive
|
1996-09-23 04:33:27 -07:00
|
|
|
open Types
|
1995-05-04 03:15:53 -07:00
|
|
|
open Typedtree
|
|
|
|
open Typetexp
|
|
|
|
|
|
|
|
type error =
|
|
|
|
Repeated_parameter
|
|
|
|
| Duplicate_constructor of string
|
1995-05-22 08:43:44 -07:00
|
|
|
| Too_many_constructors
|
1995-05-04 03:15:53 -07:00
|
|
|
| Duplicate_label of string
|
|
|
|
| Recursive_abbrev of string
|
1995-09-26 13:23:29 -07:00
|
|
|
| Definition_mismatch of type_expr
|
2000-05-24 01:06:33 -07:00
|
|
|
| Constraint_failed of type_expr * type_expr
|
2001-12-25 19:43:41 -08:00
|
|
|
| Unconsistent_constraint of (type_expr * type_expr) list
|
1997-02-20 12:39:02 -08:00
|
|
|
| Type_clash of (type_expr * type_expr) list
|
2000-05-24 19:09:13 -07:00
|
|
|
| Parameters_differ of type_expr * type_expr
|
1997-05-13 07:07:00 -07:00
|
|
|
| Null_arity_external
|
2000-06-05 05:18:30 -07:00
|
|
|
| Missing_native_external
|
1998-06-24 12:22:26 -07:00
|
|
|
| Unbound_type_var
|
2000-03-12 05:10:29 -08:00
|
|
|
| Unbound_exception of Longident.t
|
|
|
|
| Not_an_exception of Longident.t
|
2000-09-07 03:57:32 -07:00
|
|
|
| Bad_variance
|
2001-09-28 15:55:27 -07:00
|
|
|
| Unavailable_type_constructor of Path.t
|
1995-05-04 03:15:53 -07:00
|
|
|
|
|
|
|
exception Error of Location.t * error
|
|
|
|
|
|
|
|
(* Enter all declared types in the environment as abstract types *)
|
|
|
|
|
2000-05-23 23:19:39 -07:00
|
|
|
let enter_type env (name, sdecl) id =
|
|
|
|
let decl =
|
|
|
|
{ type_params =
|
|
|
|
List.map (fun _ -> Btype.newgenvar ()) sdecl.ptype_params;
|
|
|
|
type_arity = List.length sdecl.ptype_params;
|
|
|
|
type_kind = Type_abstract;
|
2000-08-03 20:29:42 -07:00
|
|
|
type_manifest =
|
2000-09-06 03:21:07 -07:00
|
|
|
begin match sdecl.ptype_manifest with None -> None
|
|
|
|
| Some _ -> Some(Ctype.newvar ()) end;
|
|
|
|
type_variance = List.map (fun _ -> true, true) sdecl.ptype_params;
|
|
|
|
}
|
2000-05-23 23:19:39 -07:00
|
|
|
in
|
|
|
|
Env.add_type id decl env
|
1995-05-04 03:15:53 -07:00
|
|
|
|
2000-08-03 20:29:42 -07:00
|
|
|
let update_type temp_env env id loc =
|
|
|
|
let path = Path.Pident id in
|
|
|
|
let decl = Env.find_type path temp_env in
|
|
|
|
match decl.type_manifest with None -> ()
|
|
|
|
| Some ty ->
|
|
|
|
let params = List.map (fun _ -> Ctype.newvar ()) decl.type_params in
|
|
|
|
try Ctype.unify env (Ctype.newconstr path params) ty
|
|
|
|
with Ctype.Unify trace ->
|
|
|
|
raise (Error(loc, Type_clash trace))
|
|
|
|
|
2000-03-21 06:43:25 -08:00
|
|
|
(* Determine if a type is (an abbreviation for) the type "float" *)
|
|
|
|
|
|
|
|
let is_float env ty =
|
|
|
|
match Ctype.repr (Ctype.expand_head env ty) with
|
|
|
|
{desc = Tconstr(p, _, _)} -> Path.same p Predef.path_float
|
|
|
|
| _ -> false
|
|
|
|
|
1995-05-04 03:15:53 -07:00
|
|
|
(* Translate one type declaration *)
|
|
|
|
|
1995-05-30 06:36:40 -07:00
|
|
|
module StringSet =
|
|
|
|
Set.Make(struct
|
|
|
|
type t = string
|
|
|
|
let compare = compare
|
|
|
|
end)
|
|
|
|
|
2000-05-23 23:19:39 -07:00
|
|
|
let transl_declaration env (name, sdecl) id =
|
1997-04-24 06:41:16 -07:00
|
|
|
(* Bind type parameters *)
|
|
|
|
reset_type_variables();
|
2000-05-24 01:06:33 -07:00
|
|
|
let params =
|
|
|
|
try List.map (enter_type_variable true) sdecl.ptype_params
|
|
|
|
with Already_bound ->
|
|
|
|
raise(Error(sdecl.ptype_loc, Repeated_parameter))
|
|
|
|
in
|
2000-05-23 23:19:39 -07:00
|
|
|
let decl =
|
1997-04-24 06:41:16 -07:00
|
|
|
{ type_params = params;
|
2000-05-23 23:19:39 -07:00
|
|
|
type_arity = List.length params;
|
1995-09-26 13:23:29 -07:00
|
|
|
type_kind =
|
|
|
|
begin match sdecl.ptype_kind with
|
2000-09-07 03:57:32 -07:00
|
|
|
Ptype_abstract ->
|
1995-09-26 13:23:29 -07:00
|
|
|
Type_abstract
|
|
|
|
| Ptype_variant cstrs ->
|
|
|
|
let all_constrs = ref StringSet.empty in
|
|
|
|
List.iter
|
|
|
|
(fun (name, args) ->
|
|
|
|
if StringSet.mem name !all_constrs then
|
|
|
|
raise(Error(sdecl.ptype_loc, Duplicate_constructor name));
|
|
|
|
all_constrs := StringSet.add name !all_constrs)
|
|
|
|
cstrs;
|
2000-05-22 01:24:05 -07:00
|
|
|
if List.length (List.filter (fun (name, args) -> args <> []) cstrs)
|
2002-01-20 09:29:18 -08:00
|
|
|
> (Config.max_tag + 1) then
|
1995-09-26 13:23:29 -07:00
|
|
|
raise(Error(sdecl.ptype_loc, Too_many_constructors));
|
|
|
|
Type_variant(List.map
|
|
|
|
(fun (name, args) ->
|
|
|
|
(name, List.map (transl_simple_type env true) args))
|
|
|
|
cstrs)
|
|
|
|
| Ptype_record lbls ->
|
|
|
|
let all_labels = ref StringSet.empty in
|
|
|
|
List.iter
|
|
|
|
(fun (name, mut, arg) ->
|
|
|
|
if StringSet.mem name !all_labels then
|
|
|
|
raise(Error(sdecl.ptype_loc, Duplicate_label name));
|
|
|
|
all_labels := StringSet.add name !all_labels)
|
|
|
|
lbls;
|
2000-03-21 06:43:25 -08:00
|
|
|
let lbls' =
|
|
|
|
List.map
|
|
|
|
(fun (name, mut, arg) ->
|
|
|
|
(name, mut, transl_simple_type env true arg))
|
|
|
|
lbls in
|
|
|
|
let rep =
|
|
|
|
if List.for_all (fun (name, mut, arg) -> is_float env arg) lbls'
|
|
|
|
then Record_float
|
|
|
|
else Record_regular in
|
|
|
|
Type_record(lbls', rep)
|
1995-09-26 13:23:29 -07:00
|
|
|
end;
|
2000-05-23 23:19:39 -07:00
|
|
|
type_manifest =
|
|
|
|
begin match sdecl.ptype_manifest with
|
|
|
|
None -> None
|
|
|
|
| Some sty ->
|
|
|
|
let ty = transl_simple_type env true sty in
|
|
|
|
if Ctype.cyclic_abbrev env id ty then
|
|
|
|
raise(Error(sdecl.ptype_loc, Recursive_abbrev name));
|
|
|
|
Some ty
|
2000-09-06 03:21:07 -07:00
|
|
|
end;
|
|
|
|
type_variance = List.map (fun _ -> true, true) params;
|
|
|
|
} in
|
2000-05-23 23:19:39 -07:00
|
|
|
|
|
|
|
(* Check constraints *)
|
|
|
|
List.iter
|
|
|
|
(function (sty, sty', loc) ->
|
|
|
|
try
|
|
|
|
Ctype.unify env (transl_simple_type env false sty)
|
|
|
|
(transl_simple_type env false sty')
|
2001-12-25 19:43:41 -08:00
|
|
|
with Ctype.Unify tr ->
|
|
|
|
raise(Error(loc, Unconsistent_constraint tr)))
|
2000-05-23 23:19:39 -07:00
|
|
|
sdecl.ptype_cstrs;
|
|
|
|
|
2000-09-07 03:57:32 -07:00
|
|
|
(id, decl)
|
1997-02-20 12:39:02 -08:00
|
|
|
|
|
|
|
(* Generalize a type declaration *)
|
|
|
|
|
|
|
|
let generalize_decl decl =
|
|
|
|
List.iter Ctype.generalize decl.type_params;
|
1996-04-22 04:15:41 -07:00
|
|
|
begin match decl.type_kind with
|
|
|
|
Type_abstract ->
|
|
|
|
()
|
|
|
|
| Type_variant v ->
|
|
|
|
List.iter (fun (_, tyl) -> List.iter Ctype.generalize tyl) v
|
2000-03-21 06:43:25 -08:00
|
|
|
| Type_record(r, rep) ->
|
1996-04-22 04:15:41 -07:00
|
|
|
List.iter (fun (_, _, ty) -> Ctype.generalize ty) r
|
|
|
|
end;
|
|
|
|
begin match decl.type_manifest with
|
|
|
|
None -> ()
|
|
|
|
| Some ty -> Ctype.generalize ty
|
1997-02-20 12:39:02 -08:00
|
|
|
end
|
|
|
|
|
2000-05-23 23:19:39 -07:00
|
|
|
(* Check that all constraints are enforced *)
|
|
|
|
|
2000-05-24 01:06:33 -07:00
|
|
|
module TypeSet =
|
|
|
|
Set.Make
|
|
|
|
(struct
|
|
|
|
type t = type_expr
|
|
|
|
let compare t1 t2 = t1.id - t2.id
|
|
|
|
end)
|
|
|
|
|
|
|
|
let rec check_constraints_rec env loc visited ty =
|
2000-05-23 23:19:39 -07:00
|
|
|
let ty = Ctype.repr ty in
|
2000-05-24 01:06:33 -07:00
|
|
|
if TypeSet.mem ty !visited then () else begin
|
|
|
|
visited := TypeSet.add ty !visited;
|
2000-05-23 23:19:39 -07:00
|
|
|
match ty.desc with
|
|
|
|
| Tconstr (path, args, _) ->
|
|
|
|
Ctype.begin_def ();
|
|
|
|
let args' = List.map (fun _ -> Ctype.newvar ()) args in
|
2000-05-24 19:09:13 -07:00
|
|
|
let ty' = Ctype.newconstr path args' in
|
2000-05-23 23:19:39 -07:00
|
|
|
begin try Ctype.enforce_constraints env ty'
|
|
|
|
with Ctype.Unify _ -> assert false
|
2001-09-28 15:55:27 -07:00
|
|
|
| Not_found -> raise (Error(loc, Unavailable_type_constructor path))
|
2000-05-23 23:19:39 -07:00
|
|
|
end;
|
|
|
|
Ctype.end_def ();
|
|
|
|
Ctype.generalize ty';
|
2000-08-03 20:29:42 -07:00
|
|
|
if not (List.for_all2 (Ctype.moregeneral env false) args' args) then
|
2000-05-24 01:06:33 -07:00
|
|
|
raise (Error(loc, Constraint_failed (ty, ty')));
|
|
|
|
List.iter (check_constraints_rec env loc visited) args
|
2000-05-23 23:19:39 -07:00
|
|
|
| _ ->
|
2000-05-24 01:06:33 -07:00
|
|
|
Btype.iter_type_expr (check_constraints_rec env loc visited) ty
|
|
|
|
end
|
2000-05-23 23:19:39 -07:00
|
|
|
|
|
|
|
let check_constraints env (_, sdecl) (_, decl) =
|
2000-05-24 01:06:33 -07:00
|
|
|
let visited = ref TypeSet.empty in
|
2000-05-23 23:19:39 -07:00
|
|
|
begin match decl.type_kind with
|
|
|
|
| Type_abstract -> ()
|
|
|
|
| Type_variant l ->
|
|
|
|
let pl =
|
|
|
|
match sdecl.ptype_kind with Ptype_variant pl -> pl | _ -> assert false
|
|
|
|
in
|
|
|
|
List.iter
|
|
|
|
(fun (name, tyl) ->
|
|
|
|
let styl = try List.assoc name pl with Not_found -> assert false in
|
|
|
|
List.iter2
|
2000-05-24 01:06:33 -07:00
|
|
|
(fun sty ty -> check_constraints_rec env sty.ptyp_loc visited ty)
|
2000-05-23 23:19:39 -07:00
|
|
|
styl tyl)
|
|
|
|
l
|
|
|
|
| Type_record (l, _) ->
|
|
|
|
let pl =
|
|
|
|
match sdecl.ptype_kind with Ptype_record pl -> pl | _ -> assert false
|
|
|
|
in
|
|
|
|
let rec get_loc name = function
|
|
|
|
[] -> assert false
|
|
|
|
| (name', _, sty) :: tl ->
|
|
|
|
if name = name' then sty.ptyp_loc else get_loc name tl
|
|
|
|
in
|
|
|
|
List.iter
|
2000-05-24 01:06:33 -07:00
|
|
|
(fun (name, _, ty) ->
|
|
|
|
check_constraints_rec env (get_loc name pl) visited ty)
|
2000-05-23 23:19:39 -07:00
|
|
|
l
|
|
|
|
end;
|
|
|
|
begin match decl.type_manifest with
|
|
|
|
| None -> ()
|
|
|
|
| Some ty ->
|
|
|
|
let sty =
|
|
|
|
match sdecl.ptype_manifest with Some sty -> sty | _ -> assert false
|
|
|
|
in
|
2000-05-24 01:06:33 -07:00
|
|
|
check_constraints_rec env sty.ptyp_loc visited ty
|
2000-05-23 23:19:39 -07:00
|
|
|
end
|
|
|
|
|
1997-02-20 12:39:02 -08:00
|
|
|
(*
|
|
|
|
If both a variant/record definition and a type equation are given,
|
|
|
|
need to check that the equation refers to a type of the same kind
|
|
|
|
with the same constructors and labels.
|
|
|
|
*)
|
|
|
|
let check_abbrev env (_, sdecl) (id, decl) =
|
|
|
|
match decl with
|
1995-11-03 05:23:03 -08:00
|
|
|
{type_kind = (Type_variant _ | Type_record _); type_manifest = Some ty} ->
|
1997-02-20 12:39:02 -08:00
|
|
|
begin match (Ctype.repr ty).desc with
|
1996-04-22 04:15:41 -07:00
|
|
|
Tconstr(path, args, _) ->
|
1995-11-03 05:23:03 -08:00
|
|
|
begin try
|
|
|
|
let decl' = Env.find_type path env in
|
1998-02-26 04:54:44 -08:00
|
|
|
if List.length args = List.length decl.type_params
|
|
|
|
&& Ctype.equal env false args decl.type_params
|
|
|
|
&& Includecore.type_declarations env id
|
1997-05-12 04:30:03 -07:00
|
|
|
decl'
|
1996-11-13 07:32:07 -08:00
|
|
|
(Subst.type_declaration (Subst.add_type id path Subst.identity)
|
|
|
|
decl)
|
1995-11-03 05:23:03 -08:00
|
|
|
then ()
|
|
|
|
else raise(Error(sdecl.ptype_loc, Definition_mismatch ty))
|
|
|
|
with Not_found ->
|
2001-09-28 15:55:27 -07:00
|
|
|
raise(Error(sdecl.ptype_loc, Unavailable_type_constructor path))
|
1995-11-03 05:23:03 -08:00
|
|
|
end
|
|
|
|
| _ -> raise(Error(sdecl.ptype_loc, Definition_mismatch ty))
|
|
|
|
end
|
|
|
|
| _ -> ()
|
1995-05-04 03:15:53 -07:00
|
|
|
|
1996-04-22 04:15:41 -07:00
|
|
|
(* Check for ill-defined abbrevs *)
|
1995-05-04 03:15:53 -07:00
|
|
|
|
1997-05-11 14:34:04 -07:00
|
|
|
(* Occur check *)
|
1995-05-04 03:15:53 -07:00
|
|
|
let check_recursive_abbrev env (name, sdecl) (id, decl) =
|
1995-09-26 13:23:29 -07:00
|
|
|
match decl.type_manifest with
|
|
|
|
Some ty ->
|
1996-04-22 04:15:41 -07:00
|
|
|
begin try Ctype.correct_abbrev env id decl.type_params ty with
|
|
|
|
Ctype.Recursive_abbrev ->
|
|
|
|
raise(Error(sdecl.ptype_loc, Recursive_abbrev name))
|
|
|
|
end
|
|
|
|
| _ ->
|
|
|
|
()
|
1995-05-04 03:15:53 -07:00
|
|
|
|
2000-05-24 19:09:13 -07:00
|
|
|
(* Recursive expansion check *)
|
|
|
|
|
2001-01-08 16:18:52 -08:00
|
|
|
let rec check_expansion_rec env id args loc id_check_list visited ty =
|
2000-05-24 19:09:13 -07:00
|
|
|
let ty = Ctype.repr ty in
|
|
|
|
if List.memq ty visited then () else
|
|
|
|
let visited = ty :: visited in
|
|
|
|
begin match ty.desc with
|
|
|
|
| Tconstr(Path.Pident id' as path, args', _) ->
|
|
|
|
if Ident.same id id' then begin
|
|
|
|
if not (Ctype.equal env false args args') then
|
|
|
|
raise (Error(loc, Parameters_differ(ty, Ctype.newconstr path args)))
|
|
|
|
end else begin try
|
2001-01-08 16:18:52 -08:00
|
|
|
let (loc, checked) = List.assoc id' id_check_list in
|
|
|
|
if List.exists (Ctype.equal env false args') !checked then () else
|
2000-05-24 19:09:13 -07:00
|
|
|
begin
|
2001-01-08 16:18:52 -08:00
|
|
|
checked := args' :: !checked;
|
|
|
|
let id_check_list = List.remove_assoc id' id_check_list in
|
|
|
|
let (params, body) = Env.find_type_expansion path env in
|
|
|
|
let (params, body) = Ctype.instance_parameterized_type params body in
|
|
|
|
begin
|
|
|
|
try List.iter2 (Ctype.unify env) params args'
|
|
|
|
with Ctype.Unify _ -> assert false
|
|
|
|
end;
|
|
|
|
check_expansion_rec env id args loc id_check_list visited body
|
|
|
|
end
|
2000-05-24 19:09:13 -07:00
|
|
|
with Not_found -> ()
|
|
|
|
end
|
|
|
|
| _ -> ()
|
|
|
|
end;
|
|
|
|
Btype.iter_type_expr
|
2001-01-08 16:18:52 -08:00
|
|
|
(check_expansion_rec env id args loc id_check_list visited) ty
|
2000-05-24 19:09:13 -07:00
|
|
|
|
|
|
|
let check_expansion env id_loc_list (id, decl) =
|
2001-01-08 16:18:52 -08:00
|
|
|
if decl.type_params = [] then () else
|
2000-05-24 19:09:13 -07:00
|
|
|
match decl.type_manifest with
|
|
|
|
| None -> ()
|
|
|
|
| Some body ->
|
|
|
|
let (args, body) =
|
|
|
|
Ctype.instance_parameterized_type decl.type_params body in
|
2001-01-08 16:18:52 -08:00
|
|
|
let id_check_list =
|
|
|
|
List.map (fun (id, loc) -> (id, (loc, ref []))) id_loc_list in
|
2000-05-24 19:09:13 -07:00
|
|
|
check_expansion_rec env id args
|
2001-01-08 16:18:52 -08:00
|
|
|
(List.assoc id id_loc_list) id_check_list [] body
|
2000-05-24 19:09:13 -07:00
|
|
|
|
2000-09-06 03:21:07 -07:00
|
|
|
(* Compute variance *)
|
|
|
|
let compute_variance env tvl nega posi ty =
|
|
|
|
let pvisited = ref TypeSet.empty
|
|
|
|
and nvisited = ref TypeSet.empty in
|
|
|
|
let rec compute_variance_rec posi nega ty =
|
|
|
|
let ty = Ctype.repr ty in
|
|
|
|
if (not posi || TypeSet.mem ty !pvisited)
|
|
|
|
&& (not nega || TypeSet.mem ty !nvisited) then
|
|
|
|
()
|
|
|
|
else begin
|
|
|
|
if posi then pvisited := TypeSet.add ty !pvisited;
|
|
|
|
if nega then nvisited := TypeSet.add ty !nvisited;
|
|
|
|
match ty.desc with
|
2001-04-19 01:34:21 -07:00
|
|
|
Tarrow (_, ty1, ty2, _) ->
|
2000-09-06 03:21:07 -07:00
|
|
|
compute_variance_rec nega posi ty1;
|
|
|
|
compute_variance_rec posi nega ty2
|
|
|
|
| Ttuple tl ->
|
|
|
|
List.iter (compute_variance_rec posi nega) tl
|
|
|
|
| Tconstr (path, tl, _) ->
|
2001-09-28 15:55:27 -07:00
|
|
|
if tl = [] then () else begin
|
|
|
|
try
|
|
|
|
let decl = Env.find_type path env in
|
|
|
|
List.iter2
|
|
|
|
(fun ty (co,cn) ->
|
|
|
|
compute_variance_rec
|
|
|
|
(posi && co || nega && cn)
|
|
|
|
(posi && cn || nega && co)
|
|
|
|
ty)
|
|
|
|
tl decl.type_variance
|
|
|
|
with Not_found ->
|
|
|
|
List.iter (compute_variance_rec true true) tl
|
|
|
|
end
|
2000-09-06 03:21:07 -07:00
|
|
|
| Tobject (ty, _) ->
|
|
|
|
compute_variance_rec posi nega ty
|
|
|
|
| Tfield (_, _, ty1, ty2) ->
|
|
|
|
compute_variance_rec posi nega ty1;
|
|
|
|
compute_variance_rec posi nega ty2
|
|
|
|
| Tsubst ty ->
|
|
|
|
compute_variance_rec posi nega ty
|
|
|
|
| Tvariant row ->
|
|
|
|
List.iter
|
|
|
|
(fun (_,f) ->
|
|
|
|
match Btype.row_field_repr f with
|
|
|
|
Rpresent (Some ty) ->
|
|
|
|
compute_variance_rec posi nega ty
|
2001-03-02 16:14:35 -08:00
|
|
|
| Reither (_, tyl, _, _) ->
|
2000-09-06 03:21:07 -07:00
|
|
|
List.iter (compute_variance_rec posi nega) tyl
|
|
|
|
| _ -> ())
|
|
|
|
(Btype.row_repr row).row_fields
|
|
|
|
| Tvar | Tnil | Tlink _ -> ()
|
|
|
|
end
|
|
|
|
in
|
|
|
|
compute_variance_rec nega posi ty;
|
|
|
|
List.iter
|
|
|
|
(fun (ty, covar, convar) ->
|
|
|
|
if TypeSet.mem ty !pvisited then covar := true;
|
|
|
|
if TypeSet.mem ty !nvisited then convar := true)
|
|
|
|
tvl
|
|
|
|
|
2000-09-07 03:57:32 -07:00
|
|
|
let compute_variance_decl env decl (required, loc) =
|
|
|
|
if decl.type_kind = Type_abstract && decl.type_manifest = None then
|
|
|
|
List.map (fun (c, n) -> if c || n then (c, n) else (true, true)) required
|
|
|
|
else
|
2000-09-06 03:21:07 -07:00
|
|
|
let tvl = List.map (fun ty -> (Btype.repr ty, ref false, ref false))
|
|
|
|
decl.type_params in
|
|
|
|
begin match decl.type_kind with
|
|
|
|
Type_abstract ->
|
2000-09-07 03:57:32 -07:00
|
|
|
begin match decl.type_manifest with
|
|
|
|
None -> assert false
|
|
|
|
| Some ty -> compute_variance env tvl true false ty
|
2000-09-06 03:21:07 -07:00
|
|
|
end
|
|
|
|
| Type_variant tll ->
|
|
|
|
List.iter
|
|
|
|
(fun (_,tl) -> List.iter (compute_variance env tvl true false) tl)
|
|
|
|
tll
|
|
|
|
| Type_record (ftl, _) ->
|
|
|
|
List.iter
|
|
|
|
(fun (_, mut, ty) -> compute_variance env tvl true (mut = Mutable) ty)
|
|
|
|
ftl
|
|
|
|
end;
|
2000-09-07 03:57:32 -07:00
|
|
|
List.map2
|
|
|
|
(fun (_, co, cn) (c, n) ->
|
|
|
|
if c && !cn || n && !co then raise (Error(loc, Bad_variance));
|
|
|
|
(!co, !cn))
|
|
|
|
tvl required
|
2000-09-06 03:21:07 -07:00
|
|
|
|
2000-09-07 03:57:32 -07:00
|
|
|
let rec compute_variance_fixpoint env decls required variances =
|
2000-09-06 03:21:07 -07:00
|
|
|
let new_decls =
|
|
|
|
List.map2
|
|
|
|
(fun (id, decl) variance -> id, {decl with type_variance = variance})
|
|
|
|
decls variances
|
|
|
|
in
|
|
|
|
let new_env =
|
|
|
|
List.fold_right (fun (id, decl) env -> Env.add_type id decl env)
|
|
|
|
new_decls env
|
|
|
|
in
|
|
|
|
let new_variances =
|
|
|
|
List.map2 (fun (_, decl) -> compute_variance_decl new_env decl)
|
2000-09-07 03:57:32 -07:00
|
|
|
new_decls required
|
2000-09-06 03:21:07 -07:00
|
|
|
in
|
|
|
|
let new_variances =
|
|
|
|
List.map2 (List.map2 (fun (c1,n1) (c2,n2) -> (c1||c2), (n1||n2)))
|
|
|
|
new_variances variances in
|
|
|
|
if new_variances = variances then
|
|
|
|
new_decls, new_env
|
|
|
|
else
|
2000-09-07 03:57:32 -07:00
|
|
|
compute_variance_fixpoint env decls required new_variances
|
2000-09-06 03:21:07 -07:00
|
|
|
|
|
|
|
(* for typeclass.ml *)
|
|
|
|
let compute_variance_decls env decls =
|
2000-09-07 03:57:32 -07:00
|
|
|
let decls, required = List.split decls in
|
2000-09-06 03:21:07 -07:00
|
|
|
let variances =
|
2000-09-07 03:57:32 -07:00
|
|
|
List.map (fun (l,_) -> List.map (fun _ -> false, false) l) required in
|
|
|
|
fst (compute_variance_fixpoint env decls required variances)
|
2000-09-06 03:21:07 -07:00
|
|
|
|
1995-05-04 03:15:53 -07:00
|
|
|
(* Translate a set of mutually recursive type declarations *)
|
|
|
|
let transl_type_decl env name_sdecl_list =
|
1997-02-20 12:39:02 -08:00
|
|
|
(* Create identifiers. *)
|
|
|
|
let id_list =
|
|
|
|
List.map (fun (name, _) -> Ident.create name) name_sdecl_list
|
|
|
|
in
|
|
|
|
(*
|
|
|
|
Since we've introduced fresh idents, make sure the definition
|
|
|
|
level is at least the binding time of these events. Otherwise,
|
|
|
|
passing one of the recursively-defined type constrs as argument
|
|
|
|
to an abbreviation may fail.
|
|
|
|
*)
|
1996-09-24 08:45:58 -07:00
|
|
|
Ctype.init_def(Ident.current_time());
|
1997-02-20 12:39:02 -08:00
|
|
|
Ctype.begin_def();
|
|
|
|
(* Enter types. *)
|
2000-05-23 23:19:39 -07:00
|
|
|
let temp_env = List.fold_left2 enter_type env name_sdecl_list id_list in
|
1997-02-20 12:39:02 -08:00
|
|
|
(* Translate each declaration. *)
|
1995-08-28 04:23:33 -07:00
|
|
|
let decls =
|
2000-05-23 23:19:39 -07:00
|
|
|
List.map2 (transl_declaration temp_env) name_sdecl_list id_list in
|
1997-02-20 12:39:02 -08:00
|
|
|
(* Build the final env. *)
|
1995-05-04 03:15:53 -07:00
|
|
|
let newenv =
|
1995-08-28 04:23:33 -07:00
|
|
|
List.fold_right
|
|
|
|
(fun (id, decl) env -> Env.add_type id decl env)
|
1997-02-20 12:39:02 -08:00
|
|
|
decls env
|
|
|
|
in
|
2000-08-03 20:29:42 -07:00
|
|
|
(* Update stubs *)
|
|
|
|
List.iter2
|
|
|
|
(fun id (_, sdecl) -> update_type temp_env newenv id sdecl.ptype_loc)
|
|
|
|
id_list name_sdecl_list;
|
|
|
|
(* Generalize type declarations. *)
|
|
|
|
Ctype.end_def();
|
|
|
|
List.iter (fun (_, decl) -> generalize_decl decl) decls;
|
2000-05-23 23:19:39 -07:00
|
|
|
(* Check for recursive abbrevs *)
|
|
|
|
List.iter2 (check_recursive_abbrev newenv) name_sdecl_list decls;
|
1998-06-24 12:22:26 -07:00
|
|
|
(* Check that all type variable are closed *)
|
|
|
|
List.iter2
|
|
|
|
(fun (_, sdecl) (id, decl) ->
|
|
|
|
match Ctype.closed_type_decl decl with
|
|
|
|
Some _ -> raise(Error(sdecl.ptype_loc, Unbound_type_var))
|
|
|
|
| None -> ())
|
|
|
|
name_sdecl_list decls;
|
1997-02-20 12:39:02 -08:00
|
|
|
(* Check re-exportation *)
|
|
|
|
List.iter2 (check_abbrev newenv) name_sdecl_list decls;
|
2000-05-23 23:19:39 -07:00
|
|
|
(* Check that constraints are enforced *)
|
|
|
|
List.iter2 (check_constraints newenv) name_sdecl_list decls;
|
2000-05-24 19:09:13 -07:00
|
|
|
(* Check that abbreviations have same parameters *)
|
|
|
|
let id_loc_list =
|
|
|
|
List.map2
|
|
|
|
(fun id (_,sdecl) ->
|
|
|
|
match sdecl.ptype_manifest with None -> []
|
|
|
|
| Some {ptyp_loc=loc} -> [id, loc])
|
|
|
|
id_list name_sdecl_list
|
|
|
|
in
|
|
|
|
List.iter (check_expansion newenv (List.flatten id_loc_list)) decls;
|
2000-09-06 03:21:07 -07:00
|
|
|
(* Add variances to the environment *)
|
2000-09-07 03:57:32 -07:00
|
|
|
let required =
|
|
|
|
List.map (fun (_, sdecl) -> sdecl.ptype_variance, sdecl.ptype_loc)
|
|
|
|
name_sdecl_list
|
|
|
|
in
|
2000-09-06 03:21:07 -07:00
|
|
|
let final_decls, final_env =
|
2000-09-07 03:57:32 -07:00
|
|
|
compute_variance_fixpoint env decls required
|
2000-09-06 03:21:07 -07:00
|
|
|
(List.map
|
|
|
|
(fun (_,decl) -> List.map (fun _ -> (false, false)) decl.type_params)
|
|
|
|
decls) in
|
1995-05-04 03:15:53 -07:00
|
|
|
(* Done *)
|
2000-09-06 03:21:07 -07:00
|
|
|
(final_decls, final_env)
|
1995-05-04 03:15:53 -07:00
|
|
|
|
|
|
|
(* Translate an exception declaration *)
|
|
|
|
let transl_exception env excdecl =
|
|
|
|
reset_type_variables();
|
1997-02-20 12:39:02 -08:00
|
|
|
Ctype.begin_def();
|
|
|
|
let types = List.map (transl_simple_type env true) excdecl in
|
|
|
|
Ctype.end_def();
|
|
|
|
List.iter Ctype.generalize types;
|
|
|
|
types
|
1995-05-04 03:15:53 -07:00
|
|
|
|
2000-03-12 05:10:29 -08:00
|
|
|
(* Translate an exception rebinding *)
|
|
|
|
let transl_exn_rebind env loc lid =
|
|
|
|
let cdescr =
|
|
|
|
try
|
|
|
|
Env.lookup_constructor lid env
|
|
|
|
with Not_found ->
|
|
|
|
raise(Error(loc, Unbound_exception lid)) in
|
|
|
|
match cdescr.cstr_tag with
|
|
|
|
Cstr_exception path -> (path, cdescr.cstr_args)
|
|
|
|
| _ -> raise(Error(loc, Not_an_exception lid))
|
|
|
|
|
1995-07-25 04:40:07 -07:00
|
|
|
(* Translate a value declaration *)
|
|
|
|
let transl_value_decl env valdecl =
|
|
|
|
let ty = Typetexp.transl_type_scheme env valdecl.pval_type in
|
1997-05-13 07:07:00 -07:00
|
|
|
match valdecl.pval_prim with
|
|
|
|
[] ->
|
|
|
|
{ val_type = ty; val_kind = Val_reg }
|
|
|
|
| decl ->
|
|
|
|
let arity = Ctype.arity ty in
|
|
|
|
if arity = 0 then
|
|
|
|
raise(Error(valdecl.pval_type.ptyp_loc, Null_arity_external));
|
|
|
|
let prim = Primitive.parse_declaration arity decl in
|
2000-06-05 05:18:30 -07:00
|
|
|
if !Clflags.native_code
|
|
|
|
&& prim.prim_arity > 5
|
|
|
|
&& prim.prim_native_name = ""
|
|
|
|
then raise(Error(valdecl.pval_type.ptyp_loc, Missing_native_external));
|
1997-05-13 07:07:00 -07:00
|
|
|
{ val_type = ty; val_kind = Val_prim prim }
|
1995-07-25 04:40:07 -07:00
|
|
|
|
1995-09-28 03:42:38 -07:00
|
|
|
(* Translate a "with" constraint -- much simplified version of
|
|
|
|
transl_type_decl. *)
|
|
|
|
let transl_with_constraint env sdecl =
|
|
|
|
reset_type_variables();
|
1996-04-22 04:15:41 -07:00
|
|
|
Ctype.begin_def();
|
1995-09-28 03:42:38 -07:00
|
|
|
let params =
|
|
|
|
try
|
1996-05-26 06:42:34 -07:00
|
|
|
List.map (enter_type_variable true) sdecl.ptype_params
|
1995-09-28 03:42:38 -07:00
|
|
|
with Already_bound ->
|
|
|
|
raise(Error(sdecl.ptype_loc, Repeated_parameter)) in
|
1997-02-20 12:39:02 -08:00
|
|
|
List.iter
|
1998-06-24 12:22:26 -07:00
|
|
|
(function (ty, ty', loc) ->
|
1997-02-20 12:39:02 -08:00
|
|
|
try
|
1998-06-24 12:22:26 -07:00
|
|
|
Ctype.unify env (transl_simple_type env false ty)
|
|
|
|
(transl_simple_type env false ty')
|
2001-12-25 19:43:41 -08:00
|
|
|
with Ctype.Unify tr ->
|
|
|
|
raise(Error(loc, Unconsistent_constraint tr)))
|
1997-02-20 12:39:02 -08:00
|
|
|
sdecl.ptype_cstrs;
|
|
|
|
let decl =
|
|
|
|
{ type_params = params;
|
|
|
|
type_arity = List.length params;
|
|
|
|
type_kind = Type_abstract;
|
|
|
|
type_manifest =
|
1995-09-28 03:42:38 -07:00
|
|
|
begin match sdecl.ptype_manifest with
|
|
|
|
None -> None
|
|
|
|
| Some sty -> Some(transl_simple_type env true sty)
|
2000-09-06 03:21:07 -07:00
|
|
|
end;
|
|
|
|
type_variance = [];
|
|
|
|
}
|
1997-02-20 12:39:02 -08:00
|
|
|
in
|
2000-09-06 03:21:07 -07:00
|
|
|
let decl =
|
2000-09-07 03:57:32 -07:00
|
|
|
{decl with type_variance =
|
|
|
|
compute_variance_decl env decl (sdecl.ptype_variance, sdecl.ptype_loc)} in
|
1997-02-20 12:39:02 -08:00
|
|
|
Ctype.end_def();
|
|
|
|
generalize_decl decl;
|
|
|
|
decl
|
1995-09-28 03:42:38 -07:00
|
|
|
|
1997-02-20 12:39:02 -08:00
|
|
|
(**** Error report ****)
|
1995-05-04 03:15:53 -07:00
|
|
|
|
2000-03-06 14:12:09 -08:00
|
|
|
open Format
|
1995-05-04 03:15:53 -07:00
|
|
|
|
2000-03-06 14:12:09 -08:00
|
|
|
let report_error ppf = function
|
|
|
|
| Repeated_parameter ->
|
|
|
|
fprintf ppf "A type parameter occurs several times"
|
1995-05-04 03:15:53 -07:00
|
|
|
| Duplicate_constructor s ->
|
2000-03-06 14:12:09 -08:00
|
|
|
fprintf ppf "Two constructors are named %s" s
|
1995-05-22 08:43:44 -07:00
|
|
|
| Too_many_constructors ->
|
2000-05-22 01:24:05 -07:00
|
|
|
fprintf ppf "Too many non-constant constructors -- \
|
|
|
|
maximum is %i non-constant constructors"
|
2002-01-20 09:29:18 -08:00
|
|
|
(Config.max_tag + 1)
|
1995-05-04 03:15:53 -07:00
|
|
|
| Duplicate_label s ->
|
2000-03-06 14:12:09 -08:00
|
|
|
fprintf ppf "Two labels are named %s" s
|
1995-05-04 03:15:53 -07:00
|
|
|
| Recursive_abbrev s ->
|
2000-03-06 14:12:09 -08:00
|
|
|
fprintf ppf "The type abbreviation %s is cyclic" s
|
1995-09-26 13:23:29 -07:00
|
|
|
| Definition_mismatch ty ->
|
2000-03-06 14:12:09 -08:00
|
|
|
Printtyp.reset_and_mark_loops ty;
|
|
|
|
fprintf ppf
|
|
|
|
"The variant or record definition does not match that of type@ %a"
|
|
|
|
Printtyp.type_expr ty
|
2000-05-24 01:06:33 -07:00
|
|
|
| Constraint_failed (ty, ty') ->
|
|
|
|
fprintf ppf "Constraints are not satisfied in this type.@.";
|
2000-05-23 23:19:39 -07:00
|
|
|
Printtyp.reset_and_mark_loops ty;
|
|
|
|
Printtyp.mark_loops ty';
|
2000-05-24 01:06:33 -07:00
|
|
|
fprintf ppf "@[<hv>Type@ %a@ should be an instance of@ %a@]"
|
2000-05-23 23:19:39 -07:00
|
|
|
Printtyp.type_expr ty Printtyp.type_expr ty'
|
2000-05-24 19:09:13 -07:00
|
|
|
| Parameters_differ (ty, ty') ->
|
|
|
|
Printtyp.reset_and_mark_loops ty;
|
|
|
|
Printtyp.mark_loops ty';
|
|
|
|
fprintf ppf
|
|
|
|
"@[<hv>In this definition, type@ %a@ should be@ %a@]"
|
|
|
|
Printtyp.type_expr ty Printtyp.type_expr ty'
|
2001-12-25 19:43:41 -08:00
|
|
|
| Unconsistent_constraint trace ->
|
|
|
|
fprintf ppf "The type constraints are not consistent.@.";
|
|
|
|
Printtyp.report_unification_error ppf trace
|
|
|
|
(fun ppf -> fprintf ppf "Type")
|
|
|
|
(fun ppf -> fprintf ppf "is not compatible with type")
|
1997-02-20 12:39:02 -08:00
|
|
|
| Type_clash trace ->
|
2000-03-06 14:12:09 -08:00
|
|
|
Printtyp.report_unification_error ppf trace
|
|
|
|
(function ppf ->
|
|
|
|
fprintf ppf "This type constructor expands to type")
|
|
|
|
(function ppf ->
|
|
|
|
fprintf ppf "but is here used with type")
|
1997-05-13 07:07:00 -07:00
|
|
|
| Null_arity_external ->
|
2000-03-06 14:12:09 -08:00
|
|
|
fprintf ppf "External identifiers must be functions"
|
2000-06-05 05:18:30 -07:00
|
|
|
| Missing_native_external ->
|
|
|
|
fprintf ppf "@[<hv>An external function with more than 5 arguments \
|
|
|
|
requires second stub function@ \
|
|
|
|
for native-code compilation@]"
|
1998-06-24 12:22:26 -07:00
|
|
|
| Unbound_type_var ->
|
2000-03-12 05:10:29 -08:00
|
|
|
fprintf ppf "A type variable is unbound in this type declaration"
|
|
|
|
| Unbound_exception lid ->
|
|
|
|
fprintf ppf "Unbound exception constructor@ %a" Printtyp.longident lid
|
|
|
|
| Not_an_exception lid ->
|
|
|
|
fprintf ppf "The constructor@ %a@ is not an exception"
|
|
|
|
Printtyp.longident lid
|
2000-09-07 03:57:32 -07:00
|
|
|
| Bad_variance ->
|
|
|
|
fprintf ppf
|
|
|
|
"In this definition, expected parameter variances are not satisfied"
|
2001-09-28 15:55:27 -07:00
|
|
|
| Unavailable_type_constructor p ->
|
|
|
|
fprintf ppf "The definition of type %a@ is unavailable" Printtyp.path p
|