diff options
Diffstat (limited to 'contrib/extraction/mlutil.ml')
| -rw-r--r-- | contrib/extraction/mlutil.ml | 414 |
1 files changed, 355 insertions, 59 deletions
diff --git a/contrib/extraction/mlutil.ml b/contrib/extraction/mlutil.ml index 073d574bb9..0aa76805f7 100644 --- a/contrib/extraction/mlutil.ml +++ b/contrib/extraction/mlutil.ml @@ -36,7 +36,155 @@ let id_of_name = function | Name id when id = dummy_name -> anonymous | Name id -> id -(*S Operations upon ML types. *) +(*S Operations upon ML types (with meta). *) + +let meta_count = ref 0 + +let reset_meta_count () = meta_count := 0 + +let new_meta _ = + incr meta_count; + Tmeta {id = !meta_count; contents = None} + +(*s From a type schema to a type. All [Tvar] becomes fresh [Tmeta]. *) + +let instantiation (nb,t) = + let c = !meta_count in + let a = Array.make nb {id=0; contents = None} + in + for i = 0 to nb-1 do + a.(i) <- {id=i+c+1; contents=None} + done; + let rec var2meta t = match t with + | Tvar i -> Tmeta a.(i-1) + | Tmeta {contents=None} -> t + | Tmeta {contents=Some u} -> var2meta u + | Tglob (r,l) -> Tglob(r, List.map var2meta l) + | Tarr (t1,t2) -> Tarr (var2meta t1, var2meta t2) + | t -> t + in + meta_count := !meta_count + nb; + var2meta t + +(*s Occur-check of a uninstantiated meta in a type *) + +let rec type_occurs alpha t = + match t with + | Tmeta {id=beta; contents=None} -> alpha = beta + | Tmeta {contents=Some u} -> type_occurs alpha u + | Tarr (t1, t2) -> type_occurs alpha t1 || type_occurs alpha t2 + | Tglob (r,l) -> List.exists (type_occurs alpha) l + | _ -> false + +(*s Most General Unificator *) + +let rec mgu = function + | Tmeta m, Tmeta m' when m.id = m'.id -> () + | Tmeta m, t when m.contents=None -> + if type_occurs m.id t then raise Impossible + else m.contents <- Some t + | t, Tmeta m when m.contents=None -> + if type_occurs m.id t then raise Impossible + else m.contents <- Some t + | Tmeta {contents=Some u}, t -> mgu (u, t) + | t, Tmeta {contents=Some u} -> mgu (t, u) + | Tarr(a, b), Tarr(a', b') -> + mgu (a, a'); mgu (b, b') + | Tglob (r,l), Tglob (r',l') when r = r' -> + List.iter mgu (List.combine l l') + | Tvar i, Tvar j when i = j -> () + | Tvar' i, Tvar' j when i = j -> () + | Tdummy, Tdummy -> () + | Tunknown, Tunknown -> () + | _ -> raise Impossible + +let needs_magic p = try mgu p; false with Impossible -> true + +let put_magic_if b a = if b then MLmagic a else a + +let put_magic p a = if needs_magic p then MLmagic a else a + + +(*S ML type env. *) + +module Mlenv = struct + + let meta_cmp m m' = compare m.id m'.id + module Metaset = Set.Make(struct type t = ml_meta let compare = meta_cmp end) + + (* Main MLenv type. [env] is the real environment, whereas [free] + (tries to) keep trace of the free meta variables occurring in [env]. *) + + type t = { env : ml_schema list; mutable free : Metaset.t} + + (* Empty environment. *) + + let empty = { env = []; free = Metaset.empty } + + (* [get] returns a instantiated copy of the n-th most recently added + type in the environment. *) + + let get mle n = + assert (List.length mle.env >= n); + instantiation (List.nth mle.env (n-1)) + + (* [find_free] finds the free meta in a type. *) + + let rec find_free set = function + | Tmeta m when m.contents = None -> Metaset.add m set + | Tmeta {contents = Some t} -> find_free set t + | Tarr (a,b) -> find_free (find_free set a) b + | Tglob (_,l) -> List.fold_left find_free set l + | _ -> set + + (* The [free] set of an environment can be outdate after + some unifications. [clean_free] takes care of that. *) + + let clean_free mle = + let rem = ref Metaset.empty + and add = ref Metaset.empty in + let clean m = match m.contents with + | None -> () + | Some u -> rem := Metaset.add m !rem; add := find_free !add u + in + Metaset.iter clean mle.free; + mle.free <- Metaset.union (Metaset.diff mle.free !rem) !add + + (* From a type to a type schema. If a [Tmeta] is still uninstantiated + and does appears in the [mle], then it becomes a [Tvar]. *) + + let generalization mle t = + let c = ref 0 in + let map = ref (Intmap.empty : int Intmap.t) in + let add_new i = incr c; map := Intmap.add i !c !map; !c in + let rec meta2var t = match t with + | Tmeta {contents=Some u} -> meta2var u + | Tmeta ({id=i} as m) -> + (try Tvar (Intmap.find i !map) + with Not_found -> + if Metaset.mem m mle.free then t + else Tvar (add_new i)) + | Tarr (t1,t2) -> Tarr (meta2var t1, meta2var t2) + | Tglob (r,l) -> Tglob (r, List.map meta2var l) + | t -> t + in !c, meta2var t + + (* Adding a type in an environment, after generalizing. *) + + let push_gen mle t = + clean_free mle; + { env = generalization mle t :: mle.env; free = mle.free } + + let push_type {env=e;free=f} t = + { env = (0,t) :: e; free = find_free f t} + + let push_std_type {env=e;free=f} t = + { env = (0,t) :: e; free = f} + +end + + +(*S Operations upon ML types (without meta). *) (*s Does a section path occur in a ML type ? *) @@ -47,10 +195,118 @@ let kn_of_r r = match r with | _ -> assert false let rec type_mem_kn kn = function + | Tmeta _ -> assert false | Tglob (r,l) -> (kn_of_r r) = kn || List.exists (type_mem_kn kn) l | Tarr (a,b) -> (type_mem_kn kn a) || (type_mem_kn kn b) | _ -> false +let type_maxvar t = + let rec parse n = function + | Tmeta _ -> assert false + | Tvar i -> max i n + | Tarr (a,b) -> parse (parse n a) b + | Tglob (_,l) -> List.fold_left parse n l + | _ -> n + in parse 0 t + +let rec type_decomp = function + | Tmeta _ -> assert false + | Tarr (a,b) -> let l,h = type_decomp b in a::l, h + | a -> [],a + +let rec type_recomp (l,t) = match l with + | [] -> t + | a::l -> Tarr (a, type_recomp (l,t)) + +let rec var2var' = function + | Tmeta _ -> assert false + | Tvar i -> Tvar' i + | Tarr (a,b) -> Tarr (var2var' a, var2var' b) + | Tglob (r,l) -> Tglob (r, List.map var2var' l) + | a -> a + +(*s Sustitution of [Tvar i] by [t] in a ML type. *) + +let type_subst i t = + let rec subst = function + | Tvar j when i = j -> t + | Tarr (a,b) -> Tarr (subst a, subst b) + | Tglob (r, l) -> Tglob (r, List.map subst l) + | a -> a + in subst + +(* Simultaneous substitution of [Tvar 1;...; Tvar n] by [l] in a ML type. *) + +let type_subst_all l t = + let rec subst = function + | Tvar j -> List.nth l (j-1) + | Tarr (a,b) -> Tarr (subst a, subst b) + | Tglob (r, l) -> Tglob (r, List.map subst l) + | a -> a + in subst t + +type abbrev_map = global_reference -> ml_type option + +(*s Delta-reduction of type constants everywhere in a ML type [t]. + [env] is a function of type [ml_type_env]. *) + +let type_expand env t = + let rec expand = function + | Tglob (r,l) as t -> + (match env r with + | Some mlt -> expand (type_subst_all l mlt) + | None -> Tglob (r, List.map expand l)) + | Tarr (a,b) -> Tarr (expand a, expand b) + | a -> a + in expand t + +(*s Idem, but only at the top level of implications. *) + +let is_arrow = function Tarr _ -> true | _ -> false + +let type_weak_expand env t = + let rec expand = function + | Tglob (r,l) as t -> + (match env r with + | Some mlt -> + let u = expand (type_subst_all l mlt) in + if is_arrow u then u else t + | None -> t) + | Tarr (a,b) -> Tarr (a, expand b) + | a -> a + in expand t + +(*s Equality over ML types modulo delta-reduction *) + +let type_eq env t t' = (type_expand env t = type_expand env t') + +let type_neq env t t' = (type_expand env t <> type_expand env t') + +let type_to_sign env t = + let rec f = function + | Tarr (a,b) -> (Tdummy <> a) :: (f b) + | _ -> [] + in f (type_expand env t) + +let type_expunge env t = + let s = type_to_sign env t in + if s = [] then t + else if List.mem true s then + let rec f t s = + if List.mem false s then + match t with + | Tarr (a,b) -> + let t = f b (List.tl s) in + if List.hd s then Tarr (a, t) else t + | Tglob (r,l) -> + (match env r with + | Some mlt -> f (type_subst_all l mlt) s + | None -> assert false) + | _ -> assert false + else t + in f t s + else Tarr (Tdummy, snd (type_decomp (type_weak_expand env t))) + (*S Generic functions over ML ast terms. *) (*s [ast_iter_rel f t] applies [f] on every [MLrel] in t. It takes care @@ -68,7 +324,7 @@ let ast_iter_rel f = | MLcons (_,l) -> List.iter (iter n) l | MLcast (a,_) -> iter n a | MLmagic a -> iter n a - | MLglob _ | MLexn _ | MLdummy | MLdummy' -> () + | MLglob _ | MLexn _ | MLdummy -> () in iter 0 (*s Map over asts. *) @@ -84,7 +340,7 @@ let ast_map f = function | MLcons (c,l) -> MLcons (c, List.map f l) | MLcast (a,t) -> MLcast (f a, t) | MLmagic a -> MLmagic (f a) - | MLrel _ | MLglob _ | MLexn _ | MLdummy | MLdummy' as a -> a + | MLrel _ | MLglob _ | MLexn _ | MLdummy as a -> a (*s Map over asts, with binding depth as parameter. *) @@ -100,7 +356,7 @@ let ast_map_lift f n = function | MLcons (c,l) -> MLcons (c, List.map (f n) l) | MLcast (a,t) -> MLcast (f n a, t) | MLmagic a -> MLmagic (f n a) - | MLrel _ | MLglob _ | MLexn _ | MLdummy | MLdummy' as a -> a + | MLrel _ | MLglob _ | MLexn _ | MLdummy as a -> a (*s Iter over asts. *) @@ -115,7 +371,7 @@ let ast_iter f = function | MLcons (c,l) -> List.iter f l | MLcast (a,t) -> f a | MLmagic a -> f a - | MLrel _ | MLglob _ | MLexn _ | MLdummy | MLdummy' as a -> () + | MLrel _ | MLglob _ | MLexn _ | MLdummy as a -> () (*S Searching occurrences of a particular term (no lifting done). *) @@ -124,17 +380,35 @@ let rec ast_search t a = let decl_search t l = let one_decl = function - | Dterm (_,a) -> ast_search t a - | Dfix (_,c) -> Array.iter (ast_search t) c + | Dterm (_,a,_) -> ast_search t a + | Dfix (_,c,_) -> Array.iter (ast_search t) c + | _ -> () + in + try List.iter one_decl l; false with Found -> true + +let rec type_search t = function + | Tarr (a,b) -> type_search t a; type_search t b + | Tglob (r,l) -> List.iter (type_search t) l + | u -> if t = u then raise Found + +let decl_type_search t l = + let one_decl = function + | Dind(l,_) -> + List.iter (fun (_,_,l) -> + (List.iter (fun (_,l) -> + List.iter (type_search t) l) l)) l + | Dterm (_,_,u) -> type_search t u + | Dfix (_,_,v) -> Array.iter (type_search t) v + | Dtype (_,_,u) -> type_search t u | _ -> () in try List.iter one_decl l; false with Found -> true (*S Operations concerning De Bruijn indices. *) -(*s [occurs k t] returns [true] if [(Rel k)] occurs in [t]. *) +(*s [ast_occurs k t] returns [true] if [(Rel k)] occurs in [t]. *) -let occurs k t = +let ast_occurs k t = try ast_iter_rel (fun i -> if i = k then raise Found) t; false with Found -> true @@ -157,16 +431,15 @@ let nb_occur_k k t = let nb_occur t = nb_occur_k 1 t (*s Lifting on terms. - [ml_lift k t] lifts the binding depth of [t] across [k] bindings. *) + [ast_lift k t] lifts the binding depth of [t] across [k] bindings. *) -let ml_lift k t = +let ast_lift k t = let rec liftrec n = function | MLrel i as a -> if i-n < 1 then a else MLrel (i+k) | a -> ast_map_lift liftrec n a in if k = 0 then t else liftrec 0 t -let ml_pop t = ml_lift (-1) t - +let ast_pop t = ast_lift (-1) t (*s [permut_rels k k' c] translates [Rel 1 ... Rel k] to [Rel (k'+1) ... Rel (k'+k)] and [Rel (k+1) ... Rel (k+k')] to [Rel 1 ... Rel k'] *) @@ -184,11 +457,11 @@ let permut_rels k k' = (*s Substitution. [ml_subst e t] substitutes [e] for [Rel 1] in [t]. Lifting (of one binder) is done at the same time. *) -let rec ml_subst e = +let ast_subst e = let rec subst n = function | MLrel i as a -> let i' = i-n in - if i'=1 then ml_lift n e + if i'=1 then ast_lift n e else if i'<1 then a else MLrel (i-1) | a -> ast_map_lift subst n a @@ -205,7 +478,7 @@ let gen_subst v d t = let i'= i-n in if i' < 1 then a else if i' < Array.length v then - if v.(i') = 0 then MLdummy' + if v.(i') = 0 then MLdummy else MLrel (v.(i')+n) else MLrel (i+d) | a -> ast_map_lift subst n a @@ -264,6 +537,13 @@ let rec dummy_lams a = function | 0 -> a | n -> dummy_lams (MLlam (dummy_name,a)) (pred n) +(*s mixed according to a signature. *) + +let rec anonym_or_dummy_lams a = function + | [] -> a + | true :: s -> MLlam(anonymous, anonym_or_dummy_lams a s) + | false :: s -> MLlam(dummy_name, anonym_or_dummy_lams a s) + (*S Operations concerning eta. *) (*s The following function creates [MLrel n;...;MLrel 1] *) @@ -271,6 +551,13 @@ let rec dummy_lams a = function let rec eta_args n = if n = 0 then [] else (MLrel n)::(eta_args (pred n)) +(*s Same, but filtered by a signature. *) + +let rec eta_args_sign n = function + | [] -> [] + | true :: s -> (MLrel n) :: (eta_args_sign (n-1) s) + | false :: s -> eta_args_sign (n-1) s + (*s This one tests [MLrel (n+k); ... ;MLrel (1+k)] *) let rec test_eta_args_lift k n = function @@ -291,7 +578,7 @@ let eta_red e = let a1,a2 = list_chop m a in let f = if m = 0 then f else MLapp (f,a1) in if test_eta_args_lift 0 n a2 && not (occurs_itvl 1 n f) - then ml_lift (-n) f + then ast_lift (-n) f else e | _ -> e @@ -331,11 +618,11 @@ let check_constant_case br = let (r,l,t) = br.(0) in let n = List.length l in if occurs_itvl 1 n t then raise Impossible; - let cst = ml_lift (-n) t in + let cst = ast_lift (-n) t in for i = 1 to Array.length br - 1 do let (r,l,t) = br.(i) in let n = List.length l in - if (occurs_itvl 1 n t) || (cst <> (ml_lift (-n) t)) + if (occurs_itvl 1 n t) || (cst <> (ast_lift (-n) t)) then raise Impossible done; cst @@ -382,7 +669,7 @@ let iota_gen br = | MLcons (r,a) -> let (_,ids,c) = br.(constructor_index r) in let c = List.fold_right (fun id t -> MLlam (id,t)) ids c in - let c = ml_lift k c in + let c = ast_lift k c in MLapp (c,a) | MLcase(e,br') -> let new_br = @@ -392,7 +679,7 @@ let iota_gen br = in iota 0 let is_atomic = function - | MLrel _ | MLglob _ | MLexn _ | MLdummy | MLdummy' -> true + | MLrel _ | MLglob _ | MLexn _ | MLdummy -> true | _ -> false (*S The main simplification function. *) @@ -409,38 +696,38 @@ let rec simpl o = function simpl_case o br (simpl o e) | MLletin(id,c,e) when (id = dummy_name) || (is_atomic c) || (nb_occur e <= 1) -> - simpl o (ml_subst c e) + simpl o (ast_subst c e) | MLfix(i,ids,c) as t when o -> let n = Array.length ids in if occurs_itvl 1 n c.(i) then MLfix (i, ids, Array.map (simpl o) c) - else simpl o (ml_lift (-n) c.(i)) (* Dummy fixpoint *) + else simpl o (ast_lift (-n) c.(i)) (* Dummy fixpoint *) | a -> ast_map (simpl o) a and simpl_app o a = function | MLapp (f',a') -> simpl_app o (a'@a) f' | MLlam (id,t) when id = dummy_name -> - simpl o (MLapp (ml_pop t, List.tl a)) + simpl o (MLapp (ast_pop t, List.tl a)) | MLlam (id,t) -> (* Beta redex *) (match nb_occur t with - | 0 -> simpl o (MLapp (ml_pop t, List.tl a)) + | 0 -> simpl o (MLapp (ast_pop t, List.tl a)) | 1 when o -> - simpl o (MLapp (ml_subst (List.hd a) t, List.tl a)) + simpl o (MLapp (ast_subst (List.hd a) t, List.tl a)) | _ -> - let a' = List.map (ml_lift 1) (List.tl a) in + let a' = List.map (ast_lift 1) (List.tl a) in simpl o (MLletin (id, List.hd a, MLapp (t, a')))) | MLletin (id,e1,e2) -> (* Application of a letin: we push arguments inside *) - MLletin (id, e1, simpl o (MLapp (e2, List.map (ml_lift 1) a))) + MLletin (id, e1, simpl o (MLapp (e2, List.map (ast_lift 1) a))) | MLcase (e,br) -> (* Application of a case: we push arguments inside *) let br' = Array.map (fun (n,l,t) -> let k = List.length l in - let a' = List.map (ml_lift k) a in + let a' = List.map (ast_lift k) a in (n, l, simpl o (MLapp (t,a')))) br in simpl o (MLcase (e,br')) - | (MLdummy | MLdummy' | MLexn _) as e -> e + | (MLdummy | MLexn _) as e -> e (* We just discard arguments in those cases. *) | f -> MLapp (f,a) @@ -461,11 +748,11 @@ and simpl_case o br e = let ids,br = permut_case_fun br [] in let n = List.length ids in if n = 0 then MLcase (e, br) - else named_lams ids (MLcase (ml_lift n e, br)) + else named_lams ids (MLcase (ast_lift n e, br)) let rec post_simpl = function | MLletin(_,c,e) when (is_atomic (eta_red c)) -> - post_simpl (ml_subst (eta_red c) e) + post_simpl (ast_subst (eta_red c) e) | a -> ast_map post_simpl a (*S Local prop elimination. *) @@ -491,7 +778,7 @@ let kill_some_lams bl (ids,c) = let n = List.length bl in let n' = List.fold_left (fun n b -> if b then (n+1) else n) 0 bl in if n = n' then ids,c - else if n' = 0 then [],ml_lift (-n) c + else if n' = 0 then [],ast_lift (-n) c else begin let v = Array.make (n+1) 0 in let rec parse_ids i j = function @@ -523,15 +810,15 @@ let kill_dummy_args ids t0 t = let m = List.length ids in let bl = List.rev_map ((<>) dummy_name) ids in let rec killrec n = function - | MLapp(e, a) when e = ml_lift n t0 -> + | MLapp(e, a) when e = ast_lift n t0 -> let k = max 0 (m - (List.length a)) in let a = List.map (killrec n) a in - let a = List.map (ml_lift k) a in + let a = List.map (ast_lift k) a in let a = select_via_bl bl (a @ (eta_args k)) in - named_lams (list_firstn k ids) (MLapp (ml_lift k e, a)) - | e when e = ml_lift n t0 -> + named_lams (list_firstn k ids) (MLapp (ast_lift k e, a)) + | e when e = ast_lift n t0 -> let a = select_via_bl bl (eta_args m) in - named_lams ids (MLapp (ml_lift m e, a)) + named_lams ids (MLapp (ast_lift m e, a)) | e -> ast_map_lift killrec n e in killrec 0 t @@ -541,14 +828,14 @@ let rec kill_dummy = function | MLfix(i,fi,c) -> (try let ids,c = kill_dummy_fix i fi c in - ml_subst (MLfix (i,fi,c)) (kill_dummy_args ids (MLrel 1) (MLrel 1)) + ast_subst (MLfix (i,fi,c)) (kill_dummy_args ids (MLrel 1) (MLrel 1)) with Impossible -> MLfix (i,fi,Array.map kill_dummy c)) | MLapp (MLfix (i,fi,c),a) -> (try let ids,c = kill_dummy_fix i fi c in - let a = List.map (fun t -> ml_lift 1 (kill_dummy t)) a in + let a = List.map (fun t -> ast_lift 1 (kill_dummy t)) a in let e = kill_dummy_args ids (MLrel 1) (MLapp (MLrel 1,a)) in - ml_subst (MLfix (i,fi,c)) e + ast_subst (MLfix (i,fi,c)) e with Impossible -> MLapp(MLfix(i,fi,Array.map kill_dummy c),List.map kill_dummy a)) | MLletin(id, MLfix (i,fi,c),e) -> @@ -591,7 +878,7 @@ let general_optimize_fix f ids n args m c = in list_iter_i aux args; let args_f = List.rev_map (fun i -> MLrel (i+m+1)) (Array.to_list v) in let new_f = anonym_lams (MLapp (MLrel (n+m+1),args_f)) m in - let new_c = named_lams ids (normalize (MLapp ((ml_subst new_f c),args))) in + let new_c = named_lams ids (normalize (MLapp ((ast_subst new_f c),args))) in MLfix(0,[|f|],[|new_c|]) let optimize_fix a = @@ -603,7 +890,7 @@ let optimize_fix a = else match a' with | MLfix(_,[|f|],[|c|]) -> let new_f = MLapp (MLrel (n+1),eta_args n) in - let new_c = named_lams ids (normalize (ml_subst new_f c)) + let new_c = named_lams ids (normalize (ast_subst new_f c)) in MLfix(0,[|f|],[|new_c|]) | MLapp(a',args) -> let m = List.length args in @@ -783,7 +1070,7 @@ let subst_glob_ast r m = in substrec let subst_glob_decl r m = function - | Dterm(r',t') -> Dterm(r', subst_glob_ast r m t') + | Dterm(r',t',typ) -> Dterm(r', subst_glob_ast r m t', typ) | d -> d let inline_glob r t l = @@ -802,40 +1089,42 @@ let add_ml_decls prm decls = let l2 = List.map (fun (r,s)-> DcustomTerm (r,s)) l2 in l1 @ l2 @ decls -let rec expunge_fix_decls prm v c b = function - | [] -> b, [] - | Dterm (r, t) :: l when array_exists ((=) r) v -> +let rec expunge_fix_decls prm v c map b = function + | [] -> b, [], map + | Dterm (r, t, typ) :: l when array_exists ((=) r) v -> let t = normalize t in let t' = optimize_fix t in (match t' with | MLfix(_,_,c') when c=c' -> let b',l = inline_glob r t l in - expunge_fix_decls prm v c (b || b' || List.mem r prm.to_appear) l + let b = b || b' || List.mem r prm.to_appear in + let map = Refmap.add r typ map in + expunge_fix_decls prm v c map b l | _ -> raise Impossible) - | d::l -> let b,l = expunge_fix_decls prm v c b l in b, d::l + | d::l -> let b,l,map = expunge_fix_decls prm v c map b l in b, d::l, map let rec optimize prm = function | [] -> [] - | (DdummyType r | Dterm(r,MLdummy')) as d :: l -> + | (Dtype (r,_,Tdummy) | Dterm(r,MLdummy,_)) as d :: l -> if List.mem r prm.to_appear then d :: (optimize prm l) else optimize prm l - | Dterm (r,t) :: l -> + | Dterm (r,t,typ) :: l -> let t = normalize t in let b,l = inline_glob r t l in let b = b || prm.modular || List.mem r prm.to_appear in let t' = optimize_fix t in - (try optimize_Dfix prm r t' b l - with Impossible -> - if b then Dterm (r,t') :: (optimize prm l) - else optimize prm l) + (try optimize_Dfix prm (r,t',typ) b l + with Impossible -> + if b then Dterm (r,t',typ) :: (optimize prm l) + else optimize prm l) | d :: l -> d :: (optimize prm l) -and optimize_Dfix prm r t b l = +and optimize_Dfix prm (r,t,typ) b l = match t with | MLfix (_, f, c) -> if Array.length f = 1 then - if b then Dfix ([|r|], c) :: (optimize prm l) + if b then Dfix ([|r|], c,[|typ|]) :: (optimize prm l) else optimize prm l else let v = try @@ -843,8 +1132,15 @@ and optimize_Dfix prm r t b l = Array.map (fun id -> locate (make_qualid d id)) f with Not_found -> raise Impossible in - let b,l = expunge_fix_decls prm v c b l in - if b then Dfix (v, c) :: (optimize prm l) + let map = Refmap.add r typ (Refmap.empty) in + let b,l,map = expunge_fix_decls prm v c map b l in + if b then + let typs = + Array.map + (fun r -> try Refmap.find r map + with Not_found -> Tunknown) v + in + Dfix (v, c, typs) :: (optimize prm l) else optimize prm l | _ -> raise Impossible |
