]> matita.cs.unibo.it Git - helm.git/blob - matita/components/ng_cic_content/interpretations.ml
Number notation ported to new library.
[helm.git] / matita / components / ng_cic_content / interpretations.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 = NotationPt
31
32
33 let debug = false
34 let debug_print s = if debug then prerr_endline (Lazy.force s) else ()
35
36 type id = string
37 let hide_coercions = ref true;;
38
39 type cic_id = string
40
41 type term_info =
42   { sort: (cic_id, Ast.sort_kind) Hashtbl.t;
43     uri: (cic_id, NReference.reference) Hashtbl.t;
44   }
45
46 module IntMap = Map.Make(struct type t = int let compare = compare end);;
47 module StringMap = Map.Make(String);;
48
49 type db = {
50   counter: int;
51   pattern32_matrix: (bool * NotationPt.cic_appl_pattern * int) list;
52   level2_patterns32:
53    (string * string * NotationPt.argument_pattern list *
54      NotationPt.cic_appl_pattern) IntMap.t;
55   interpretations: int list StringMap.t; (* symb -> id list *)
56   compiled32:
57    (NCic.term -> ((string * NCic.term) list * NCic.term list * int) option)
58     Lazy.t
59 }
60
61 let initial_db = {
62    counter = -1; 
63    pattern32_matrix = [];
64    level2_patterns32 = IntMap.empty;
65    interpretations = StringMap.empty;
66    compiled32 = lazy (Ncic2astMatcher.Matcher32.compiler [])
67 }
68
69 class type g_status =
70   object
71     inherit NCicCoercion.g_status
72     method interp_db: db
73   end
74  
75 class status =
76  object
77    inherit NCicCoercion.status
78    val interp_db = initial_db  
79    method interp_db = interp_db
80    method set_interp_db v = {< interp_db = v >}
81    method set_interp_status
82     : 'status. #g_status as 'status -> 'self
83     = fun o -> {< interp_db = o#interp_db >}#set_coercion_status o
84  end
85
86 let idref register_ref =
87  let id = ref 0 in
88   fun ?reference t ->
89    incr id;
90    let id = "i" ^ string_of_int !id in
91     (match reference with None -> () | Some r -> register_ref id r);
92     Ast.AttributedTerm (`IdRef id, t)
93 ;;
94
95 let level_of_uri u = 
96   let name = NUri.name_of_uri u in
97   assert(String.length name > String.length "Type");
98   String.sub name 4 (String.length name - 4)
99 ;;
100
101 let find_level2_patterns32 status pid =
102  IntMap.find pid status#interp_db.level2_patterns32
103
104 let add_idrefs =
105   List.fold_right (fun idref t -> Ast.AttributedTerm (`IdRef idref, t))
106
107 let instantiate32 idrefs env symbol args =
108   let rec instantiate_arg = function
109     | Ast.IdentArg (n, name) ->
110         let t = 
111           try List.assoc name env 
112           with Not_found -> prerr_endline ("name not found in env: "^name);
113                             assert false
114         in
115         let rec count_lambda = function
116           | Ast.AttributedTerm (_, t) -> count_lambda t
117           | Ast.Binder (`Lambda, _, body) -> 1 + count_lambda body
118           | _ -> 0
119         in
120         let rec add_lambda t n =
121           if n > 0 then
122             let name = NotationUtil.fresh_name () in
123             Ast.Binder (`Lambda, (Ast.Ident (name, None), None),
124               Ast.Appl [add_lambda t (n - 1); Ast.Ident (name, None)])
125           else
126             t
127         in
128         add_lambda t (n - count_lambda t)
129   in
130   let head =
131     let symbol = Ast.Symbol (symbol, 0) in
132     add_idrefs idrefs symbol
133   in
134   if args = [] then head
135   else Ast.Appl (head :: List.map instantiate_arg args)
136
137 let fresh_id status =
138   let counter = status#interp_db.counter+1 in
139    status#set_interp_db ({ status#interp_db with counter = counter  }), counter
140
141 let load_patterns32 status t =
142  let t =
143   HExtlib.filter_map (function (true, ap, id) -> Some (ap, id) | _ -> None) t
144  in
145   status#set_interp_db
146    {status#interp_db with
147      compiled32 = lazy (Ncic2astMatcher.Matcher32.compiler t) }
148 ;;
149
150 let add_interpretation status dsc (symbol, args) appl_pattern =
151   let status,id = fresh_id status in
152   let ids =
153    try
154     id::StringMap.find symbol status#interp_db.interpretations
155    with Not_found -> [id] in
156   let status =
157    status#set_interp_db { status#interp_db with
158     level2_patterns32 =
159       IntMap.add id (dsc, symbol, args, appl_pattern)
160        status#interp_db.level2_patterns32;
161     pattern32_matrix = (true,appl_pattern,id)::status#interp_db.pattern32_matrix;
162     interpretations = StringMap.add symbol ids status#interp_db.interpretations
163    }
164   in
165    load_patterns32 status status#interp_db.pattern32_matrix
166
167 let toggle_active_interpretations status b =
168   status#set_interp_db { status#interp_db with
169    pattern32_matrix =
170      List.map (fun (_,ap,id) -> b,ap,id) status#interp_db.pattern32_matrix }
171
172 exception Interpretation_not_found
173
174 let lookup_interpretations status ?(sorted=true) symbol =
175   try
176     let raw = 
177       List.map (
178         fun id ->
179           let (dsc, _, args, appl_pattern) =
180             try IntMap.find id status#interp_db.level2_patterns32
181             with Not_found -> assert false 
182           in
183           dsc, args, appl_pattern
184       ) (StringMap.find symbol status#interp_db.interpretations)
185     in
186     if sorted then HExtlib.list_uniq (List.sort Pervasives.compare raw)
187               else raw
188   with Not_found -> raise Interpretation_not_found
189
190 let instantiate_appl_pattern 
191   ~mk_appl ~mk_implicit ~term_of_nref env appl_pattern 
192 =
193   let lookup name =
194     try List.assoc name env
195     with Not_found ->
196       prerr_endline (sprintf "Name %s not found" name);
197       assert false
198   in
199   let rec aux = function
200     | Ast.NRefPattern nref -> term_of_nref nref
201     | Ast.ImplicitPattern -> mk_implicit false
202     | Ast.VarPattern name -> lookup name
203     | Ast.ApplPattern terms -> mk_appl (List.map aux terms)
204   in
205   aux appl_pattern
206
207 let destroy_nat =
208   let is_nat_URI = NUri.eq (NUri.uri_of_string
209   "cic:/matita/arithmetics/nat/nat.ind") in
210   let is_zero = function
211     | NCic.Const (NReference.Ref (uri, NReference.Con (0, 1, 0))) when
212        is_nat_URI uri -> true
213     | _ -> false
214   in
215   let is_succ = function
216     | NCic.Const (NReference.Ref (uri, NReference.Con (0, 2, 0))) when
217        is_nat_URI uri -> true
218     | _ -> false
219   in
220   let rec aux acc = function
221     | NCic.Appl [he ; tl] when is_succ he -> aux (acc + 1) tl
222     | t when is_zero t -> Some acc
223     | _ -> None
224   in
225    aux 0
226
227 (* CODICE c&p da NCicPp *)
228 let nast_of_cic0 status
229  ~(idref:
230     ?reference:NReference.reference -> NotationPt.term -> NotationPt.term)
231  ~output_type ~metasenv ~subst k ~context =
232   function
233     | NCic.Rel n ->
234        (try 
235          let name,_ = List.nth context (n-1) in
236          let name = if name = "_" then "__"^string_of_int n else name in
237           idref (Ast.Ident (name,None))
238         with Failure "nth" | Invalid_argument "List.nth" -> 
239          idref (Ast.Ident ("-" ^ string_of_int (n - List.length context),None)))
240     | NCic.Const r -> idref ~reference:r (Ast.Ident (NCicPp.r2s true r, None))
241     | NCic.Meta (n,lc) when List.mem_assoc n subst -> 
242         let _,_,t,_ = List.assoc n subst in
243          k ~context (NCicSubstitution.subst_meta lc t)
244     | NCic.Meta (n,(s,l)) ->
245        (* CSC: qua non dovremmo espandere *)
246        let l = NCicUtils.expand_local_context l in
247         idref (Ast.Meta
248          (n, List.map (fun x -> Some (k ~context (NCicSubstitution.lift s x))) l))
249     | NCic.Sort NCic.Prop -> idref (Ast.Sort `Prop)
250     | NCic.Sort NCic.Type [] -> idref (Ast.Sort `Set)
251     | NCic.Sort NCic.Type ((`Type,u)::_) -> 
252               idref(Ast.Sort (`NType (level_of_uri u)))
253     | NCic.Sort NCic.Type ((`CProp,u)::_) -> 
254               idref(Ast.Sort (`NCProp (level_of_uri u)))
255     | NCic.Sort NCic.Type ((`Succ,u)::_) -> 
256               idref(Ast.Sort (`NType (level_of_uri u ^ "+1")))
257     | NCic.Implicit `Hole -> idref (Ast.UserInput)
258     | NCic.Implicit `Vector -> idref (Ast.Implicit `Vector)
259     | NCic.Implicit _ -> idref (Ast.Implicit `JustOne)
260     | NCic.Prod (n,s,t) ->
261         let n = if n.[0] = '_' then "_" else n in
262         let binder_kind = `Forall in
263          idref (Ast.Binder (binder_kind, (Ast.Ident (n,None), Some (k ~context s)),
264           k ~context:((n,NCic.Decl s)::context) t))
265     | NCic.Lambda (n,s,t) ->
266         idref (Ast.Binder (`Lambda,(Ast.Ident (n,None), Some (k ~context s)),
267          k ~context:((n,NCic.Decl s)::context) t))
268     | NCic.LetIn (n,s,ty,NCic.Rel 1) ->
269         idref (Ast.Cast (k ~context ty, k ~context s))
270     | NCic.LetIn (n,s,ty,t) ->
271         idref (Ast.LetIn ((Ast.Ident (n,None), Some (k ~context s)), k ~context
272           ty, k ~context:((n,NCic.Decl s)::context) t))
273     | NCic.Appl (NCic.Meta (n,lc) :: args) when List.mem_assoc n subst -> 
274        let _,_,t,_ = List.assoc n subst in
275        let hd = NCicSubstitution.subst_meta lc t in
276         k ~context
277          (NCicReduction.head_beta_reduce ~upto:(List.length args)
278            (match hd with
279            | NCic.Appl l -> NCic.Appl (l@args)
280            | _ -> NCic.Appl (hd :: args)))
281     | NCic.Appl args as t ->
282        (match destroy_nat t with
283          | Some n -> idref (Ast.Num (string_of_int n, -1))
284          | None ->
285             let args =
286              if not !hide_coercions then args
287              else
288               match
289                NCicCoercion.match_coercion status ~metasenv ~context ~subst t
290               with
291                | None -> args
292                | Some (_,sats,cpos) -> 
293 (* CSC: sats e' il numero di pi, ma non so cosa farmene! voglio il numero di
294    argomenti da saltare, come prima! *)
295                   if cpos < List.length args - 1 then
296                    List.nth args (cpos + 1) ::
297                     try snd (HExtlib.split_nth (cpos+sats+2) args)
298                     with Failure _->[]
299                   else
300                    args
301             in
302              (match args with
303                  [arg] -> idref (k ~context arg)
304                | _ -> idref (Ast.Appl (List.map (k ~context) args))))
305     | NCic.Match (NReference.Ref (uri,_) as r,outty,te,patterns) ->
306         let name = NUri.name_of_uri uri in
307 (* CSC
308         let uri_str = UriManager.string_of_uri uri in
309         let puri_str = sprintf "%s#xpointer(1/%d)" uri_str (typeno+1) in
310         let ctor_puri j =
311           UriManager.uri_of_string
312             (sprintf "%s#xpointer(1/%d/%d)" uri_str (typeno+1) j)
313         in
314 *)
315         let case_indty =
316          name, None(*CSC Some (UriManager.uri_of_string puri_str)*) in
317         let constructors, leftno =
318          let _,leftno,tys,_,n = NCicEnvironment.get_checked_indtys r in
319          let _,_,_,cl  = List.nth tys n in
320           cl,leftno
321         in
322         let rec eat_branch n ctx ty pat =
323           match (ty, pat) with
324           | NCic.Prod (name, s, t), _ when n > 0 ->
325              eat_branch (pred n) ctx t pat 
326           | NCic.Prod (_, _, t), NCic.Lambda (name, s, t') ->
327               let cv, rhs = eat_branch 0 ((name,NCic.Decl s)::ctx) t t' in
328               (Ast.Ident (name,None), Some (k ~context:ctx s)) :: cv, rhs
329           | _, _ -> [], k ~context:ctx pat
330         in
331         let j = ref 0 in
332         let patterns =
333           try
334             List.map2
335               (fun (_, name, ty) pat ->
336                 incr j;
337                 let name,(capture_variables,rhs) =
338                  match output_type with
339                     `Term -> name, eat_branch leftno context ty pat
340                   | `Pattern -> "_", ([], k ~context pat)
341                 in
342                  Ast.Pattern (name, None(*CSC Some (ctor_puri !j)*), capture_variables), rhs
343               ) constructors patterns
344           with Invalid_argument _ -> assert false
345         in
346         let indty =
347          match output_type with
348             `Pattern -> None
349           | `Term -> Some case_indty
350         in
351          idref (Ast.Case (k ~context te, indty, Some (k ~context outty), patterns))
352 ;;
353
354 let rec nast_of_cic1 status ~idref ~output_type ~metasenv ~subst ~context term =
355   match Lazy.force status#interp_db.compiled32 term with
356   | None ->
357      nast_of_cic0 status ~idref ~output_type ~metasenv ~subst
358       (nast_of_cic1 status ~idref ~output_type ~metasenv ~subst) ~context term 
359   | Some (env, ctors, pid) -> 
360       let idrefs =
361        List.map
362         (fun term ->
363           let attrterm =
364            idref
365             ~reference:
366               (match term with NCic.Const nref -> nref | _ -> assert false)
367            (NotationPt.Ident ("dummy",None))
368           in
369            match attrterm with
370               Ast.AttributedTerm (`IdRef id, _) -> id
371             | _ -> assert false
372         ) ctors
373       in
374       let env =
375        List.map
376         (fun (name, term) ->
377           name,
378            nast_of_cic1 status ~idref ~output_type ~subst ~metasenv ~context
379             term
380         ) env
381       in
382       let _, symbol, args, _ =
383         try
384          find_level2_patterns32 status pid
385         with Not_found -> assert false
386       in
387       let ast = instantiate32 idrefs env symbol args in
388       idref ast (*Ast.AttributedTerm (`IdRef (idref term), ast)*)
389 ;;
390
391 let nmap_sequent0 status ~idref ~metasenv ~subst (i,(n,context,ty)) =
392  let module K = Content in
393  let nast_of_cic =
394   nast_of_cic1 status ~idref ~output_type:`Term ~metasenv ~subst in
395  let context',_ =
396   List.fold_right
397    (fun item (res,context) ->
398      match item with
399       | name,NCic.Decl t ->
400          Some
401           (* We should call build_decl_item, but we have not computed *)
402           (* the inner-types ==> we always produce a declaration      *)
403           (`Declaration
404             { K.dec_name = (Some name);
405               K.dec_id = "-1"; 
406               K.dec_inductive = false;
407               K.dec_aref = "-1";
408               K.dec_type = nast_of_cic ~context t
409             })::res,item::context
410       | name,NCic.Def (t,ty) ->
411          Some
412           (* We should call build_def_item, but we have not computed *)
413           (* the inner-types ==> we always produce a declaration     *)
414           (`Definition
415              { K.def_name = (Some name);
416                K.def_id = "-1"; 
417                K.def_aref = "-1";
418                K.def_term = nast_of_cic ~context t;
419                K.def_type = nast_of_cic ~context ty
420              })::res,item::context
421    ) context ([],[])
422  in
423   ("-1",i,context',nast_of_cic ~context ty)
424 ;;
425
426 let nmap_sequent status ~metasenv ~subst conjecture =
427  let module K = Content in
428  let ids_to_refs = Hashtbl.create 211 in
429  let register_ref = Hashtbl.add ids_to_refs in
430   nmap_sequent0 status ~idref:(idref register_ref) ~metasenv ~subst conjecture,
431   ids_to_refs
432 ;;
433
434 let object_prefix = "obj:";;
435 let declaration_prefix = "decl:";;
436 let definition_prefix = "def:";;
437 let inductive_prefix = "ind:";;
438 let joint_prefix = "joint:";;
439
440 let get_id =
441  function
442     Ast.AttributedTerm (`IdRef id, _) -> id
443   | _ -> assert false
444 ;;
445
446 let gen_id prefix seed =
447  let res = prefix ^ string_of_int !seed in
448   incr seed ;
449   res
450 ;;
451
452 let build_def_item seed context metasenv id n t ty =
453  let module K = Content in
454 (*
455   try
456    let sort = Hashtbl.find ids_to_inner_sorts id in
457    if sort = `Prop then
458        (let p = 
459         (acic2content seed context metasenv ?name:(name_of n) ~ids_to_inner_sorts  ~ids_to_inner_types t)
460        in 
461         `Proof p;)
462    else 
463 *)
464       `Definition
465         { K.def_name = Some n;
466           K.def_id = gen_id definition_prefix seed; 
467           K.def_aref = id;
468           K.def_term = t;
469           K.def_type = ty
470         }
471 (*
472   with
473    Not_found -> assert false
474 *)
475
476 let build_decl_item seed id n s =
477  let module K = Content in
478 (*
479  let sort =
480    try
481     Some (Hashtbl.find ids_to_inner_sorts (Cic2acic.source_id_of_id id))
482    with Not_found -> None
483  in
484  match sort with
485  | Some `Prop ->
486     `Hypothesis
487       { K.dec_name = name_of n;
488         K.dec_id = gen_id declaration_prefix seed; 
489         K.dec_inductive = false;
490         K.dec_aref = id;
491         K.dec_type = s
492       }
493  | _ ->
494 *)
495     `Declaration
496       { K.dec_name = Some n;
497         K.dec_id = gen_id declaration_prefix seed; 
498         K.dec_inductive = false;
499         K.dec_aref = id;
500         K.dec_type = s
501       }
502 ;;
503
504 let nmap_obj status (uri,_,metasenv,subst,kind) =
505   let module K = Content in
506   let ids_to_refs = Hashtbl.create 211 in
507   let register_ref = Hashtbl.add ids_to_refs in
508   let idref = idref register_ref in
509   let nast_of_cic =
510    nast_of_cic1 status ~idref ~output_type:`Term ~metasenv ~subst in
511   let seed = ref 0 in
512   let conjectures =
513    match metasenv with
514       [] -> None
515     | _ -> (*Some (List.map (map_conjectures seed) metasenv)*)
516       (*CSC: used to be the previous line, that uses seed *)
517       Some (List.map (nmap_sequent0 status ~idref ~metasenv ~subst) metasenv)
518   in
519 let  build_constructors seed l =
520       List.map 
521        (fun (_,n,ty) ->
522            let ty = nast_of_cic ~context:[] ty in
523            { K.dec_name = Some n;
524              K.dec_id = gen_id declaration_prefix seed;
525              K.dec_inductive = false;
526              K.dec_aref = "";
527              K.dec_type = ty
528            }) l
529 in
530 let build_inductive b seed = 
531       fun (_,n,ty,cl) ->
532         let ty = nast_of_cic ~context:[] ty in
533         `Inductive
534           { K.inductive_id = gen_id inductive_prefix seed;
535             K.inductive_name = n;
536             K.inductive_kind = b;
537             K.inductive_type = ty;
538             K.inductive_constructors = build_constructors seed cl
539            }
540 in
541 let build_fixpoint b seed = 
542       fun (_,n,_,ty,t) ->
543         let t = nast_of_cic ~context:[] t in
544         let ty = nast_of_cic ~context:[] ty in
545         `Definition
546           { K.def_id = gen_id inductive_prefix seed;
547             K.def_name = Some n;
548             K.def_aref = "";
549             K.def_type = ty;
550             K.def_term = t;
551            }
552 in
553   let res =
554    match kind with
555     | NCic.Fixpoint (is_rec, ifl, _) -> 
556          (gen_id object_prefix seed, conjectures,
557             `Joint
558               { K.joint_id = gen_id joint_prefix seed;
559                 K.joint_kind = 
560                    if is_rec then 
561                         `Recursive (List.map (fun (_,_,i,_,_) -> i) ifl)
562                    else `CoRecursive;
563                 K.joint_defs = List.map (build_fixpoint is_rec seed) ifl
564               }) 
565     | NCic.Inductive (is_ind, lno, itl, _) ->
566          (gen_id object_prefix seed, conjectures,
567             `Joint
568               { K.joint_id = gen_id joint_prefix seed;
569                 K.joint_kind = 
570                    if is_ind then `Inductive lno else `CoInductive lno;
571                 K.joint_defs = List.map (build_inductive is_ind seed) itl
572               }) 
573     | NCic.Constant (_,_,Some bo,ty,_) ->
574        let ty = nast_of_cic ~context:[] ty in
575        let bo = nast_of_cic ~context:[] bo in
576         (gen_id object_prefix seed, conjectures,
577           `Def (K.Const,ty,
578             build_def_item seed [] [] (get_id bo) (NUri.name_of_uri uri) bo ty))
579     | NCic.Constant (_,_,None,ty,_) ->
580        let ty = nast_of_cic ~context:[] ty in
581          (gen_id object_prefix seed, conjectures,
582            `Decl (K.Const,
583              (*CSC: ??? get_id ty here used to be the id of the axiom! *)
584              build_decl_item seed (get_id ty) (NUri.name_of_uri uri) ty))
585  in
586   res,ids_to_refs
587 ;;