diff options
author | Jérôme Vouillon <Jerome.Vouillon@pps.jussieu.fr> | 1997-03-08 22:05:39 +0000 |
---|---|---|
committer | Jérôme Vouillon <Jerome.Vouillon@pps.jussieu.fr> | 1997-03-08 22:05:39 +0000 |
commit | be337662634824d98c79e7c42236e6ad9ace0158 (patch) | |
tree | 96b3011e3c15324cc5a25c71500df76601853020 | |
parent | 9198297d2ae873406e00a85bc29cd21677e050f4 (diff) |
Nettoyage de moregeneral et non_recursive_abbrev.
git-svn-id: http://caml.inria.fr/svn/ocaml/trunk@1348 f963ae5c-01c2-4b8c-9fe0-0dff7051ff02
-rw-r--r-- | typing/ctype.ml | 276 |
1 files changed, 138 insertions, 138 deletions
diff --git a/typing/ctype.ml b/typing/ctype.ml index 90ac1166f..75ea2c541 100644 --- a/typing/ctype.ml +++ b/typing/ctype.ml @@ -32,14 +32,14 @@ open Types as greatest). - The level of a type constructor is superior to the binding time of its path. - + - Recursive types without limitation should be handled (even if + there is still an occur check. *) (* A faire ======= - - Ordonner ctype.mli comme ctype.ml. - - Se debarasser de [Ident.identify] (utiliser plutot des substitutions). + - XXX Se debarasser de [Ident.identify] (utiliser plutot des substitutions). - Revoir affichage des types. - Types recursifs sans limitation. - Etendre la portee d'un alias [... as 'a] a tout le type englobant. @@ -77,6 +77,8 @@ exception Subtype of exception Cannot_expand +exception Recursive_abbrev + (**** Type level management ****) let generic_level = (-1) @@ -90,18 +92,23 @@ let end_def () = decr current_level let reset_global_level () = global_level := !current_level + 1 +(* Used to mark a type during a traversal. *) +let lowest_level = generic_level +let pivot_level = 2 * lowest_level - 1 + (* pivot_level - lowest_level < lowest_level *) + (**** Some type creators ****) +let newty desc = { desc = desc; level = !current_level } let newgenty desc = { desc = desc; level = generic_level } -let newgenvar () = newgenty Tvar +let new_global_ty desc = { desc = desc; level = !global_level } -let newty desc = { desc = desc; level = !current_level } let newvar () = { desc = Tvar; level = !current_level } -let newobj fields = newty (Tobject (fields, ref None)) - -let new_global_ty desc = { desc = desc; level = !global_level } +let newgenvar () = newgenty Tvar let new_global_var () = new_global_ty Tvar +let newobj fields = newty (Tobject (fields, ref None)) + let none = newty (Ttuple []) (* Clearly ill-formed type *) (**** Representative of a type ****) @@ -139,10 +146,7 @@ let flatten_fields ty = (List.rev l, r) let build_fields = - List.fold_right - (fun (s, ty1) ty2 -> - {desc = Tfield(s, ty1, ty2); - level = ty2.level}) + List.fold_right (fun (s, ty1) ty2 -> newty (Tfield(s, ty1, ty2))) let associate_fields fields1 fields2 = let rec associate p s s' = @@ -162,7 +166,7 @@ let associate_fields fields1 fields2 = (**** Check whether an object is open ****) -(* XXX Il faudra penser a eventuellement expanser l'abreviation *) +(* +++ Il faudra penser a eventuellement expanser l'abreviation *) let rec opened_object ty = match (repr ty).desc with Tobject (t, _) -> opened_object t @@ -188,7 +192,7 @@ let close_object ty = (**** Object name manipulation ****) -(* XXX Bientot obsolete *) +(* +++ Bientot obsolete *) let rec row_variable ty = let ty = repr ty in @@ -315,8 +319,8 @@ let make_nongen ty = update_level Env.empty !current_level ty (* Remove marks from a type. *) let rec unmark_type ty = let ty = repr ty in - if ty.level < -1 then begin - ty.level <- -10 - ty.level; + if ty.level < lowest_level then begin + ty.level <- pivot_level - ty.level; iter_type_expr unmark_type ty end @@ -521,7 +525,7 @@ let expand_abbrev env path args abbrev level = be correct anymore, and so we flush the cache. This is safe but quite pessimistic: it would be enough to flush the cache at the ends of structures and signatures. - XXX Do it ! + +++ Do it ! *) if env != !previous_env then begin cleanup_abbrev (); @@ -540,7 +544,7 @@ let expand_abbrev env path args abbrev level = generation and debugger), as a non-generic type variable can be instanciated afterwards to a previously undefined type constructor. - (XXX actually, it is still true for the moment, due to the + (+++ actually, it is still true for the moment, due to the strong constraint on type levels and constructor binding time.) (XXX except that moregeneral can bind variables to out of @@ -570,7 +574,6 @@ let rec expand_head env ty = (* Recursively expand the head of a type. Also expand #-types. *) -(* XXX Bricolage ! *) let rec full_expand env ty = let ty = repr (expand_head env ty) in match ty.desc with @@ -605,7 +608,7 @@ let generic_abbrev env path = exception Occur -(* XXX A supprimer (?) *) +(* +++ A supprimer (?) *) let occur env ty0 ty = let visited = ref ([] : type_expr list) in let rec occur_rec ty = @@ -628,7 +631,7 @@ let occur env ty0 ty = occur_rec ty (**** Transform error trace ****) -(* XXX Move it to some other place ? *) +(* +++ Move it to some other place ? *) let expand_trace env trace = List.fold_right @@ -652,9 +655,9 @@ let rec filter_trace = let deep_occur t0 ty = let rec occur_rec ty = let ty = repr ty in - if ty.level >= -1 then begin + if ty.level >= lowest_level then begin if ty == t0 then raise Occur; - ty.level <- -10 - ty.level; + ty.level <- pivot_level - ty.level; iter_type_expr occur_rec ty end in @@ -777,7 +780,7 @@ and unify3 env t1 t1' t2 t2' = Some (_, va::_) when (repr va).desc = Tvar -> () | _ -> nm2 := !nm1 end - | (Tfield _, Tfield _) -> + | (Tfield _, Tfield _) -> (* Actually unused *) unify_fields env t1 t2 | (Tnil, Tnil) -> () @@ -906,80 +909,91 @@ let rec filter_method env name ty = (* Matching between type schemes *) (***********************************) +(* + Levels: + !current_level : generic variables from the pattern + !current_level - 1 : generic variables from the subject + + A generic variable from the subject cannot be instantiated, and its + level must remain unchanged. A generic variable from the pattern + can be instantiated to anything. + + Usually, the subject is given by the user, and the pattern is + unimportant. So, no need to propagate abbreviations. +*) -(* XXX Remplacer -10 par une variable *) -(* Check that no generic variable occur in the type. *) -let moregen_occur ty = +(* + Update the level of [ty]. Check that the levels of generic variables + from the subject are not lowered. +*) +let moregen_occur env level ty = let rec occur_rec ty = let ty = repr ty in - if ty.level >= -1 then begin - if (ty.desc = Tvar) && (ty.level = !current_level) then raise Occur; - ty.level <- -10 - ty.level; + if ty.level >= !current_level - 1 then begin + if (ty.desc = Tvar) && (ty.level = !current_level - 1) then + raise Occur; + ty.level <- pivot_level - ty.level; iter_type_expr occur_rec ty end in - try - occur_rec ty; unmark_type ty - with Occur -> - unmark_type ty; raise (Unify []) + if level < !current_level - 1 then begin + begin try + occur_rec ty; unmark_type ty + with Occur -> + unmark_type ty; raise (Unify []) + end; + update_level env level ty + end -(* XXX On veut que le motif reste inchange *) -(* Le motif n'est pas necessairement completement polymorphe *) -(* XXX Undo complet en cas d'erreur ? *) let rec moregen env t1 t2 = if t1 == t2 then () else let t1 = repr t1 in let t2 = repr t2 in if t1 == t2 then () else - let d1 = t1.desc in + let d2 = ref t2.desc in + moregen_occur env t1.level t2; + (* Ensure termination *) + t2.desc <- Tlink t1; try - begin match (t1.desc, t2.desc) with - (Tvar, _) -> - if t1.level = generic_level then raise (Unify []); - (* t1 has level = !current_level iff it is generic - in the original type scheme. In this case, it can be freely - instantiated. Otherwise, t1 is not generic - and cannot be instantiated by a type that contains - generic variables. *) - if t1.level < !current_level then begin - let t2' = instance t2 in - moregen_occur t2'; - update_level env t1.level t2'; - t1.desc <- Tlink t2' - end else - t1.desc <- Tlink t2 + begin match (t1.desc, !d2) with + (Tvar, _) when t1.level <> !current_level - 1 -> + t2.desc <- !d2; + moregen_occur env t1.level t2; + t1.desc <- Tlink t2 + | (_, Tvar) when t2.level <> !current_level - 1 -> + moregen_occur env t2.level t1; + d2 := Tlink t1 | (Tarrow(t1, u1), Tarrow(t2, u2)) -> moregen env t1 t2; moregen env u1 u2 | (Ttuple tl1, Ttuple tl2) -> moregen_list env tl1 tl2 + | (Tconstr(p1, tl1, abbrev1), Tconstr(p2, tl2, abbrev2)) + when Path.same p1 p2 -> + begin try + moregen_list env tl1 tl2; + with Unify _ -> + try + moregen env t1 (expand_abbrev env p2 tl2 abbrev2 t2.level) + with Cannot_expand -> + t2.desc <- !d2; + try + moregen env (expand_abbrev env p1 tl1 abbrev1 t1.level) t2 + with Cannot_expand -> + raise (Unify []) + end | (Tconstr(p1, tl1, abbrev1), Tconstr(p2, tl2, abbrev2)) -> - if Path.same p1 p2 then begin - try - t1.desc <- Tlink t2; - moregen_list env tl1 tl2; - t1.desc <- d1 - with Unify lst -> - t1.desc <- d1; - try - moregen env (expand_abbrev env p1 tl1 abbrev1 t1.level) t2 - with Cannot_expand -> - try - moregen env t1 (expand_abbrev env p2 tl2 abbrev2 t2.level) - with Cannot_expand -> - raise (Unify lst) - end else begin - try - moregen env (expand_abbrev env p1 tl1 abbrev1 t1.level) t2 - with Cannot_expand -> - try - moregen env t1 (expand_abbrev env p2 tl2 abbrev2 t2.level) - with Cannot_expand -> - raise (Unify []) + begin try + moregen env (expand_abbrev env p1 tl1 abbrev1 t1.level) t2 + with Cannot_expand -> + try + moregen env t1 (expand_abbrev env p2 tl2 abbrev2 t2.level) + with Cannot_expand -> + raise (Unify []) end | (Tobject(f1, _), Tobject(f2, _)) -> - t1.desc <- Tlink t2; moregen_fields env f1 f2 | (Tconstr(p1, tl1, abbrev1), _) -> + t2.desc <- !d2; begin try moregen env (expand_abbrev env p1 tl1 abbrev1 t1.level) t2 with Cannot_expand -> @@ -991,11 +1005,17 @@ let rec moregen env t1 t2 = with Cannot_expand -> raise (Unify []) end + | (Tfield _, Tfield _) -> (* Actually unused *) + t2.desc <- !d2; + moregen_fields env t1 t2 + | (Tnil, Tnil) -> + () | (_, _) -> raise (Unify []) - end + end; + t2.desc <- !d2 with exn -> - t1.desc <- d1; + t2.desc <- !d2; raise exn and moregen_list env tl1 tl2 = @@ -1007,30 +1027,24 @@ and moregen_fields env ty1 ty2 = let (fields1, rest1) = flatten_fields ty1 and (fields2, rest2) = flatten_fields ty2 in let (pairs, miss1, miss2) = associate_fields fields1 fields2 in - (* Combiner avec [moregen]... *) - if miss1 <> [] then raise (Unify []); - begin match rest1.desc with - Tvar -> - if rest1.level = generic_level then raise (Unify []); - let fi = build_fields miss2 rest2 in - (* XXX ??? *) - if rest1.level < !current_level then moregen_occur fi - | Tnil -> - if miss2 <> [] then raise (Unify []); - if rest2.desc <> Tnil then raise (Unify []) - | _ -> - fatal_error "moregen_fields" - end; + let va = newvar () in + moregen env (build_fields miss1 va) rest2; + moregen env rest1 (build_fields miss2 va); List.iter (fun (t1, t2) -> moregen env t1 t2) pairs let moregeneral env sch1 sch2 = - begin_def(); + begin_def (); + let ty2 = instance sch2 in + begin_def (); + let ty1 = instance sch1 in try - moregen env (instance sch1) sch2; - end_def(); + moregen env ty1 ty2; + end_def (); + end_def (); true with Unify _ -> - end_def(); + end_def (); + end_def (); false @@ -1256,27 +1270,12 @@ and subtype_fields env trace ty1 ty2 = let (fields1, rest1) = flatten_fields ty1 in let (fields2, rest2) = flatten_fields ty2 in let (pairs, miss1, miss2) = associate_fields fields1 fields2 in - (* XXX A verifier... *) [(trace, rest1, build_fields miss2 (newvar ()))] -(* - begin match rest1.desc with - Tvar -> [(trace, rest1, build_fields miss2 (newvar ()))] - | Tnil -> if miss2 = [] then [] else subtype_error env trace - | _ -> fatal_error "Ctype.subtype_fields (1)" - end -*) @ begin match rest2.desc with Tnil -> [] | _ -> [(trace, build_fields miss1 rest1, rest2)] end -(* - begin match rest2.desc with - Tvar -> [(trace, build_fields miss1 (rest1), rest2)] - | Tnil -> [] - | _ -> fatal_error "Ctype.subtype_fields (2)" - end -*) @ (List.fold_left (fun cstrs (t1, t2) -> cstrs @ (subtype_rec env ((t1, t2)::trace) t1 t2)) @@ -1382,35 +1381,37 @@ let nondep_class_type env id decl = (******************************) -(* XXX A supprimer... (occur-check) *) -exception Recursive_abbrev +(* +++ A supprimer... (occur-check) *) + +let marked_types = ref [] -let rec non_recursive_abbrev env path constrs ty = +let rec non_recursive_abbrev env path ty = let ty = repr ty in - match ty.desc with - Tarrow (ty1, ty2) -> - non_recursive_abbrev env path constrs ty1; - non_recursive_abbrev env path constrs ty2 - | Ttuple tl -> - List.iter (non_recursive_abbrev env path constrs) tl - | Tconstr(p, args, abbrev) -> - if Path.same path p then + if ty.level >= lowest_level then begin + let level = ty.level in + ty.level <- pivot_level - level; + match ty.desc with + Tconstr(p, _, _) when Path.same path p -> raise Recursive_abbrev - else begin + | Tconstr(p, args, abbrev) -> begin try - let ty' = expand_abbrev env p args abbrev ty.level in - if List.memq ty' constrs then () else - non_recursive_abbrev env path (ty'::constrs) ty' - with Cannot_expand -> - () - end - end - | _ (* Tvar | Tobject (_, _) | Tfield (_, _, _) | Tnil *) -> - () + let ty' = repr (expand_abbrev env p args abbrev level) in + if ty'.level >= lowest_level then begin + marked_types := ty' :: !marked_types; + non_recursive_abbrev env path ty' + end + with Cannot_expand -> () end + | Tobject (_, _) -> + () + | _ -> + iter_type_expr (non_recursive_abbrev env path) ty + end let correct_abbrev env ident params ty = - let path = Path.Pident ident in - non_recursive_abbrev env path [] ty + marked_types := [ty]; + non_recursive_abbrev env (Path.Pident ident) ty; + List.iter unmark_type !marked_types; + marked_types := [] (**************************************) @@ -1423,12 +1424,12 @@ exception Failed of closed_schema_result let rec closed_schema_rec fullgen row ty = let ty = repr ty in - if ty.level >= -1 then begin + if ty.level >= lowest_level then begin let level = ty.level in if fullgen then - ty.level <- -10 - generic_level (* Generalize type *) + ty.level <- pivot_level - generic_level (* Generalize type *) else - ty.level <- -10 - level; + ty.level <- pivot_level - level; match ty.desc with Tvar when level != generic_level -> raise (Failed (if row then Row_var ty else Var ty)) @@ -1495,7 +1496,6 @@ let unroll_abbrev id tl ty = ty | _ -> let ty' = {desc = ty.desc; level = ty.level} in -(* let ty' = {desc = ty.desc; level = generic_level} in *) ty.desc <- Tlink {desc = Tconstr (Path.Pident id, tl, ref Mnil); level = ty.level}; ty' |