vive les methodes polymorphes!
git-svn-id: http://caml.inria.fr/svn/ocaml/trunk@4694 f963ae5c-01c2-4b8c-9fe0-0dff7051ff02master
parent
4b70ed64c4
commit
0a8236066f
BIN
boot/ocamlc
BIN
boot/ocamlc
Binary file not shown.
BIN
boot/ocamllex
BIN
boot/ocamllex
Binary file not shown.
|
@ -69,7 +69,6 @@ let copy_object_file oc name =
|
|||
let compunit_pos = input_binary_int ic in
|
||||
seek_in ic compunit_pos;
|
||||
let compunit = (input_value ic : compilation_unit) in
|
||||
Bytelink.check_consistency file_name compunit;
|
||||
copy_compunit ic oc compunit;
|
||||
close_in ic;
|
||||
[compunit]
|
||||
|
@ -78,7 +77,6 @@ let copy_object_file oc name =
|
|||
let toc_pos = input_binary_int ic in
|
||||
seek_in ic toc_pos;
|
||||
let toc = (input_value ic : library) in
|
||||
List.iter (Bytelink.check_consistency file_name) toc.lib_units;
|
||||
add_ccobjs toc;
|
||||
List.iter (copy_compunit ic oc) toc.lib_units;
|
||||
close_in ic;
|
||||
|
|
|
@ -431,14 +431,14 @@ let build_custom_runtime prim_name exec_name =
|
|||
(Printf.sprintf
|
||||
"%s -o %s %s %s %s %s %s -lcamlrun %s"
|
||||
!Clflags.c_linker
|
||||
(Filename.quote exec_name)
|
||||
exec_name
|
||||
(Clflags.std_include_flag "-I")
|
||||
(String.concat " " (List.rev !Clflags.ccopts))
|
||||
prim_name
|
||||
(Ccomp.quote_files
|
||||
(String.concat " "
|
||||
(List.map (fun dir -> if dir = "" then "" else "-L" ^ dir)
|
||||
!load_path))
|
||||
(Ccomp.quote_files (List.rev !Clflags.ccobjs))
|
||||
(String.concat " " (List.rev !Clflags.ccobjs))
|
||||
Config.bytecomp_c_libraries)
|
||||
| "Win32" ->
|
||||
let retcode =
|
||||
|
@ -446,13 +446,13 @@ let build_custom_runtime prim_name exec_name =
|
|||
(Printf.sprintf
|
||||
"%s /Fe%s %s %s %s %s %s %s"
|
||||
!Clflags.c_linker
|
||||
(Filename.quote exec_name)
|
||||
exec_name
|
||||
(Clflags.std_include_flag "-I")
|
||||
(String.concat " " (List.rev !Clflags.ccopts))
|
||||
prim_name
|
||||
(Ccomp.quote_files
|
||||
(List.rev_map Ccomp.expand_libname !Clflags.ccobjs))
|
||||
(Filename.quote (Ccomp.expand_libname "-lcamlrun"))
|
||||
(String.concat " "
|
||||
(List.rev_map Ccomp.expand_libname !Clflags.ccobjs))
|
||||
(Ccomp.expand_libname "-lcamlrun")
|
||||
Config.bytecomp_c_libraries) in
|
||||
(* C compiler doesn't clean up after itself. Note that the .obj
|
||||
file is created in the current working directory. *)
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
struct lexer_buffer {
|
||||
value refill_buff;
|
||||
value lex_buffer;
|
||||
value lex_buffer_len;
|
||||
value lex_buffer_end;
|
||||
value lex_abs_pos;
|
||||
value lex_start_pos;
|
||||
value lex_curr_pos;
|
||||
|
@ -72,7 +72,7 @@ CAMLprim value lex_engine(struct lexing_table *tbl, value start_state,
|
|||
lexbuf->lex_last_action = Val_int(backtrk);
|
||||
}
|
||||
/* See if we need a refill */
|
||||
if (lexbuf->lex_curr_pos >= lexbuf->lex_buffer_len){
|
||||
if (lexbuf->lex_curr_pos >= lexbuf->lex_buffer_end){
|
||||
if (lexbuf->lex_eof_reached == Val_bool (0)){
|
||||
return Val_int(-state - 1);
|
||||
}else{
|
||||
|
|
|
@ -157,10 +157,13 @@ char * search_dll_in_path(struct ext_table * path, char * name)
|
|||
#ifndef RTLD_GLOBAL
|
||||
#define RTLD_GLOBAL 0
|
||||
#endif
|
||||
#ifndef RTLD_NODELETE
|
||||
#define RTLD_NODELETE 0
|
||||
#endif
|
||||
|
||||
void * caml_dlopen(char * libname)
|
||||
{
|
||||
return dlopen(libname, RTLD_NOW|RTLD_GLOBAL);
|
||||
return dlopen(libname, RTLD_NOW|RTLD_GLOBAL|RTLD_NODELETE);
|
||||
}
|
||||
|
||||
void caml_dlclose(void * handle)
|
||||
|
|
|
@ -95,6 +95,7 @@ module Options = Main_args.Make_options (struct
|
|||
let _output_obj () = output_c_object := true; custom_runtime := true
|
||||
let _pack = set make_package
|
||||
let _pp s = preprocessor := Some s
|
||||
let _principal = set principal
|
||||
let _rectypes = set recursive_types
|
||||
let _thread = set thread_safe
|
||||
let _unsafe = set fast
|
||||
|
|
|
@ -39,6 +39,7 @@ module Make_options (F :
|
|||
val _output_obj : unit -> unit
|
||||
val _pack : unit -> unit
|
||||
val _pp : string -> unit
|
||||
val _principal : unit -> unit
|
||||
val _rectypes : unit -> unit
|
||||
val _thread : unit -> unit
|
||||
val _unsafe : unit -> unit
|
||||
|
@ -101,6 +102,8 @@ struct
|
|||
" Package the given .cmo files into one .cmo";
|
||||
"-pp", Arg.String F._pp,
|
||||
"<command> Pipe sources through preprocessor <command>";
|
||||
"-principal", Arg.Unit F._principal,
|
||||
" Check principality of type inference";
|
||||
"-rectypes", Arg.Unit F._rectypes, " Allow arbitrary recursive types";
|
||||
"-thread", Arg.Unit F._thread, " Use thread-safe standard library";
|
||||
"-unsafe", Arg.Unit F._unsafe,
|
||||
|
|
|
@ -39,6 +39,7 @@ module Make_options (F :
|
|||
val _output_obj : unit -> unit
|
||||
val _pack : unit -> unit
|
||||
val _pp : string -> unit
|
||||
val _principal : unit -> unit
|
||||
val _rectypes : unit -> unit
|
||||
val _thread : unit -> unit
|
||||
val _unsafe : unit -> unit
|
||||
|
|
|
@ -110,6 +110,8 @@ let main () =
|
|||
" Package the given .cmo files into one .cmo";
|
||||
"-pp", Arg.String(fun s -> preprocessor := Some s),
|
||||
"<command> Pipe sources through preprocessor <command>";
|
||||
"-principal", Arg.Set principal,
|
||||
" Check principality of type inference";
|
||||
"-rectypes", Arg.Set recursive_types,
|
||||
" Allow arbitrary recursive types";
|
||||
"-S", Arg.Set keep_asm_file, " Keep intermediate assembly file";
|
||||
|
|
|
@ -127,7 +127,8 @@ let rec search_pos_type t ~pos ~env =
|
|||
| Ptyp_class (lid, tl, _) ->
|
||||
List.iter tl ~f:(search_pos_type ~pos ~env);
|
||||
add_found_sig (`Type, lid) ~env ~loc:t.ptyp_loc
|
||||
| Ptyp_alias (t, _) -> search_pos_type ~pos ~env t
|
||||
| Ptyp_alias (t, _)
|
||||
| Ptyp_poly (_, t) -> search_pos_type ~pos ~env t
|
||||
end
|
||||
|
||||
let rec search_pos_class_type cl ~pos ~env =
|
||||
|
|
|
@ -612,14 +612,18 @@ value:
|
|||
symbol_rloc () }
|
||||
;
|
||||
virtual_method:
|
||||
METHOD PRIVATE VIRTUAL label COLON core_type
|
||||
METHOD PRIVATE VIRTUAL label COLON poly_type
|
||||
{ $4, Private, $6, symbol_rloc () }
|
||||
| METHOD VIRTUAL private_flag label COLON core_type
|
||||
| METHOD VIRTUAL private_flag label COLON poly_type
|
||||
{ $4, $3, $6, symbol_rloc () }
|
||||
;
|
||||
concrete_method :
|
||||
METHOD private_flag label fun_binding
|
||||
{ $3, $2, $4, symbol_rloc () }
|
||||
METHOD private_flag label strict_binding
|
||||
{ $3, $2, mkexp(Pexp_poly ($4, None)), symbol_rloc () }
|
||||
| METHOD private_flag label COLON poly_type EQUAL seq_expr
|
||||
{ $3, $2, mkexp(Pexp_poly($7,Some $5)), symbol_rloc () }
|
||||
| METHOD private_flag LABEL poly_type EQUAL seq_expr
|
||||
{ $3, $2, mkexp(Pexp_poly($6,Some $4)), symbol_rloc () }
|
||||
;
|
||||
|
||||
/* Class types */
|
||||
|
@ -680,7 +684,7 @@ XXX Should be removed
|
|||
*/
|
||||
;
|
||||
method_type:
|
||||
METHOD private_flag label COLON core_type
|
||||
METHOD private_flag label COLON poly_type
|
||||
{ $3, $2, $5, symbol_rloc () }
|
||||
;
|
||||
constrain:
|
||||
|
@ -964,10 +968,20 @@ let_binding:
|
|||
{ ($1, $3) }
|
||||
;
|
||||
fun_binding:
|
||||
/*
|
||||
EQUAL seq_expr
|
||||
{ $2 }
|
||||
| labeled_simple_pattern fun_binding
|
||||
{ let (l, o, p) = $1 in mkexp(Pexp_function(l, o, [p, $2])) }
|
||||
*/
|
||||
strict_binding
|
||||
{ $1 }
|
||||
| type_constraint EQUAL seq_expr
|
||||
{ let (t, t') = $1 in mkexp(Pexp_constraint($3, t, t')) }
|
||||
;
|
||||
strict_binding:
|
||||
EQUAL seq_expr
|
||||
{ $2 }
|
||||
| labeled_simple_pattern fun_binding
|
||||
{ let (l, o, p) = $1 in mkexp(Pexp_function(l, o, [p, $2])) }
|
||||
;
|
||||
|
@ -1164,7 +1178,7 @@ label_declarations:
|
|||
| label_declarations SEMI label_declaration { $3 :: $1 }
|
||||
;
|
||||
label_declaration:
|
||||
mutable_flag label COLON core_type { ($2, $1, $4) }
|
||||
mutable_flag label COLON poly_type { ($2, $1, $4) }
|
||||
;
|
||||
|
||||
/* "with" constraints (additional type equations over signature components) */
|
||||
|
@ -1188,6 +1202,19 @@ with_constraint:
|
|||
{ ($2, Pwith_module $4) }
|
||||
;
|
||||
|
||||
/* Polymorphic types */
|
||||
|
||||
typevar_list:
|
||||
QUOTE ident { [$2] }
|
||||
| typevar_list QUOTE ident { $3 :: $1 }
|
||||
;
|
||||
poly_type:
|
||||
core_type
|
||||
{ mktyp(Ptyp_poly([], $1)) }
|
||||
| typevar_list DOT core_type
|
||||
{ mktyp(Ptyp_poly(List.rev $1, $3)) }
|
||||
;
|
||||
|
||||
/* Core types */
|
||||
|
||||
core_type:
|
||||
|
@ -1306,7 +1333,7 @@ meth_list:
|
|||
| DOTDOT { [mkfield Pfield_var] }
|
||||
;
|
||||
field:
|
||||
label COLON core_type { mkfield(Pfield($1, $3)) }
|
||||
label COLON poly_type { mkfield(Pfield($1, $3)) }
|
||||
;
|
||||
label:
|
||||
LIDENT { $1 }
|
||||
|
|
|
@ -32,6 +32,7 @@ and core_type_desc =
|
|||
| Ptyp_class of Longident.t * core_type list * label list
|
||||
| Ptyp_alias of core_type * string
|
||||
| Ptyp_variant of row_field list * bool * label list option
|
||||
| Ptyp_poly of string list * core_type
|
||||
|
||||
and core_field_type =
|
||||
{ pfield_desc: core_field_desc;
|
||||
|
@ -108,6 +109,7 @@ and expression_desc =
|
|||
| Pexp_assert of expression
|
||||
| Pexp_assertfalse
|
||||
| Pexp_lazy of expression
|
||||
| Pexp_poly of expression * core_type option
|
||||
|
||||
(* Value descriptions *)
|
||||
|
||||
|
|
|
@ -125,6 +125,10 @@ let rec core_type i ppf x =
|
|||
| Ptyp_alias (ct, s) ->
|
||||
line i ppf "Ptyp_alias \"%s\"\n" s;
|
||||
core_type i ppf ct;
|
||||
| Ptyp_poly (sl, ct) ->
|
||||
line i ppf "Ptyp_poly%a\n"
|
||||
(fun ppf -> List.iter (fun x -> fprintf ppf " '%s" x)) sl;
|
||||
core_type i ppf ct;
|
||||
|
||||
and core_field_type i ppf x =
|
||||
line i ppf "core_field_type %a\n" fmt_location x.pfield_loc;
|
||||
|
@ -274,6 +278,10 @@ and expression i ppf x =
|
|||
| Pexp_lazy (e) ->
|
||||
line i ppf "Pexp_lazy";
|
||||
expression i ppf e;
|
||||
| Pexp_poly (e, cto) ->
|
||||
line i ppf "Pexp_poly\n";
|
||||
expression i ppf e;
|
||||
option i core_type ppf cto;
|
||||
|
||||
and value_description i ppf x =
|
||||
line i ppf "value_description\n";
|
||||
|
|
|
@ -78,4 +78,4 @@ let catch_break on =
|
|||
(* OCaml version string, moved from utils/config.mlp.
|
||||
Must be in the format described in sys.mli. *)
|
||||
|
||||
let ocaml_version = "3.04+9 (2002-04-04)"
|
||||
let ocaml_version = "3.04+10 (2002-04-18)"
|
||||
|
|
|
@ -253,7 +253,8 @@ let rec add_labels_expr ~text ~values ~classes expr =
|
|||
| Pexp_setinstvar (_, e)
|
||||
| Pexp_letmodule (_, _, e)
|
||||
| Pexp_assert e
|
||||
| Pexp_lazy e ->
|
||||
| Pexp_lazy e
|
||||
| Pexp_poly (e, _) ->
|
||||
add_labels_rec e
|
||||
| Pexp_record (lst, opt) ->
|
||||
List.iter lst ~f:(fun (_,e) -> add_labels_rec e);
|
||||
|
|
|
@ -51,6 +51,7 @@ let rec add_type bv ty =
|
|||
(function Rtag(_,_,stl) -> List.iter (add_type bv) stl
|
||||
| Rinherit sty -> add_type bv sty)
|
||||
fl
|
||||
| Ptyp_poly(_, t) -> add_type bv t
|
||||
|
||||
and add_field_type bv ft =
|
||||
match ft.pfield_desc with
|
||||
|
@ -151,6 +152,7 @@ let rec add_expr bv exp =
|
|||
| Pexp_assert (e) -> add_expr bv e
|
||||
| Pexp_assertfalse -> ()
|
||||
| Pexp_lazy (e) -> add_expr bv e
|
||||
| Pexp_poly (e, t) -> add_expr bv e; add_opt add_type bv t
|
||||
|
||||
and add_pat_expr_list bv pel =
|
||||
List.iter (fun (p, e) -> add_pattern bv p; add_expr bv e) pel
|
||||
|
|
|
@ -58,6 +58,7 @@ module Options = Main_args.Make_options (struct
|
|||
let _output_obj = option "-output-obj"
|
||||
let _pack = option "-pack"
|
||||
let _pp s = incompatible "-pp"
|
||||
let _principal = option "-principal"
|
||||
let _rectypes = option "-rectypes"
|
||||
let _thread () = ismultithreaded := "-thread"; option "-thread" ()
|
||||
let _unsafe = option "-unsafe"
|
||||
|
|
|
@ -287,6 +287,8 @@ and rw_exp iflag sexp =
|
|||
|
||||
| Pexp_lazy (expr) -> rewrite_exp iflag expr
|
||||
|
||||
| Pexp_poly (sexp, _) -> rewrite_exp iflag sexp
|
||||
|
||||
and rewrite_ifbody iflag ghost sifbody =
|
||||
if !instr_if && not ghost then
|
||||
insert_profile rw_exp sifbody
|
||||
|
|
|
@ -313,6 +313,10 @@ module Make(O : OBJ)(EVP : EVALPATH with type value = O.t) = struct
|
|||
tree_of_val (depth - 1) obj ty
|
||||
| Tfield(_, _, _, _) | Tnil | Tlink _ ->
|
||||
fatal_error "Printval.outval_of_value"
|
||||
| Tpoly (ty, _) ->
|
||||
tree_of_val (depth - 1) obj ty
|
||||
| Tunivar ->
|
||||
Oval_stuff "<poly>"
|
||||
end
|
||||
|
||||
and tree_of_val_list start depth obj ty_list =
|
||||
|
|
|
@ -45,6 +45,7 @@ let main () =
|
|||
"-nolabels", Arg.Set classic, " Ignore labels and do not commute";
|
||||
"-nostdlib", Arg.Set no_std_include,
|
||||
" do not add default directory to the list of include directories";
|
||||
"-principal", Arg.Set principal, " Check principality of type inference";
|
||||
"-rectypes", Arg.Set recursive_types, " Allow arbitrary recursive types";
|
||||
"-unsafe", Arg.Set fast, " No bound checking on array and string access";
|
||||
"-w", Arg.String (Warnings.parse_options false),
|
||||
|
|
|
@ -121,7 +121,7 @@ let rec iter_row f row =
|
|||
row.row_fields;
|
||||
match (repr row.row_more).desc with
|
||||
Tvariant row -> iter_row f row
|
||||
| Tvar | Tnil ->
|
||||
| Tvar | Tnil | Tunivar ->
|
||||
Misc.may (fun (_,l) -> List.iter f l) row.row_name;
|
||||
List.iter f row.row_bound
|
||||
| _ -> assert false
|
||||
|
@ -140,8 +140,15 @@ let iter_type_expr f ty =
|
|||
| Tnil -> ()
|
||||
| Tlink ty -> f ty
|
||||
| Tsubst ty -> f ty
|
||||
| Tunivar -> ()
|
||||
| Tpoly (ty, tyl) -> f ty; List.iter f tyl
|
||||
|
||||
let copy_row f row keep more =
|
||||
let rec iter_abbrev f = function
|
||||
Mnil -> ()
|
||||
| Mcons(_, ty, ty', rem) -> f ty; f ty'; iter_abbrev f rem
|
||||
| Mlink rem -> iter_abbrev f !rem
|
||||
|
||||
let copy_row f fixed row keep more =
|
||||
let bound = ref [] in
|
||||
let fields = List.map
|
||||
(fun (l, fi) -> l,
|
||||
|
@ -149,6 +156,7 @@ let copy_row f row keep more =
|
|||
| Rpresent(Some ty) -> Rpresent(Some(f ty))
|
||||
| Reither(c, tl, m, e) ->
|
||||
let e = if keep then e else ref None in
|
||||
let m = if row.row_fixed then fixed else m in
|
||||
let tl = List.map f tl in
|
||||
bound := List.filter
|
||||
(function {desc=Tconstr(_,[],_)} -> false | _ -> true)
|
||||
|
@ -160,7 +168,8 @@ let copy_row f row keep more =
|
|||
let name =
|
||||
match row.row_name with None -> None
|
||||
| Some (path, tl) -> Some (path, List.map f tl) in
|
||||
{ row_fields = fields; row_more = more; row_bound = !bound;
|
||||
{ row_fields = fields; row_more = more;
|
||||
row_bound = !bound; row_fixed = row.row_fixed && fixed;
|
||||
row_closed = row.row_closed; row_name = name; }
|
||||
|
||||
let rec copy_kind = function
|
||||
|
@ -182,56 +191,14 @@ let rec copy_type_desc f = function
|
|||
| Tobject (ty, _) -> Tobject (f ty, ref None)
|
||||
| Tvariant row ->
|
||||
let row = row_repr row in
|
||||
Tvariant (copy_row f row false (f row.row_more))
|
||||
Tvariant (copy_row f true row false (f row.row_more))
|
||||
| Tfield (p, k, ty1, ty2) -> Tfield (p, copy_kind k, f ty1, f ty2)
|
||||
| Tnil -> Tnil
|
||||
| Tlink ty -> copy_type_desc f ty.desc
|
||||
| Tsubst ty -> assert false
|
||||
| Tunivar -> Tunivar
|
||||
| Tpoly (ty, tyl) -> Tpoly (f ty, List.map f tyl)
|
||||
|
||||
(*
|
||||
let rec iter_signature f =
|
||||
List.iter (iter_signature_item f)
|
||||
|
||||
and iter_signature_item f = function
|
||||
Tsig_value (_, d) ->
|
||||
f d.val_type;
|
||||
(match d.val_kind with Val_reg | Val_prim _ -> () | _ -> assert false)
|
||||
| Tsig_type (_, d) ->
|
||||
List.iter f d.type_params;
|
||||
begin match d.type_kind with
|
||||
Type_abstract -> ()
|
||||
| Type_variant l -> List.iter (fun (_, tl) -> List.iter f tl) l
|
||||
| Type_record r -> List.iter (fun (_, _, t) -> f t)
|
||||
end;
|
||||
may f d.type_manifest
|
||||
| Tsig_exception (_, d) -> List.iter f d
|
||||
| Tsig_module (_, m) -> iter_module_type f m
|
||||
| Tsig_modtype (_, Tmodtype_manifest m) -> iter_module_type f m
|
||||
| Tsig_modtype (_, Tmodtype_bastract) -> ()
|
||||
| Tsig_class (_, d) ->
|
||||
List.iter f d.cty_params;
|
||||
iter_class_type f d.cty_type;
|
||||
may f d.cty_new
|
||||
| Tsig_cltype (_, d) ->
|
||||
List.iter f d.clty_params;
|
||||
iter_class_type f d.clty_type
|
||||
|
||||
and iter_module_type f = function
|
||||
Tmty_ident _ -> ()
|
||||
| Tmty_signature sg -> iter_signature f sg
|
||||
| Tmty_functor (_, m1, m2) -> iter_module_type f m1; iter_module_type f m2
|
||||
|
||||
and iter_class_type f = function
|
||||
Tcty_constr (_, tl, ct) ->
|
||||
List.iter f tl;
|
||||
iter_class_type f ct
|
||||
| Tcty_fun (_, t, ct) ->
|
||||
f t;
|
||||
iter_class_type f ct
|
||||
| Tcty_signature s ->
|
||||
f s.cty_self;
|
||||
Vars.iter (fun _ (_, t) -> f t) s.cty_vars
|
||||
*)
|
||||
|
||||
(* Utilities for copying *)
|
||||
|
||||
|
|
|
@ -60,11 +60,14 @@ val iter_type_expr: (type_expr -> unit) -> type_expr -> unit
|
|||
(* Iteration on types *)
|
||||
val iter_row: (type_expr -> unit) -> row_desc -> unit
|
||||
(* Iteration on types in a row *)
|
||||
val iter_abbrev: (type_expr -> unit) -> abbrev_memo -> unit
|
||||
(* Iteration on types in an abbreviation list *)
|
||||
|
||||
val copy_type_desc: (type_expr -> type_expr) -> type_desc -> type_desc
|
||||
(* Copy on types *)
|
||||
val copy_row:
|
||||
(type_expr -> type_expr) -> row_desc -> bool -> type_expr -> row_desc
|
||||
(type_expr -> type_expr) ->
|
||||
bool -> row_desc -> bool -> type_expr -> row_desc
|
||||
val copy_kind: field_kind -> field_kind
|
||||
|
||||
val save_desc: type_expr -> type_desc -> unit
|
||||
|
|
497
typing/ctype.ml
497
typing/ctype.ml
|
@ -129,6 +129,10 @@ let restore_global_level () =
|
|||
gl::rem -> global_level := gl; saved_global_level := rem
|
||||
| [] -> assert false
|
||||
|
||||
(* Abbreviations without parameters *)
|
||||
(* Shall reset after generalizing *)
|
||||
let simple_abbrevs = ref Mnil
|
||||
|
||||
(**** Some type creators ****)
|
||||
|
||||
(* Re-export generic type creators *)
|
||||
|
@ -381,8 +385,7 @@ let rec free_vars_rec real ty =
|
|||
| Tvariant row ->
|
||||
let row = row_repr row in
|
||||
iter_row (free_vars_rec true) {row with row_bound = []};
|
||||
if not (static_row row) then
|
||||
free_variables := (row_more row, false) :: !free_variables
|
||||
if not (static_row row) then free_vars_rec false row.row_more
|
||||
| _ ->
|
||||
iter_type_expr (free_vars_rec true) ty
|
||||
end;
|
||||
|
@ -497,22 +500,18 @@ let rec iter_generalize tyl ty =
|
|||
ty.level <- generic_level;
|
||||
begin match ty.desc with
|
||||
Tconstr (_, _, abbrev) ->
|
||||
generalize_expans tyl !abbrev
|
||||
iter_abbrev (iter_generalize tyl) !abbrev
|
||||
| _ -> ()
|
||||
end;
|
||||
iter_type_expr (iter_generalize tyl) ty
|
||||
end else
|
||||
tyl := ty :: !tyl
|
||||
|
||||
and generalize_expans tyl =
|
||||
function
|
||||
Mnil -> ()
|
||||
| Mcons(_, ty, ty', rem) -> iter_generalize tyl ty;
|
||||
iter_generalize tyl ty';
|
||||
generalize_expans tyl rem
|
||||
| Mlink rem -> generalize_expans tyl !rem
|
||||
let iter_generalize tyl ty =
|
||||
simple_abbrevs := Mnil;
|
||||
iter_generalize tyl ty
|
||||
|
||||
let rec generalize ty =
|
||||
let generalize ty =
|
||||
iter_generalize (ref []) ty
|
||||
|
||||
(* Efficient repeated generalisation of the same type *)
|
||||
|
@ -522,6 +521,43 @@ let iterative_generalization min_level tyl =
|
|||
List.fold_right (fun ty l -> if ty.level <= min_level then l else ty::l)
|
||||
!tyl' []
|
||||
|
||||
(* Generalize the structure and lower the variables *)
|
||||
|
||||
let rec generalize_structure var_level ty =
|
||||
let ty = repr ty in
|
||||
if ty.level <> generic_level then begin
|
||||
if ty.desc = Tvar && ty.level > var_level then
|
||||
ty.level <- var_level
|
||||
else if ty.level > !current_level then begin
|
||||
ty.level <- generic_level;
|
||||
begin match ty.desc with
|
||||
Tconstr (_, _, abbrev) ->
|
||||
iter_abbrev (generalize_structure var_level) !abbrev
|
||||
| _ -> ()
|
||||
end;
|
||||
iter_type_expr (generalize_structure var_level) ty
|
||||
end
|
||||
end
|
||||
|
||||
let generalize_structure var_level ty =
|
||||
simple_abbrevs := Mnil;
|
||||
generalize_structure var_level ty
|
||||
|
||||
let generalize_expansive ty = generalize_structure !nongen_level ty
|
||||
let generalize_global ty = generalize_structure !global_level ty
|
||||
let generalize_structure ty = generalize_structure !current_level ty
|
||||
|
||||
(* Generalize the spine of a function, if the level >= !current_level *)
|
||||
|
||||
let rec generalize_spine ty =
|
||||
let ty = repr ty in
|
||||
if ty.level < !current_level || ty.level = generic_level then () else
|
||||
match ty.desc with
|
||||
Tarrow (_, _, ty', _) | Tpoly (ty', _) ->
|
||||
ty.level <- generic_level;
|
||||
generalize_spine ty'
|
||||
| _ -> ()
|
||||
|
||||
let try_expand_head' = (* Forward declaration *)
|
||||
ref (fun env ty -> raise Cannot_expand)
|
||||
|
||||
|
@ -662,7 +698,10 @@ let rec copy ty =
|
|||
t.desc <-
|
||||
begin match desc with
|
||||
| Tconstr (p, tl, _) ->
|
||||
begin match find_repr p !(!abbreviations) with
|
||||
let abbrevs =
|
||||
if tl = [] && not !Clflags.principal then simple_abbrevs
|
||||
else !abbreviations in
|
||||
begin match find_repr p !abbrevs with
|
||||
Some ty when repr ty != t -> (* XXX Commentaire... *)
|
||||
Tlink ty
|
||||
| _ ->
|
||||
|
@ -685,19 +724,24 @@ let rec copy ty =
|
|||
let more = repr row.row_more in
|
||||
(* We must substitute in a subtle way *)
|
||||
begin match more.desc with
|
||||
Tsubst ty2 ->
|
||||
Tsubst ({desc=Tvariant _} as ty2) ->
|
||||
(* This variant type has been already copied *)
|
||||
ty.desc <- Tsubst ty2; (* avoid Tlink in the new type *)
|
||||
Tlink ty2
|
||||
| _ ->
|
||||
(* If the row variable is not generic, we must keep it *)
|
||||
let keep = more.level <> generic_level in
|
||||
let desc = more.desc in
|
||||
(* Register new type first for recursion *)
|
||||
save_desc more more.desc;
|
||||
more.desc <- ty.desc;
|
||||
(* Return a new copy *)
|
||||
let more' = if keep then more else newvar () in
|
||||
Tvariant (copy_row copy row keep more')
|
||||
let more' =
|
||||
if keep then more else
|
||||
match desc with Tsubst ty -> ty
|
||||
| _ -> newty desc
|
||||
in
|
||||
Tvariant (copy_row copy true row keep more')
|
||||
end
|
||||
| _ -> copy_type_desc copy desc
|
||||
end;
|
||||
|
@ -721,12 +765,6 @@ let instance_constructor cstr =
|
|||
cleanup_types ();
|
||||
(ty_args, ty_res)
|
||||
|
||||
let instance_label lbl =
|
||||
let ty_res = copy lbl.lbl_res in
|
||||
let ty_arg = copy lbl.lbl_arg in
|
||||
cleanup_types ();
|
||||
(ty_arg, ty_res)
|
||||
|
||||
let instance_parameterized_type sch_args sch =
|
||||
let ty_args = List.map copy sch_args in
|
||||
let ty = copy sch in
|
||||
|
@ -759,6 +797,130 @@ let instance_class params cty =
|
|||
cleanup_types ();
|
||||
(params', cty')
|
||||
|
||||
(**** Instanciation for types with free universal variables ****)
|
||||
|
||||
module TypeHash = Hashtbl.Make(TypeOps)
|
||||
module TypeSet = Set.Make(TypeOps)
|
||||
|
||||
type inv_type_expr =
|
||||
{ inv_type : type_expr;
|
||||
mutable inv_parents : inv_type_expr list }
|
||||
|
||||
let rec inv_type hash pty ty =
|
||||
let ty = repr ty in
|
||||
try
|
||||
let inv = TypeHash.find hash ty in
|
||||
inv.inv_parents <- pty @ inv.inv_parents
|
||||
with Not_found ->
|
||||
let inv = { inv_type = ty; inv_parents = pty } in
|
||||
TypeHash.add hash ty inv;
|
||||
iter_type_expr (inv_type hash [inv]) ty
|
||||
|
||||
let compute_univars ty =
|
||||
let inverted = TypeHash.create 17 in
|
||||
inv_type inverted [] ty;
|
||||
let node_univars = TypeHash.create 17 in
|
||||
let rec add_univar univ inv =
|
||||
match inv.inv_type.desc with
|
||||
Tpoly (ty, tl) when List.memq univ (List.map repr tl) -> ()
|
||||
| _ ->
|
||||
try
|
||||
let univs = TypeHash.find node_univars inv.inv_type in
|
||||
if not (TypeSet.mem univ !univs) then begin
|
||||
univs := TypeSet.add univ !univs;
|
||||
List.iter (add_univar univ) inv.inv_parents
|
||||
end
|
||||
with Not_found ->
|
||||
TypeHash.add node_univars inv.inv_type (ref(TypeSet.singleton univ));
|
||||
List.iter (add_univar univ) inv.inv_parents
|
||||
in
|
||||
TypeHash.iter
|
||||
(fun ty inv -> if ty.desc = Tunivar then add_univar ty inv)
|
||||
inverted;
|
||||
fun ty ->
|
||||
try !(TypeHash.find node_univars ty) with Not_found -> TypeSet.empty
|
||||
|
||||
let rec diff_list l1 l2 =
|
||||
if l1 == l2 then [] else
|
||||
match l1 with [] -> invalid_arg "Ctype.diff_list"
|
||||
| a :: l1 -> a :: diff_list l1 l2
|
||||
|
||||
let conflicts free bound =
|
||||
let bound = List.map repr bound in
|
||||
TypeSet.exists (fun t -> List.memq (repr t) bound) free
|
||||
|
||||
let delayed_copy = ref []
|
||||
(* copying to do later *)
|
||||
|
||||
(* Copy without sharing until there are no free univars left *)
|
||||
(* all free univars must be included in [visited] *)
|
||||
let rec copy_sep fixed free bound visited ty =
|
||||
let ty = repr ty in
|
||||
let univars = free ty in
|
||||
if TypeSet.is_empty univars then
|
||||
if ty.level <> generic_level then ty else
|
||||
let t = newvar () in
|
||||
delayed_copy :=
|
||||
lazy (t.desc <- Tlink (copy ty))
|
||||
:: !delayed_copy;
|
||||
t
|
||||
else try
|
||||
let t, bound_t = List.assq ty visited in
|
||||
let dl = if ty.desc = Tunivar then [] else diff_list bound bound_t in
|
||||
if dl <> [] && conflicts univars dl then raise Not_found;
|
||||
t
|
||||
with Not_found -> begin
|
||||
let t = newvar() in (* Stub *)
|
||||
let visited =
|
||||
match ty.desc with
|
||||
Tarrow _ | Ttuple _ | Tvariant _ | Tconstr _ | Tobject _ ->
|
||||
(ty,(t,bound)) :: visited
|
||||
| _ -> visited in
|
||||
let copy_rec = copy_sep fixed free bound visited in
|
||||
t.desc <-
|
||||
begin match ty.desc with
|
||||
| Tvariant row0 ->
|
||||
let row = row_repr row0 in
|
||||
let more = repr row.row_more in
|
||||
(* We shall really check the level on the row variable *)
|
||||
let keep = more.desc = Tvar && more.level <> generic_level in
|
||||
let more' = copy_rec more in
|
||||
let row = copy_row copy_rec fixed row keep more' in
|
||||
Tvariant row
|
||||
| Tpoly (t1, tl) ->
|
||||
let tl = List.map repr tl in
|
||||
let tl' = List.map (fun t -> newty Tunivar) tl in
|
||||
let bound = tl @ bound in
|
||||
let visited =
|
||||
List.map2 (fun ty t -> ty,(t,bound)) tl tl' @ visited in
|
||||
Tpoly (copy_rec t1, tl')
|
||||
| _ -> copy_type_desc copy_rec ty.desc
|
||||
end;
|
||||
t
|
||||
end
|
||||
|
||||
let instance_poly fixed univars sch =
|
||||
let vars = List.map (fun _ -> newvar ()) univars in
|
||||
let pairs = List.map2 (fun u v -> repr u, (v, [])) univars vars in
|
||||
delayed_copy := [];
|
||||
let ty = copy_sep fixed (compute_univars sch) [] pairs sch in
|
||||
List.iter Lazy.force !delayed_copy;
|
||||
delayed_copy := [];
|
||||
cleanup_types ();
|
||||
vars, ty
|
||||
|
||||
let instance_label fixed lbl =
|
||||
let ty_res = copy lbl.lbl_res in
|
||||
let vars, ty_arg =
|
||||
match repr lbl.lbl_arg with
|
||||
{desc = Tpoly (ty, tl)} ->
|
||||
instance_poly fixed tl ty
|
||||
| ty ->
|
||||
[], copy lbl.lbl_arg
|
||||
in
|
||||
cleanup_types ();
|
||||
(vars, ty_arg, ty_res)
|
||||
|
||||
(**** Instantiation with parameter substitution ****)
|
||||
|
||||
let unify' = (* Forward declaration *)
|
||||
|
@ -771,7 +933,10 @@ let rec subst env level abbrev ty params args body =
|
|||
let body0 = newvar () in (* Stub *)
|
||||
begin match ty with
|
||||
None -> ()
|
||||
| Some ({desc = Tconstr (path, _, _)} as ty) ->
|
||||
| Some ({desc = Tconstr (path, tl, _)} as ty) ->
|
||||
let abbrev =
|
||||
if tl = [] && not !Clflags.principal then simple_abbrevs else abbrev
|
||||
in
|
||||
memorize_abbrev abbrev path ty body0
|
||||
| _ ->
|
||||
assert false
|
||||
|
@ -856,7 +1021,10 @@ let expand_abbrev env ty =
|
|||
end;
|
||||
match ty with
|
||||
{desc = Tconstr (path, args, abbrev); level = level} ->
|
||||
begin match find_expans path !abbrev with
|
||||
let lookup_abbrev =
|
||||
if args = [] && not !Clflags.principal then simple_abbrevs
|
||||
else abbrev in
|
||||
begin match find_expans path !lookup_abbrev with
|
||||
Some ty ->
|
||||
if level <> generic_level then
|
||||
begin try
|
||||
|
@ -1021,6 +1189,68 @@ let occur env ty0 ty =
|
|||
raise (match exn with Occur -> Unify [] | _ -> exn)
|
||||
|
||||
|
||||
(*****************************)
|
||||
(* Polymorphic Unification *)
|
||||
(*****************************)
|
||||
|
||||
(* Since we cannot duplicate universal variables, unification must
|
||||
be done at meta-level, using bindings in univar_pairs *)
|
||||
let rec unify_univar t1 t2 = function
|
||||
(cl1, cl2) :: rem ->
|
||||
let repr_univ = List.map (fun (t,o) -> repr t, o) in
|
||||
let cl1 = repr_univ cl1 and cl2 = repr_univ cl2 in
|
||||
begin try
|
||||
let r1 = List.assq t1 cl1 in
|
||||
match !r1 with
|
||||
Some t -> if t2 != repr t then raise (Unify [])
|
||||
| None ->
|
||||
try
|
||||
let r2 = List.assq t2 cl2 in
|
||||
if !r2 <> None then raise (Unify []);
|
||||
r1 := Some t2; r2 := Some t1
|
||||
with Not_found ->
|
||||
raise (Unify [])
|
||||
with Not_found ->
|
||||
unify_univar t1 t2 rem
|
||||
end
|
||||
| [] -> raise (Unify [])
|
||||
|
||||
module TypeMap = Map.Make (TypeOps)
|
||||
|
||||
(* Test the occurence of free univars in a type *)
|
||||
(* that's way too expansive. Must do some kind of cacheing *)
|
||||
let occur_univar ty =
|
||||
let visited = ref TypeMap.empty in
|
||||
let rec occur_rec bound ty =
|
||||
let ty = repr ty in
|
||||
if ty.level >= lowest_level &&
|
||||
if TypeSet.is_empty bound then
|
||||
(ty.level <- pivot_level - ty.level; true)
|
||||
else try
|
||||
let bound' = TypeMap.find ty !visited in
|
||||
if TypeSet.exists (fun x -> not (TypeSet.mem x bound)) bound' then
|
||||
(visited := TypeMap.add ty (TypeSet.inter bound bound') !visited;
|
||||
true)
|
||||
else false
|
||||
with Not_found ->
|
||||
visited := TypeMap.add ty bound !visited;
|
||||
true
|
||||
then
|
||||
match ty.desc with
|
||||
Tunivar -> if not (TypeSet.mem ty bound) then raise Occur
|
||||
| Tpoly (ty, tyl) ->
|
||||
let bound = List.fold_right TypeSet.add (List.map repr tyl) bound in
|
||||
occur_rec bound ty
|
||||
| _ -> iter_type_expr (occur_rec bound) ty
|
||||
in
|
||||
try
|
||||
occur_rec TypeSet.empty ty; unmark_type ty
|
||||
with Occur ->
|
||||
unmark_type ty; raise (Unify [])
|
||||
|
||||
let univar_pairs = ref []
|
||||
|
||||
|
||||
(*****************)
|
||||
(* Unification *)
|
||||
(*****************)
|
||||
|
@ -1097,13 +1327,17 @@ let rec unify env t1 t2 =
|
|||
| (Tconstr _, Tvar) when deep_occur t2 t1 ->
|
||||
unify2 env t1 t2
|
||||
| (Tvar, _) ->
|
||||
occur env t1 t2;
|
||||
occur env t1 t2; occur_univar t2;
|
||||
update_level env t1.level t2;
|
||||
t1.desc <- Tlink t2
|
||||
| (_, Tvar) ->
|
||||
occur env t2 t1;
|
||||
occur env t2 t1; occur_univar t1;
|
||||
update_level env t2.level t1;
|
||||
t2.desc <- Tlink t1
|
||||
| (Tunivar, Tunivar) ->
|
||||
unify_univar t1 t2 !univar_pairs;
|
||||
update_level env t1.level t2;
|
||||
t1.desc <- Tlink t2
|
||||
| (Tconstr (p1, [], a1), Tconstr (p2, [], a2))
|
||||
when Path.same p1 p2
|
||||
(* This optimization assumes that t1 does not expand to t2
|
||||
|
@ -1147,9 +1381,11 @@ and unify3 env t1 t1' t2 t2' =
|
|||
try
|
||||
begin match (d1, d2) with
|
||||
(Tvar, _) ->
|
||||
()
|
||||
occur_univar t2
|
||||
| (_, Tvar) ->
|
||||
occur env t2' (newty d1);
|
||||
let td1 = newgenty d1 in
|
||||
occur env t2' td1;
|
||||
occur_univar td1;
|
||||
if t1 == t1' then begin
|
||||
(* The variable must be instantiated... *)
|
||||
let ty = newty2 t1'.level d1 in
|
||||
|
@ -1178,8 +1414,8 @@ and unify3 env t1 t1' t2 t2' =
|
|||
(* XXX One should do some kind of unification... *)
|
||||
begin match (repr t2').desc with
|
||||
Tobject (_, {contents = Some (_, va::_)})
|
||||
when (repr va).desc = Tvar ->
|
||||
()
|
||||
when let va = repr va in va.desc = Tvar || va.desc = Tunivar ->
|
||||
()
|
||||
| Tobject (_, nm2) ->
|
||||
nm2 := !nm1
|
||||
| _ ->
|
||||
|
@ -1191,6 +1427,30 @@ and unify3 env t1 t1' t2 t2' =
|
|||
unify_fields env t1' t2'
|
||||
| (Tnil, Tnil) ->
|
||||
()
|
||||
| (Tpoly (t1, []), Tpoly (t2, [])) ->
|
||||
unify env t1 t2
|
||||
| (Tpoly (t1, tl1), Tpoly (t2, tl2)) ->
|
||||
if List.length tl1 <> List.length tl2 then raise (Unify []);
|
||||
let old_univars = !univar_pairs in
|
||||
let cl1 = List.map (fun t -> t, ref None) tl1
|
||||
and cl2 = List.map (fun t -> t, ref None) tl2 in
|
||||
univar_pairs := (cl1,cl2) :: (cl2,cl1) :: old_univars;
|
||||
begin try
|
||||
unify env t1 t2;
|
||||
let tl1 = List.map repr tl1 and tl2 = List.map repr tl2 in
|
||||
List.iter
|
||||
(fun t1 ->
|
||||
if List.memq t1 tl2 then () else
|
||||
try
|
||||
let t2 =
|
||||
List.find (fun t2 -> not (List.memq (repr t2) tl1)) tl2 in
|
||||
t2.desc <- Tlink t1
|
||||
with Not_found -> assert false)
|
||||
tl1;
|
||||
univar_pairs := old_univars
|
||||
with exn ->
|
||||
univar_pairs := old_univars; raise exn
|
||||
end
|
||||
| (_, _) ->
|
||||
raise (Unify [])
|
||||
end;
|
||||
|
@ -1244,7 +1504,11 @@ and unify_fields env ty1 ty2 = (* Optimization *)
|
|||
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
|
||||
let va =
|
||||
if miss1 = [] then rest2
|
||||
else if miss2 = [] then rest1
|
||||
else newvar ()
|
||||
in
|
||||
unify env (build_fields (repr ty1).level miss1 va) rest2;
|
||||
unify env rest1 (build_fields (repr ty2).level miss2 va);
|
||||
List.iter
|
||||
|
@ -1276,7 +1540,12 @@ and unify_row env row1 row2 =
|
|||
with Not_found -> (h,l)::hl)
|
||||
(List.map (fun (l,_) -> (hash_variant l, l)) row1.row_fields)
|
||||
(List.map fst r2));
|
||||
let more = newty2 (min rm1.level rm2.level) Tvar
|
||||
let more =
|
||||
if row1.row_fixed then rm1 else
|
||||
if row2.row_fixed then rm2 else
|
||||
newgenvar ()
|
||||
in update_level env (min rm1.level rm2.level) more;
|
||||
let fixed = row1.row_fixed || row2.row_fixed
|
||||
and closed = row1.row_closed || row2.row_closed in
|
||||
let keep switch =
|
||||
List.for_all
|
||||
|
@ -1305,28 +1574,36 @@ and unify_row env row1 row2 =
|
|||
in
|
||||
let bound = row1.row_bound @ row2.row_bound in
|
||||
let row0 = {row_fields = []; row_more = more; row_bound = bound;
|
||||
row_closed = closed; row_name = name} in
|
||||
let more row rest =
|
||||
row_closed = closed; row_fixed = fixed; row_name = name} in
|
||||
let set_more row rest =
|
||||
let rest =
|
||||
if closed then
|
||||
filter_row_fields row.row_closed rest
|
||||
else rest in
|
||||
if rest <> [] && row.row_closed then raise (Unify []);
|
||||
let ty =
|
||||
newty2 generic_level (Tvariant {row0 with row_fields = rest}) in
|
||||
update_level env (repr row.row_more).level ty;
|
||||
ty
|
||||
if rest <> [] && (row.row_closed || row.row_fixed)
|
||||
|| closed && row.row_fixed && not row.row_closed
|
||||
then raise (Unify []);
|
||||
let rm = row_more row in
|
||||
if row.row_fixed then
|
||||
if row0.row_more == rm then () else rm.desc <- Tlink row0.row_more
|
||||
else
|
||||
let ty = newty2 generic_level (Tvariant {row0 with row_fields = rest}) in
|
||||
update_level env rm.level ty;
|
||||
rm.desc <- Tlink ty
|
||||
in
|
||||
let md1 = rm1.desc and md2 = rm2.desc in
|
||||
begin try
|
||||
rm1.desc <- Tlink (more row1 r2);
|
||||
rm2.desc <- Tlink (more row2 r1);
|
||||
List.iter (fun (l,f1,f2) -> unify_row_field env f1 f2) pairs
|
||||
set_more row1 r2;
|
||||
set_more row2 r1;
|
||||
List.iter
|
||||
(fun (l,f1,f2) ->
|
||||
unify_row_field env row1.row_fixed row2.row_fixed f1 f2)
|
||||
pairs
|
||||
with exn ->
|
||||
rm1.desc <- md1; rm2.desc <- md2; raise exn
|
||||
end
|
||||
|
||||
and unify_row_field env f1 f2 =
|
||||
and unify_row_field env fixed1 fixed2 f1 f2 =
|
||||
let f1 = row_field_repr f1 and f2 = row_field_repr f2 in
|
||||
if f1 == f2 then () else
|
||||
match f1, f2 with
|
||||
|
@ -1350,19 +1627,19 @@ and unify_row_field env f1 f2 =
|
|||
let f1 = Reither(c1 || c2, tl1', m1 || m2, e)
|
||||
and f2 = Reither(c1 || c2, tl2', m1 || m2, e) in
|
||||
e1 := Some f1; e2 := Some f2
|
||||
| Reither(false, tl, _, e1), Rpresent(Some t2) ->
|
||||
e1 := Some f2;
|
||||
(try List.iter (fun t1 -> unify env t1 t2) tl
|
||||
with exn -> e1 := None; raise exn)
|
||||
| Rpresent(Some t1), Reither(false, tl, _, e2) ->
|
||||
e2 := Some f1;
|
||||
(try List.iter (unify env t1) tl
|
||||
with exn -> e2 := None; raise exn)
|
||||
| Reither(true, [], _, e1), Rpresent None -> e1 := Some f2
|
||||
| Rpresent None, Reither(true, [], _, e2) -> e2 := Some f1
|
||||
| Reither(_, _, false, e1), Rabsent -> e1 := Some f2
|
||||
| Rabsent, Reither(_, _, false, e2) -> e2 := Some f1
|
||||
| Rabsent, Rabsent -> ()
|
||||
| Reither(false, tl, _, e1), Rpresent(Some t2) when not fixed1 ->
|
||||
e1 := Some f2;
|
||||
(try List.iter (fun t1 -> unify env t1 t2) tl
|
||||
with exn -> e1 := None; raise exn)
|
||||
| Rpresent(Some t1), Reither(false, tl, _, e2) when not fixed2 ->
|
||||
e2 := Some f1;
|
||||
(try List.iter (unify env t1) tl
|
||||
with exn -> e2 := None; raise exn)
|
||||
| Reither(true, [], _, e1), Rpresent None when not fixed1 -> e1 := Some f2
|
||||
| Rpresent None, Reither(true, [], _, e2) when not fixed2 -> e2 := Some f1
|
||||
| _ -> raise (Unify [])
|
||||
|
||||
let unify env ty1 ty2 =
|
||||
|
@ -1371,7 +1648,31 @@ let unify env ty1 ty2 =
|
|||
with Unify trace ->
|
||||
raise (Unify (expand_trace env trace))
|
||||
|
||||
let _ = unify' := unify
|
||||
let unify_var env t1 t2 =
|
||||
let t1 = repr t1 and t2 = repr t2 in
|
||||
if t1 == t2 then () else
|
||||
match t1.desc with
|
||||
Tvar ->
|
||||
begin try
|
||||
occur env t1 t2;
|
||||
update_level env t1.level t2;
|
||||
t1.desc <- Tlink t2
|
||||
with Unify trace ->
|
||||
raise (Unify ((t1,t2)::trace))
|
||||
end
|
||||
| _ ->
|
||||
unify env t1 t2
|
||||
|
||||
let _ = unify' := unify_var
|
||||
|
||||
let unify_pairs env ty1 ty2 pairs =
|
||||
univar_pairs := pairs;
|
||||
unify env ty1 ty2
|
||||
|
||||
let unify env ty1 ty2 =
|
||||
univar_pairs := [];
|
||||
unify env ty1 ty2
|
||||
|
||||
|
||||
(**** Special cases of unification ****)
|
||||
|
||||
|
@ -1477,6 +1778,8 @@ let moregen_occur env level ty =
|
|||
with Occur ->
|
||||
unmark_type ty; raise (Unify [])
|
||||
end;
|
||||
(* also check for free univars *)
|
||||
occur_univar ty;
|
||||
update_level env level ty
|
||||
|
||||
let rec moregen inst_nongen type_pairs env t1 t2 =
|
||||
|
@ -1487,7 +1790,9 @@ let rec moregen inst_nongen type_pairs env t1 t2 =
|
|||
|
||||
try
|
||||
match (t1.desc, t2.desc) with
|
||||
(Tvar, _) when if inst_nongen then t1.level <> generic_level - 1
|
||||
(Tunivar, Tunivar) ->
|
||||
unify_univar t1 t2 !univar_pairs
|
||||
| (Tvar, _) when if inst_nongen then t1.level <> generic_level - 1
|
||||
else t1.level = generic_level ->
|
||||
moregen_occur env t1.level t2;
|
||||
occur env t1 t2;
|
||||
|
@ -1532,6 +1837,19 @@ let rec moregen inst_nongen type_pairs env t1 t2 =
|
|||
moregen inst_nongen type_pairs env t1' t2''
|
||||
| (Tnil, Tnil) ->
|
||||
()
|
||||
| (Tpoly (t1, []), Tpoly (t2, [])) ->
|
||||
moregen inst_nongen type_pairs env t1 t2
|
||||
| (Tpoly (t1, tl1), Tpoly (t2, tl2)) ->
|
||||
let old_univars = !univar_pairs in
|
||||
let cl1 = List.map (fun t -> t, ref None) tl1
|
||||
and cl2 = List.map (fun t -> t, ref None) tl2 in
|
||||
univar_pairs := (cl1,cl2) :: (cl2,cl1) :: old_univars;
|
||||
begin try
|
||||
moregen inst_nongen type_pairs env t1 t2;
|
||||
univar_pairs := old_univars
|
||||
with exn ->
|
||||
univar_pairs := old_univars; raise exn
|
||||
end
|
||||
| (_, _) ->
|
||||
raise (Unify [])
|
||||
end
|
||||
|
@ -1635,6 +1953,7 @@ let moregeneral env inst_nongen pat_sch subj_sch =
|
|||
current_level := generic_level;
|
||||
(* Duplicate generic variables *)
|
||||
let patt = instance pat_sch in
|
||||
univar_pairs := [];
|
||||
let res =
|
||||
try moregen inst_nongen (TypePairs.create 13) env patt subj; true with
|
||||
Unify _ -> false
|
||||
|
@ -1704,6 +2023,21 @@ let rec eqtype rename type_pairs subst env t1 t2 =
|
|||
eqtype rename type_pairs subst env t1' t2''
|
||||
| (Tnil, Tnil) ->
|
||||
()
|
||||
| (Tpoly (t1, []), Tpoly (t2, [])) ->
|
||||
eqtype rename type_pairs subst env t1 t2
|
||||
| (Tpoly (t1, tl1), Tpoly (t2, tl2)) ->
|
||||
let old_univars = !univar_pairs in
|
||||
let cl1 = List.map (fun t -> t, ref None) tl1
|
||||
and cl2 = List.map (fun t -> t, ref None) tl2 in
|
||||
univar_pairs := (cl1,cl2) :: (cl2,cl1) :: old_univars;
|
||||
begin try eqtype rename type_pairs subst env t1 t2
|
||||
with exn ->
|
||||
univar_pairs := old_univars;
|
||||
raise exn
|
||||
end;
|
||||
univar_pairs := old_univars
|
||||
| (Tunivar, Tunivar) ->
|
||||
unify_univar t1 t2 !univar_pairs
|
||||
| (_, _) ->
|
||||
raise (Unify [])
|
||||
end
|
||||
|
@ -1772,6 +2106,7 @@ and eqtype_row rename type_pairs subst env row1 row2 =
|
|||
(* Two modes: with or without renaming of variables *)
|
||||
let equal env rename tyl1 tyl2 =
|
||||
try
|
||||
univar_pairs := [];
|
||||
eqtype_list rename (TypePairs.create 11) (ref []) env tyl1 tyl2; true
|
||||
with
|
||||
Unify _ -> false
|
||||
|
@ -1843,6 +2178,7 @@ let match_class_types env pat_sch subj_sch =
|
|||
let type_pairs = TypePairs.create 53 in
|
||||
let old_level = !current_level in
|
||||
current_level := generic_level - 1;
|
||||
univar_pairs := [];
|
||||
(*
|
||||
Generic variables are first duplicated with [instance]. So,
|
||||
their levels are lowered to [generic_level - 1]. The subject is
|
||||
|
@ -1971,6 +2307,7 @@ let rec equal_clty trace type_pairs subst env cty1 cty2 =
|
|||
(* XXX Correct ? (variables de type dans parametres et corps de classe *)
|
||||
let match_class_declarations env patt_params patt_type subj_params subj_type =
|
||||
let type_pairs = TypePairs.create 53 in
|
||||
univar_pairs := [];
|
||||
let subst = ref [] in
|
||||
let sign1 = signature_of_class_type patt_type in
|
||||
let sign2 = signature_of_class_type subj_type in
|
||||
|
@ -2137,7 +2474,7 @@ let rec build_subtype env visited loops posi onlyloop t =
|
|||
let (ty1', _) = build_subtype env visited loops posi onlyloop ty1 in
|
||||
assert (t''.desc = Tvar);
|
||||
t''.desc <- Tobject (ty1', ref None);
|
||||
(try unify env ty t with Unify _ -> assert false);
|
||||
(try unify_var env ty t with Unify _ -> assert false);
|
||||
(t'', true)
|
||||
| _ -> raise Not_found
|
||||
with Not_found -> build_subtype env visited loops posi onlyloop t'
|
||||
|
@ -2191,7 +2528,7 @@ let rec build_subtype env visited loops posi onlyloop t =
|
|||
if posi && fields = [] then (t, false) else
|
||||
let row =
|
||||
{ row_fields = List.map fst fields; row_more = newvar();
|
||||
row_bound = !bound; row_closed = posi;
|
||||
row_bound = !bound; row_closed = posi; row_fixed = false;
|
||||
row_name = if List.exists snd fields then None else row.row_name }
|
||||
in
|
||||
(newty (Tvariant row), true)
|
||||
|
@ -2217,6 +2554,12 @@ let rec build_subtype env visited loops posi onlyloop t =
|
|||
(t, false)
|
||||
| Tsubst _ | Tlink _ ->
|
||||
assert false
|
||||
| Tpoly(t1, tl) ->
|
||||
let (t1', c) = build_subtype env visited loops posi onlyloop t1 in
|
||||
if c then (newty (Tpoly(t1', tl)), true)
|
||||
else (t, false)
|
||||
| Tunivar ->
|
||||
(t, false)
|
||||
|
||||
let enlarge_type env ty =
|
||||
let (ty', _) = build_subtype env [] [] true false ty in
|
||||
|
@ -2255,7 +2598,7 @@ let rec subtype_rec env trace t1 t2 cstrs =
|
|||
TypePairs.add subtypes (t1, t2) ();
|
||||
match (t1.desc, t2.desc) with
|
||||
(Tvar, _) | (_, Tvar) ->
|
||||
(trace, t1, t2)::cstrs
|
||||
(trace, t1, t2, !univar_pairs)::cstrs
|
||||
| (Tarrow(l1, t1, u1, _), Tarrow(l2, t2, u2, _)) when l1 = l2
|
||||
|| !Clflags.classic && not (is_optional l1 || is_optional l2) ->
|
||||
let cstrs = subtype_rec env ((t2, t1)::trace) t2 t1 cstrs in
|
||||
|
@ -2276,19 +2619,19 @@ let rec subtype_rec env trace t1 t2 cstrs =
|
|||
if co then
|
||||
if cn then
|
||||
(trace, newty2 t1.level (Ttuple[t1]),
|
||||
newty2 t2.level (Ttuple[t2])) :: cstrs
|
||||
newty2 t2.level (Ttuple[t2]), !univar_pairs) :: cstrs
|
||||
else subtype_rec env ((t1, t2)::trace) t1 t2 cstrs
|
||||
else
|
||||
if cn then subtype_rec env ((t2, t1)::trace) t2 t1 cstrs
|
||||
else cstrs)
|
||||
cstrs decl.type_variance (List.combine tl1 tl2)
|
||||
with Not_found ->
|
||||
(trace, t1, t2)::cstrs
|
||||
(trace, t1, t2, !univar_pairs)::cstrs
|
||||
end
|
||||
| (Tobject (f1, _), Tobject (f2, _))
|
||||
when opened_object f1 && opened_object f2 ->
|
||||
(* Same row variable implies same object. *)
|
||||
(trace, t1, t2)::cstrs
|
||||
(trace, t1, t2, !univar_pairs)::cstrs
|
||||
| (Tobject (f1, _), Tobject (f2, _)) ->
|
||||
subtype_fields env trace f1 f2 cstrs
|
||||
| (Tvariant row1, Tvariant row2) ->
|
||||
|
@ -2311,10 +2654,20 @@ let rec subtype_rec env trace t1 t2 cstrs =
|
|||
| _ -> raise Exit)
|
||||
cstrs pairs
|
||||
with Exit ->
|
||||
(trace, t1, t2)::cstrs
|
||||
(trace, t1, t2, !univar_pairs)::cstrs
|
||||
end
|
||||
| (Tpoly (u1, []), Tpoly (u2, [])) ->
|
||||
subtype_rec env trace u1 u2 cstrs
|
||||
| (Tpoly (t1, tl1), Tpoly (t2,tl2)) ->
|
||||
let old_univars = !univar_pairs in
|
||||
let cl1 = List.map (fun t -> t, ref None) tl1
|
||||
and cl2 = List.map (fun t -> t, ref None) tl2 in
|
||||
univar_pairs := (cl1,cl2) :: (cl2,cl1) :: old_univars;
|
||||
let cstrs = subtype_rec env trace t1 t2 cstrs in
|
||||
univar_pairs := old_univars;
|
||||
cstrs
|
||||
| (_, _) ->
|
||||
(trace, t1, t2)::cstrs
|
||||
(trace, t1, t2, !univar_pairs)::cstrs
|
||||
end
|
||||
|
||||
and subtype_list env trace tl1 tl2 cstrs =
|
||||
|
@ -2328,11 +2681,13 @@ and subtype_fields env trace ty1 ty2 cstrs =
|
|||
let (fields1, rest1) = flatten_fields ty1 in
|
||||
let (fields2, rest2) = flatten_fields ty2 in
|
||||
let (pairs, miss1, miss2) = associate_fields fields1 fields2 in
|
||||
[(trace, rest1, build_fields (repr ty2).level miss2 (newvar ()))]
|
||||
@
|
||||
(trace, rest1, build_fields (repr ty2).level miss2 (newvar ()),
|
||||
!univar_pairs)
|
||||
::
|
||||
begin match rest2.desc with
|
||||
Tnil -> []
|
||||
| _ -> [(trace, build_fields (repr ty1).level miss1 rest1, rest2)]
|
||||
| _ ->
|
||||
[trace, build_fields (repr ty1).level miss1 rest1, rest2, !univar_pairs]
|
||||
end
|
||||
@
|
||||
(List.fold_left
|
||||
|
@ -2343,14 +2698,15 @@ and subtype_fields env trace ty1 ty2 cstrs =
|
|||
|
||||
let subtype env ty1 ty2 =
|
||||
TypePairs.clear subtypes;
|
||||
univar_pairs := [];
|
||||
(* Build constraint set. *)
|
||||
let cstrs = subtype_rec env [(ty1, ty2)] ty1 ty2 [] in
|
||||
TypePairs.clear subtypes;
|
||||
(* Enforce constraints. *)
|
||||
function () ->
|
||||
List.iter
|
||||
(function (trace0, t1, t2) ->
|
||||
try unify env t1 t2 with Unify trace ->
|
||||
(function (trace0, t1, t2, pairs) ->
|
||||
try unify_pairs env t1 t2 pairs with Unify trace ->
|
||||
raise (Subtype (expand_trace env (List.rev trace0),
|
||||
List.tl (List.tl trace))))
|
||||
(List.rev cstrs)
|
||||
|
@ -2444,7 +2800,7 @@ let rec normalize_type_rec env ty =
|
|||
| Some (n, v :: l) ->
|
||||
let v' = repr v in
|
||||
begin match v'.desc with
|
||||
| Tvar -> if v' != v then nm := Some (n, v' :: l)
|
||||
| Tvar|Tunivar -> if v' != v then nm := Some (n, v' :: l)
|
||||
| Tnil -> ty.desc <- Tconstr (n, l, ref Mnil)
|
||||
| _ -> nm := None
|
||||
end
|
||||
|
@ -2484,7 +2840,7 @@ let normalize_type env ty =
|
|||
let rec nondep_type_rec env id ty =
|
||||
let ty = repr ty in
|
||||
match ty.desc with
|
||||
Tvar -> ty
|
||||
Tvar | Tunivar -> ty
|
||||
| Tsubst ty -> ty
|
||||
| _ ->
|
||||
let desc = ty.desc in
|
||||
|
@ -2532,7 +2888,8 @@ let rec nondep_type_rec env id ty =
|
|||
more.desc <- ty.desc;
|
||||
let more' = if static then newgenvar () else more in
|
||||
(* Return a new copy *)
|
||||
let row = copy_row (nondep_type_rec env id) row true more' in
|
||||
let row =
|
||||
copy_row (nondep_type_rec env id) true row true more' in
|
||||
match row.row_name with
|
||||
Some (p, tl) when Path.isfree id p ->
|
||||
Tvariant {row with row_name = None}
|
||||
|
|
|
@ -83,6 +83,15 @@ val generalize: type_expr -> unit
|
|||
(* Generalize in-place the given type *)
|
||||
val iterative_generalization: int -> type_expr list -> type_expr list
|
||||
(* Efficient repeated generalization of a type *)
|
||||
val generalize_expansive: type_expr -> unit
|
||||
(* Generalize the structure of a type, making variables
|
||||
non-generalizable *)
|
||||
val generalize_global: type_expr -> unit
|
||||
(* Same, but variables are lowered to !global_level *)
|
||||
val generalize_structure: type_expr -> unit
|
||||
(* Same, but variables are only lowered to !current_level *)
|
||||
val generalize_spine: type_expr -> unit
|
||||
(* Special function to generalize a method during inference *)
|
||||
val make_nongen: type_expr -> unit
|
||||
(* Make non-generalizable the given type *)
|
||||
val correct_levels: type_expr -> type_expr
|
||||
|
@ -98,8 +107,6 @@ val instance_list: type_expr list -> type_expr list
|
|||
val instance_constructor:
|
||||
constructor_description -> type_expr list * type_expr
|
||||
(* Same, for a constructor *)
|
||||
val instance_label: label_description -> type_expr * type_expr
|
||||
(* Same, for a label *)
|
||||
val instance_parameterized_type:
|
||||
type_expr list -> type_expr -> type_expr list * type_expr
|
||||
val instance_parameterized_type_2:
|
||||
|
@ -107,6 +114,12 @@ val instance_parameterized_type_2:
|
|||
type_expr list * type_expr list * type_expr
|
||||
val instance_class:
|
||||
type_expr list -> class_type -> type_expr list * class_type
|
||||
val instance_poly:
|
||||
bool -> type_expr list -> type_expr -> type_expr list * type_expr
|
||||
(* Take an instance of a type scheme containing free univars *)
|
||||
val instance_label:
|
||||
bool -> label_description -> type_expr list * type_expr * type_expr
|
||||
(* Same, for a label *)
|
||||
val apply:
|
||||
Env.t -> type_expr list -> type_expr -> type_expr list -> type_expr
|
||||
(* [apply [p1...pN] t [a1...aN]] match the arguments [ai] to
|
||||
|
@ -120,6 +133,9 @@ val enforce_constraints: Env.t -> type_expr -> unit
|
|||
|
||||
val unify: Env.t -> type_expr -> type_expr -> unit
|
||||
(* Unify the two types given. Raise [Unify] if not possible. *)
|
||||
val unify_var: Env.t -> type_expr -> type_expr -> unit
|
||||
(* Same as [unify], but allow free univars when first type
|
||||
is a variable. *)
|
||||
val filter_arrow: Env.t -> type_expr -> label -> type_expr * type_expr
|
||||
(* A special case of unification (with l:'a -> 'b). *)
|
||||
val filter_method: Env.t -> string -> private_flag -> type_expr -> type_expr
|
||||
|
|
|
@ -116,10 +116,20 @@ let rec print_list pr sep ppf =
|
|||
let pr_present =
|
||||
print_list (fun ppf s -> fprintf ppf "`%s" s) (fun ppf -> fprintf ppf "@ ")
|
||||
|
||||
let pr_vars =
|
||||
print_list (fun ppf s -> fprintf ppf "'%s" s) (fun ppf -> fprintf ppf "@ ")
|
||||
|
||||
let rec print_out_type ppf =
|
||||
function
|
||||
Otyp_alias (ty, s) -> fprintf ppf "@[%a as '%s@]" print_out_type ty s
|
||||
| ty -> print_out_type_1 ppf ty
|
||||
| Otyp_alias (ty, s) ->
|
||||
fprintf ppf "@[%a as '%s@]" print_out_type ty s
|
||||
| Otyp_poly (sl, ty) ->
|
||||
fprintf ppf "@[<hov 2>%a.@ %a@]"
|
||||
pr_vars sl
|
||||
print_out_type ty
|
||||
| ty ->
|
||||
print_out_type_1 ppf ty
|
||||
|
||||
and print_out_type_1 ppf =
|
||||
function
|
||||
Otyp_arrow (lab, ty1, ty2) ->
|
||||
|
@ -158,10 +168,10 @@ and print_simple_out_type ppf =
|
|||
in
|
||||
fprintf ppf "%s[%s@[<hv>@[<hv>%a@]%a]@]" (if non_gen then "_" else "")
|
||||
(if closed then if tags = None then " " else "< "
|
||||
else if tags = None then "> "
|
||||
else "? ")
|
||||
print_fields row_fields print_present tags
|
||||
| Otyp_alias (_, _) | Otyp_arrow (_, _, _) | Otyp_tuple _ as ty ->
|
||||
else if tags = None then "> " else "? ")
|
||||
print_fields row_fields
|
||||
print_present tags
|
||||
| Otyp_alias _ | Otyp_poly _ | Otyp_arrow _ | Otyp_tuple _ as ty ->
|
||||
fprintf ppf "@[<1>(%a)@]" print_out_type ty
|
||||
| Otyp_abstract | Otyp_sum _ | Otyp_record _ | Otyp_manifest (_, _) -> ()
|
||||
and print_fields rest ppf =
|
||||
|
|
|
@ -56,6 +56,7 @@ type out_type =
|
|||
| Otyp_var of bool * string
|
||||
| Otyp_variant of
|
||||
bool * out_variant * bool * (string list) option
|
||||
| Otyp_poly of string list * out_type
|
||||
and out_variant =
|
||||
| Ovar_fields of (string * bool * out_type list) list
|
||||
| Ovar_name of out_ident * out_type list
|
||||
|
|
|
@ -380,7 +380,7 @@ let full_match tdefs force env = match env with
|
|||
env
|
||||
in
|
||||
let row = Btype.row_repr row in
|
||||
if force then begin
|
||||
if force && not row.row_fixed then begin
|
||||
(* force=true, we are called from check_partial, and must close *)
|
||||
let (ok, nm) =
|
||||
List.fold_left
|
||||
|
|
|
@ -24,6 +24,16 @@ open Types
|
|||
open Btype
|
||||
open Outcometree
|
||||
|
||||
(* Redefine it here since goal differs *)
|
||||
|
||||
let rec opened_object ty =
|
||||
match (repr ty).desc with
|
||||
Tobject (t, _) -> opened_object t
|
||||
| Tfield(_, _, _, t) -> opened_object t
|
||||
| Tvar -> true
|
||||
| Tunivar -> true
|
||||
| _ -> false
|
||||
|
||||
(* Print a long identifier *)
|
||||
|
||||
let rec longident ppf = function
|
||||
|
@ -83,21 +93,35 @@ let name_of_type t =
|
|||
|
||||
let check_name_of_type t = ignore(name_of_type t)
|
||||
|
||||
let print_name_of_type ppf t = fprintf ppf "%s" (name_of_type t)
|
||||
let non_gen_mark sch ty =
|
||||
if sch && ty.desc = Tvar && ty.level <> generic_level then "_" else ""
|
||||
|
||||
let visited_objects = ref ([] : type_expr list)
|
||||
let aliased = ref ([] : type_expr list)
|
||||
|
||||
let is_aliased ty = List.memq ty !aliased
|
||||
let add_alias ty =
|
||||
if not (is_aliased ty) then aliased := ty :: !aliased
|
||||
let print_name_of_type sch ppf t =
|
||||
fprintf ppf "'%s%s" (non_gen_mark sch t) (name_of_type t)
|
||||
|
||||
let proxy ty =
|
||||
let ty = repr ty in
|
||||
match ty.desc with
|
||||
| Tvariant row -> Btype.row_more row
|
||||
| Tobject (ty, _) ->
|
||||
let rec proxy_obj ty =
|
||||
let ty = repr ty in
|
||||
match ty.desc with
|
||||
Tfield (_, _, _, ty) -> proxy_obj ty
|
||||
| Tvar | Tnil | Tunivar -> ty
|
||||
| _ -> assert false
|
||||
in proxy_obj ty
|
||||
| _ -> ty
|
||||
|
||||
let visited_objects = ref ([] : type_expr list)
|
||||
let aliased = ref ([] : type_expr list)
|
||||
let delayed = ref ([] : type_expr list)
|
||||
|
||||
let is_aliased ty = List.memq (proxy ty) !aliased
|
||||
let add_alias ty =
|
||||
let px = proxy ty in
|
||||
if not (is_aliased px) then aliased := px :: !aliased
|
||||
|
||||
let namable_row row =
|
||||
row.row_name <> None &&
|
||||
List.for_all
|
||||
|
@ -139,9 +163,14 @@ let rec mark_loops_rec visited ty =
|
|||
visited_objects := px :: !visited_objects;
|
||||
begin match !nm with
|
||||
| None ->
|
||||
mark_loops_rec visited fi
|
||||
let fields, _ = flatten_fields fi in
|
||||
List.iter
|
||||
(fun (_, kind, ty) ->
|
||||
if field_kind_repr kind = Fpresent then
|
||||
mark_loops_rec visited ty)
|
||||
fields
|
||||
| Some (_, l) ->
|
||||
List.iter (mark_loops_rec visited) l
|
||||
List.iter (mark_loops_rec visited) (List.tl l)
|
||||
end
|
||||
end
|
||||
| Tfield(_, kind, ty1, ty2) when field_kind_repr kind = Fpresent ->
|
||||
|
@ -151,22 +180,26 @@ let rec mark_loops_rec visited ty =
|
|||
| Tnil -> ()
|
||||
| Tsubst ty -> mark_loops_rec visited ty
|
||||
| Tlink _ -> fatal_error "Printtyp.mark_loops_rec (2)"
|
||||
| Tpoly (ty, tyl) ->
|
||||
List.iter (fun t -> add_alias t) tyl;
|
||||
mark_loops_rec visited ty
|
||||
| Tunivar -> ()
|
||||
|
||||
let mark_loops ty =
|
||||
normalize_type Env.empty ty;
|
||||
mark_loops_rec [] ty;;
|
||||
|
||||
let reset_loop_marks () =
|
||||
visited_objects := []; aliased := []
|
||||
visited_objects := []; aliased := []; delayed := []
|
||||
|
||||
let reset () =
|
||||
reset_names (); reset_loop_marks ()
|
||||
|
||||
let reset_and_mark_loops ty =
|
||||
reset (); mark_loops ty;;
|
||||
reset (); mark_loops ty
|
||||
|
||||
let reset_and_mark_loops_list tyl =
|
||||
reset (); List.iter mark_loops tyl;;
|
||||
reset (); List.iter mark_loops tyl
|
||||
|
||||
(* Disabled in classic mode when printing an unification error *)
|
||||
let print_labels = ref true
|
||||
|
@ -176,12 +209,12 @@ let print_label ppf l =
|
|||
let rec tree_of_typexp sch ty =
|
||||
let ty = repr ty in
|
||||
let px = proxy ty in
|
||||
if List.mem_assq px !names then
|
||||
let mark = if ty.desc = Tvar then is_non_gen sch px else false in
|
||||
if List.mem_assq px !names && not (List.memq px !delayed) then
|
||||
let mark = is_non_gen sch px in
|
||||
Otyp_var (mark, name_of_type px) else
|
||||
|
||||
let pr_typ () =
|
||||
(match ty.desc with
|
||||
match ty.desc with
|
||||
| Tvar ->
|
||||
Otyp_var (is_non_gen sch ty, name_of_type ty)
|
||||
| Tarrow(l, ty1, ty2, _) ->
|
||||
|
@ -239,13 +272,25 @@ let rec tree_of_typexp sch ty =
|
|||
Otyp_variant (non_gen, Ovar_fields fields, row.row_closed, tags)
|
||||
end
|
||||
| Tobject (fi, nm) ->
|
||||
tree_of_typobject sch ty fi nm
|
||||
tree_of_typobject sch fi nm
|
||||
| Tsubst ty ->
|
||||
tree_of_typexp sch ty
|
||||
| Tlink _ | Tnil | Tfield _ ->
|
||||
fatal_error "Printtyp.tree_of_typexp"
|
||||
) in
|
||||
if is_aliased px then begin
|
||||
| Tpoly (ty, []) ->
|
||||
tree_of_typexp sch ty
|
||||
| Tpoly (ty, tyl) ->
|
||||
let tyl = List.map repr tyl in
|
||||
let tyl = List.filter is_aliased tyl in
|
||||
if tyl = [] then tree_of_typexp sch ty else
|
||||
let tl = List.map name_of_type tyl in
|
||||
delayed := tyl @ !delayed;
|
||||
Otyp_poly (tl, tree_of_typexp sch ty)
|
||||
| Tunivar ->
|
||||
Otyp_var (false, name_of_type ty)
|
||||
in
|
||||
if List.memq px !delayed then delayed := List.filter ((!=) px) !delayed;
|
||||
if is_aliased px && ty.desc <> Tvar && ty.desc <> Tunivar then begin
|
||||
check_name_of_type px;
|
||||
Otyp_alias (pr_typ (), name_of_type px) end
|
||||
else pr_typ ()
|
||||
|
@ -266,7 +311,7 @@ and tree_of_typlist sch = function
|
|||
let tr = tree_of_typexp sch ty in
|
||||
tr :: tree_of_typlist sch tyl
|
||||
|
||||
and tree_of_typobject sch ty fi nm =
|
||||
and tree_of_typobject sch fi nm =
|
||||
begin match !nm with
|
||||
| None ->
|
||||
let pr_fields fi =
|
||||
|
@ -283,8 +328,8 @@ and tree_of_typobject sch ty fi nm =
|
|||
tree_of_typfields sch rest sorted_fields in
|
||||
let (fields, rest) = pr_fields fi in
|
||||
Otyp_object (fields, rest)
|
||||
| Some (p, {desc = Tvar} :: tyl) ->
|
||||
let non_gen = is_non_gen sch ty in
|
||||
| Some (p, ty :: tyl) ->
|
||||
let non_gen = is_non_gen sch (repr ty) in
|
||||
let args = tree_of_typlist sch tyl in
|
||||
Otyp_class (non_gen, tree_of_path p, args)
|
||||
| _ ->
|
||||
|
@ -292,13 +337,13 @@ and tree_of_typobject sch ty fi nm =
|
|||
end
|
||||
|
||||
and is_non_gen sch ty =
|
||||
sch && ty.level <> generic_level
|
||||
sch && ty.desc = Tvar && ty.level <> generic_level
|
||||
|
||||
and tree_of_typfields sch rest = function
|
||||
| [] ->
|
||||
let rest =
|
||||
match rest.desc with
|
||||
| Tvar -> Some (is_non_gen sch rest)
|
||||
| Tvar | Tunivar -> Some (is_non_gen sch rest)
|
||||
| Tnil -> None
|
||||
| _ -> fatal_error "typfields (1)"
|
||||
in
|
||||
|
@ -362,7 +407,7 @@ let rec tree_of_type_decl id decl =
|
|||
|
||||
let params = filter_params decl.type_params in
|
||||
|
||||
aliased := params @ !aliased;
|
||||
List.iter add_alias params;
|
||||
List.iter mark_loops params;
|
||||
List.iter check_name_of_type (List.map proxy params);
|
||||
begin match decl.type_manifest with
|
||||
|
@ -485,6 +530,12 @@ let tree_of_metho sch concrete csil (lab, kind, ty) =
|
|||
end
|
||||
else csil
|
||||
|
||||
let prepare_class_field ty =
|
||||
let ty = repr ty in
|
||||
match ty.desc with
|
||||
Tpoly(ty, _) -> mark_loops ty
|
||||
| _ -> mark_loops ty
|
||||
|
||||
let rec prepare_class_type params = function
|
||||
| Tcty_constr (p, tyl, cty) ->
|
||||
let sty = Ctype.self_type cty in
|
||||
|
@ -501,11 +552,11 @@ let rec prepare_class_type params = function
|
|||
let sty = repr sign.cty_self in
|
||||
(* Self may have a name *)
|
||||
if List.memq sty !visited_objects then add_alias sty
|
||||
else visited_objects := sty :: !visited_objects;
|
||||
else visited_objects := proxy sty :: !visited_objects;
|
||||
let (fields, _) =
|
||||
Ctype.flatten_fields (Ctype.object_fields sign.cty_self)
|
||||
in
|
||||
List.iter (fun (_, _, ty) -> mark_loops ty) fields;
|
||||
List.iter (fun (_, _, ty) -> prepare_class_field ty) fields;
|
||||
Vars.iter (fun _ (_, ty) -> mark_loops ty) sign.cty_vars
|
||||
| Tcty_fun (_, ty, cty) ->
|
||||
mark_loops ty;
|
||||
|
@ -524,7 +575,8 @@ let rec tree_of_class_type sch params =
|
|||
| Tcty_signature sign ->
|
||||
let sty = repr sign.cty_self in
|
||||
let self_ty =
|
||||
if is_aliased sty then Some (Otyp_var (false, name_of_type sty))
|
||||
if is_aliased sty then
|
||||
Some (Otyp_var (false, name_of_type (proxy sty)))
|
||||
else None
|
||||
in
|
||||
let (fields, _) =
|
||||
|
@ -574,13 +626,13 @@ let tree_of_class_declaration id cl =
|
|||
let params = filter_params cl.cty_params in
|
||||
|
||||
reset ();
|
||||
aliased := params @ !aliased;
|
||||
List.iter add_alias params;
|
||||
prepare_class_type params cl.cty_type;
|
||||
let sty = self_type cl.cty_type in
|
||||
List.iter mark_loops params;
|
||||
|
||||
List.iter check_name_of_type (List.map proxy params);
|
||||
if is_aliased sty then check_name_of_type sty;
|
||||
if is_aliased sty then check_name_of_type (proxy sty);
|
||||
|
||||
let vir_flag = cl.cty_new = None in
|
||||
Osig_class
|
||||
|
@ -600,7 +652,7 @@ let tree_of_cltype_declaration id cl =
|
|||
List.iter mark_loops params;
|
||||
|
||||
List.iter check_name_of_type (List.map proxy params);
|
||||
if is_aliased sty then check_name_of_type sty;
|
||||
if is_aliased sty then check_name_of_type (proxy sty);
|
||||
|
||||
let sign = Ctype.signature_of_class_type cl.clty_type in
|
||||
|
||||
|
|
|
@ -58,17 +58,17 @@ let type_path s = function
|
|||
let new_id = ref (-1)
|
||||
let reset_for_saving () = new_id := -1
|
||||
|
||||
let newpersvar () =
|
||||
decr new_id; { desc = Tvar; level = generic_level; id = !new_id }
|
||||
let newpersty desc =
|
||||
decr new_id; { desc = desc; level = generic_level; id = !new_id }
|
||||
|
||||
(* Similar to [Ctype.nondep_type_rec]. *)
|
||||
let rec typexp s ty =
|
||||
let ty = repr ty in
|
||||
match ty.desc with
|
||||
Tvar ->
|
||||
Tvar | Tunivar ->
|
||||
if s.for_saving then
|
||||
let ty' = newpersvar () in
|
||||
save_desc ty Tvar; ty.desc <- Tsubst ty'; ty'
|
||||
let ty' = newpersty ty.desc in
|
||||
save_desc ty ty.desc; ty.desc <- Tsubst ty'; ty'
|
||||
else ty
|
||||
| Tsubst ty ->
|
||||
ty
|
||||
|
@ -80,7 +80,7 @@ let rec typexp s ty =
|
|||
let desc = ty.desc in
|
||||
save_desc ty desc;
|
||||
(* Make a stub *)
|
||||
let ty' = if s.for_saving then newpersvar () else newgenvar () in
|
||||
let ty' = if s.for_saving then newpersty Tvar else newgenvar () in
|
||||
ty.desc <- Tsubst ty';
|
||||
ty'.desc <-
|
||||
begin match desc with
|
||||
|
@ -97,20 +97,25 @@ let rec typexp s ty =
|
|||
let more = repr row.row_more in
|
||||
(* We must substitute in a subtle way *)
|
||||
begin match more.desc with
|
||||
Tsubst ty2 ->
|
||||
Tsubst ({desc=Tvariant _} as ty2) ->
|
||||
(* This variant type has been already copied *)
|
||||
ty.desc <- Tsubst ty2; (* avoid Tlink in the new type *)
|
||||
Tlink ty2
|
||||
| _ ->
|
||||
let static = static_row row in
|
||||
(* Various cases for the row variable *)
|
||||
let more' =
|
||||
match more.desc with Tsubst ty -> ty
|
||||
| _ ->
|
||||
if s.for_saving then newpersty more.desc else
|
||||
if static then newgenvar () else more
|
||||
in
|
||||
(* Register new type first for recursion *)
|
||||
save_desc more more.desc;
|
||||
more.desc <- ty.desc;
|
||||
let more' =
|
||||
if s.for_saving then newpersvar () else
|
||||
if static then newgenvar () else more in
|
||||
(* Return a new copy *)
|
||||
let row = copy_row (typexp s) row (not s.for_saving) more' in
|
||||
let row =
|
||||
copy_row (typexp s) true row (not s.for_saving) more' in
|
||||
let row =
|
||||
if s.for_saving then {row with row_bound = []} else row in
|
||||
match row.row_name with
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
(* *)
|
||||
(***********************************************************************)
|
||||
|
||||
(* $Id$ *)
|
||||
(* typeclass.ml,v 1.57.4.6 2002/02/15 14:26:04 garrigue Exp *)
|
||||
|
||||
open Misc
|
||||
open Parsetree
|
||||
|
@ -233,6 +233,19 @@ let virtual_method val_env meths self_type lab priv sty loc =
|
|||
try Ctype.unify val_env ty ty' with Ctype.Unify trace ->
|
||||
raise(Error(loc, Method_type_mismatch (lab, trace)))
|
||||
|
||||
let declare_method val_env meths self_type lab priv sty loc =
|
||||
let (_, ty') =
|
||||
Ctype.filter_self_method val_env lab priv meths self_type
|
||||
in
|
||||
let ty =
|
||||
match sty.ptyp_desc with
|
||||
Ptyp_poly ([],sty) -> transl_simple_type_univars val_env sty
|
||||
| _ -> transl_simple_type val_env false sty
|
||||
in
|
||||
begin try Ctype.unify val_env ty ty' with Ctype.Unify trace ->
|
||||
raise(Error(loc, Method_type_mismatch (lab, trace)))
|
||||
end
|
||||
|
||||
let type_constraint val_env sty sty' loc =
|
||||
let ty = transl_simple_type val_env false sty in
|
||||
let ty' = transl_simple_type val_env false sty' in
|
||||
|
@ -279,11 +292,11 @@ let rec class_type_field env self_type meths (val_sig, concr_meths) =
|
|||
(Vars.add lab (mut, ty) val_sig, concr_meths)
|
||||
|
||||
| Pctf_virt (lab, priv, sty, loc) ->
|
||||
virtual_method env meths self_type lab priv sty loc;
|
||||
declare_method env meths self_type lab priv sty loc;
|
||||
(val_sig, concr_meths)
|
||||
|
||||
| Pctf_meth (lab, priv, sty, loc) ->
|
||||
virtual_method env meths self_type lab priv sty loc;
|
||||
declare_method env meths self_type lab priv sty loc;
|
||||
(val_sig, Concr.add lab concr_meths)
|
||||
|
||||
| Pctf_cstr (sty, sty', loc) ->
|
||||
|
@ -399,10 +412,15 @@ let rec class_field cl_num self_type meths vars
|
|||
| Pcf_val (lab, mut, sexp, loc) ->
|
||||
if StringSet.mem lab inh_vals then
|
||||
Location.prerr_warning loc (Warnings.Hide_instance_variable lab);
|
||||
if !Clflags.principal then Ctype.begin_def ();
|
||||
let exp =
|
||||
try type_exp val_env sexp with Ctype.Unify [(ty, _)] ->
|
||||
raise(Error(loc, Make_nongen_seltype ty))
|
||||
in
|
||||
if !Clflags.principal then begin
|
||||
Ctype.end_def ();
|
||||
Ctype.generalize_structure exp.exp_type
|
||||
end;
|
||||
let (id, val_env, met_env, par_env) =
|
||||
enter_val cl_num vars lab mut exp.exp_type val_env met_env par_env
|
||||
in
|
||||
|
@ -414,23 +432,38 @@ let rec class_field cl_num self_type meths vars
|
|||
(val_env, met_env, par_env, fields, concr_meths, inh_vals)
|
||||
|
||||
| Pcf_meth (lab, priv, expr, loc) ->
|
||||
let meth_expr = make_method cl_num expr in
|
||||
Ctype.raise_nongen_level ();
|
||||
let (_, ty) =
|
||||
Ctype.filter_self_method val_env lab priv meths self_type
|
||||
in
|
||||
let meth_type = Ctype.newvar () in
|
||||
let (obj_ty, res_ty) = Ctype.filter_arrow val_env meth_type "" in
|
||||
Ctype.unify val_env obj_ty self_type;
|
||||
Ctype.unify val_env res_ty ty;
|
||||
let ty' = type_approx met_env expr in
|
||||
begin try Ctype.unify met_env ty' res_ty with Ctype.Unify trace ->
|
||||
raise(Typecore.Error(expr.pexp_loc, Expr_type_clash(trace)))
|
||||
begin try match expr.pexp_desc with
|
||||
Pexp_poly (sbody, sty) ->
|
||||
begin match sty with None -> ()
|
||||
| Some sty ->
|
||||
Ctype.unify val_env
|
||||
(Typetexp.transl_simple_type val_env false sty) ty
|
||||
end;
|
||||
begin match (Ctype.repr ty).desc with
|
||||
Tvar ->
|
||||
let ty' = Ctype.newvar () in
|
||||
Ctype.unify val_env (Ctype.newty (Tpoly (ty', []))) ty;
|
||||
Ctype.unify val_env (type_approx val_env sbody) ty'
|
||||
| Tpoly (ty1, tl) ->
|
||||
let _, ty1' = Ctype.instance_poly false tl ty1 in
|
||||
let ty2 = type_approx val_env sbody in
|
||||
Ctype.unify val_env ty2 ty1'
|
||||
| _ -> assert false
|
||||
end
|
||||
| _ -> assert false
|
||||
with Ctype.Unify trace ->
|
||||
raise(Error(loc, Method_type_mismatch (lab, trace)))
|
||||
end;
|
||||
Ctype.end_def ();
|
||||
let meth_expr = make_method cl_num expr in
|
||||
let vars_local = !vars in
|
||||
|
||||
let field =
|
||||
lazy begin
|
||||
let meth_type =
|
||||
Ctype.newty (Tarrow("", self_type, Ctype.instance ty, Cok)) in
|
||||
Ctype.raise_nongen_level ();
|
||||
vars := vars_local;
|
||||
let texp = type_expect met_env meth_expr meth_type in
|
||||
|
@ -480,10 +513,9 @@ let rec class_field cl_num self_type meths vars
|
|||
let field =
|
||||
lazy begin
|
||||
Ctype.raise_nongen_level ();
|
||||
let meth_type = Ctype.newvar () in
|
||||
let (obj_ty, res_ty) = Ctype.filter_arrow val_env meth_type "" in
|
||||
Ctype.unify val_env obj_ty self_type;
|
||||
Ctype.unify val_env res_ty (Ctype.instance Predef.type_unit);
|
||||
let meth_type =
|
||||
Ctype.newty
|
||||
(Tarrow ("", self_type, Ctype.instance Predef.type_unit, Cok)) in
|
||||
vars := vars_local;
|
||||
let texp = type_expect met_env expr meth_type in
|
||||
Ctype.end_def ();
|
||||
|
@ -518,9 +550,16 @@ and class_structure cl_num val_env met_env (spat, str) =
|
|||
(val_env, meth_env, par_env, [], Concr.empty, StringSet.empty)
|
||||
str
|
||||
in
|
||||
Ctype.unify val_env self_type (Ctype.newvar ());
|
||||
let methods =
|
||||
if !Clflags.principal then
|
||||
fst (Ctype.flatten_fields (Ctype.object_fields self_type))
|
||||
else [] in
|
||||
List.iter (fun (_,_,ty) -> Ctype.generalize_spine ty) methods;
|
||||
let vars_final = !vars in
|
||||
let fields = List.map Lazy.force (List.rev fields) in
|
||||
vars := vars_final;
|
||||
List.iter (fun (_,_,ty) -> Ctype.unify val_env ty (Ctype.newvar ())) methods;
|
||||
|
||||
{cl_field = fields;
|
||||
cl_meths = Meths.map (function (id, ty) -> id) !meths},
|
||||
|
@ -592,10 +631,15 @@ and class_expr cl_num val_env met_env scl =
|
|||
Pcl_let(Default, [spat, smatch], sbody)})}
|
||||
in
|
||||
class_expr cl_num val_env met_env sfun
|
||||
| Pcl_fun (l, _, spat, scl') ->
|
||||
| Pcl_fun (l, None, spat, scl') ->
|
||||
if !Clflags.principal then Ctype.begin_def ();
|
||||
let (pat, pv, val_env, met_env) =
|
||||
Typecore.type_class_arg_pattern cl_num val_env met_env l spat
|
||||
in
|
||||
if !Clflags.principal then begin
|
||||
Ctype.end_def ();
|
||||
iter_pattern (fun {pat_type=ty} -> Ctype.generalize_structure ty) pat
|
||||
end;
|
||||
let pv =
|
||||
List.map
|
||||
(function (id, id', ty) ->
|
||||
|
@ -625,7 +669,7 @@ and class_expr cl_num val_env met_env scl =
|
|||
(Warnings.Other "This optional argument cannot be erased");
|
||||
{cl_desc = Tclass_fun (pat, pv, cl, partial);
|
||||
cl_loc = scl.pcl_loc;
|
||||
cl_type = Tcty_fun (l, pat.pat_type, cl.cl_type)}
|
||||
cl_type = Tcty_fun (l, Ctype.instance pat.pat_type, cl.cl_type)}
|
||||
| Pcl_apply (scl', sargs) ->
|
||||
let cl = class_expr cl_num val_env met_env scl' in
|
||||
let rec nonopt_labels ls ty_fun =
|
||||
|
@ -826,6 +870,7 @@ let rec initial_env define_class approx
|
|||
|
||||
(* Temporary type for the class constructor *)
|
||||
let constr_type = approx cl.pci_expr in
|
||||
if !Clflags.principal then Ctype.generalize_spine constr_type;
|
||||
let dummy_cty =
|
||||
Tcty_signature
|
||||
{ cty_self = Ctype.newvar ();
|
||||
|
@ -948,7 +993,9 @@ let class_infos define_class kind
|
|||
|
||||
(* Type of the class constructor *)
|
||||
begin try
|
||||
Ctype.unify env (constructor_type constr obj_type) constr_type
|
||||
Ctype.unify env
|
||||
(constructor_type constr obj_type)
|
||||
(Ctype.instance constr_type)
|
||||
with Ctype.Unify trace ->
|
||||
raise(Error(cl.pci_loc,
|
||||
Constructor_type_mismatch (cl.pci_name, trace)))
|
||||
|
@ -998,7 +1045,7 @@ let class_infos define_class kind
|
|||
cty_new =
|
||||
match cl.pci_virt with
|
||||
Virtual -> None
|
||||
| Concrete -> Some constr_type}
|
||||
| Concrete -> Some (Ctype.instance constr_type)}
|
||||
in
|
||||
let obj_abbr =
|
||||
{type_params = obj_params;
|
||||
|
|
|
@ -55,6 +55,7 @@ type error =
|
|||
| Masked_instance_variable of Longident.t
|
||||
| Not_a_variant_type of Longident.t
|
||||
| Incoherent_label_order
|
||||
| Less_general of string * (type_expr * type_expr) list
|
||||
|
||||
exception Error of Location.t * error
|
||||
|
||||
|
@ -177,18 +178,19 @@ let rec build_as_type env p =
|
|||
| Tpat_variant(l, p', _) ->
|
||||
let ty = may_map (build_as_type env) p' in
|
||||
newty (Tvariant{row_fields=[l, Rpresent ty]; row_more=newvar();
|
||||
row_bound=[]; row_name=None; row_closed=false})
|
||||
row_bound=[]; row_name=None;
|
||||
row_fixed=false; row_closed=false})
|
||||
| Tpat_record lpl ->
|
||||
let lbl = fst(List.hd lpl) in
|
||||
let ty = newvar () in
|
||||
let do_label lbl =
|
||||
let ty_arg, ty_res = instance_label lbl in
|
||||
let _, ty_arg, ty_res = instance_label false lbl in
|
||||
unify_pat env {p with pat_type = ty} ty_res;
|
||||
if lbl.lbl_mut = Immutable && List.mem_assoc lbl lpl then begin
|
||||
let arg = List.assoc lbl lpl in
|
||||
unify_pat env {arg with pat_type = build_as_type env arg} ty_arg
|
||||
end else begin
|
||||
let ty_arg', ty_res' = instance_label lbl in
|
||||
let _, ty_arg', ty_res' = instance_label false lbl in
|
||||
unify env ty_arg ty_arg';
|
||||
unify_pat env p ty_res'
|
||||
end in
|
||||
|
@ -242,7 +244,7 @@ let build_or_pat env loc lid =
|
|||
([],[]) fields in
|
||||
let row =
|
||||
{ row_fields = List.rev fields; row_more = newvar(); row_bound = !bound;
|
||||
row_closed = false; row_name = Some (path, tyl) }
|
||||
row_closed = false; row_fixed = false; row_name = Some (path, tyl) }
|
||||
in
|
||||
let ty = newty (Tvariant row) in
|
||||
let pats =
|
||||
|
@ -326,6 +328,7 @@ let rec type_pat env sp =
|
|||
row_bound = arg_type;
|
||||
row_closed = false;
|
||||
row_more = newvar ();
|
||||
row_fixed = false;
|
||||
row_name = None } in
|
||||
{ pat_desc = Tpat_variant(l, arg, row);
|
||||
pat_loc = sp.ppat_loc;
|
||||
|
@ -346,7 +349,7 @@ let rec type_pat env sp =
|
|||
Env.lookup_label lid env
|
||||
with Not_found ->
|
||||
raise(Error(sp.ppat_loc, Unbound_label lid)) in
|
||||
let (ty_arg, ty_res) = instance_label label in
|
||||
let (_, ty_arg, ty_res) = instance_label false label in
|
||||
begin try
|
||||
unify env ty_res ty
|
||||
with Unify trace ->
|
||||
|
@ -470,7 +473,7 @@ let check_unused_variant pat =
|
|||
begin match opat with None -> assert false
|
||||
| Some pat -> List.iter (unify_pat pat.pat_env pat) (ty::tl)
|
||||
end
|
||||
| Reither (c, l, true, e) ->
|
||||
| Reither (c, l, true, e) when not row.row_fixed ->
|
||||
e := Some (Reither (c, [], false, ref None))
|
||||
| _ -> ()
|
||||
end
|
||||
|
@ -675,6 +678,23 @@ let rec list_labels_aux env visited ls ty_fun =
|
|||
|
||||
let list_labels env ty = list_labels_aux env [] [] ty
|
||||
|
||||
(* Check that all univars are safe in a type *)
|
||||
let check_univars env kind exp ty_expected vars =
|
||||
let vars' =
|
||||
List.filter
|
||||
(fun t ->
|
||||
let t = repr t in
|
||||
generalize t;
|
||||
if t.desc = Tvar && t.level = generic_level then
|
||||
(t.desc <- Tunivar; true)
|
||||
else false)
|
||||
vars in
|
||||
if List.length vars = List.length vars' then () else
|
||||
let ty = newgenty (Tpoly(repr exp.exp_type, vars'))
|
||||
and ty_expected = repr ty_expected in
|
||||
raise (Error (exp.exp_loc,
|
||||
Less_general(kind, [ty, ty; ty_expected, ty_expected])))
|
||||
|
||||
(* Hack to allow coercion of self. Will clean-up later. *)
|
||||
let self_coercion = ref ([] : (Path.t * Location.t list ref) list)
|
||||
|
||||
|
@ -732,8 +752,14 @@ let rec type_exp env sexp =
|
|||
| Pexp_function _ -> (* defined in type_expect *)
|
||||
type_expect env sexp (newvar())
|
||||
| Pexp_apply(sfunct, sargs) ->
|
||||
if !Clflags.principal then begin_def ();
|
||||
let funct = type_exp env sfunct in
|
||||
if !Clflags.principal then begin
|
||||
end_def ();
|
||||
generalize_structure funct.exp_type
|
||||
end;
|
||||
let (args, ty_res) = type_application env funct sargs in
|
||||
let funct = {funct with exp_type = instance funct.exp_type} in
|
||||
{ exp_desc = Texp_apply(funct, args);
|
||||
exp_loc = sexp.pexp_loc;
|
||||
exp_type = ty_res;
|
||||
|
@ -773,6 +799,7 @@ let rec type_exp env sexp =
|
|||
row_more = newvar ();
|
||||
row_bound = [];
|
||||
row_closed = false;
|
||||
row_fixed = false;
|
||||
row_name = None});
|
||||
exp_env = env }
|
||||
| Pexp_record(lid_sexp_list, opt_sexp) ->
|
||||
|
@ -784,13 +811,22 @@ let rec type_exp env sexp =
|
|||
Env.lookup_label lid env
|
||||
with Not_found ->
|
||||
raise(Error(sexp.pexp_loc, Unbound_label lid)) in
|
||||
let (ty_arg, ty_res) = instance_label label in
|
||||
begin_def ();
|
||||
if !Clflags.principal then begin_def ();
|
||||
let (vars, ty_arg, ty_res) = instance_label true label in
|
||||
if !Clflags.principal then begin
|
||||
end_def ();
|
||||
generalize_structure ty_arg;
|
||||
generalize_structure ty_res
|
||||
end;
|
||||
begin try
|
||||
unify env ty_res ty
|
||||
unify env (instance ty_res) ty
|
||||
with Unify trace ->
|
||||
raise(Error(sexp.pexp_loc, Label_mismatch(lid, trace)))
|
||||
end;
|
||||
let arg = type_expect env sarg ty_arg in
|
||||
let arg = type_argument env sarg ty_arg in
|
||||
end_def ();
|
||||
check_univars env "field value" arg label.lbl_arg vars;
|
||||
num_fields := Array.length label.lbl_all;
|
||||
(label, arg) in
|
||||
let lbl_exp_list = List.map type_label_exp lid_sexp_list in
|
||||
|
@ -810,8 +846,8 @@ let rec type_exp env sexp =
|
|||
if List.for_all (fun (lbl',_) -> lbl'.lbl_pos <> lbl.lbl_pos)
|
||||
lbl_exp_list
|
||||
then begin
|
||||
let ty_arg1, ty_res1 = instance_label lbl
|
||||
and ty_arg2, ty_res2 = instance_label lbl in
|
||||
let _, ty_arg1, ty_res1 = instance_label false lbl
|
||||
and _, ty_arg2, ty_res2 = instance_label false lbl in
|
||||
unify env ty_exp ty_res1;
|
||||
unify env ty ty_res2;
|
||||
unify env ty_arg1 ty_arg2
|
||||
|
@ -844,7 +880,7 @@ let rec type_exp env sexp =
|
|||
Env.lookup_label lid env
|
||||
with Not_found ->
|
||||
raise(Error(sexp.pexp_loc, Unbound_label lid)) in
|
||||
let (ty_arg, ty_res) = instance_label label in
|
||||
let (_, ty_arg, ty_res) = instance_label false label in
|
||||
unify_exp env arg ty_res;
|
||||
{ exp_desc = Texp_field(arg, label);
|
||||
exp_loc = sexp.pexp_loc;
|
||||
|
@ -859,9 +895,12 @@ let rec type_exp env sexp =
|
|||
raise(Error(sexp.pexp_loc, Unbound_label lid)) in
|
||||
if label.lbl_mut = Immutable then
|
||||
raise(Error(sexp.pexp_loc, Label_not_mutable lid));
|
||||
let (ty_arg, ty_res) = instance_label label in
|
||||
begin_def ();
|
||||
let (vars, ty_arg, ty_res) = instance_label true label in
|
||||
unify_exp env record ty_res;
|
||||
let newval = type_expect env snewval ty_arg in
|
||||
end_def ();
|
||||
check_univars env "field value" newval label.lbl_arg vars;
|
||||
{ exp_desc = Texp_setfield(record, label, newval);
|
||||
exp_loc = sexp.pexp_loc;
|
||||
exp_type = instance Predef.type_unit;
|
||||
|
@ -922,8 +961,15 @@ let rec type_exp env sexp =
|
|||
let arg = type_exp env sarg in
|
||||
(arg, arg.exp_type)
|
||||
| (Some sty, None) ->
|
||||
if !Clflags.principal then begin_def ();
|
||||
let ty = Typetexp.transl_simple_type env false sty in
|
||||
(type_expect env sarg ty, ty)
|
||||
if !Clflags.principal then begin
|
||||
end_def ();
|
||||
generalize_structure ty;
|
||||
let ty1 = instance ty and ty2 = instance ty in
|
||||
(type_expect env sarg ty1, ty2)
|
||||
end else
|
||||
(type_expect env sarg ty, ty)
|
||||
| (None, Some sty') ->
|
||||
let (ty', force) =
|
||||
Typetexp.transl_simple_type_delayed env sty'
|
||||
|
@ -969,6 +1015,7 @@ let rec type_exp env sexp =
|
|||
exp_type = body.exp_type;
|
||||
exp_env = env }
|
||||
| Pexp_send (e, met) ->
|
||||
if !Clflags.principal then begin_def ();
|
||||
let obj = type_exp env e in
|
||||
begin try
|
||||
let (exp, typ) =
|
||||
|
@ -996,7 +1043,7 @@ let rec type_exp env sexp =
|
|||
let method_type = newvar () in
|
||||
let (obj_ty, res_ty) = filter_arrow env method_type "" in
|
||||
unify env obj_ty desc.val_type;
|
||||
unify env res_ty typ;
|
||||
unify env res_ty (instance typ);
|
||||
(Texp_apply({exp_desc = Texp_ident(Path.Pident method_id,
|
||||
{val_type = method_type;
|
||||
val_kind = Val_reg});
|
||||
|
@ -1015,6 +1062,29 @@ let rec type_exp env sexp =
|
|||
| _ ->
|
||||
(Texp_send(obj, Tmeth_name met),
|
||||
filter_method env met Public obj.exp_type)
|
||||
in
|
||||
if !Clflags.principal then begin
|
||||
end_def ();
|
||||
generalize_structure typ;
|
||||
end;
|
||||
let typ =
|
||||
match repr typ with
|
||||
{desc = Tpoly (ty, [])} ->
|
||||
instance ty
|
||||
| {desc = Tpoly (ty, tl); level = l} ->
|
||||
if !Clflags.principal && l <> generic_level then
|
||||
Location.prerr_warning sexp.pexp_loc
|
||||
(Warnings.Other
|
||||
"This use of a polymorphic method is not principal");
|
||||
snd (instance_poly false tl ty)
|
||||
| {desc = Tvar} as ty ->
|
||||
let ty' = newvar () in
|
||||
unify env (instance ty) (newty(Tpoly(ty',[])));
|
||||
(* if not !Clflags.nolabels then
|
||||
Location.prerr_warning loc (Warnings.Unknown_method met); *)
|
||||
ty'
|
||||
| _ ->
|
||||
assert false
|
||||
in
|
||||
{ exp_desc = exp;
|
||||
exp_loc = sexp.pexp_loc;
|
||||
|
@ -1042,7 +1112,7 @@ let rec type_exp env sexp =
|
|||
let (path, desc) = Env.lookup_value (Longident.Lident lab) env in
|
||||
match desc.val_kind with
|
||||
Val_ivar (Mutable, cl_num) ->
|
||||
let newval = type_expect env snewval desc.val_type in
|
||||
let newval = type_expect env snewval (instance desc.val_type) in
|
||||
let (path_self, _) =
|
||||
Env.lookup_value (Longident.Lident ("self-" ^ cl_num)) env
|
||||
in
|
||||
|
@ -1080,7 +1150,7 @@ let rec type_exp env sexp =
|
|||
let type_override (lab, snewval) =
|
||||
begin try
|
||||
let (id, _, ty) = Vars.find lab !vars in
|
||||
(Path.Pident id, type_expect env snewval ty)
|
||||
(Path.Pident id, type_expect env snewval (instance ty))
|
||||
with
|
||||
Not_found ->
|
||||
raise(Error(sexp.pexp_loc, Unbound_instance_variable lab))
|
||||
|
@ -1138,31 +1208,45 @@ let rec type_exp env sexp =
|
|||
exp_type = instance (Predef.type_lazy_t arg.exp_type);
|
||||
exp_env = env;
|
||||
}
|
||||
| Pexp_poly _ ->
|
||||
assert false
|
||||
|
||||
and type_argument env sarg ty_expected =
|
||||
and type_argument env sarg ty_expected' =
|
||||
(* ty_expected' may be generic *)
|
||||
let no_labels ty =
|
||||
let ls, tvar = list_labels env ty in
|
||||
not tvar && List.for_all ((=) "") ls
|
||||
in
|
||||
match expand_head env ty_expected, sarg with
|
||||
let ty_expected = instance ty_expected' in
|
||||
match expand_head env ty_expected', sarg with
|
||||
| _, {pexp_desc = Pexp_function(l,_,_)} when not (is_optional l) ->
|
||||
type_expect env sarg ty_expected
|
||||
| {desc = Tarrow("",ty_arg,ty_res,_)}, _ ->
|
||||
| {desc = Tarrow("",ty_arg,ty_res,_); level = lv}, _ ->
|
||||
(* apply optional arguments when expected type is "" *)
|
||||
(* we must be very careful about not breaking the semantics *)
|
||||
if !Clflags.principal then begin_def ();
|
||||
let texp = type_exp env sarg in
|
||||
if !Clflags.principal then begin
|
||||
end_def ();
|
||||
generalize_structure texp.exp_type
|
||||
end;
|
||||
let rec make_args args ty_fun =
|
||||
match (expand_head env ty_fun).desc with
|
||||
| Tarrow (l,ty_arg,ty_fun,_) when is_optional l ->
|
||||
make_args
|
||||
((Some(option_none ty_arg sarg.pexp_loc), Optional) :: args)
|
||||
((Some(option_none (instance ty_arg) sarg.pexp_loc), Optional)
|
||||
:: args)
|
||||
ty_fun
|
||||
| Tarrow (l,_,ty_res',_) when l = "" || !Clflags.classic ->
|
||||
args, ty_fun, no_labels ty_res'
|
||||
| Tvar -> args, ty_fun, false
|
||||
| _ -> [], texp.exp_type, false
|
||||
in
|
||||
let args, ty_fun, simple_res = make_args [] texp.exp_type in
|
||||
let args, ty_fun', simple_res = make_args [] texp.exp_type in
|
||||
let warn = !Clflags.principal &&
|
||||
(lv <> generic_level || (repr ty_fun').level <> generic_level)
|
||||
and texp = {texp with exp_type = instance texp.exp_type}
|
||||
and ty_fun = instance ty_fun' in
|
||||
if not (simple_res || no_labels ty_res) then begin
|
||||
unify_exp env texp ty_expected;
|
||||
texp
|
||||
|
@ -1184,6 +1268,8 @@ and type_argument env sarg ty_expected =
|
|||
Texp_apply (texp, args@
|
||||
[Some eta_var, Required])}],
|
||||
Total) } in
|
||||
if warn then Location.prerr_warning texp.exp_loc
|
||||
(Warnings.Other "Eliminated optional argument without principality");
|
||||
if is_nonexpansive texp then func texp else
|
||||
(* let-expand to have side effects *)
|
||||
let let_pat, let_var = var_pair "let" texp.exp_type in
|
||||
|
@ -1194,6 +1280,7 @@ and type_argument env sarg ty_expected =
|
|||
type_expect env sarg ty_expected
|
||||
|
||||
and type_application env funct sargs =
|
||||
(* funct.exp_type may be generic *)
|
||||
let result_type omitted ty_fun =
|
||||
List.fold_left
|
||||
(fun ty_fun (l,ty,lv) -> newty2 lv (Tarrow(l,ty,ty_fun,Cok)))
|
||||
|
@ -1209,7 +1296,7 @@ and type_application env funct sargs =
|
|||
(List.map
|
||||
(function None, x -> None, x | Some f, x -> Some (f ()), x)
|
||||
(List.rev args),
|
||||
result_type omitted ty_fun)
|
||||
instance (result_type omitted ty_fun))
|
||||
| (l1, sarg1) :: sargl ->
|
||||
let (ty1, ty2) =
|
||||
match (expand_head env ty_fun).desc with
|
||||
|
@ -1256,10 +1343,18 @@ and type_application env funct sargs =
|
|||
true)
|
||||
end
|
||||
in
|
||||
let warned = ref false in
|
||||
let rec type_args args omitted ty_fun ty_old sargs more_sargs =
|
||||
match expand_head env ty_fun with
|
||||
{desc=Tarrow (l, ty, ty_fun, com); level=lv} as ty_fun'
|
||||
when (sargs <> [] || more_sargs <> []) && commu_repr com = Cok ->
|
||||
let may_warn loc msg =
|
||||
if not !warned && !Clflags.principal && lv <> generic_level
|
||||
then begin
|
||||
warned := true;
|
||||
Location.prerr_warning loc (Warnings.Other msg)
|
||||
end
|
||||
in
|
||||
let name = label_name l
|
||||
and optional = if is_optional l then Optional else Required in
|
||||
let sargs, more_sargs, arg =
|
||||
|
@ -1278,28 +1373,45 @@ and type_application env funct sargs =
|
|||
end else try
|
||||
let (l', sarg0, sargs, more_sargs) =
|
||||
try
|
||||
let (l', sarg0, sargs1, sargs2) = extract_label name sargs
|
||||
in (l', sarg0, sargs1 @ sargs2, more_sargs)
|
||||
let (l', sarg0, sargs1, sargs2) = extract_label name sargs in
|
||||
if sargs1 <> [] then
|
||||
may_warn sarg0.pexp_loc
|
||||
"Commuting this argument is not principal";
|
||||
(l', sarg0, sargs1 @ sargs2, more_sargs)
|
||||
with Not_found ->
|
||||
let (l', sarg0, sargs1, sargs2) = extract_label name more_sargs
|
||||
in (l', sarg0, sargs @ sargs1, sargs2)
|
||||
let (l', sarg0, sargs1, sargs2) =
|
||||
extract_label name more_sargs in
|
||||
if sargs1 <> [] || sargs <> [] then
|
||||
may_warn sarg0.pexp_loc
|
||||
"Commuting this argument is not principal";
|
||||
(l', sarg0, sargs @ sargs1, sargs2)
|
||||
in
|
||||
sargs, more_sargs,
|
||||
if optional = Required || is_optional l' then
|
||||
Some (fun () -> type_argument env sarg0 ty)
|
||||
else
|
||||
else begin
|
||||
may_warn sarg0.pexp_loc
|
||||
"Using an optional argument here is not principal";
|
||||
Some (fun () -> option_some (type_argument env sarg0
|
||||
(extract_option_type env ty)))
|
||||
end
|
||||
with Not_found ->
|
||||
sargs, more_sargs,
|
||||
if optional = Optional &&
|
||||
(List.mem_assoc "" sargs || List.mem_assoc "" more_sargs)
|
||||
then begin
|
||||
may_warn funct.exp_loc
|
||||
"Eliminated an optional argument without principality";
|
||||
ignored := (l,ty,lv) :: !ignored;
|
||||
Some (fun () -> option_none ty Location.none)
|
||||
end else None
|
||||
Some (fun () -> option_none (instance ty) Location.none)
|
||||
end else begin
|
||||
may_warn funct.exp_loc
|
||||
"Commuted an argument without principality";
|
||||
None
|
||||
end
|
||||
in
|
||||
let omitted = if arg = None then (l,ty,lv) :: omitted else omitted in
|
||||
let omitted =
|
||||
if arg = None then (l,ty,lv) :: omitted else omitted in
|
||||
let ty_old = if sargs = [] then ty_fun else ty_old in
|
||||
type_args ((arg,optional)::args) omitted ty_fun ty_old sargs more_sargs
|
||||
| _ ->
|
||||
|
@ -1307,13 +1419,14 @@ and type_application env funct sargs =
|
|||
(l, sarg0) :: _ when ignore_labels ->
|
||||
raise(Error(sarg0.pexp_loc, Apply_wrong_label(l, ty_old)));
|
||||
| _ ->
|
||||
type_unknown_args args omitted ty_fun (sargs @ more_sargs)
|
||||
type_unknown_args args omitted (instance ty_fun)
|
||||
(sargs @ more_sargs)
|
||||
in
|
||||
match funct.exp_desc, sargs with
|
||||
(* Special case for ignore: avoid discarding warning *)
|
||||
Texp_ident (_, {val_kind=Val_prim{Primitive.prim_name="%ignore"}}),
|
||||
["", sarg] ->
|
||||
let ty_arg, ty_res = filter_arrow env funct.exp_type "" in
|
||||
let ty_arg, ty_res = filter_arrow env (instance funct.exp_type) "" in
|
||||
let exp = type_expect env sarg ty_arg in
|
||||
begin match expand_head env exp.exp_type with
|
||||
| {desc = Tarrow _} ->
|
||||
|
@ -1343,14 +1456,20 @@ and type_construct env loc lid sarg explicit_arity ty_expected =
|
|||
if List.length sargs <> constr.cstr_arity then
|
||||
raise(Error(loc, Constructor_arity_mismatch
|
||||
(lid, constr.cstr_arity, List.length sargs)));
|
||||
if !Clflags.principal then begin_def ();
|
||||
let (ty_args, ty_res) = instance_constructor constr in
|
||||
if !Clflags.principal then begin
|
||||
end_def ();
|
||||
List.iter generalize_structure ty_args;
|
||||
generalize_structure ty_res
|
||||
end;
|
||||
let texp =
|
||||
{ exp_desc = Texp_construct(constr, []);
|
||||
exp_loc = loc;
|
||||
exp_type = ty_res;
|
||||
exp_type = instance ty_res;
|
||||
exp_env = env } in
|
||||
unify_exp env texp ty_expected;
|
||||
let args = List.map2 (type_expect env) sargs ty_args in
|
||||
let args = List.map2 (type_argument env) sargs ty_args in
|
||||
{ texp with exp_desc = Texp_construct(constr, args) }
|
||||
|
||||
(* Typing of an expression with an expected type.
|
||||
|
@ -1444,6 +1563,34 @@ and type_expect ?in_function env sexp ty_expected =
|
|||
exp_loc = sexp.pexp_loc;
|
||||
exp_type = newty (Tarrow(l, ty_arg, ty_res, Cok));
|
||||
exp_env = env }
|
||||
| Pexp_poly(sbody, sty) ->
|
||||
let ty =
|
||||
match sty with None -> repr ty_expected
|
||||
| Some sty ->
|
||||
let ty = Typetexp.transl_simple_type env false sty in
|
||||
repr ty
|
||||
in
|
||||
let set_type ty =
|
||||
unify_exp env
|
||||
{ exp_desc = Texp_tuple []; exp_loc = sexp.pexp_loc;
|
||||
exp_type = ty; exp_env = env } ty_expected in
|
||||
begin
|
||||
match ty.desc with
|
||||
Tpoly (ty', []) ->
|
||||
if sty <> None then set_type ty;
|
||||
let exp = type_expect env sbody ty' in
|
||||
{ exp with exp_type = ty }
|
||||
| Tpoly (ty', tl) ->
|
||||
if sty <> None then set_type ty;
|
||||
(* One more level to generalize locally *)
|
||||
begin_def ();
|
||||
let vars, ty'' = instance_poly true tl ty' in
|
||||
let exp = type_expect env sbody ty'' in
|
||||
end_def ();
|
||||
check_univars env "method" exp ty_expected vars;
|
||||
{ exp with exp_type = ty }
|
||||
| _ -> assert false
|
||||
end
|
||||
| _ ->
|
||||
let exp = type_exp env sexp in
|
||||
unify_exp env exp ty_expected;
|
||||
|
@ -1470,7 +1617,15 @@ and type_cases ?in_function env ty_arg ty_res partial_loc caselist =
|
|||
let pat_env_list =
|
||||
List.map
|
||||
(fun (spat, sexp) ->
|
||||
if !Clflags.principal then begin_def ();
|
||||
let (pat, ext_env) = type_pattern env spat in
|
||||
let pat =
|
||||
if !Clflags.principal then begin
|
||||
end_def ();
|
||||
iter_pattern (fun {pat_type=t} -> generalize_structure t) pat;
|
||||
{ pat with pat_type = instance pat.pat_type }
|
||||
end else pat
|
||||
in
|
||||
unify_pat env pat ty_arg';
|
||||
(pat, ext_env))
|
||||
caselist in
|
||||
|
@ -1509,6 +1664,7 @@ and type_cases ?in_function env ty_arg ty_res partial_loc caselist =
|
|||
|
||||
and type_let env rec_flag spat_sexp_list =
|
||||
begin_def();
|
||||
if !Clflags.principal then begin_def ();
|
||||
let (pat_list, new_env) =
|
||||
type_pattern_list env (List.map (fun (spat, sexp) -> spat) spat_sexp_list)
|
||||
in
|
||||
|
@ -1516,6 +1672,15 @@ and type_let env rec_flag spat_sexp_list =
|
|||
List.iter2
|
||||
(fun pat (_, sexp) -> unify_pat env pat (type_approx env sexp))
|
||||
pat_list spat_sexp_list;
|
||||
let pat_list =
|
||||
if !Clflags.principal then begin
|
||||
end_def ();
|
||||
List.map
|
||||
(fun pat ->
|
||||
iter_pattern (fun pat -> generalize_structure pat.pat_type) pat;
|
||||
{pat with pat_type = instance pat.pat_type})
|
||||
pat_list
|
||||
end else pat_list in
|
||||
let exp_env =
|
||||
match rec_flag with Nonrecursive | Default -> env | Recursive -> new_env in
|
||||
let exp_list =
|
||||
|
@ -1529,7 +1694,9 @@ and type_let env rec_flag spat_sexp_list =
|
|||
List.iter2
|
||||
(fun pat exp ->
|
||||
if not (is_nonexpansive exp) then
|
||||
iter_pattern (fun pat -> make_nongen pat.pat_type) pat)
|
||||
let f =
|
||||
if !Clflags.principal then generalize_expansive else make_nongen in
|
||||
iter_pattern (fun pat -> f pat.pat_type) pat)
|
||||
pat_list exp_list;
|
||||
List.iter
|
||||
(fun pat -> iter_pattern (fun pat -> generalize pat.pat_type) pat)
|
||||
|
@ -1550,6 +1717,7 @@ let type_expression env sexp =
|
|||
let exp = type_exp env sexp in
|
||||
end_def();
|
||||
if is_nonexpansive exp then generalize exp.exp_type
|
||||
else if !Clflags.principal then generalize_expansive exp.exp_type
|
||||
else make_nongen exp.exp_type;
|
||||
exp
|
||||
|
||||
|
@ -1690,3 +1858,7 @@ let report_error ppf = function
|
|||
fprintf ppf "This function is applied to arguments@ ";
|
||||
fprintf ppf "in an order different from other calls.@ ";
|
||||
fprintf ppf "This is only allowed when the real type is known."
|
||||
| Less_general (kind, trace) ->
|
||||
report_unification_error ppf trace
|
||||
(fun ppf -> fprintf ppf "This %s has type" kind)
|
||||
(fun ppf -> fprintf ppf "which is less general than")
|
||||
|
|
|
@ -53,6 +53,7 @@ val type_argument:
|
|||
val option_some: Typedtree.expression -> Typedtree.expression
|
||||
val option_none: type_expr -> Location.t -> Typedtree.expression
|
||||
val extract_option_type: Env.t -> type_expr -> type_expr
|
||||
val iter_pattern: (Typedtree.pattern -> unit) -> Typedtree.pattern -> unit
|
||||
|
||||
val self_coercion : (Path.t * Location.t list ref) list ref
|
||||
|
||||
|
@ -88,6 +89,7 @@ type error =
|
|||
| Masked_instance_variable of Longident.t
|
||||
| Not_a_variant_type of Longident.t
|
||||
| Incoherent_label_order
|
||||
| Less_general of string * (type_expr * type_expr) list
|
||||
|
||||
exception Error of Location.t * error
|
||||
|
||||
|
|
|
@ -87,11 +87,18 @@ module StringSet =
|
|||
let transl_declaration env (name, sdecl) id =
|
||||
(* Bind type parameters *)
|
||||
reset_type_variables();
|
||||
Ctype.begin_def ();
|
||||
let params =
|
||||
try List.map (enter_type_variable true) sdecl.ptype_params
|
||||
with Already_bound ->
|
||||
raise(Error(sdecl.ptype_loc, Repeated_parameter))
|
||||
in
|
||||
let cstrs = List.map
|
||||
(fun (sty, sty', loc) ->
|
||||
transl_simple_type env false sty,
|
||||
transl_simple_type env false sty', loc)
|
||||
sdecl.ptype_cstrs
|
||||
in
|
||||
let decl =
|
||||
{ type_params = params;
|
||||
type_arity = List.length params;
|
||||
|
@ -125,7 +132,8 @@ let transl_declaration env (name, sdecl) id =
|
|||
let lbls' =
|
||||
List.map
|
||||
(fun (name, mut, arg) ->
|
||||
(name, mut, transl_simple_type env true arg))
|
||||
let ty = transl_simple_type env true arg in
|
||||
name, mut, match ty.desc with Tpoly(t,[]) -> t | _ -> ty)
|
||||
lbls in
|
||||
let rep =
|
||||
if List.for_all (fun (name, mut, arg) -> is_float env arg) lbls'
|
||||
|
@ -147,13 +155,11 @@ let transl_declaration env (name, sdecl) id =
|
|||
|
||||
(* Check constraints *)
|
||||
List.iter
|
||||
(function (sty, sty', loc) ->
|
||||
try
|
||||
Ctype.unify env (transl_simple_type env false sty)
|
||||
(transl_simple_type env false sty')
|
||||
with Ctype.Unify tr ->
|
||||
raise(Error(loc, Unconsistent_constraint tr)))
|
||||
sdecl.ptype_cstrs;
|
||||
(fun (ty, ty', loc) ->
|
||||
try Ctype.unify env ty ty' with Ctype.Unify tr ->
|
||||
raise(Error(loc, Unconsistent_constraint tr)))
|
||||
cstrs;
|
||||
Ctype.end_def ();
|
||||
|
||||
(id, decl)
|
||||
|
||||
|
@ -201,6 +207,9 @@ let rec check_constraints_rec env loc visited ty =
|
|||
if not (List.for_all2 (Ctype.moregeneral env false) args' args) then
|
||||
raise (Error(loc, Constraint_failed (ty, ty')));
|
||||
List.iter (check_constraints_rec env loc visited) args
|
||||
| Tpoly (ty, tl) ->
|
||||
let _, ty = Ctype.instance_poly false tl ty in
|
||||
check_constraints_rec env loc visited ty
|
||||
| _ ->
|
||||
Btype.iter_type_expr (check_constraints_rec env loc visited) ty
|
||||
end
|
||||
|
@ -376,7 +385,9 @@ let compute_variance env tvl nega posi ty =
|
|||
List.iter (compute_variance_rec posi nega) tyl
|
||||
| _ -> ())
|
||||
(Btype.row_repr row).row_fields
|
||||
| Tvar | Tnil | Tlink _ -> ()
|
||||
| Tpoly (ty, _) ->
|
||||
compute_variance_rec posi nega ty
|
||||
| Tvar | Tnil | Tlink _ | Tunivar -> ()
|
||||
end
|
||||
in
|
||||
compute_variance_rec nega posi ty;
|
||||
|
|
|
@ -35,12 +35,15 @@ and type_desc =
|
|||
| Tlink of type_expr
|
||||
| Tsubst of type_expr
|
||||
| Tvariant of row_desc
|
||||
| Tunivar
|
||||
| Tpoly of type_expr * type_expr list
|
||||
|
||||
and row_desc =
|
||||
{ row_fields: (label * row_field) list;
|
||||
row_more: type_expr;
|
||||
row_bound: type_expr list;
|
||||
row_closed: bool;
|
||||
row_fixed: bool;
|
||||
row_name: (Path.t * type_expr list) option }
|
||||
|
||||
and row_field =
|
||||
|
@ -63,6 +66,13 @@ and commutable =
|
|||
| Cunknown
|
||||
| Clink of commutable ref
|
||||
|
||||
module TypeOps = struct
|
||||
type t = type_expr
|
||||
let compare t1 t2 = t1.id - t2.id
|
||||
let hash t = t.id
|
||||
let equal t1 t2 = t1 == t2
|
||||
end
|
||||
|
||||
(* Maps of methods and instance variables *)
|
||||
|
||||
module OrderedString = struct type t = string let compare = compare end
|
||||
|
|
|
@ -34,12 +34,15 @@ and type_desc =
|
|||
| Tlink of type_expr
|
||||
| Tsubst of type_expr (* for copying *)
|
||||
| Tvariant of row_desc
|
||||
| Tunivar
|
||||
| Tpoly of type_expr * type_expr list
|
||||
|
||||
and row_desc =
|
||||
{ row_fields: (label * row_field) list;
|
||||
row_more: type_expr;
|
||||
row_bound: type_expr list;
|
||||
row_closed: bool;
|
||||
row_fixed: bool;
|
||||
row_name: (Path.t * type_expr list) option }
|
||||
|
||||
and row_field =
|
||||
|
@ -65,6 +68,13 @@ and commutable =
|
|||
| Cunknown
|
||||
| Clink of commutable ref
|
||||
|
||||
module TypeOps : sig
|
||||
type t = type_expr
|
||||
val compare : t -> t -> int
|
||||
val equal : t -> t -> bool
|
||||
val hash : t -> int
|
||||
end
|
||||
|
||||
(* Maps of methods and instance variables *)
|
||||
|
||||
module Meths : Map.S with type key = string
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
(* *)
|
||||
(***********************************************************************)
|
||||
|
||||
(* $Id$ *)
|
||||
(* typetexp.ml,v 1.34.4.9 2002/01/07 08:39:16 garrigue Exp *)
|
||||
|
||||
(* Typechecking of type expressions for the core language *)
|
||||
|
||||
|
@ -37,6 +37,8 @@ type error =
|
|||
| Constructor_mismatch of type_expr * type_expr
|
||||
| Not_a_variant of type_expr
|
||||
| Variant_tags of string * string
|
||||
| No_row_variable of string
|
||||
| Bad_alias of string
|
||||
|
||||
exception Error of Location.t * error
|
||||
|
||||
|
@ -44,6 +46,8 @@ exception Error of Location.t * error
|
|||
|
||||
let type_variables = ref (Tbl.empty : (string, type_expr) Tbl.t)
|
||||
let saved_type_variables = ref ([] : (string, type_expr) Tbl.t list)
|
||||
let univars = ref ([] : (string * type_expr) list)
|
||||
let pre_univars = ref ([] : type_expr list)
|
||||
|
||||
let used_variables = ref (Tbl.empty : (string, type_expr) Tbl.t)
|
||||
let bindings = ref ([] : (Location.t * type_expr * type_expr) list)
|
||||
|
@ -80,33 +84,61 @@ let type_variable loc name =
|
|||
with Not_found ->
|
||||
raise(Error(loc, Unbound_type_variable ("'" ^ name)))
|
||||
|
||||
type policy = Fixed | Extensible | Delayed
|
||||
let wrap_method ty =
|
||||
match (Ctype.repr ty).desc with
|
||||
Tpoly _ -> ty
|
||||
| _ -> Ctype.newty (Tpoly (ty, []))
|
||||
|
||||
let rec transl_type env policy styp =
|
||||
let new_pre_univar () =
|
||||
let v = newvar () in pre_univars := v :: !pre_univars; v
|
||||
|
||||
let rec swap_list = function
|
||||
x :: y :: l -> y :: x :: swap_list l
|
||||
| l -> l
|
||||
|
||||
type policy = Fixed | Extensible | Delayed | Univars
|
||||
|
||||
let rec transl_type env policy rowvar styp =
|
||||
if rowvar <> None then begin
|
||||
match styp.ptyp_desc with
|
||||
Ptyp_variant _ | Ptyp_object _ | Ptyp_class _ -> ()
|
||||
| _ -> raise(Error(styp.ptyp_loc, No_row_variable ""))
|
||||
end;
|
||||
match styp.ptyp_desc with
|
||||
Ptyp_any -> Ctype.newvar ()
|
||||
Ptyp_any ->
|
||||
if policy = Univars then new_pre_univar () else newvar ()
|
||||
| Ptyp_var name ->
|
||||
begin
|
||||
begin try
|
||||
List.assoc name !univars
|
||||
with Not_found ->
|
||||
match policy with
|
||||
Fixed ->
|
||||
begin try
|
||||
Tbl.find name !type_variables
|
||||
instance (Tbl.find name !type_variables)
|
||||
with Not_found ->
|
||||
raise(Error(styp.ptyp_loc, Unbound_type_variable ("'" ^ name)))
|
||||
end
|
||||
| Extensible ->
|
||||
begin try
|
||||
Tbl.find name !type_variables
|
||||
instance (Tbl.find name !type_variables)
|
||||
with Not_found ->
|
||||
let v = new_global_var () in
|
||||
type_variables := Tbl.add name v !type_variables;
|
||||
v
|
||||
end
|
||||
| Univars ->
|
||||
begin try
|
||||
instance (Tbl.find name !type_variables)
|
||||
with Not_found ->
|
||||
let v = new_pre_univar () in
|
||||
type_variables := Tbl.add name v !type_variables;
|
||||
v
|
||||
end
|
||||
| Delayed ->
|
||||
begin try
|
||||
Tbl.find name !used_variables
|
||||
with Not_found -> try
|
||||
let v1 = Tbl.find name !type_variables in
|
||||
let v1 = instance (Tbl.find name !type_variables) in
|
||||
let v2 = new_global_var () in
|
||||
used_variables := Tbl.add name v2 !used_variables;
|
||||
bindings := (styp.ptyp_loc, v1, v2)::!bindings;
|
||||
|
@ -119,11 +151,11 @@ let rec transl_type env policy styp =
|
|||
end
|
||||
end
|
||||
| Ptyp_arrow(l, st1, st2) ->
|
||||
let ty1 = transl_type env policy st1 in
|
||||
let ty2 = transl_type env policy st2 in
|
||||
let ty1 = transl_type env policy None st1 in
|
||||
let ty2 = transl_type env policy None st2 in
|
||||
newty (Tarrow(l, ty1, ty2, Cok))
|
||||
| Ptyp_tuple stl ->
|
||||
newty (Ttuple(List.map (transl_type env policy) stl))
|
||||
newty (Ttuple(List.map (transl_type env policy None) stl))
|
||||
| Ptyp_constr(lid, stl) ->
|
||||
let (path, decl) =
|
||||
try
|
||||
|
@ -133,7 +165,7 @@ let rec transl_type env policy styp =
|
|||
if List.length stl <> decl.type_arity then
|
||||
raise(Error(styp.ptyp_loc, Type_arity_mismatch(lid, decl.type_arity,
|
||||
List.length stl)));
|
||||
let args = List.map (transl_type env policy) stl in
|
||||
let args = List.map (transl_type env policy None) stl in
|
||||
let params = List.map (fun _ -> Ctype.newvar ()) args in
|
||||
let cstr = newty (Tconstr(path, params, ref Mnil)) in
|
||||
begin try
|
||||
|
@ -143,14 +175,18 @@ let rec transl_type env policy styp =
|
|||
end;
|
||||
List.iter2
|
||||
(fun (sty, ty) ty' ->
|
||||
try unify env ty ty' with Unify trace ->
|
||||
raise (Error(sty.ptyp_loc, Type_mismatch trace)))
|
||||
try unify_var env ty' ty with Unify trace ->
|
||||
raise (Error(sty.ptyp_loc, Type_mismatch (swap_list trace))))
|
||||
(List.combine stl args) params;
|
||||
cstr
|
||||
| Ptyp_object fields ->
|
||||
newobj (transl_fields env policy fields)
|
||||
begin try
|
||||
newobj (transl_fields env policy rowvar fields)
|
||||
with Error (loc, No_row_variable _) when loc = Location.none ->
|
||||
raise (Error(styp.ptyp_loc, No_row_variable "object "))
|
||||
end
|
||||
| Ptyp_class(lid, stl, present) ->
|
||||
if policy = Fixed then
|
||||
if policy = Fixed & rowvar = None then
|
||||
raise(Error(styp.ptyp_loc, Unbound_row_variable lid));
|
||||
let (path, decl, is_variant) =
|
||||
try
|
||||
|
@ -182,8 +218,8 @@ let rec transl_type env policy styp =
|
|||
in
|
||||
if List.length stl <> decl.type_arity then
|
||||
raise(Error(styp.ptyp_loc, Type_arity_mismatch(lid, decl.type_arity,
|
||||
List.length stl)));
|
||||
let args = List.map (transl_type env policy) stl in
|
||||
List.length stl)));
|
||||
let args = List.map (transl_type env policy None) stl in
|
||||
let cstr = newty (Tconstr(path, args, ref Mnil)) in
|
||||
let ty =
|
||||
try Ctype.expand_head env cstr
|
||||
|
@ -193,8 +229,8 @@ let rec transl_type env policy styp =
|
|||
let params = Ctype.instance_list decl.type_params in
|
||||
List.iter2
|
||||
(fun (sty, ty') ty ->
|
||||
try unify env ty' ty with Unify trace ->
|
||||
raise (Error(sty.ptyp_loc, Type_mismatch trace)))
|
||||
try unify_var env ty ty' with Unify trace ->
|
||||
raise (Error(sty.ptyp_loc, Type_mismatch (swap_list trace))))
|
||||
(List.combine stl args) params;
|
||||
begin match ty.desc with
|
||||
Tvariant row ->
|
||||
|
@ -204,6 +240,7 @@ let rec transl_type env policy styp =
|
|||
raise(Error(styp.ptyp_loc, Present_has_no_type l)))
|
||||
present;
|
||||
let bound = ref row.row_bound in
|
||||
let fixed = rowvar <> None || policy = Univars in
|
||||
let fields =
|
||||
List.map
|
||||
(fun (l,f) -> l,
|
||||
|
@ -211,34 +248,78 @@ let rec transl_type env policy styp =
|
|||
match Btype.row_field_repr f with
|
||||
| Rpresent (Some ty) ->
|
||||
bound := ty :: !bound;
|
||||
Reither(false, [ty], false, ref None)
|
||||
Reither(false, [ty], fixed, ref None)
|
||||
| Rpresent None ->
|
||||
Reither (true, [], false, ref None)
|
||||
Reither (true, [], fixed, ref None)
|
||||
| _ -> f)
|
||||
row.row_fields
|
||||
in
|
||||
let row = { row with row_fields = fields; row_bound = !bound;
|
||||
row_name = Some (path, args) } in
|
||||
newty (Tvariant row)
|
||||
| _ ->
|
||||
let row = { row_closed = true;
|
||||
row_fields = fields;
|
||||
row_bound = !bound;
|
||||
row_name = Some (path, args);
|
||||
row_fixed = fixed;
|
||||
row_more = match rowvar with Some v -> v
|
||||
| None ->
|
||||
if policy = Univars then new_pre_univar ()
|
||||
else newvar () }
|
||||
in newty (Tvariant row)
|
||||
| Tobject (fi, _) ->
|
||||
let _, tv = flatten_fields fi in
|
||||
if policy = Univars then pre_univars := tv :: !pre_univars;
|
||||
begin match rowvar with None -> ()
|
||||
| Some rv ->
|
||||
let _, tv = flatten_fields fi in
|
||||
try unify_var env tv rv with Unify trace ->
|
||||
raise(Error(styp.ptyp_loc, Alias_type_mismatch trace))
|
||||
end;
|
||||
ty
|
||||
| _ ->
|
||||
assert false
|
||||
end
|
||||
| Ptyp_alias(st, alias) ->
|
||||
if Tbl.mem alias !type_variables then
|
||||
raise(Error(styp.ptyp_loc, Bound_type_variable alias))
|
||||
else
|
||||
let ty' = new_global_var () in
|
||||
type_variables := Tbl.add alias ty' !type_variables;
|
||||
let ty = transl_type env policy st in
|
||||
begin try unify env ty ty' with Unify trace ->
|
||||
raise(Error(styp.ptyp_loc, Alias_type_mismatch trace))
|
||||
end;
|
||||
ty
|
||||
if List.mem_assoc alias !univars then
|
||||
match List.assoc alias !univars with
|
||||
{desc=Tlink({desc=Tunivar} as tc)} as tr ->
|
||||
let ty = transl_type env policy (Some tc) st in
|
||||
tr.level <- tc.level;
|
||||
tr.desc <- Tvar;
|
||||
begin try unify_var env tr ty with Unify trace ->
|
||||
let trace = swap_list trace in
|
||||
raise(Error(styp.ptyp_loc, Alias_type_mismatch trace))
|
||||
end;
|
||||
ty
|
||||
| _ ->
|
||||
raise(Error(styp.ptyp_loc, Bound_type_variable alias))
|
||||
else begin
|
||||
try
|
||||
let t = instance (Tbl.find alias !type_variables) in
|
||||
let ty = transl_type env policy None st in
|
||||
begin try unify_var env t ty with Unify trace ->
|
||||
let trace = swap_list trace in
|
||||
raise(Error(styp.ptyp_loc, Alias_type_mismatch trace))
|
||||
end;
|
||||
ty
|
||||
with Not_found ->
|
||||
begin_def ();
|
||||
let t = newvar () in
|
||||
type_variables := Tbl.add alias t !type_variables;
|
||||
let ty = transl_type env policy None st in
|
||||
begin try unify_var env t ty with Unify trace ->
|
||||
let trace = swap_list trace in
|
||||
raise(Error(styp.ptyp_loc, Alias_type_mismatch trace))
|
||||
end;
|
||||
end_def ();
|
||||
generalize_global t;
|
||||
instance t
|
||||
end
|
||||
| Ptyp_variant(fields, closed, present) ->
|
||||
let bound = ref [] and name = ref None in
|
||||
let fixed = rowvar <> None || policy = Univars in
|
||||
let mkfield l f =
|
||||
newty (Tvariant {row_fields=[l,f]; row_more=newty Tnil;
|
||||
row_bound=[]; row_closed=true; row_name=None}) in
|
||||
row_bound=[]; row_closed=true;
|
||||
row_fixed=fixed; row_name=None}) in
|
||||
let add_typed_field loc l f fields =
|
||||
try
|
||||
let f' = List.assoc l fields in
|
||||
|
@ -253,18 +334,18 @@ let rec transl_type env policy styp =
|
|||
name := None;
|
||||
let f = match present with
|
||||
Some present when not (List.mem l present) ->
|
||||
let tl = List.map (transl_type env policy) stl in
|
||||
let tl = List.map (transl_type env policy None) stl in
|
||||
bound := tl @ !bound;
|
||||
Reither(c, tl, false, ref None)
|
||||
Reither(c, tl, fixed, ref None)
|
||||
| _ ->
|
||||
if List.length stl > 1 || c && stl <> [] then
|
||||
raise(Error(styp.ptyp_loc, Present_has_conjunction l));
|
||||
match stl with [] -> Rpresent None
|
||||
| st :: _ -> Rpresent (Some(transl_type env policy st))
|
||||
| st :: _ -> Rpresent (Some(transl_type env policy None st))
|
||||
in
|
||||
add_typed_field styp.ptyp_loc l f fields
|
||||
| Rinherit sty ->
|
||||
let ty = transl_type env policy sty in
|
||||
let ty = transl_type env policy None sty in
|
||||
let nm =
|
||||
match repr ty with
|
||||
{desc=Tconstr(p, tl, _)} -> Some(p, tl)
|
||||
|
@ -287,9 +368,9 @@ let rec transl_type env policy styp =
|
|||
begin match f with
|
||||
Rpresent(Some ty) ->
|
||||
bound := ty :: !bound;
|
||||
Reither(false, [ty], false, ref None)
|
||||
Reither(false, [ty], fixed, ref None)
|
||||
| Rpresent None ->
|
||||
Reither(true, [], false, ref None)
|
||||
Reither(true, [], fixed, ref None)
|
||||
| _ ->
|
||||
assert false
|
||||
end
|
||||
|
@ -320,32 +401,77 @@ let rec transl_type env policy styp =
|
|||
end;
|
||||
let row =
|
||||
{ row_fields = List.rev fields; row_more = newvar ();
|
||||
row_bound = !bound; row_closed = closed; row_name = !name } in
|
||||
if policy = Fixed && not (Btype.static_row row) then
|
||||
raise(Error(styp.ptyp_loc, Unbound_type_variable "[..]"));
|
||||
row_bound = !bound; row_closed = closed;
|
||||
row_fixed = fixed; row_name = !name } in
|
||||
let static = Btype.static_row row in
|
||||
let row =
|
||||
{ row with row_more =
|
||||
match rowvar with Some v -> v
|
||||
| None ->
|
||||
if static then newty Tnil else
|
||||
if policy = Univars then new_pre_univar () else
|
||||
if policy = Fixed && not static then
|
||||
raise(Error(styp.ptyp_loc, Unbound_type_variable "[..]"))
|
||||
else row.row_more
|
||||
} in
|
||||
newty (Tvariant row)
|
||||
| Ptyp_poly(vars, st) ->
|
||||
(* aliases are stubs, in case one wants to redefine them *)
|
||||
let ty_list = List.map (fun _ -> newty Tunivar) vars in
|
||||
let new_univars =
|
||||
List.map2 (fun name ty -> name, newty (Tlink ty)) vars ty_list in
|
||||
let old_univars = !univars in
|
||||
univars := new_univars @ !univars;
|
||||
let ty = transl_type env policy None st in
|
||||
univars := old_univars;
|
||||
newty (Tpoly(ty, ty_list))
|
||||
|
||||
and transl_fields env policy =
|
||||
and transl_fields env policy rowvar =
|
||||
function
|
||||
[] ->
|
||||
newty Tnil
|
||||
| {pfield_desc = Pfield_var} as field::_ ->
|
||||
if policy = Fixed then
|
||||
raise(Error(field.pfield_loc, Unbound_type_variable "<..>"));
|
||||
newvar ()
|
||||
begin match rowvar with
|
||||
None ->
|
||||
if policy = Fixed then
|
||||
raise(Error(field.pfield_loc, Unbound_type_variable ".."));
|
||||
if policy = Univars then new_pre_univar () else newvar ()
|
||||
| Some v -> v
|
||||
end
|
||||
| {pfield_desc = Pfield(s, e)}::l ->
|
||||
let ty1 = transl_type env policy e in
|
||||
let ty2 = transl_fields env policy l in
|
||||
let ty1 = transl_type env policy None e in
|
||||
let ty2 = transl_fields env policy rowvar l in
|
||||
newty (Tfield (s, Fpresent, ty1, ty2))
|
||||
|
||||
let transl_simple_type env fixed styp =
|
||||
let typ = transl_type env (if fixed then Fixed else Extensible) styp in
|
||||
univars := [];
|
||||
let typ = transl_type env (if fixed then Fixed else Extensible) None styp in
|
||||
typ
|
||||
|
||||
let transl_simple_type_univars env styp =
|
||||
univars := [];
|
||||
pre_univars := [];
|
||||
begin_def ();
|
||||
let typ = transl_type env Univars None styp in
|
||||
end_def ();
|
||||
generalize typ;
|
||||
let univs =
|
||||
List.fold_left
|
||||
(fun acc v ->
|
||||
let v = repr v in
|
||||
if v.desc <> Tvar || v.level <> Btype.generic_level || List.memq v acc
|
||||
then acc
|
||||
else (v.desc <- Tunivar ; v :: acc))
|
||||
[] !pre_univars
|
||||
in
|
||||
pre_univars := [];
|
||||
instance (Btype.newgenty (Tpoly (typ, univs)))
|
||||
|
||||
let transl_simple_type_delayed env styp =
|
||||
univars := [];
|
||||
used_variables := Tbl.empty;
|
||||
bindings := [];
|
||||
let typ = transl_type env Delayed styp in
|
||||
let typ = transl_type env Delayed None styp in
|
||||
let b = !bindings in
|
||||
used_variables := Tbl.empty;
|
||||
bindings := [];
|
||||
|
@ -424,3 +550,9 @@ let report_error ppf = function
|
|||
fprintf ppf
|
||||
"Variant tags `%s@ and `%s have same hash value.@ Change one of them."
|
||||
lab1 lab2
|
||||
| No_row_variable s ->
|
||||
fprintf ppf "This %stype has no row variable" s
|
||||
| Bad_alias name ->
|
||||
fprintf ppf
|
||||
"The alias %s cannot be used here. It captures universal variables."
|
||||
name
|
||||
|
|
|
@ -18,6 +18,8 @@ open Format;;
|
|||
|
||||
val transl_simple_type:
|
||||
Env.t -> bool -> Parsetree.core_type -> Types.type_expr
|
||||
val transl_simple_type_univars:
|
||||
Env.t -> Parsetree.core_type -> Types.type_expr
|
||||
val transl_simple_type_delayed:
|
||||
Env.t -> Parsetree.core_type -> Types.type_expr * (unit -> unit)
|
||||
(* Translate a type, but leave type variables unbound. Returns
|
||||
|
@ -48,6 +50,8 @@ type error =
|
|||
| Constructor_mismatch of Types.type_expr * Types.type_expr
|
||||
| Not_a_variant of Types.type_expr
|
||||
| Variant_tags of string * string
|
||||
| No_row_variable of string
|
||||
| Bad_alias of string
|
||||
|
||||
exception Error of Location.t * error
|
||||
|
||||
|
|
|
@ -40,8 +40,9 @@ and noassert = ref false (* -noassert *)
|
|||
and verbose = ref false (* -verbose *)
|
||||
and use_prims = ref "" (* -use-prims ... *)
|
||||
and use_runtime = ref "" (* -use-runtime ... *)
|
||||
and principal = ref false (* -principal *)
|
||||
and recursive_types = ref false (* -rectypes *)
|
||||
and make_runtime = ref false (* -make-runtime *)
|
||||
and make_runtime = ref false (* -make_runtime *)
|
||||
and gprofile = ref false (* -p *)
|
||||
and c_compiler = ref Config.bytecomp_c_compiler (* -cc *)
|
||||
and c_linker = ref Config.bytecomp_c_linker (* -cc *)
|
||||
|
|
Loading…
Reference in New Issue