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 msg
144 | NCicUnification.Uncertain msg ->
145 raise (GrafiteTypes.Command_error ("bad source pattern: " ^
147 | MultiPassDisambiguator.DisambiguationError _ ->
148 raise (GrafiteTypes.Command_error ("bad source pattern:
149 disambiguation error")))
154 let status, tgt, arity =
155 let metasenv,subst,status,tgt =
156 GrafiteDisambiguate.disambiguate_nterm
157 status None [] [] [] ("",0,tgt) in
158 let tgt = NCicUntrusted.apply_subst status subst [] tgt in
159 (* CHECK che sia unificabile mancante *)
160 let rec count_prod = function
161 | NCic.Prod (_,_,x) -> 1 + count_prod x
164 let arity = count_prod tgt in
166 if arity > 0 then cleanup_funclass_skel tgt
167 else cleanup_skel status () tgt
171 status, src, tgt, cpos, arity
174 let fresh_uri status prefix suffix =
175 let mk x = NUri.uri_of_string (status#baseuri ^ "/" ^ prefix ^ x ^ suffix) in
176 let rec diverge u i =
177 if NCicLibrary.aliases_of u = [] then u
178 else diverge (mk ("__" ^ string_of_int i)) (i+1)
185 let close_graph name t s d to_s from_d p a status =
188 (function (_,_,NCic.Appl (x::_),_,_) -> x = t | _ -> assert false)
189 (NCicCoercion.look_for_coercion status [] [] [] s d)
191 let compose_names a b = a ^ "__o__" ^ b in
195 (fun (n1,m1,t1,_,j) (n,mc,c,_,i) ->
196 compose_names n1 n,m1@mc,c,[i,t1],j,a)
201 (fun (n,mc,c,_,j) (n1,m1,t1,ty,i) ->
202 compose_names n n1,m1@mc,t1,[i,c],j,count_prod ty)
205 let to_s_o_c_o_from_d =
207 (fun (n1,m1,t1,_,j) (n,m,t,upl,i,a)->
208 compose_names n1 n,m@m1,t,(i,t1)::upl,j,a)
211 to_s_o_c @ c_o_from_d @ to_s_o_c_o_from_d
215 (fun (name,metasenv, bo, upl, p, arity) ->
217 let metasenv, subst =
219 (fun (metasenv,subst) (a,b) ->
220 NCicUnification.unify status metasenv subst [] a b)
223 let bo = NCicUntrusted.apply_subst status subst [] bo in
224 let p = NCicUntrusted.apply_subst status subst [] p in
225 let metasenv = NCicUntrusted.apply_subst_metasenv status subst metasenv in
226 let metasenv = toposort status metasenv in
227 let bo = close_in_context status bo metasenv in
230 | NCic.Meta (p,_) -> pos_in_list p (List.map fst metasenv)
233 let ty = NCicTypeChecker.typeof status ~metasenv:[] ~subst:[] [] bo in
234 let src,tgt = src_tgt_of_ty_cpos_arity status ty pos arity in
235 let src = only_head src in
236 let tgt = only_head tgt in
238 "composite " ^ name ^ ": "^
239 status#ppterm ~metasenv:[] ~subst:[] ~context:[] bo ^ " : " ^
240 status#ppterm ~metasenv:[] ~subst:[] ~context:[] ty ^ " as " ^
241 status#ppterm ~metasenv:[] ~subst:[] ~context:[] src ^ " ===> " ^
242 status#ppterm ~metasenv:[] ~subst:[] ~context:[] tgt ^
243 " cpos=" ^ string_of_int pos ^ " arity=" ^ string_of_int arity));
244 let uri = fresh_uri status name ".con" in
245 let obj_kind = NCic.Constant
246 ([],name,Some bo,ty,(`Generated,`Definition,`Coercion arity))
248 let height = NCicTypeChecker.height_of_obj_kind status uri [] obj_kind in
249 let obj = uri,height,[],[],obj_kind in
252 (NReference.reference_of_spec uri (NReference.Def height))
254 Some (obj,name,c,src,tgt,pos,arity)
256 | NCicTypeChecker.TypeCheckerFailure _
257 | NCicUnification.UnificationFailure _
258 | NCicUnification.Uncertain _ | Stop -> None
265 let basic_index_ncoercion (name,_compose,t,s,d,position,arity) status =
266 NCicCoercion.index_coercion status name t s d arity position
269 let basic_eval_ncoercion (name,compose,t,s,d,p,a) status =
271 NCicCoercion.look_for_coercion status [] [] [] skel_dummy s
274 NCicCoercion.look_for_coercion status [] [] [] d skel_dummy
276 let status = NCicCoercion.index_coercion status name t s d a p in
278 if compose then close_graph name t s d to_s from_d p a status else [] in
280 (fun (uris,infos,st) ((uri,_,_,_,_ as obj),name,t,s,d,p,a) ->
281 let info = name,compose,t,s,d,p,a in
282 let st = NCicLibrary.add_obj st obj in
283 let st = basic_index_ncoercion info st in
284 uri::uris, info::infos, st)
285 ([],[],status) composites
288 let record_ncoercion =
289 let aux (name,compose,t,s,d,p,a) ~refresh_uri_in_term =
290 let t = refresh_uri_in_term t in
291 let s = refresh_uri_in_term s in
292 let d = refresh_uri_in_term d in
293 basic_index_ncoercion (name,compose,t,s,d,p,a)
295 let aux_l l ~refresh_uri_in_universe ~refresh_uri_in_term
296 ~refresh_uri_in_reference ~alias_only status
298 if not alias_only then
299 List.fold_right (aux ~refresh_uri_in_term:(refresh_uri_in_term (status:>NCic.status))) l status
303 GrafiteTypes.Serializer.register#run "ncoercion" aux_l
306 let basic_eval_and_record_ncoercion infos status =
307 let uris, cinfos, status = basic_eval_ncoercion infos status in
308 NCicLibrary.dump_obj status (record_ncoercion (infos::cinfos)), uris
311 let basic_eval_and_record_ncoercion_from_t_cpos_arity
312 status (name,compose,t,cpos,arity)
314 let ty = NCicTypeChecker.typeof status ~subst:[] ~metasenv:[] [] t in
315 let src,tgt = src_tgt_of_ty_cpos_arity status ty cpos arity in
317 basic_eval_and_record_ncoercion (name,compose,t,src,tgt,cpos,arity) status
322 let eval_ncoercion (status: #GrafiteTypes.status) name compose t ty (id,src) tgt =
323 let metasenv,subst,status,ty =
324 GrafiteDisambiguate.disambiguate_nterm status None [] [] [] ("",0,ty) in
325 assert (metasenv=[]);
326 let ty = NCicUntrusted.apply_subst status subst [] ty in
327 let metasenv,subst,status,t =
328 GrafiteDisambiguate.disambiguate_nterm status (Some ty) [] [] [] ("",0,t) in
329 assert (metasenv=[]);
330 let t = NCicUntrusted.apply_subst status subst [] t in
331 let status, src, tgt, cpos, arity =
332 src_tgt_cpos_arity_of_ty_id_src_tgt status ty id src tgt in
334 basic_eval_and_record_ncoercion (name,compose,t,src,tgt,cpos,arity) status