]> matita.cs.unibo.it Git - helm.git/blob - helm/software/components/acic_content/termAcicContent.ml
Preparing for 0.5.9 release.
[helm.git] / helm / software / components / acic_content / termAcicContent.ml
1 (* Copyright (C) 2005, HELM Team.
2  * 
3  * This file is part of HELM, an Hypertextual, Electronic
4  * Library of Mathematics, developed at the Computer Science
5  * Department, University of Bologna, Italy.
6  * 
7  * HELM is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  * 
12  * HELM is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with HELM; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
20  * MA  02111-1307, USA.
21  * 
22  * For details, see the HELM World-Wide-Web page,
23  * http://helm.cs.unibo.it/
24  *)
25
26 (* $Id$ *)
27
28 open Printf
29
30 module Ast = CicNotationPt
31 module Obj = LibraryObjects
32
33 let debug = false
34 let debug_print s = if debug then prerr_endline (Lazy.force s) else ()
35
36 type interpretation_id = int
37
38 let idref id t = Ast.AttributedTerm (`IdRef id, t)
39
40 type term_info =
41   { sort: (Cic.id, Ast.sort_kind) Hashtbl.t;
42     uri: (Cic.id, UriManager.uri) Hashtbl.t;
43   }
44
45 let get_types uri =
46   let o,_ = CicEnvironment.get_obj CicUniv.oblivion_ugraph uri in
47     match o with
48       | Cic.InductiveDefinition (l,_,lpsno,_) -> l, lpsno 
49       | _ -> assert false
50
51 let name_of_inductive_type uri i = 
52   let types, _ = get_types uri in
53   let (name, _, _, _) = try List.nth types i with Not_found -> assert false in
54   name
55
56   (* returns <name, type> pairs *)
57 let constructors_of_inductive_type uri i =
58   let types, _ = get_types uri in
59   let (_, _, _, constructors) = 
60     try List.nth types i with Not_found -> assert false
61   in
62   constructors
63
64   (* returns name only *)
65 let constructor_of_inductive_type uri i j =
66   (try
67     fst (List.nth (constructors_of_inductive_type uri i) (j-1))
68   with Not_found -> assert false)
69
70   (* returns the number of left parameters *)
71 let left_params_no_of_inductive_type uri =
72    snd (get_types uri)
73
74 let destroy_nat annterm =
75   let is_zero = function
76     | Cic.AMutConstruct (_, uri, 0, 1, _) when Obj.is_nat_URI uri -> true
77     | _ -> false
78   in
79   let is_succ = function
80     | Cic.AMutConstruct (_, uri, 0, 2, _) when Obj.is_nat_URI uri -> true
81     | _ -> false
82   in
83   let rec aux acc = function
84     | Cic.AAppl (_, [he ; tl]) when is_succ he -> aux (acc + 1) tl
85     | t when is_zero t -> Some acc
86     | _ -> None in
87   aux 0 annterm
88
89 let ast_of_acic0 ~output_type term_info acic k =
90   let k = k term_info in
91   let id_to_uris = term_info.uri in
92   let register_uri id uri = Hashtbl.add id_to_uris id uri in
93   let sort_of_id id =
94     try
95       Hashtbl.find term_info.sort id
96     with Not_found ->
97       prerr_endline (sprintf "warning: sort of id %s not found, using Type" id);
98       `Type (CicUniv.fresh ())
99   in
100   let aux_substs substs =
101     Some
102       (List.map
103         (fun (uri, annterm) -> (UriManager.name_of_uri uri, k annterm))
104         substs)
105   in
106   let aux_context context =
107     List.map
108       (function
109         | None -> None
110         | Some annterm -> Some (k annterm))
111       context
112   in
113   let aux = function
114     | Cic.ARel (id,_,_,b) -> idref id (Ast.Ident (b, None))
115     | Cic.AVar (id,uri,substs) ->
116         register_uri id uri;
117         idref id (Ast.Ident (UriManager.name_of_uri uri, aux_substs substs))
118     | Cic.AMeta (id,n,l) -> idref id (Ast.Meta (n, aux_context l))
119     | Cic.ASort (id,Cic.Prop) -> idref id (Ast.Sort `Prop)
120     | Cic.ASort (id,Cic.Set) -> idref id (Ast.Sort `Set)
121     | Cic.ASort (id,Cic.Type u) -> idref id (Ast.Sort (`Type u))
122     | Cic.ASort (id,Cic.CProp u) -> idref id (Ast.Sort (`CProp u))
123     | Cic.AImplicit (id, Some `Hole) -> idref id Ast.UserInput
124     | Cic.AImplicit (id, _) -> idref id (Ast.Implicit `JustOne)
125     | Cic.AProd (id,n,s,t) ->
126         let binder_kind =
127           match sort_of_id id with
128           | `Set | `Type _ | `NType _ -> `Pi
129           | `Prop | `CProp _ | `NCProp _ -> `Forall
130         in
131         idref id (Ast.Binder (binder_kind,
132           (CicNotationUtil.name_of_cic_name n, Some (k s)), k t))
133     | Cic.ACast (id,v,t) -> idref id (Ast.Cast (k v, k t))
134     | Cic.ALambda (id,n,s,t) ->
135         idref id (Ast.Binder (`Lambda,
136           (CicNotationUtil.name_of_cic_name n, Some (k s)), k t))
137     | Cic.ALetIn (id,n,s,ty,t) ->
138         idref id (Ast.LetIn ((CicNotationUtil.name_of_cic_name n, Some (k ty)),
139           k s, k t))
140     | Cic.AAppl (aid,(Cic.AConst _ as he::tl as args))
141     | Cic.AAppl (aid,(Cic.AMutInd _ as he::tl as args))
142     | Cic.AAppl (aid,(Cic.AMutConstruct _ as he::tl as args)) as t ->
143        (match destroy_nat t with
144        | Some n -> idref aid (Ast.Num (string_of_int n, -1))
145        | None ->
146            let deannot_he = Deannotate.deannotate_term he in
147            let coercion_info = CoercDb.is_a_coercion deannot_he in
148            if coercion_info <> None && !Acic2content.hide_coercions then
149              match coercion_info with
150              | None -> assert false 
151              | Some (_,_,_,sats,cpos) -> 
152                  if cpos < List.length tl then
153                    let _,rest = 
154                      try HExtlib.split_nth (cpos+sats+1) tl with Failure _ -> [],[] 
155                    in
156                    if rest = [] then
157                      idref aid (k (List.nth tl cpos))
158                    else
159                      idref aid (Ast.Appl (List.map k (List.nth tl cpos::rest)))
160                  else
161                    idref aid (Ast.Appl (List.map k args))
162            else
163              idref aid (Ast.Appl (List.map k args)))
164     | Cic.AAppl (aid,args) ->
165         idref aid (Ast.Appl (List.map k args))
166     | Cic.AConst (id,uri,substs) ->
167         register_uri id uri;
168         idref id (Ast.Ident (UriManager.name_of_uri uri, aux_substs substs))
169     | Cic.AMutInd (id,uri,i,substs) ->
170         let name = name_of_inductive_type uri i in
171         let uri_str = UriManager.string_of_uri uri in
172         let puri_str = sprintf "%s#xpointer(1/%d)" uri_str (i+1) in
173         register_uri id (UriManager.uri_of_string puri_str);
174         idref id (Ast.Ident (name, aux_substs substs))
175     | Cic.AMutConstruct (id,uri,i,j,substs) ->
176         let name = constructor_of_inductive_type uri i j in
177         let uri_str = UriManager.string_of_uri uri in
178         let puri_str = sprintf "%s#xpointer(1/%d/%d)" uri_str (i + 1) j in
179         register_uri id (UriManager.uri_of_string puri_str);
180         idref id (Ast.Ident (name, aux_substs substs))
181     | Cic.AMutCase (id,uri,typeno,ty,te,patterns) ->
182         let name = name_of_inductive_type uri typeno in
183         let uri_str = UriManager.string_of_uri uri in
184         let puri_str = sprintf "%s#xpointer(1/%d)" uri_str (typeno+1) in
185         let ctor_puri j =
186           UriManager.uri_of_string
187             (sprintf "%s#xpointer(1/%d/%d)" uri_str (typeno+1) j)
188         in
189         let case_indty = name, Some (UriManager.uri_of_string puri_str) in
190         let constructors = constructors_of_inductive_type uri typeno in
191         let lpsno = left_params_no_of_inductive_type uri in
192         let rec eat_branch n ty pat =
193           match (ty, pat) with
194           | Cic.Prod (_, _, t), _ when n > 0 -> eat_branch (pred n) t pat 
195           | Cic.Prod (_, _, t), Cic.ALambda (_, name, s, t') ->
196               let (cv, rhs) = eat_branch 0 t t' in
197               (CicNotationUtil.name_of_cic_name name, Some (k s)) :: cv, rhs
198           | _, _ -> [], k pat
199         in
200         let j = ref 0 in
201         let patterns =
202           try
203             List.map2
204               (fun (name, ty) pat ->
205                 incr j;
206                 let name,(capture_variables,rhs) =
207                  match output_type with
208                     `Term -> name, eat_branch lpsno ty pat
209                   | `Pattern -> "_", ([], k pat)
210                 in
211                  Ast.Pattern (name, Some (ctor_puri !j), capture_variables), rhs
212               ) constructors patterns
213           with Invalid_argument _ -> assert false
214         in
215         let indty =
216          match output_type with
217             `Pattern -> None
218           | `Term -> Some case_indty
219         in
220         idref id (Ast.Case (k te, indty, Some (k ty), patterns))
221     | Cic.AFix (id, no, funs) -> 
222         let defs = 
223           List.map
224             (fun (_, n, decr_idx, ty, bo) ->
225               let params,bo =
226                let rec aux =
227                 function
228                    Cic.ALambda (_,name,so,ta) ->
229                     let params,rest = aux ta in
230                      (CicNotationUtil.name_of_cic_name name,Some (k so))::
231                       params, rest
232                  | t -> [],t
233                in
234                 aux bo
235               in
236               let ty =
237                let rec eat_pis =
238                 function
239                    0,ty -> ty
240                  | n,Cic.AProd (_,_,_,ta) -> eat_pis (n - 1,ta)
241                  | n,ty ->
242                     (* I should do a whd here, but I have no context *)
243                     assert false
244                in
245                 eat_pis ((List.length params),ty)
246               in
247                (params,(Ast.Ident (n, None), Some (k ty)), k bo, decr_idx))
248             funs
249         in
250         let name =
251           try
252             (match List.nth defs no with
253             | _, (Ast.Ident (n, _), _), _, _ when n <> "_" -> n
254             | _ -> assert false)
255           with Not_found -> assert false
256         in
257          idref id (Ast.LetRec (`Inductive, defs, Ast.Ident (name, None)))
258     | Cic.ACoFix (id, no, funs) -> 
259         let defs = 
260           List.map
261             (fun (_, n, ty, bo) ->
262               let params,bo =
263                let rec aux =
264                 function
265                    Cic.ALambda (_,name,so,ta) ->
266                     let params,rest = aux ta in
267                      (CicNotationUtil.name_of_cic_name name,Some (k so))::
268                       params, rest
269                  | t -> [],t
270                in
271                 aux bo
272               in
273               let ty =
274                let rec eat_pis =
275                 function
276                    0,ty -> ty
277                  | n,Cic.AProd (_,_,_,ta) -> eat_pis (n - 1,ta)
278                  | n,ty ->
279                     (* I should do a whd here, but I have no context *)
280                     assert false
281                in
282                 eat_pis ((List.length params),ty)
283               in
284                (params,(Ast.Ident (n, None), Some (k ty)), k bo, 0))
285             funs
286         in
287         let name =
288           try
289             (match List.nth defs no with
290             | _, (Ast.Ident (n, _), _), _, _ when n <> "_" -> n
291             | _ -> assert false)
292           with Not_found -> assert false
293         in
294         idref id (Ast.LetRec (`CoInductive, defs, Ast.Ident (name, None)))
295   in
296   aux acic
297
298   (* persistent state *)
299
300 let initial_level2_patterns32 () = Hashtbl.create 211
301 let initial_interpretations () = Hashtbl.create 211
302
303 let level2_patterns32 = ref (initial_level2_patterns32 ())
304 (* symb -> id list ref *)
305 let interpretations = ref (initial_interpretations ())
306 let compiled32 = ref None
307 let pattern32_matrix = ref []
308 let counter = ref ~-1 
309 let find_level2_patterns32 pid = Hashtbl.find !level2_patterns32 pid;;
310
311 let stack = ref []
312
313 let push () =
314  stack := (!counter,!level2_patterns32,!interpretations,!compiled32,!pattern32_matrix)::!stack;
315  counter := ~-1;
316  level2_patterns32 := initial_level2_patterns32 ();
317  interpretations := initial_interpretations ();
318  compiled32 := None;
319  pattern32_matrix := []
320 ;;
321
322 let pop () =
323  match !stack with
324     [] -> assert false
325   | (ocounter,olevel2_patterns32,ointerpretations,ocompiled32,opattern32_matrix)::old ->
326    stack := old;
327    counter := ocounter;
328    level2_patterns32 := olevel2_patterns32;
329    interpretations := ointerpretations;
330    compiled32 := ocompiled32;
331    pattern32_matrix := opattern32_matrix
332 ;;
333
334 let get_compiled32 () =
335   match !compiled32 with
336   | None -> assert false
337   | Some f -> Lazy.force f
338
339 let set_compiled32 f = compiled32 := Some f
340
341 let add_idrefs =
342   List.fold_right (fun idref t -> Ast.AttributedTerm (`IdRef idref, t))
343
344 let instantiate32 term_info idrefs env symbol args =
345   let rec instantiate_arg = function
346     | Ast.IdentArg (n, name) ->
347         let t = 
348           try List.assoc name env 
349           with Not_found -> prerr_endline ("name not found in env: "^name);
350                             assert false
351         in
352         let rec count_lambda = function
353           | Ast.AttributedTerm (_, t) -> count_lambda t
354           | Ast.Binder (`Lambda, _, body) -> 1 + count_lambda body
355           | _ -> 0
356         in
357         let rec add_lambda t n =
358           if n > 0 then
359             let name = CicNotationUtil.fresh_name () in
360             Ast.Binder (`Lambda, (Ast.Ident (name, None), None),
361               Ast.Appl [add_lambda t (n - 1); Ast.Ident (name, None)])
362           else
363             t
364         in
365         add_lambda t (n - count_lambda t)
366   in
367   let head =
368     let symbol = Ast.Symbol (symbol, 0) in
369     add_idrefs idrefs symbol
370   in
371   if args = [] then head
372   else Ast.Appl (head :: List.map instantiate_arg args)
373
374 let rec ast_of_acic1 ~output_type term_info annterm = 
375   let id_to_uris = term_info.uri in
376   let register_uri id uri = Hashtbl.add id_to_uris id uri in
377   match (get_compiled32 ()) annterm with
378   | None ->
379      ast_of_acic0 ~output_type term_info annterm (ast_of_acic1 ~output_type)
380   | Some (env, ctors, pid) -> 
381       let idrefs =
382         List.map
383           (fun annterm ->
384             let idref = CicUtil.id_of_annterm annterm in
385             (try
386               register_uri idref
387                 (CicUtil.uri_of_term (Deannotate.deannotate_term annterm))
388             with Invalid_argument _ -> ());
389             idref)
390           ctors
391       in
392       let env' =
393        List.map
394         (fun (name, term) -> name, ast_of_acic1 ~output_type term_info term) env
395       in
396       let _, symbol, args, _ =
397         try
398           find_level2_patterns32 pid
399         with Not_found -> assert false
400       in
401       let ast = instantiate32 term_info idrefs env' symbol args in
402       Ast.AttributedTerm (`IdRef (CicUtil.id_of_annterm annterm), ast)
403
404 let load_patterns32s =
405  let load_patterns32 t =
406   let t =
407     HExtlib.filter_map (function (true, ap, id) -> Some (ap, id) | _ -> None) t
408   in
409    set_compiled32 (lazy (Acic2astMatcher.Matcher32.compiler t))
410  in
411   ref [load_patterns32]
412 ;;
413
414 let add_load_patterns32 f = load_patterns32s := f :: !load_patterns32s;;
415
416 let ast_of_acic ~output_type id_to_sort annterm =
417   debug_print (lazy ("ast_of_acic <- "
418     ^ CicPp.ppterm (Deannotate.deannotate_term annterm)));
419   let term_info = { sort = id_to_sort; uri = Hashtbl.create 211 } in
420   let ast = ast_of_acic1 ~output_type term_info annterm in
421   debug_print (lazy ("ast_of_acic -> " ^ CicNotationPp.pp_term ast));
422   ast, term_info.uri
423
424 let fresh_id =
425   fun () ->
426     incr counter;
427     !counter
428
429 let add_interpretation dsc (symbol, args) appl_pattern =
430   let id = fresh_id () in
431   Hashtbl.add !level2_patterns32 id (dsc, symbol, args, appl_pattern);
432   pattern32_matrix := (true, appl_pattern, id) :: !pattern32_matrix;
433   List.iter (fun f -> f !pattern32_matrix) !load_patterns32s;
434   (try
435     let ids = Hashtbl.find !interpretations symbol in
436     ids := id :: !ids
437   with Not_found -> Hashtbl.add !interpretations symbol (ref [id]));
438   id
439
440 let get_all_interpretations () =
441   List.map
442     (function (_, _, id) ->
443       let (dsc, _, _, _) =
444         try
445           Hashtbl.find !level2_patterns32 id
446         with Not_found -> assert false
447       in
448       (id, dsc))
449     !pattern32_matrix
450
451 let get_active_interpretations () =
452   HExtlib.filter_map (function (true, _, id) -> Some id | _ -> None)
453     !pattern32_matrix
454
455 let set_active_interpretations ids =
456   let pattern32_matrix' =
457     List.map
458       (function 
459         | (_, ap, id) when List.mem id ids -> (true, ap, id)
460         | (_, ap, id) -> (false, ap, id))
461       !pattern32_matrix
462   in
463   pattern32_matrix := pattern32_matrix';
464   List.iter (fun f -> f !pattern32_matrix) !load_patterns32s
465
466 exception Interpretation_not_found
467
468 let lookup_interpretations ?(sorted=true) symbol =
469   try
470     let raw = 
471       List.map (
472         fun id ->
473           let (dsc, _, args, appl_pattern) =
474             try
475               Hashtbl.find !level2_patterns32 id
476             with Not_found -> assert false 
477           in
478           dsc, args, appl_pattern
479       )
480       !(Hashtbl.find !interpretations symbol)
481     in
482     if sorted then HExtlib.list_uniq (List.sort Pervasives.compare raw)
483               else raw
484   with Not_found -> raise Interpretation_not_found
485
486 let remove_interpretation id =
487   (try
488     let dsc, symbol, _, _ = Hashtbl.find !level2_patterns32 id in
489     let ids = Hashtbl.find !interpretations symbol in
490     ids := List.filter ((<>) id) !ids;
491     Hashtbl.remove !level2_patterns32 id;
492   with Not_found -> raise Interpretation_not_found);
493   pattern32_matrix :=
494     List.filter (fun (_, _, id') -> id <> id') !pattern32_matrix;
495   List.iter (fun f -> f !pattern32_matrix) !load_patterns32s
496
497 let init () = List.iter (fun f -> f []) !load_patterns32s
498
499 let instantiate_appl_pattern 
500   ~mk_appl ~mk_implicit ~term_of_uri ~term_of_nref env appl_pattern 
501 =
502   let lookup name =
503     try List.assoc name env
504     with Not_found ->
505       prerr_endline (sprintf "Name %s not found" name);
506       assert false
507   in
508   let rec aux = function
509     | Ast.UriPattern uri -> term_of_uri uri
510     | Ast.NRefPattern nref -> term_of_nref nref
511     | Ast.ImplicitPattern -> mk_implicit false
512     | Ast.VarPattern name -> lookup name
513     | Ast.ApplPattern terms -> mk_appl (List.map aux terms)
514   in
515   aux appl_pattern
516