2 ||M|| This file is part of HELM, an Hypertextual, Electronic
3 ||A|| Library of Mathematics, developed at the Computer Science
4 ||T|| Department, University of Bologna, Italy.
6 ||T|| HELM is free software; you can redistribute it and/or
7 ||A|| modify it under the terms of the GNU General Public License
8 \ / version 2 or (at your option) any later version.
9 \ / This software is distributed as is, NO WARRANTY.
10 V_______________________________________________________________ *)
12 (* let debug s = prerr_endline (Lazy.force s) ;;*)
15 let skel_dummy = NCic.Implicit `Type;;
29 HExtlib.list_findopt (fun y i -> if y = x then Some i else None) l
32 | None -> assert false
35 let rec count_prod = function
36 | NCic.Prod (_,_,x) -> 1 + count_prod x
44 HExtlib.list_findopt (fun y j -> if i+1=j then Some y else None) l
47 | None -> assert false)
51 let rec cleanup_funclass_skel = function
52 | NCic.Prod (_,_,t) ->
53 NCic.Prod ("_",skel_dummy, cleanup_funclass_skel t)
57 let src_tgt_of_ty_cpos_arity status ty cpos arity =
58 let pis = count_prod ty in
59 let tpos = pis - arity in
60 let rec pi_nth i j = function
61 | NCic.Prod (_,s,_) when i = j -> s
62 | NCic.Prod (_,_,t) -> pi_nth (i+1) j t
63 | t -> assert (i = j); t
65 let rec pi_tail i j = function
66 | NCic.Prod (_,_,_) as t when i = j -> cleanup_funclass_skel t
67 | NCic.Prod (_,_,t) -> pi_tail (i+1) j t
68 | t -> assert (i = j); t
71 let rec aux () = function
73 | NCic.Implicit _ as x -> x
74 | NCic.Rel _ -> skel_dummy
75 | t -> NCicUtils.map status (fun _ () -> ()) () aux t
79 mask (pi_nth 0 cpos ty),
80 mask (pi_tail 0 tpos ty)
83 let rec cleanup_skel status () = function
84 | NCic.Meta _ -> skel_dummy
85 | t -> NCicUtils.map status (fun _ () -> ()) () (cleanup_skel status) t
88 let close_in_context status t metasenv =
89 let rec aux m_subst subst ctx = function
90 | (i,(tag,[],ty)) :: tl ->
91 let name = "x" ^ string_of_int (List.length ctx) in
92 let subst = (i,(tag,[],NCic.Rel (List.length tl+1),ty))::subst in
93 let ty = NCicUntrusted.apply_subst status (m_subst (List.length ctx)) ctx ty in
95 (i,(tag,[],NCic.Rel (m-List.length ctx),ty))::(m_subst m)
97 NCic.Lambda (name, ty, aux m_subst subst ((name,NCic.Decl ty)::ctx) tl)
100 since metas occurring in t have an empty context,
101 the substitution i build makes sense (i.e, the Rel
102 I pun in the subst will not be lifted by subst_meta *)
103 NCicUntrusted.apply_subst status subst ctx
104 (NCicSubstitution.lift status (List.length ctx) t)
107 aux (fun _ -> []) [] [] metasenv
110 let toposort status metasenv =
111 let module T = HTopoSort.Make(
112 struct type t = int * NCic.conjecture let compare (i,_) (j,_) = i-j end)
114 let deps (_,(_,_,t)) =
115 List.filter (fun (j,_) ->
116 List.mem j (NCicUntrusted.metas_of_term status [] [] t)) metasenv
118 T.topological_sort metasenv deps
121 let only_head = function
122 | NCic.Appl (h::tl) ->
123 NCic.Appl (h :: HExtlib.mk_list skel_dummy (List.length tl))
127 let src_tgt_cpos_arity_of_ty_id_src_tgt status ty id src tgt =
128 let status, src, cpos =
129 let rec aux cpos ctx = function
130 | NCic.Prod (name,ty,bo) ->
131 if name <> id then aux (cpos+1) ((name,NCic.Decl ty)::ctx) bo
134 let metasenv,subst,status,src =
135 GrafiteDisambiguate.disambiguate_nterm
136 status None ctx [] [] ("",0,src) in
137 let src = NCicUntrusted.apply_subst status subst [] src in
138 (* CHECK that the declared pattern matches the abstraction *)
139 let _ = NCicUnification.unify status metasenv subst ctx ty src in
140 let src = cleanup_skel status () src in
143 | NCicUnification.UnificationFailure _
144 | NCicUnification.Uncertain _
145 | MultiPassDisambiguator.DisambiguationError _ ->
146 raise (GrafiteTypes.Command_error "bad source pattern"))
151 let status, tgt, arity =
152 let metasenv,subst,status,tgt =
153 GrafiteDisambiguate.disambiguate_nterm
154 status None [] [] [] ("",0,tgt) in
155 let tgt = NCicUntrusted.apply_subst status subst [] tgt in
156 (* CHECK che sia unificabile mancante *)
157 let rec count_prod = function
158 | NCic.Prod (_,_,x) -> 1 + count_prod x
161 let arity = count_prod tgt in
163 if arity > 0 then cleanup_funclass_skel tgt
164 else cleanup_skel status () tgt
168 status, src, tgt, cpos, arity
171 let fresh_uri status prefix suffix =
172 let mk x = NUri.uri_of_string (status#baseuri ^ "/" ^ prefix ^ x ^ suffix) in
173 let rec diverge u i =
174 if NCicLibrary.aliases_of u = [] then u
175 else diverge (mk ("__" ^ string_of_int i)) (i+1)
182 let close_graph name t s d to_s from_d p a status =
185 (function (_,_,NCic.Appl (x::_),_,_) -> x = t | _ -> assert false)
186 (NCicCoercion.look_for_coercion status [] [] [] s d)
188 let compose_names a b = a ^ "__o__" ^ b in
192 (fun (n1,m1,t1,_,j) (n,mc,c,_,i) ->
193 compose_names n1 n,m1@mc,c,[i,t1],j,a)
198 (fun (n,mc,c,_,j) (n1,m1,t1,ty,i) ->
199 compose_names n n1,m1@mc,t1,[i,c],j,count_prod ty)
202 let to_s_o_c_o_from_d =
204 (fun (n1,m1,t1,_,j) (n,m,t,upl,i,a)->
205 compose_names n1 n,m@m1,t,(i,t1)::upl,j,a)
208 to_s_o_c @ c_o_from_d @ to_s_o_c_o_from_d
212 (fun (name,metasenv, bo, upl, p, arity) ->
214 let metasenv, subst =
216 (fun (metasenv,subst) (a,b) ->
217 NCicUnification.unify status metasenv subst [] a b)
220 let bo = NCicUntrusted.apply_subst status subst [] bo in
221 let p = NCicUntrusted.apply_subst status subst [] p in
222 let metasenv = NCicUntrusted.apply_subst_metasenv status subst metasenv in
223 let metasenv = toposort status metasenv in
224 let bo = close_in_context status bo metasenv in
227 | NCic.Meta (p,_) -> pos_in_list p (List.map fst metasenv)
230 let ty = NCicTypeChecker.typeof status ~metasenv:[] ~subst:[] [] bo in
231 let src,tgt = src_tgt_of_ty_cpos_arity status ty pos arity in
232 let src = only_head src in
233 let tgt = only_head tgt in
235 "composite " ^ name ^ ": "^
236 status#ppterm ~metasenv:[] ~subst:[] ~context:[] bo ^ " : " ^
237 status#ppterm ~metasenv:[] ~subst:[] ~context:[] ty ^ " as " ^
238 status#ppterm ~metasenv:[] ~subst:[] ~context:[] src ^ " ===> " ^
239 status#ppterm ~metasenv:[] ~subst:[] ~context:[] tgt ^
240 " cpos=" ^ string_of_int pos ^ " arity=" ^ string_of_int arity));
241 let uri = fresh_uri status name ".con" in
242 let obj_kind = NCic.Constant
243 ([],name,Some bo,ty,(`Generated,`Definition,`Coercion arity))
245 let height = NCicTypeChecker.height_of_obj_kind status uri [] obj_kind in
246 let obj = uri,height,[],[],obj_kind in
249 (NReference.reference_of_spec uri (NReference.Def height))
251 Some (obj,name,c,src,tgt,pos,arity)
253 | NCicTypeChecker.TypeCheckerFailure _
254 | NCicUnification.UnificationFailure _
255 | NCicUnification.Uncertain _ | Stop -> None
262 let basic_index_ncoercion (name,t,s,d,position,arity) status =
263 NCicCoercion.index_coercion status name t s d arity position
266 let basic_eval_ncoercion (name,t,s,d,p,a) status =
268 NCicCoercion.look_for_coercion status [] [] [] skel_dummy s
271 NCicCoercion.look_for_coercion status [] [] [] d skel_dummy
273 let status = NCicCoercion.index_coercion status name t s d a p in
274 let composites = close_graph name t s d to_s from_d p a status in
276 (fun (uris,infos,st) ((uri,_,_,_,_ as obj),name,t,s,d,p,a) ->
277 let info = name,t,s,d,p,a in
278 let st = NCicLibrary.add_obj st obj in
279 let st = basic_index_ncoercion info st in
280 uri::uris, info::infos, st)
281 ([],[],status) composites
284 let record_ncoercion =
285 let aux (name,t,s,d,p,a) ~refresh_uri_in_term =
286 let t = refresh_uri_in_term t in
287 let s = refresh_uri_in_term s in
288 let d = refresh_uri_in_term d in
289 basic_index_ncoercion (name,t,s,d,p,a)
291 let aux_l l ~refresh_uri_in_universe ~refresh_uri_in_term
292 ~refresh_uri_in_reference ~alias_only status
294 if not alias_only then
295 List.fold_right (aux ~refresh_uri_in_term:(refresh_uri_in_term (status:>NCic.status))) l status
299 GrafiteTypes.Serializer.register#run "ncoercion" aux_l
302 let basic_eval_and_record_ncoercion infos status =
303 let uris, cinfos, status = basic_eval_ncoercion infos status in
304 NCicLibrary.dump_obj status (record_ncoercion (infos::cinfos)), uris
307 let basic_eval_and_record_ncoercion_from_t_cpos_arity
308 status (name,t,cpos,arity)
310 let ty = NCicTypeChecker.typeof status ~subst:[] ~metasenv:[] [] t in
311 let src,tgt = src_tgt_of_ty_cpos_arity status ty cpos arity in
313 basic_eval_and_record_ncoercion (name,t,src,tgt,cpos,arity) status
318 let eval_ncoercion (status: #GrafiteTypes.status) name t ty (id,src) tgt =
319 let metasenv,subst,status,ty =
320 GrafiteDisambiguate.disambiguate_nterm status None [] [] [] ("",0,ty) in
321 assert (metasenv=[]);
322 let ty = NCicUntrusted.apply_subst status subst [] ty in
323 let metasenv,subst,status,t =
324 GrafiteDisambiguate.disambiguate_nterm status (Some ty) [] [] [] ("",0,t) in
325 assert (metasenv=[]);
326 let t = NCicUntrusted.apply_subst status subst [] t in
327 let status, src, tgt, cpos, arity =
328 src_tgt_cpos_arity_of_ty_id_src_tgt status ty id src tgt in
330 basic_eval_and_record_ncoercion (name,t,src,tgt,cpos,arity) status