1 (* Copyright (C) 2000, HELM Team.
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.
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.
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.
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,
22 * For details, see the HELM World-Wide-Web page,
23 * http://cs.unibo.it/helm/.
26 (* $Id: cicPp.ml 7413 2007-05-29 15:30:53Z tassi $ *)
28 exception CicExportationInternalError;;
29 exception NotEnoughElements;;
34 UriManager.eq (UriManager.uri_of_string
35 "cic:/matita/freescale/opcode/mcu_type.ind") u
38 (* Utility functions *)
40 let analyze_term context t =
41 match fst(CicTypeChecker.type_of_aux' [] context t CicUniv.oblivion_ugraph)with
43 | Cic.MutInd (u,0,_) when is_mcu_type u -> `Optimize
46 fst (CicTypeChecker.type_of_aux' [] context ty CicUniv.oblivion_ugraph)
48 | Cic.Sort Cic.Prop -> `Proof
52 let analyze_type context t =
56 | Cic.MutInd (u,0,_) when is_mcu_type u -> `Optimize
57 | Cic.Prod (_,_,t) -> aux t
61 `Sort _ | `Optimize as res -> res
64 fst(CicTypeChecker.type_of_aux' [] context t CicUniv.oblivion_ugraph)
66 Cic.Sort Cic.Prop -> `Statement
80 let n = String.uncapitalize n in
81 if List.mem n reserved then n ^ "_" else n
87 | Cic.Anonymous -> "_"
90 (* get_nth l n returns the nth element of the list l if it exists or *)
91 (* raises NotEnoughElements if l has less than n elements *)
95 | (n, he::tail) when n > 1 -> get_nth tail (n-1)
96 | (_,_) -> raise NotEnoughElements
99 let qualified_name_of_uri current_module_uri ?(capitalize=false) uri =
102 String.capitalize (UriManager.name_of_uri uri)
104 ppid (UriManager.name_of_uri uri) in
106 let suri = UriManager.buri_of_uri uri in
107 let s = String.sub suri 5 (String.length suri - 5) in
108 let s = Pcre.replace ~pat:"/" ~templ:"_" s in
109 String.uncapitalize s in
110 if current_module_uri = UriManager.buri_of_uri uri then
113 String.capitalize filename ^ "." ^ name
116 let current_go_up = ref "(.!(";;
119 current_go_up := "(.~(";
121 current_go_up := "(.!(";
124 current_go_up := "(.!(";
128 let pp current_module_uri ?metasenv ~in_type =
129 let rec pp ~in_type t context =
130 let module C = Cic in
135 (match get_nth context n with
136 Some (C.Name s,_) -> ppid s
137 | Some (C.Anonymous,_) -> "__" ^ string_of_int n
138 | None -> "_hidden_" ^ string_of_int n
141 NotEnoughElements -> string_of_int (List.length context - n)
143 | C.Var (uri,exp_named_subst) ->
144 qualified_name_of_uri current_module_uri uri ^
145 pp_exp_named_subst exp_named_subst context
149 "?" ^ (string_of_int n) ^ "[" ^
154 | Some t -> pp ~in_type:false t context) l1) ^
158 let _,context,_ = CicUtil.lookup_meta n metasenv in
159 "?" ^ (string_of_int n) ^ "[" ^
167 | Some _, Some t -> pp ~in_type:false t context
171 CicUtil.Meta_not_found _
172 | Invalid_argument _ ->
173 "???" ^ (string_of_int n) ^ "[" ^
175 (List.rev_map (function None -> "_" | Some t ->
176 pp ~in_type:false t context) l1) ^
184 (*| C.Type u -> ("Type" ^ CicUniv.string_of_universe u)*)
185 | C.CProp _ -> "CProp"
187 | C.Implicit (Some `Hole) -> "%"
188 | C.Implicit _ -> "?"
192 let n = "'" ^ String.uncapitalize n in
193 "(" ^ pp ~in_type:true s context ^ " -> " ^
194 pp ~in_type:true t ((Some (Cic.Name n,Cic.Decl s))::context) ^ ")"
196 "(" ^ pp ~in_type:true s context ^ " -> " ^
197 pp ~in_type:true t ((Some (b,Cic.Decl s))::context) ^ ")")
198 | C.Cast (v,t) -> pp ~in_type v context
199 | C.Lambda (b,s,t) ->
200 (match analyze_type context s with
202 | `Statement -> pp ~in_type t ((Some (b,Cic.Decl s))::context)
203 | `Optimize -> prerr_endline "XXX lambda";assert false
205 "(function " ^ ppname b ^ " -> " ^
206 pp ~in_type t ((Some (b,Cic.Decl s))::context) ^ ")")
207 | C.LetIn (b,s,ty,t) ->
208 (match analyze_term context s with
210 | `Proof -> pp ~in_type t ((Some (b,Cic.Def (s,ty)))::context)
213 "(let " ^ ppname b ^ (*" : " ^ pp ~in_type:true ty context ^*)
214 " = " ^ pp ~in_type:false s context ^ " in " ^
215 pp ~in_type t ((Some (b,Cic.Def (s,ty)))::context) ^ ")")
216 | C.Appl (he::tl) when in_type ->
217 let hes = pp ~in_type he context in
218 let stl = String.concat "," (clean_args_for_ty context tl) in
219 (if stl = "" then "" else "(" ^ stl ^ ") ") ^ hes
220 | C.Appl (C.MutInd _ as he::tl) ->
221 let hes = pp ~in_type he context in
222 let stl = String.concat "," (clean_args_for_ty context tl) in
223 (if stl = "" then "" else "(" ^ stl ^ ") ") ^ hes
224 | C.Appl (C.MutConstruct (uri,n,_,_) as he::tl) ->
226 match fst(CicEnvironment.get_obj CicUniv.oblivion_ugraph uri) with
227 C.InductiveDefinition (_,_,nparams,_) -> nparams
228 | _ -> assert false in
229 let hes = pp ~in_type he context in
230 let stl = String.concat "," (clean_args_for_constr nparams context tl) in
231 "(" ^ hes ^ (if stl = "" then "" else "(" ^ stl ^ ")") ^ ")"
233 "(" ^ String.concat " " (clean_args context li) ^ ")"
234 | C.Const (uri,exp_named_subst) ->
235 qualified_name_of_uri current_module_uri uri ^
236 pp_exp_named_subst exp_named_subst context
237 | C.MutInd (uri,n,exp_named_subst) ->
239 match fst(CicEnvironment.get_obj CicUniv.oblivion_ugraph uri) with
240 C.InductiveDefinition (dl,_,_,_) ->
241 let (name,_,_,_) = get_nth dl (n+1) in
242 qualified_name_of_uri current_module_uri
243 (UriManager.uri_of_string
244 (UriManager.buri_of_uri uri ^ "/" ^ name ^ ".con")) ^
245 pp_exp_named_subst exp_named_subst context
246 | _ -> raise CicExportationInternalError
248 Sys.Break as exn -> raise exn
249 | _ -> UriManager.string_of_uri uri ^ "#1/" ^ string_of_int (n + 1)
251 | C.MutConstruct (uri,n1,n2,exp_named_subst) ->
253 match fst(CicEnvironment.get_obj CicUniv.oblivion_ugraph uri) with
254 C.InductiveDefinition (dl,_,_,_) ->
255 let _,_,_,cons = get_nth dl (n1+1) in
256 let id,_ = get_nth cons n2 in
257 qualified_name_of_uri current_module_uri ~capitalize:true
258 (UriManager.uri_of_string
259 (UriManager.buri_of_uri uri ^ "/" ^ id ^ ".con")) ^
260 pp_exp_named_subst exp_named_subst context
261 | _ -> raise CicExportationInternalError
263 Sys.Break as exn -> raise exn
265 UriManager.string_of_uri uri ^ "#1/" ^ string_of_int (n1 + 1) ^ "/" ^
268 | C.MutCase (uri,n1,ty,te,patterns) ->
270 "unit (* TOO POLYMORPHIC TYPE *)"
272 let rec needs_obj_magic ty =
273 match CicReduction.whd context ty with
274 | Cic.Lambda (_,_,(Cic.Lambda(_,_,_) as t)) -> needs_obj_magic t
275 | Cic.Lambda (_,_,t) -> not (DoubleTypeInference.does_not_occur 1 t)
276 | _ -> false (* it can be a Rel, e.g. in *_rec *)
278 let needs_obj_magic = needs_obj_magic ty in
279 (match analyze_term context te with
280 `Type -> assert false
283 [] -> "assert false" (* empty type elimination *)
285 pp ~in_type:false he context (* singleton elimination *)
289 if patterns = [] then "assert false"
291 (let connames_and_argsno, go_up, go_pu, go_down, go_nwod =
292 (match fst(CicEnvironment.get_obj CicUniv.oblivion_ugraph uri) with
293 C.InductiveDefinition (dl,_,paramsno,_) ->
294 let (_,_,_,cons) = get_nth dl (n1+1) in
298 (* this is just an approximation since we do not have
300 let rec count_prods toskip =
302 C.Prod (_,_,bo) when toskip > 0 ->
303 count_prods (toskip - 1) bo
304 | C.Prod (_,_,bo) -> 1 + count_prods 0 bo
307 qualified_name_of_uri current_module_uri
309 (UriManager.uri_of_string
310 (UriManager.buri_of_uri uri ^ "/" ^ id ^ ".con")),
311 count_prods paramsno ty
314 if not (is_mcu_type uri) then rc, "","","",""
315 else rc, !current_go_up, "))", "( .< (", " ) >.)"
316 | _ -> raise CicExportationInternalError
319 let connames_and_argsno_and_patterns =
323 | (x,no)::tlx,y::tly -> (x,no,y)::(combine (tlx,tly))
324 | _,_ -> assert false
326 combine (connames_and_argsno,patterns)
329 "\n(match " ^ pp ~in_type:false te context ^ " with \n " ^
330 (String.concat "\n | "
333 let rec aux argsno context =
335 Cic.Lambda (name,ty,bo) when argsno > 0 ->
338 Cic.Anonymous -> Cic.Anonymous
339 | Cic.Name n -> Cic.Name (ppid n) in
341 aux (argsno - 1) (Some (name,Cic.Decl ty)::context)
344 (match analyze_type context ty with
345 | `Optimize -> prerr_endline "XXX contructor with l2 arg"; assert false
347 | `Sort _ -> args,res
351 | C.Name s -> s)::args,res)
352 | t when argsno = 0 -> [],pp ~in_type:false t context
354 ["{" ^ string_of_int argsno ^ " args missing}"],
355 pp ~in_type:false t context
358 if argsno = 0 then x,pp ~in_type:false y context
360 let args,body = aux argsno context y in
361 let sargs = String.concat "," args in
362 x ^ (if sargs = "" then "" else "(" ^ sargs^ ")"),
365 pattern ^ " -> " ^ go_down ^
366 (if needs_obj_magic then
367 "Obj.magic (" ^ body ^ ")"
370 ) connames_and_argsno_and_patterns)) ^
372 | C.Fix (no, funs) ->
375 (fun (types,len) (n,_,ty,_) ->
376 (Some (C.Name n,(C.Decl (CicSubstitution.lift len ty)))::types,
382 (fun (name,ind,ty,bo) i -> name ^ " = \n" ^
383 pp ~in_type:false bo (names@context) ^ i)
386 (match get_nth names (no + 1) with
387 Some (Cic.Name n,_) -> n
389 | C.CoFix (no,funs) ->
392 (fun (types,len) (n,ty,_) ->
393 (Some (C.Name n,(C.Decl (CicSubstitution.lift len ty)))::types,
399 (fun (name,ty,bo) i -> "\n" ^ name ^
400 " : " ^ pp ~in_type:true ty context ^ " := \n" ^
401 pp ~in_type:false bo (names@context) ^ i)
404 and pp_exp_named_subst exp_named_subst context =
405 if exp_named_subst = [] then "" else
407 String.concat " ; " (
409 (function (uri,t) -> UriManager.name_of_uri uri ^ " \\Assign " ^ pp ~in_type:false t context)
412 and clean_args_for_constr nparams context =
413 let nparams = ref nparams in
417 match analyze_term context t with
418 `Term when !nparams < 0 -> Some (pp ~in_type:false t context)
423 and clean_args context =
425 | [] | [_] -> assert false
426 | he::arg1::tl as l ->
427 let head_arg1, rest =
428 match analyze_term context arg1 with
430 !current_go_up :: pp ~in_type:false he context ::
431 pp ~in_type:false arg1 context :: ["))"], tl
437 match analyze_term context t with
438 | `Term -> Some (pp ~in_type:false t context)
440 prerr_endline "XXX function taking twice (or not as first) a l2 term"; assert false
442 | `Proof -> None) rest
443 and clean_args_for_ty context =
446 match analyze_term context t with
447 `Type -> Some (pp ~in_type:true t context)
455 let ppty current_module_uri =
456 (* nparams is the number of left arguments
457 left arguments should either become parameters or be skipped altogether *)
458 let rec args nparams context =
463 Cic.Anonymous -> Cic.Anonymous
464 | Cic.Name n -> Cic.Name (String.uncapitalize n)
466 (match analyze_type context s with
470 args (nparams - 1) ((Some (n,Cic.Decl s))::context) t
471 | `Type when nparams > 0 ->
472 args (nparams - 1) ((Some (n,Cic.Decl s))::context) t
475 args (nparams - 1) ((Some (n,Cic.Decl s))::context) t in
476 abstr,pp ~in_type:true current_module_uri s context::args
477 | `Sort _ when nparams <= 0 ->
478 let n = Cic.Name "unit (* EXISTENTIAL TYPE *)" in
479 args (nparams - 1) ((Some (n,Cic.Decl s))::context) t
483 Cic.Anonymous -> Cic.Anonymous
484 | Cic.Name name -> Cic.Name ("'" ^ name) in
486 args (nparams - 1) ((Some (n,Cic.Decl s))::context) t
489 Cic.Anonymous -> abstr
490 | Cic.Name name -> name::abstr),
497 exception DoNotExtract;;
499 let pp_abstracted_ty current_module_uri =
500 let rec args context =
502 Cic.Lambda (n,s,t) ->
505 Cic.Anonymous -> Cic.Anonymous
506 | Cic.Name n -> Cic.Name (String.uncapitalize n)
508 (match analyze_type context s with
513 args ((Some (n,Cic.Decl s))::context) t
517 Cic.Anonymous -> Cic.Anonymous
518 | Cic.Name name -> Cic.Name ("'" ^ name) in
520 args ((Some (n,Cic.Decl s))::context) t
523 Cic.Anonymous -> abstr
524 | Cic.Name name -> name::abstr),
527 match analyze_type context ty with
529 prerr_endline "XXX abstracted l2 ty"; assert false
531 | `Statement -> raise DoNotExtract
533 (* BUG HERE: this can be a real System F type *)
534 let head = pp ~in_type:true current_module_uri ty context in
541 (* ppinductiveType (typename, inductive, arity, cons) *)
542 (* pretty-prints a single inductive definition *)
543 (* (typename, inductive, arity, cons) *)
544 let ppinductiveType current_module_uri nparams (typename, inductive, arity, cons)
546 match analyze_type [] arity with
550 | `Type -> assert false
553 "type " ^ String.uncapitalize typename ^ " = unit (* empty type *)\n"
557 (fun (id,ty) (_abstr,i) -> (* we should verify _abstr = abstr' *)
558 let abstr',sargs = ppty current_module_uri nparams [] ty in
559 let sargs = String.concat " * " sargs in
561 String.capitalize id ^
562 (if sargs = "" then "" else " of " ^ sargs) ^
563 (if i = "" then "" else "\n | ") ^ i)
567 let s = String.concat "," abstr in
568 if s = "" then "" else "(" ^ s ^ ") "
570 "type " ^ abstr ^ String.uncapitalize typename ^ " =\n" ^ scons ^ "\n")
573 let ppobj current_module_uri obj =
574 let module C = Cic in
575 let module U = UriManager in
576 let pp ~in_type = pp ~in_type current_module_uri in
578 C.Constant (name, Some t1, t2, params, _) ->
579 (match analyze_type [] t2 with
585 | Cic.Lambda (Cic.Name arg, s, t) ->
586 (match analyze_type [] s with
589 "let " ^ ppid name ^ "__1 = function " ^ ppid arg
591 at_level2 (pp ~in_type:false t) [Some (Cic.Name arg, Cic.Decl s)]
593 ^ "let " ^ ppid name ^ "__2 = ref ([] : (unit list*unit list) list);;\n"
594 ^ "let " ^ ppid name ^ " = function " ^ ppid arg
595 ^ " -> (try ignore (List.assoc "^ppid arg^" (Obj.magic !"^ppid name
596 ^"__2)) with Not_found -> "^ppid name^"__2 := (Obj.magic ("
597 ^ ppid arg^",.! ("^ppid name^"__1 "^ppid arg^")))::!"
598 ^ppid name^"__2); .< List.assoc "^ppid arg^" (Obj.magic (!"
599 ^ppid name^"__2)) >.\n;;\n"
600 ^" let xxx = prerr_endline \""^ppid name^"\"; .!("^ppid
601 name^" Matita_freescale_opcode.HCS08)"
603 "let " ^ ppid name ^ " =\n" ^ pp ~in_type:false t1 [] ^ "\n")
604 | _ -> "let " ^ ppid name ^ " =\n" ^ pp ~in_type:false t1 [] ^ "\n")
606 match analyze_type [] t1 with
608 | `Optimize -> prerr_endline "XXX aliasing l2 type"; assert false
611 let abstr,res = pp_abstracted_ty current_module_uri [] t1 in
613 let s = String.concat "," abstr in
614 if s = "" then "" else "(" ^ s ^ ") "
616 "type " ^ abstr ^ ppid name ^ " = " ^ res ^ "\n"
619 | C.Constant (name, None, ty, params, _) ->
620 (match analyze_type [] ty with
622 | `Optimize -> prerr_endline "XXX axiom l2"; assert false
624 | `Sort _ -> "type " ^ ppid name ^ "\n"
625 | `Type -> "let " ^ ppid name ^ " = assert false\n")
626 | C.Variable (name, bo, ty, params, _) ->
628 "(" ^ String.concat ";" (List.map UriManager.string_of_uri params) ^
630 pp ~in_type:true ty [] ^ "\n" ^
631 (match bo with None -> "" | Some bo -> ":= " ^ pp ~in_type:false bo [])
632 | C.CurrentProof (name, conjectures, value, ty, params, _) ->
633 "Current Proof of " ^ name ^
634 "(" ^ String.concat ";" (List.map UriManager.string_of_uri params) ^
636 let separate s = if s = "" then "" else s ^ " ; " in
638 (fun (n, context, t) i ->
639 let conjectures',name_context =
641 (fun context_entry (i,name_context) ->
642 (match context_entry with
643 Some (n,C.Decl at) ->
646 pp ~in_type:true ~metasenv:conjectures
647 at name_context ^ " ",
648 context_entry::name_context
649 | Some (n,C.Def (at,aty)) ->
652 pp ~in_type:true ~metasenv:conjectures
654 ":= " ^ pp ~in_type:false
655 ~metasenv:conjectures at name_context ^ " ",
656 context_entry::name_context
658 (separate i) ^ "_ :? _ ", context_entry::name_context)
661 conjectures' ^ " |- " ^ "?" ^ (string_of_int n) ^ ": " ^
662 pp ~in_type:true ~metasenv:conjectures t name_context ^ "\n" ^ i
664 "\n" ^ pp ~in_type:false ~metasenv:conjectures value [] ^ " : " ^
665 pp ~in_type:true ~metasenv:conjectures ty []
666 | C.InductiveDefinition (l, params, nparams, _) ->
668 (fun x i -> ppinductiveType current_module_uri nparams x ^ i) l ""
671 let ppobj current_module_uri obj =
672 let res = ppobj current_module_uri obj in
673 if res = "" then "" else res ^ ";;\n\n"