diff options
Diffstat (limited to 'typing/printtyp.ml')
| -rw-r--r-- | typing/printtyp.ml | 1000 |
1 files changed, 0 insertions, 1000 deletions
diff --git a/typing/printtyp.ml b/typing/printtyp.ml deleted file mode 100644 index 232a32abb8..0000000000 --- a/typing/printtyp.ml +++ /dev/null @@ -1,1000 +0,0 @@ -(***********************************************************************) -(* *) -(* Objective Caml *) -(* *) -(* Xavier Leroy and Jerome Vouillon, projet Cristal, INRIA Rocquencourt*) -(* *) -(* Copyright 1996 Institut National de Recherche en Informatique et *) -(* en Automatique. All rights reserved. This file is distributed *) -(* under the terms of the Q Public License version 1.0. *) -(* *) -(***********************************************************************) - -(* $Id$ *) - -(* Printing functions *) - -open Misc -open Ctype -open Format -open Longident -open Path -open Asttypes -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 - | Lident s -> fprintf ppf "%s" s - | Ldot(p, s) -> fprintf ppf "%a.%s" longident p s - | Lapply(p1, p2) -> fprintf ppf "%a(%a)" longident p1 longident p2 - -(* Print an identifier *) - -let ident ppf id = fprintf ppf "%s" (Ident.name id) - -(* Print a path *) - -let ident_pervasive = Ident.create_persistent "Pervasives" - -let rec tree_of_path = function - | Pident id -> - Oide_ident (Ident.name id) - | Pdot(Pident id, s, pos) when Ident.same id ident_pervasive -> - Oide_ident s - | Pdot(p, s, pos) -> - Oide_dot (tree_of_path p, s) - | Papply(p1, p2) -> - Oide_apply (tree_of_path p1, tree_of_path p2) - -let rec path ppf = function - | Pident id -> - ident ppf id - | Pdot(Pident id, s, pos) when Ident.same id ident_pervasive -> - fprintf ppf "%s" s - | Pdot(p, s, pos) -> - fprintf ppf "%a.%s" path p s - | Papply(p1, p2) -> - fprintf ppf "%a(%a)" path p1 path p2 - -(* Print a raw type expression, with sharing *) - -let raw_list pr ppf = function - [] -> fprintf ppf "[]" - | a :: l -> - fprintf ppf "@[<1>[%a%t]@]" pr a - (fun ppf -> List.iter (fun x -> fprintf ppf ";@,%a" pr x) l) - -let rec safe_kind_repr v = function - Fvar {contents=Some k} -> - if List.memq k v then "Fvar loop" else - safe_kind_repr (k::v) k - | Fvar _ -> "Fvar None" - | Fpresent -> "Fpresent" - | Fabsent -> "Fabsent" - -let rec safe_commu_repr v = function - Cok -> "Cok" - | Cunknown -> "Cunknown" - | Clink r -> - if List.memq r v then "Clink loop" else - safe_commu_repr (r::v) !r - -let rec safe_repr v = function - {desc = Tlink t} when not (List.memq t v) -> - safe_repr (t::v) t - | t -> t - -let rec list_of_memo = function - Mnil -> [] - | Mcons (p, t1, t2, rem) -> (p,t1,t2) :: list_of_memo rem - | Mlink rem -> list_of_memo !rem - -let visited = ref [] -let rec raw_type ppf ty = - let ty = safe_repr [] ty in - if List.memq ty !visited then fprintf ppf "{id=%d}" ty.id else begin - visited := ty :: !visited; - fprintf ppf "@[<1>{id=%d;level=%d;desc=@,%a}@]" ty.id ty.level - raw_type_desc ty.desc - end -and raw_type_list tl = raw_list raw_type tl -and raw_type_desc ppf = function - Tvar -> fprintf ppf "Tvar" - | Tarrow(l,t1,t2,c) -> - fprintf ppf "@[<hov1>Tarrow(%s,@,%a,@,%a,@,%s)@]" - l raw_type t1 raw_type t2 - (safe_commu_repr [] c) - | Ttuple tl -> - fprintf ppf "@[<1>Ttuple@,%a@]" raw_type_list tl - | Tconstr (p, tl, abbrev) -> - fprintf ppf "@[<hov1>Tconstr(@,%a,@,%a,@,%a)@]" path p - raw_type_list tl - (raw_list (fun ppf (p,t1,t2) -> - fprintf ppf "@[%a,@ %a,@ %a@]" path p raw_type t1 raw_type t2)) - (list_of_memo !abbrev) - | Tobject (t, nm) -> - fprintf ppf "@[<hov1>Tobject(@,%a,@,@[<1>ref%t@])@]" raw_type t - (fun ppf -> - match !nm with None -> fprintf ppf " None" - | Some(p,tl) -> - fprintf ppf "(Some(@,%a,@,%a))" path p raw_type_list tl) - | Tfield (f, k, t1, t2) -> - fprintf ppf "@[<hov1>Tfield(@,%s,@,%s,@,%a,@,%a)@]" f - (safe_kind_repr [] k) - raw_type t1 raw_type t2 - | Tnil -> fprintf ppf "Tnil" - | Tlink t -> fprintf ppf "@[<1>Tlink@,%a@]" raw_type t - | Tsubst t -> fprintf ppf "@[<1>Tsubst@,%a@]" raw_type t - | Tunivar -> fprintf ppf "Tunivar" - | Tpoly (t, tl) -> - fprintf ppf "@[<hov1>Tpoly(@,%a,@,%a)@]" - raw_type t - raw_type_list tl - | Tvariant row -> - fprintf ppf - "@[<hov1>{@[%s@,%a;@]@ @[%s@,%a;@]@ %s%b;@ %s%b;@ @[<1>%s%t@]}@]" - "row_fields=" - (raw_list (fun ppf (l, f) -> - fprintf ppf "@[%s,@ %a@]" l raw_field f)) - row.row_fields - "row_more=" raw_type row.row_more - "row_closed=" row.row_closed - "row_fixed=" row.row_fixed - "row_name=" - (fun ppf -> - match row.row_name with None -> fprintf ppf "None" - | Some(p,tl) -> - fprintf ppf "Some(@,%a,@,%a)" path p raw_type_list tl) - -and raw_field ppf = function - Rpresent None -> fprintf ppf "Rpresent None" - | Rpresent (Some t) -> fprintf ppf "@[<1>Rpresent(Some@,%a)@]" raw_type t - | Reither (c,tl,m,e) -> - fprintf ppf "@[<hov1>Reither(%b,@,%a,@,%b,@,@[<1>ref%t@])@]" c - raw_type_list tl m - (fun ppf -> - match !e with None -> fprintf ppf " None" - | Some f -> fprintf ppf "@,@[<1>(%a)@]" raw_field f) - | Rabsent -> fprintf ppf "Rabsent" - -let raw_type_expr ppf t = - visited := []; - raw_type ppf t; - visited := [] - -(* Print a type expression *) - -let names = ref ([] : (type_expr * string) list) -let name_counter = ref 0 - -let reset_names () = names := []; name_counter := 0 - -let new_name () = - let name = - if !name_counter < 26 - then String.make 1 (Char.chr(97 + !name_counter)) - else String.make 1 (Char.chr(97 + !name_counter mod 26)) ^ - string_of_int(!name_counter / 26) in - incr name_counter; - name - -let name_of_type t = - try List.assq t !names with Not_found -> - let name = new_name () in - names := (t, name) :: !names; - name - -let check_name_of_type t = ignore(name_of_type t) - -let non_gen_mark sch ty = - if sch && ty.desc = Tvar && ty.level <> generic_level then "_" else "" - -let print_name_of_type sch ppf t = - fprintf ppf "'%s%s" (non_gen_mark sch t) (name_of_type t) - -let visited_objects = ref ([] : type_expr list) -let aliased = ref ([] : type_expr list) -let delayed = ref ([] : type_expr list) - -let add_delayed t = - if not (List.mem_assq t !names) then delayed := t :: !delayed - -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 - (fun (_, f) -> - match row_field_repr f with - | Reither(c, l, _, _) -> - row.row_closed && if c then l = [] else List.length l = 1 - | _ -> true) - row.row_fields - -let rec mark_loops_rec visited ty = - let ty = repr ty in - let px = proxy ty in - if List.memq px visited then add_alias px else - let visited = px :: visited in - match ty.desc with - | Tvar -> () - | Tarrow(_, ty1, ty2, _) -> - mark_loops_rec visited ty1; mark_loops_rec visited ty2 - | Ttuple tyl -> List.iter (mark_loops_rec visited) tyl - | Tconstr(_, tyl, _) -> - List.iter (mark_loops_rec visited) tyl - | Tvariant row -> - if List.memq px !visited_objects then add_alias px else - begin - let row = row_repr row in - if not (static_row row) then - visited_objects := px :: !visited_objects; - match row.row_name with - | Some(p, tyl) when namable_row row -> - List.iter (mark_loops_rec visited) tyl - | _ -> - iter_row (mark_loops_rec visited) {row with row_bound = []} - end - | Tobject (fi, nm) -> - if List.memq px !visited_objects then add_alias px else - begin - if opened_object ty then - visited_objects := px :: !visited_objects; - begin match !nm with - | None -> - 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) (List.tl l) - end - end - | Tfield(_, kind, ty1, ty2) when field_kind_repr kind = Fpresent -> - mark_loops_rec visited ty1; mark_loops_rec visited ty2 - | Tfield(_, _, _, ty2) -> - mark_loops_rec visited ty2 - | 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 := []; delayed := [] - -let reset () = - reset_names (); reset_loop_marks () - -let reset_and_mark_loops ty = - reset (); mark_loops ty - -let reset_and_mark_loops_list tyl = - reset (); List.iter mark_loops tyl - -(* Disabled in classic mode when printing an unification error *) -let print_labels = ref true -let print_label ppf l = - if !print_labels && l <> "" || is_optional l then fprintf ppf "%s:" l - -let rec tree_of_typexp sch ty = - let ty = repr ty in - let px = proxy ty in - if List.mem_assq px !names && not (List.memq px !delayed) then - let mark = is_non_gen sch ty in - Otyp_var (mark, name_of_type px) else - - let pr_typ () = - match ty.desc with - | Tvar -> - Otyp_var (is_non_gen sch ty, name_of_type ty) - | Tarrow(l, ty1, ty2, _) -> - let pr_arrow l ty1 ty2 = - let lab = - if !print_labels && l <> "" || is_optional l then l else "" - in - let t1 = - if is_optional l then - match (repr ty1).desc with - | Tconstr(path, [ty], _) - when Path.same path Predef.path_option -> - tree_of_typexp sch ty - | _ -> Otyp_stuff "<hidden>" - else tree_of_typexp sch ty1 in - Otyp_arrow (lab, t1, tree_of_typexp sch ty2) in - pr_arrow l ty1 ty2 - | Ttuple tyl -> - Otyp_tuple (tree_of_typlist sch tyl) - | Tconstr(p, tyl, abbrev) -> - Otyp_constr (tree_of_path p, tree_of_typlist sch tyl) - | Tvariant row -> - let row = row_repr row in - let fields = - if row.row_closed then - List.filter (fun (_, f) -> row_field_repr f <> Rabsent) - row.row_fields - else row.row_fields in - let present = - List.filter - (fun (_, f) -> - match row_field_repr f with - | Rpresent _ -> true - | _ -> false) - fields in - let all_present = List.length present = List.length fields in - begin match row.row_name with - | Some(p, tyl) when namable_row row -> - let id = tree_of_path p in - let args = tree_of_typlist sch tyl in - if row.row_closed && all_present then - Otyp_constr (id, args) - else - let non_gen = is_non_gen sch px in - let tags = - if all_present then None else Some (List.map fst present) in - Otyp_variant (non_gen, Ovar_name(tree_of_path p, args), - row.row_closed, tags) - | _ -> - let non_gen = - not (row.row_closed && all_present) && is_non_gen sch px in - let fields = List.map (tree_of_row_field sch) fields in - let tags = - if all_present then None else Some (List.map fst present) in - Otyp_variant (non_gen, Ovar_fields fields, row.row_closed, tags) - end - | Tobject (fi, nm) -> - tree_of_typobject sch fi nm - | Tsubst ty -> - tree_of_typexp sch ty - | Tlink _ | Tnil | Tfield _ -> - fatal_error "Printtyp.tree_of_typexp" - | 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 begin - List.iter add_delayed tyl; - let tl = List.map name_of_type tyl in - Otyp_poly (tl, tree_of_typexp sch ty) - end - | 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 () - -and tree_of_row_field sch (l, f) = - match row_field_repr f with - | Rpresent None | Reither(true, [], _, _) -> (l, false, []) - | Rpresent(Some ty) -> (l, false, [tree_of_typexp sch ty]) - | Reither(c, tyl, _, _) -> - if c (* contradiction: un constructeur constant qui a un argument *) - then (l, true, tree_of_typlist sch tyl) - else (l, false, tree_of_typlist sch tyl) - | Rabsent -> (l, false, [] (* une erreur, en fait *)) - -and tree_of_typlist sch = function - | [] -> [] - | ty :: tyl -> - let tr = tree_of_typexp sch ty in - tr :: tree_of_typlist sch tyl - -and tree_of_typobject sch fi nm = - begin match !nm with - | None -> - let pr_fields fi = - let (fields, rest) = flatten_fields fi in - let present_fields = - List.fold_right - (fun (n, k, t) l -> - match field_kind_repr k with - | Fpresent -> (n, t) :: l - | _ -> l) - fields [] in - let sorted_fields = - Sort.list (fun (n, _) (n', _) -> n <= n') present_fields in - tree_of_typfields sch rest sorted_fields in - let (fields, rest) = pr_fields fi in - Otyp_object (fields, rest) - | 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) - | _ -> - fatal_error "Printtyp.tree_of_typobject" - end - -and is_non_gen sch ty = - sch && ty.desc = Tvar && ty.level <> generic_level - -and tree_of_typfields sch rest = function - | [] -> - let rest = - match rest.desc with - | Tvar | Tunivar -> Some (is_non_gen sch rest) - | Tnil -> None - | _ -> fatal_error "typfields (1)" - in - ([], rest) - | (s, t) :: l -> - let field = (s, tree_of_typexp sch t) in - let (fields, rest) = tree_of_typfields sch rest l in - (field :: fields, rest) - -let typexp sch prio ppf ty = - !Oprint.out_type ppf (tree_of_typexp sch ty) - -let type_expr ppf ty = typexp false 0 ppf ty - -and type_sch ppf ty = typexp true 0 ppf ty - -and type_scheme ppf ty = reset_and_mark_loops ty; typexp true 0 ppf ty - -(* Maxence *) -let type_scheme_max ?(b_reset_names=true) ppf ty = - if b_reset_names then reset_names () ; - typexp true 0 ppf ty -(* Fin Maxence *) - -let tree_of_type_scheme ty = reset_and_mark_loops ty; tree_of_typexp true ty - -(* Print one type declaration *) - -let tree_of_constraints params = - List.fold_right - (fun ty list -> - let ty' = unalias ty in - if proxy ty != proxy ty' then - let tr = tree_of_typexp true ty in - (tr, tree_of_typexp true ty') :: list - else list) - params [] - -let filter_params tyl = - let params = - List.fold_left - (fun tyl ty -> - let ty = repr ty in - if List.memq ty tyl then Btype.newgenty (Tsubst ty) :: tyl - else ty :: tyl) - [] tyl - in List.rev params - -let string_of_mutable = function - | Immutable -> "" - | Mutable -> "mutable " - -let rec tree_of_type_decl id decl = - - reset(); - - let params = filter_params decl.type_params in - - List.iter add_alias params; - List.iter mark_loops params; - List.iter check_name_of_type (List.map proxy params); - let ty_manifest = - match decl.type_manifest with - | None -> None - | Some ty -> - let ty = - (* Special hack to hide variant name *) - match repr ty with {desc=Tvariant row} -> - let row = row_repr row in - begin match row.row_name with - Some (Pident id', _) when Ident.same id id' -> - newgenty (Tvariant {row with row_name = None}) - | _ -> ty - end - | _ -> ty - in - mark_loops ty; - Some ty - in - begin match decl.type_kind with - | Type_abstract -> () - | Type_variant ([], _) -> () - | Type_variant (cstrs, priv) -> - List.iter (fun (_, args) -> List.iter mark_loops args) cstrs - | Type_record(l, rep, priv) -> - List.iter (fun (_, _, ty) -> mark_loops ty) l - end; - - let type_param = - function - | Otyp_var (_, id) -> id - | _ -> "?" - in - let type_defined decl = - if decl.type_kind = Type_abstract && ty_manifest = None - && List.exists (fun x -> x <> (true,true,true)) decl.type_variance then - let vari = List.map (fun (co,cn,ct) -> (co,cn)) decl.type_variance in - (Ident.name id, - List.combine - (List.map (fun ty -> type_param (tree_of_typexp false ty)) params) - vari) - else - let ty = - tree_of_typexp false - (Btype.newgenty (Tconstr(Pident id, params, ref Mnil))) - in - match ty with - | Otyp_constr (Oide_ident id, tyl) -> - (id, List.map (fun ty -> (type_param ty, (true, true))) tyl) - | _ -> ("?", []) - in - let tree_of_manifest ty1 = - match ty_manifest with - | None -> ty1 - | Some ty -> Otyp_manifest (tree_of_typexp false ty, ty1) - in - let (name, args) = type_defined decl in - let constraints = tree_of_constraints params in - let ty = - match decl.type_kind with - | Type_abstract -> - begin match ty_manifest with - | None -> Otyp_abstract - | Some ty -> tree_of_typexp false ty - end - | Type_variant(cstrs, priv) -> - tree_of_manifest (Otyp_sum (List.map tree_of_constructor cstrs, priv)) - | Type_record(lbls, rep, priv) -> - tree_of_manifest (Otyp_record (List.map tree_of_label lbls, priv)) - in - (name, args, ty, constraints) - -and tree_of_constructor (name, args) = - (name, tree_of_typlist false args) - -and tree_of_label (name, mut, arg) = - (name, mut = Mutable, tree_of_typexp false arg) - -let tree_of_type_declaration id decl = - Osig_type [tree_of_type_decl id decl] - -let type_declaration id ppf decl = - !Oprint.out_sig_item ppf (tree_of_type_declaration id decl) - -(* Print an exception declaration *) - -let tree_of_exception_declaration id decl = - let tyl = tree_of_typlist false decl in - Osig_exception (Ident.name id, tyl) - -let exception_declaration id ppf decl = - !Oprint.out_sig_item ppf (tree_of_exception_declaration id decl) - -(* Print a value declaration *) - -let tree_of_value_description id decl = - let id = Ident.name id in - let ty = tree_of_type_scheme decl.val_type in - let prims = - match decl.val_kind with - | Val_prim p -> Primitive.description_list p - | _ -> [] - in - Osig_value (id, ty, prims) - -let value_description id ppf decl = - !Oprint.out_sig_item ppf (tree_of_value_description id decl) - -(* Print a class type *) - -let class_var sch ppf l (m, t) = - fprintf ppf - "@ @[<2>val %s%s :@ %a@]" (string_of_mutable m) l (typexp sch 0) t - -let metho sch concrete ppf (lab, kind, ty) = - if lab <> dummy_method then begin - let priv = - match field_kind_repr kind with - | Fvar _ (* {contents = None} *) -> "private " - | _ (* Fpresent *) -> "" in - let virt = - if Concr.mem lab concrete then "" else "virtual " in - fprintf ppf "@ @[<2>method %s%s%s :@ %a@]" priv virt lab (typexp sch 0) ty - end - -let method_type ty = - let ty = repr ty in - match ty.desc with - Tpoly(ty, _) -> ty - | _ -> ty - -let tree_of_metho sch concrete csil (lab, kind, ty) = - if lab <> dummy_method then begin - let priv = - match field_kind_repr kind with - | Fvar _ (* {contents = None} *) -> true - | _ (* Fpresent *) -> false in - let virt = not (Concr.mem lab concrete) in - let ty = method_type ty in - Ocsg_method (lab, priv, virt, tree_of_typexp sch ty) :: csil - end - else csil - -let rec prepare_class_type params = function - | Tcty_constr (p, tyl, cty) -> - let sty = Ctype.self_type cty in - if List.memq (proxy sty) !visited_objects - || List.exists (fun ty -> (repr ty).desc <> Tvar) params - || List.exists (deep_occur sty) tyl - then prepare_class_type params cty - else List.iter mark_loops tyl - | Tcty_signature sign -> - let sty = repr sign.cty_self in - (* Self may have a name *) - let px = proxy sty in - if List.memq px !visited_objects then add_alias sty - else visited_objects := px :: !visited_objects; - let (fields, _) = - Ctype.flatten_fields (Ctype.object_fields sign.cty_self) - in - List.iter (fun (_, _, ty) -> mark_loops (method_type ty)) fields; - Vars.iter (fun _ (_, ty) -> mark_loops ty) sign.cty_vars - | Tcty_fun (_, ty, cty) -> - mark_loops ty; - prepare_class_type params cty - -let rec tree_of_class_type sch params = - function - | Tcty_constr (p', tyl, cty) -> - let sty = Ctype.self_type cty in - if List.memq (proxy sty) !visited_objects - || List.exists (fun ty -> (repr ty).desc <> Tvar) params - then - tree_of_class_type sch params cty - else - Octy_constr (tree_of_path p', tree_of_typlist true tyl) - | 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 (proxy sty))) - else None - in - let (fields, _) = - Ctype.flatten_fields (Ctype.object_fields sign.cty_self) - in - let csil = [] in - let csil = - List.fold_left - (fun csil (ty1, ty2) -> Ocsg_constraint (ty1, ty2) :: csil) - csil (tree_of_constraints params) - in - let all_vars = - Vars.fold (fun l (m, t) all -> (l, m, t) :: all) sign.cty_vars [] in - let csil = - List.fold_left - (fun csil (l, m, t) -> - Ocsg_value (l, m = Mutable, tree_of_typexp sch t) :: csil) - csil all_vars - in - let csil = - List.fold_left (tree_of_metho sch sign.cty_concr) csil fields - in - Octy_signature (self_ty, List.rev csil) - | Tcty_fun (l, ty, cty) -> - let lab = if !print_labels && l <> "" || is_optional l then l else "" in - let ty = - if is_optional l then - match (repr ty).desc with - | Tconstr(path, [ty], _) when Path.same path Predef.path_option -> ty - | _ -> newconstr (Path.Pident(Ident.create "<hidden>")) [] - else ty in - let tr = tree_of_typexp sch ty in - Octy_fun (lab, tr, tree_of_class_type sch params cty) - -let class_type ppf cty = - reset (); - prepare_class_type [] cty; - !Oprint.out_class_type ppf (tree_of_class_type false [] cty) - -let tree_of_class_params = function - | [] -> [] - | params -> - let tyl = tree_of_typlist true params in - List.map (function Otyp_var (_, s) -> s | _ -> "?") tyl - -let tree_of_class_declaration id cl = - let params = filter_params cl.cty_params in - - reset (); - 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 (proxy sty); - - let vir_flag = cl.cty_new = None in - Osig_class - (vir_flag, Ident.name id, tree_of_class_params params, - tree_of_class_type true params cl.cty_type) - -let class_declaration id ppf cl = - !Oprint.out_sig_item ppf (tree_of_class_declaration id cl) - -let tree_of_cltype_declaration id cl = - let params = List.map repr cl.clty_params in - - reset (); - List.iter add_alias params; - prepare_class_type params cl.clty_type; - let sty = self_type cl.clty_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 (proxy sty); - - let sign = Ctype.signature_of_class_type cl.clty_type in - - let virt = - let (fields, _) = - Ctype.flatten_fields (Ctype.object_fields sign.cty_self) in - List.exists - (fun (lab, _, ty) -> - not (lab = dummy_method || Concr.mem lab sign.cty_concr)) - fields in - - Osig_class_type - (virt, Ident.name id, tree_of_class_params params, - tree_of_class_type true params cl.clty_type) - -let cltype_declaration id ppf cl = - !Oprint.out_sig_item ppf (tree_of_cltype_declaration id cl) - -(* Print a module type *) - -let rec tree_of_modtype = function - | Tmty_ident p -> - Omty_ident (tree_of_path p) - | Tmty_signature sg -> - Omty_signature (tree_of_signature sg) - | Tmty_functor(param, ty_arg, ty_res) -> - Omty_functor - (Ident.name param, tree_of_modtype ty_arg, tree_of_modtype ty_res) - -and tree_of_signature = function - | [] -> [] - | item :: rem -> - match item with - | Tsig_value(id, decl) -> - tree_of_value_description id decl :: tree_of_signature rem - | Tsig_type(id, decl) -> - let (type_decl_list, rem) = - let rec more_type_declarations = function - | Tsig_type(id, decl) :: rem -> - let (type_decl_list, rem) = more_type_declarations rem in - (id, decl) :: type_decl_list, rem - | rem -> [], rem in - more_type_declarations rem - in - let type_decl_list = - List.map (fun (id, decl) -> tree_of_type_decl id decl) - ((id, decl) :: type_decl_list) - in - Osig_type type_decl_list - :: - tree_of_signature rem - | Tsig_exception(id, decl) -> - Osig_exception (Ident.name id, tree_of_typlist false decl) :: - tree_of_signature rem - | Tsig_module(id, mty) -> - Osig_module (Ident.name id, tree_of_modtype mty) :: - tree_of_signature rem - | Tsig_modtype(id, decl) -> - tree_of_modtype_declaration id decl :: tree_of_signature rem - | Tsig_class(id, decl) -> - let rem = - match rem with - | ctydecl :: tydecl1 :: tydecl2 :: rem -> rem - | _ -> [] - in - tree_of_class_declaration id decl :: tree_of_signature rem - | Tsig_cltype(id, decl) -> - let rem = - match rem with - | tydecl1 :: tydecl2 :: rem -> rem - | _ -> [] - in - tree_of_cltype_declaration id decl :: tree_of_signature rem - -and tree_of_modtype_declaration id decl = - let mty = - match decl with - | Tmodtype_abstract -> Omty_abstract - | Tmodtype_manifest mty -> tree_of_modtype mty - in - Osig_modtype (Ident.name id, mty) - -let tree_of_module id mty = Osig_module (Ident.name id, tree_of_modtype mty) - -let modtype ppf mty = !Oprint.out_module_type ppf (tree_of_modtype mty) -let modtype_declaration id ppf decl = - !Oprint.out_sig_item ppf (tree_of_modtype_declaration id decl) - -(* Print a signature body (used by -i when compiling a .ml) *) - -let print_signature ppf tree = - fprintf ppf "@[<v>%a@]" !Oprint.out_signature tree - -let signature ppf sg = - fprintf ppf "%a" print_signature (tree_of_signature sg) - -(* Print an unification error *) - -let type_expansion t ppf t' = - if t == t' then type_expr ppf t else - let t' = if proxy t = proxy t' then unalias t' else t' in - fprintf ppf "@[<2>%a@ =@ %a@]" type_expr t type_expr t' - -let rec trace fst txt ppf = function - | (t1, t1') :: (t2, t2') :: rem -> - if not fst then fprintf ppf "@,"; - fprintf ppf "@[Type@;<1 2>%a@ %s@;<1 2>%a@] %a" - (type_expansion t1) t1' txt (type_expansion t2) t2' - (trace false txt) rem - | _ -> () - -let rec mismatch = function - | [(_, t); (_, t')] -> (t, t') - | _ :: _ :: rem -> mismatch rem - | _ -> assert false - -let rec filter_trace = function - | (t1, t1') :: (t2, t2') :: rem -> - let rem' = filter_trace rem in - if t1 == t1' && t2 == t2' - then rem' - else (t1, t1') :: (t2, t2') :: rem' - | _ -> [] - -(* Hide variant name and var, to force printing the expanded type *) -let hide_variant_name t = - match repr t with - | {desc = Tvariant row} as t when (row_repr row).row_name <> None -> - newty2 t.level - (Tvariant {(row_repr row) with row_name = None; - row_more = newty2 (row_more row).level Tvar}) - | _ -> t - -let prepare_expansion (t, t') = - let t' = hide_variant_name t' in - mark_loops t; if t != t' then mark_loops t'; - (t, t') - -let print_tags ppf fields = - match fields with [] -> () - | (t, _) :: fields -> - fprintf ppf "`%s" t; - List.iter (fun (t, _) -> fprintf ppf ",@ `%s" t) fields - -let explanation unif t3 t4 ppf = - match t3.desc, t4.desc with - | Tfield _, Tvar | Tvar, Tfield _ -> - fprintf ppf "@,Self type cannot escape its class" - | Tconstr (p, _, _), Tvar - when unif && t4.level < Path.binding_time p -> - fprintf ppf - "@,@[The type constructor@;<1 2>%a@ would escape its scope@]" - path p - | Tvar, Tconstr (p, _, _) - when unif && t3.level < Path.binding_time p -> - fprintf ppf - "@,@[The type constructor@;<1 2>%a@ would escape its scope@]" - path p - | Tvar, Tunivar | Tunivar, Tvar -> - fprintf ppf "@,The universal variable %a would escape its scope" - type_expr (if t3.desc = Tunivar then t3 else t4) - | Tfield (lab, _, _, _), _ - | _, Tfield (lab, _, _, _) when lab = dummy_method -> - fprintf ppf - "@,Self type cannot be unified with a closed object type" - | Tfield (l, _, _, _), _ -> - fprintf ppf - "@,@[Only the first object type has a method %s@]" l - | _, Tfield (l, _, _, _) -> - fprintf ppf - "@,@[Only the second object type has a method %s@]" l - | Tvariant row1, Tvariant row2 -> - let row1 = row_repr row1 and row2 = row_repr row2 in - begin match - row1.row_fields, row1.row_closed, row2.row_fields, row1.row_closed with - | [], true, [], true -> - fprintf ppf "@,These two variant types have no intersection" - | [], true, fields, _ -> - fprintf ppf - "@,@[The first variant type does not allow tag(s)@ @[<hov>%a@]@]" - print_tags fields - | fields, _, [], true -> - fprintf ppf - "@,@[The second variant type does not allow tag(s)@ @[<hov>%a@]@]" - print_tags fields - | _ -> () - end - | _ -> () - -let unification_error unif tr txt1 ppf txt2 = - reset (); - let tr = List.map (fun (t, t') -> (t, hide_variant_name t')) tr in - let (t3, t4) = mismatch tr in - match tr with - | [] | _ :: [] -> assert false - | t1 :: t2 :: tr -> - try - let t1, t1' = prepare_expansion t1 - and t2, t2' = prepare_expansion t2 in - print_labels := not !Clflags.classic; - let tr = filter_trace tr in - let tr = List.map prepare_expansion tr in - fprintf ppf - "@[<v>\ - @[%t@;<1 2>%a@ \ - %t@;<1 2>%a\ - @]%a%t\ - @]" - txt1 (type_expansion t1) t1' - txt2 (type_expansion t2) t2' - (trace false "is not compatible with type") tr - (explanation unif t3 t4); - print_labels := true - with exn -> - print_labels := true; - raise exn - -let report_unification_error ppf tr txt1 txt2 = - unification_error true tr txt1 ppf txt2;; - -let trace fst txt ppf tr = - print_labels := not !Clflags.classic; - try match tr with - t1 :: t2 :: tr' -> - if fst then trace fst txt ppf (t1 :: t2 :: filter_trace tr') - else trace fst txt ppf (filter_trace tr); - print_labels := true - | _ -> () - with exn -> - print_labels := true; - raise exn - -let report_subtyping_error ppf tr1 txt1 tr2 = - reset (); - let tr1 = List.map prepare_expansion tr1 - and tr2 = List.map prepare_expansion tr2 in - trace true txt1 ppf tr1; - if tr2 = [] then () else - let t3, t4 = mismatch tr2 in - trace false "is not compatible with type" ppf tr2; - explanation true t3 t4 ppf |
