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 $ *)
29 let apply_subst subst t = assert (subst=[]); t;;
31 type typformerreference = NReference.reference
32 type reference = NReference.reference
36 | KArrow of kind * kind
37 | KSkip of kind (* dropped abstraction *)
39 let rec size_of_kind =
42 | KArrow (l, r) -> 1 + size_of_kind l + size_of_kind r
43 | KSkip k -> size_of_kind k
46 let bracket size_of pp o =
53 let rec pretty_print_kind =
56 | KArrow (l, r) -> bracket size_of_kind pretty_print_kind l ^ " -> " ^ pretty_print_kind r
57 | KSkip k -> pretty_print_kind k
64 | TConst of typformerreference
67 | Forall of string * kind * typ
70 let rec size_of_type =
77 | TSkip t -> size_of_type t
82 (* None = dropped abstraction *)
83 type typ_context = (string * kind) option list
84 type term_context = (string * [`OfKind of kind | `OfType of typ]) option list
86 type typ_former_decl = typ_context * kind
87 type typ_former_def = typ_former_decl * typ
93 | Lambda of string * (* typ **) term
95 | LetIn of string * (* typ **) term * term
96 | Match of reference * term * (term_context * term) list
98 | TLambda of string * term
99 | Inst of (*typ_former **) term
101 | UnsafeCoerce of term
104 type term_former_decl = term_context * typ
105 type term_former_def = term_former_decl * term
109 Appl args -> Appl (args@[x])
112 let rec size_of_term =
117 | Lambda (_, body) -> 1 + size_of_term body
118 | Appl l -> List.length l
119 | LetIn (_, def, body) -> 1 + size_of_term def + size_of_term body
120 | Match (_, case, pats) -> 1 + size_of_term case + List.length pats
122 | TLambda (_,t) -> size_of_term t
123 | Inst t -> size_of_term t
124 | Skip t -> size_of_term t
125 | UnsafeCoerce t -> 1 + size_of_term t
128 NCic.Const (NReference.reference_of_spec (NUri.uri_of_string "cic:/matita/basics/types/unit.ind") (NReference.Ind (true,0,0)));;
131 TypeDeclaration of typ_former_decl
132 | TypeDefinition of typ_former_def
133 | TermDeclaration of term_former_decl
134 | TermDefinition of term_former_def
135 | LetRec of (NReference.reference * obj_kind) list
136 (* reference, left, right, constructors *)
137 | Algebraic of (NReference.reference * typ_context * typ_context * (NReference.reference * typ) list) list
139 type obj = NReference.reference * obj_kind
141 (* For LetRec and Algebraic blocks *)
143 NReference.reference_of_string "cic:/matita/dummy/dummy.ind(1,1,1)"
145 let rec classify_not_term status context t =
146 match NCicReduction.whd status ~subst:[] context t with
150 | NCic.Type [`CProp,_] -> `PropKind
151 | NCic.Type [`Type,_] -> `Kind
152 | NCic.Type _ -> assert false)
153 | NCic.Prod (b,s,t) ->
154 (*CSC: using invariant on "_" *)
155 classify_not_term status ((b,NCic.Decl s)::context) t
159 | NCic.Const (NReference.Ref (_,NReference.CoFix _))
160 | NCic.Appl [] -> assert false (* NOT POSSIBLE *)
162 | NCic.Const (NReference.Ref (_,NReference.Fix _)) ->
163 (* be aware: we can be the head of an application *)
164 assert false (* TODO *)
165 | NCic.Meta _ -> assert false (* TODO *)
166 | NCic.Appl (he::_) -> classify_not_term status context he
168 let rec find_sort typ =
169 match NCicReduction.whd status ~subst:[] context (NCicSubstitution.lift status n typ) with
170 NCic.Sort NCic.Prop -> `Proposition
171 | NCic.Sort (NCic.Type [`CProp,_]) -> `Proposition
172 | NCic.Sort (NCic.Type [`Type,_]) ->
173 (*CSC: we could be more precise distinguishing the user provided
174 minimal elements of the hierarchies and classify these
177 | NCic.Sort (NCic.Type _) -> assert false (* ALGEBRAIC *)
178 | NCic.Prod (_,_,t) ->
179 (* we skipped arguments of applications, so here we need to skip
182 | _ -> assert false (* NOT A SORT *)
184 (match List.nth context (n-1) with
185 _,NCic.Decl typ -> find_sort typ
186 | _,NCic.Def _ -> assert false (* IMPOSSIBLE *))
187 | NCic.Const (NReference.Ref (_,NReference.Decl) as ref) ->
188 let _,_,ty,_,_ = NCicEnvironment.get_checked_decl status ref in
189 (match classify_not_term status [] ty with
191 | `Type -> assert false (* IMPOSSIBLE *)
193 | `KindOrType -> `Type
194 | `PropKind -> `Proposition)
195 | NCic.Const (NReference.Ref (_,NReference.Ind _) as ref) ->
196 let _,_,ityl,_,i = NCicEnvironment.get_checked_indtys status ref in
197 let _,_,arity,_ = List.nth ityl i in
198 (match classify_not_term status [] arity with
201 | `KindOrType -> assert false (* IMPOSSIBLE *)
203 | `PropKind -> `Proposition)
204 | NCic.Const (NReference.Ref (_,NReference.Con _))
205 | NCic.Const (NReference.Ref (_,NReference.Def _)) ->
206 assert false (* IMPOSSIBLE *)
209 type not_term = [`Kind | `KindOrType | `PropKind | `Proposition | `Type];;
211 let classify status ~metasenv context t =
212 match NCicTypeChecker.typeof status ~metasenv ~subst:[] context t with
214 (classify_not_term status context t : not_term :> [> not_term])
216 let ty = fix_sorts ty in
218 (match classify_not_term status context ty with
219 | `Proposition -> `Proof
221 | `KindOrType -> `TypeFormerOrTerm
222 | `Kind -> `TypeFormer
223 | `PropKind -> `PropFormer)
227 let rec kind_of status ~metasenv context k =
228 match NCicReduction.whd status ~subst:[] context k with
229 | NCic.Sort NCic.Type _ -> Type
230 | NCic.Sort _ -> assert false (* NOT A KIND *)
231 | NCic.Prod (b,s,t) ->
232 (match classify status ~metasenv context s with
234 KArrow (kind_of status ~metasenv context s,
235 kind_of ~metasenv status ((b,NCic.Decl s)::context) t)
240 KSkip (kind_of status ~metasenv ((b,NCic.Decl s)::context) t)
241 | `Term _ -> assert false (* IMPOSSIBLE *))
243 | NCic.LetIn _ -> assert false (* IMPOSSIBLE *)
246 | NCic.Const _ -> assert false (* NOT A KIND *)
247 | NCic.Appl _ -> assert false (* TODO: when head is a match/let rec;
248 otherwise NOT A KIND *)
250 | NCic.Match (_,_,_,_) -> assert false (* TODO *)
253 let rec skip_args status ~metasenv context =
256 | [],_ -> assert false (* IMPOSSIBLE *)
257 | None::tl1,_::tl2 -> skip_args status ~metasenv context (tl1,tl2)
259 match classify status ~metasenv context arg with
262 | `Term `TypeFormer ->
263 Some arg::skip_args status ~metasenv context (tl1,tl2)
266 | `PropKind -> None::skip_args status ~metasenv context (tl1,tl2)
267 | `Term _ -> assert false (* IMPOSSIBLE *)
270 module ReferenceMap = Map.Make(struct type t = NReference.reference let compare = NReference.compare end)
272 type db = (typ_context * typ option) ReferenceMap.t
274 class type g_status =
276 method extraction_db: db
279 class virtual status =
282 val extraction_db = ReferenceMap.empty
283 method extraction_db = extraction_db
284 method set_extraction_db v = {< extraction_db = v >}
285 method set_extraction_status
286 : 'status. #g_status as 'status -> 'self
287 = fun o -> {< extraction_db = o#extraction_db >}
290 let rec split_kind_prods context =
292 | KArrow (so,ta)-> split_kind_prods (Some ("_",so)::context) ta
293 | KSkip ta -> split_kind_prods (None::context) ta
294 | Type -> context,Type
297 let rec split_typ_prods context =
299 | Arrow (so,ta)-> split_typ_prods (Some ("_",`OfType so)::context) ta
300 | Forall (name,so,ta)-> split_typ_prods (Some (name,`OfKind so)::context) ta
301 | TSkip ta -> split_typ_prods (None::context) ta
302 | _ as t -> context,t
305 let rec glue_ctx_typ ctx typ =
308 | Some (_,`OfType so)::ctx -> glue_ctx_typ ctx (Arrow (so,typ))
309 | Some (name,`OfKind so)::ctx -> glue_ctx_typ ctx (Forall (name,so,typ))
310 | None::ctx -> glue_ctx_typ ctx (TSkip typ)
313 let rec split_typ_lambdas status n ~metasenv context typ =
314 if n = 0 then context,typ
316 match NCicReduction.whd status ~delta:max_int ~subst:[] context typ with
317 | NCic.Lambda (name,s,t) ->
318 split_typ_lambdas status (n-1) ~metasenv ((name,NCic.Decl s)::context) t
320 (* eta-expansion required *)
321 let ty = NCicTypeChecker.typeof status ~metasenv ~subst:[] context t in
322 match NCicReduction.whd status ~delta:max_int ~subst:[] context ty with
323 | NCic.Prod (name,typ,_) ->
324 split_typ_lambdas status (n-1) ~metasenv
325 ((name,NCic.Decl typ)::context)
326 (NCicUntrusted.mk_appl t [NCic.Rel 1])
327 | _ -> assert false (* IMPOSSIBLE *)
331 let rev_context_of_typformer status ~metasenv context =
333 NCic.Const (NReference.Ref (_,NReference.Ind _) as ref)
334 | NCic.Const (NReference.Ref (_,NReference.Def _) as ref)
335 | NCic.Const (NReference.Ref (_,NReference.Decl) as ref)
336 | NCic.Const (NReference.Ref (_,NReference.Fix _) as ref) ->
337 (try List.rev (fst (ReferenceMap.find ref status#extraction_db))
340 (* This can happen only when we are processing the type of
341 the constructor of a small singleton type. In this case
342 we are not interested in all the type, but only in its
343 backbone. That is why we can safely return the dummy context here *)
344 let rec dummy = None::dummy in
346 | NCic.Match _ -> assert false (* TODO ???? *)
349 match List.nth context (n-1) with
350 _,NCic.Decl typ -> typ
351 | _,NCic.Def _ -> assert false (* IMPOSSIBLE *) in
352 let typ_ctx = snd (HExtlib.split_nth n context) in
353 let typ = kind_of status ~metasenv typ_ctx typ in
354 List.rev (fst (split_kind_prods [] typ))
355 | NCic.Meta _ -> assert false (* TODO *)
356 | NCic.Const (NReference.Ref (_,NReference.Con _))
357 | NCic.Const (NReference.Ref (_,NReference.CoFix _))
358 | NCic.Sort _ | NCic.Implicit _ | NCic.Lambda _ | NCic.LetIn _
359 | NCic.Appl _ | NCic.Prod _ ->
360 assert false (* IMPOSSIBLE *)
362 let rec typ_of status ~metasenv context k =
363 match NCicReduction.whd status ~delta:max_int ~subst:[] context k with
364 | NCic.Prod (b,s,t) ->
365 (* CSC: non-invariant assumed here about "_" *)
366 (match classify status ~metasenv context s with
368 Forall (b, kind_of status ~metasenv context s,
369 typ_of ~metasenv status ((b,NCic.Decl s)::context) t)
371 | `KindOrType -> (* ??? *)
372 Arrow (typ_of status ~metasenv context s,
373 typ_of status ~metasenv ((b,NCic.Decl s)::context) t)
376 TSkip (typ_of status ~metasenv ((b,NCic.Decl s)::context) t)
377 | `Term _ -> assert false (* IMPOSSIBLE *))
380 | NCic.LetIn _ -> assert false (* IMPOSSIBLE *)
381 | NCic.Lambda _ -> assert false (* LAMBDA-LIFT INNER DECLARATION *)
382 | NCic.Rel n -> Var n
383 | NCic.Const ref -> TConst ref
384 | NCic.Appl (he::args) ->
385 let rev_he_context= rev_context_of_typformer status ~metasenv context he in
386 TAppl (typ_of status ~metasenv context he ::
388 (function None -> Unit | Some ty -> typ_of status ~metasenv context ty)
389 (skip_args status ~metasenv context (rev_he_context,args)))
390 | NCic.Appl _ -> assert false (* TODO: when head is a match/let rec;
391 otherwise NOT A TYPE *)
393 | NCic.Match (_,_,_,_) -> assert false (* TODO *)
396 let rec fomega_subst k t1 =
400 else if n < k then Var n
403 | TConst ref -> TConst ref
405 | Arrow (ty1,ty2) -> Arrow (fomega_subst k t1 ty1, fomega_subst (k+1) t1 ty2)
406 | TSkip t -> TSkip (fomega_subst (k+1) t1 t)
407 | Forall (n,kind,t) -> Forall (n,kind,fomega_subst (k+1) t1 t)
408 | TAppl args -> TAppl (List.map (fomega_subst k t1) args)
410 let fomega_lookup status ref = snd (ReferenceMap.find ref status#extraction_db)
412 let rec fomega_whd status ty =
415 (match fomega_lookup status r with
417 | Some ty -> fomega_whd status ty)
418 | TAppl (TConst r::args) ->
419 (match fomega_lookup status r with
421 | Some ty -> fomega_whd status (List.fold_right (fomega_subst 1) args ty))
424 let rec term_of status ~metasenv context =
428 | NCic.Prod _ -> assert false (* IMPOSSIBLE *)
429 | NCic.Lambda (b,ty,bo) ->
430 (* CSC: non-invariant assumed here about "_" *)
431 (match classify status ~metasenv context ty with
433 TLambda (b,term_of status ~metasenv ((b,NCic.Decl ty)::context) bo)
434 | `KindOrType (* ??? *)
436 Lambda (b, term_of status ~metasenv ((b,NCic.Decl ty)::context) bo)
440 Skip (term_of status ~metasenv ((b,NCic.Decl ty)::context) bo)
441 | `Term _ -> assert false (* IMPOSSIBLE *))
442 | NCic.LetIn (b,ty,t,bo) ->
443 (match classify status ~metasenv context t with
444 | `Term `TypeFormerOrTerm (* ???? *)
446 LetIn (b,term_of status ~metasenv context t,
447 term_of status ~metasenv ((b,NCic.Def (t,ty))::context) bo)
456 (* not in programming languages, we expand it *)
457 term_of status ~metasenv context
458 (NCicSubstitution.subst status ~avoid_beta_redexes:true t bo))
459 | NCic.Rel n -> Rel n
460 | NCic.Const ref -> Const ref
461 | NCic.Appl (he::args) ->
462 eat_args status metasenv
463 (term_of status ~metasenv context he) context
464 (*BUG: recomputing every time the type of the head*)
465 (typ_of status ~metasenv context
466 (NCicTypeChecker.typeof status ~metasenv ~subst:[] context he))
468 | NCic.Appl _ -> assert false (* TODO: when head is a match/let rec;
469 otherwise NOT A TYPE *)
470 | NCic.Meta _ -> assert false (* TODO *)
471 | NCic.Match (ref,_,t,pl) ->
473 let constructors, leftno =
474 let _,leftno,tys,_,n = NCicEnvironment.get_checked_indtys status ref in
475 let _,_,_,cl = List.nth tys n in
478 let rec eat_branch n ty context ctx pat =
482 | Arrow (_, t), _ when n > 0 ->
483 eat_branch (pred n) t context ctx pat
484 | _, _ when n > 0 -> assert false (*BUG: is Top possible here?*)
485 (*CSC: unify the three cases below? *)
486 | Arrow (_, t), NCic.Lambda (name, ty, t') ->
488 (Some (name,`OfType (typ_of status ~metasenv context ty)))::ctx in
489 let context = (name,NCic.Decl ty)::context in
490 eat_branch 0 t context ctx t'
491 | Forall (_,_,t),NCic.Lambda (name, ty, t') ->
493 (Some (name,`OfKind (kind_of status ~metasenv context ty)))::ctx in
494 let context = (name,NCic.Decl ty)::context in
495 eat_branch 0 t context ctx t'
496 | TSkip t,NCic.Lambda (name, ty, t') ->
497 let ctx = None::ctx in
498 let context = (name,NCic.Decl ty)::context in
499 eat_branch 0 t context ctx t'
500 | Top,_ -> assert false (*TODO: HOW??*)
501 (*BUG here, eta-expand!*)
502 | _, _ -> context,ctx, pat
506 (fun (_, name, ty) pat ->
507 (*BUG: recomputing every time the type of the constructor*)
508 let ty = typ_of status ~metasenv context ty in
509 let context,lhs,rhs = eat_branch leftno ty context [] pat in
511 (* UnsafeCoerce not always required *)
512 UnsafeCoerce (term_of status ~metasenv context rhs)
516 with Invalid_argument _ -> assert false
518 (match classify_not_term status [] (NCic.Const ref) with
521 | `Kind -> assert false (* IMPOSSIBLE *)
523 (match patterns_of pl with
525 | [_lhs,rhs] -> rhs (*BUG HERE: Rels are not ok, bound in the _lhs*)
528 Match (ref,term_of status ~metasenv context t, patterns_of pl))
529 and eat_args status metasenv acc context tyhe =
533 match fomega_whd status tyhe with
538 | _ -> term_of status ~metasenv context arg in
539 eat_args status metasenv (mk_appl acc arg) context t tl
541 eat_args status metasenv (Inst acc)
542 context (fomega_subst 1 (typ_of status ~metasenv context arg) t) tl
544 eat_args status metasenv acc context t tl
545 | Top -> assert false (*TODO: HOW??*)
546 | Unit | Var _ | TConst _ | TAppl _ -> assert false (* NOT A PRODUCT *)
556 let object_of_constant status ~metasenv ref bo ty =
557 match classify status ~metasenv [] ty with
559 let ty = kind_of status ~metasenv [] ty in
560 let ctx0,res = split_kind_prods [] ty in
562 split_typ_lambdas status ~metasenv (List.length ctx0) [] bo in
563 (match classify status ~metasenv ctx bo with
565 | `KindOrType -> (* ?? no kind formers in System F_omega *)
569 HExtlib.map_option (fun (_,k) ->
570 (*CSC: BUG here, clashes*)
571 String.uncapitalize (fst n),k) p1)
574 let bo = typ_of status ~metasenv ctx bo in
575 status#set_extraction_db
576 (ReferenceMap.add ref (nicectx,Some bo)
577 status#extraction_db),
578 Success (ref,TypeDefinition((nicectx,res),bo))
579 | `Kind -> status, Erased (* DPM: but not really, more a failure! *)
581 | `Proposition -> status, Erased
582 | `Term _ -> status, Failure "Body of type lambda classified as a term. This is a bug.")
584 | `Proposition -> status, Erased
585 | `KindOrType (* ??? *)
587 (* CSC: TO BE FINISHED, REF NON REGISTERED *)
588 let ty = typ_of status ~metasenv [] ty in
590 Success (ref, TermDefinition (split_typ_prods [] ty, term_of status ~metasenv [] bo))
591 | `Term _ -> status, Failure "Non-term classified as a term. This is a bug."
594 let object_of_inductive status ~metasenv uri ind leftno il =
595 let status,_,rev_tyl =
597 (fun (status,i,res) (_,_,arity,cl) ->
598 match classify_not_term status [] arity with
601 | `Type -> assert false (* IMPOSSIBLE *)
602 | `PropKind -> status,i+1,res
604 let arity = kind_of status ~metasenv [] arity in
605 let ctx,_ = split_kind_prods [] arity in
606 let right,left = HExtlib.split_nth (List.length ctx - leftno) ctx in
608 NReference.reference_of_spec uri (NReference.Ind (ind,i,leftno)) in
610 status#set_extraction_db
611 (ReferenceMap.add ref (ctx,None) status#extraction_db) in
616 NCicReduction.split_prods status ~subst:[] [] leftno ty in
617 let ty = typ_of status ~metasenv ctx ty in
618 NReference.mk_constructor (j+1) ref,ty
621 status,i+1,(ref,left,right,cl)::res
626 | _ -> status, Success (dummyref, Algebraic (List.rev rev_tyl))
629 let object_of status (uri,height,metasenv,subst,obj_kind) =
630 let obj_kind = apply_subst subst obj_kind in
632 | NCic.Constant (_,_,None,ty,_) ->
633 let ref = NReference.reference_of_spec uri NReference.Decl in
634 (match classify status ~metasenv [] ty with
636 let ty = kind_of status ~metasenv [] ty in
637 let ctx,_ as res = split_kind_prods [] ty in
638 status#set_extraction_db
639 (ReferenceMap.add ref (ctx,None) status#extraction_db),
640 Success (ref, TypeDeclaration res)
642 | `Proposition -> status, Erased
644 | `KindOrType (*???*) ->
645 let ty = typ_of status ~metasenv [] ty in
646 status, Success (ref, TermDeclaration (split_typ_prods [] ty))
647 | `Term _ -> status, Failure "Type classified as a term. This is a bug.")
648 | NCic.Constant (_,_,Some bo,ty,_) ->
649 let ref = NReference.reference_of_spec uri (NReference.Def height) in
650 object_of_constant status ~metasenv ref bo ty
651 | NCic.Fixpoint (fix_or_cofix,fs,_) ->
654 (fun (_,_name,recno,ty,bo) (i,status,res) ->
657 NReference.reference_of_spec
658 uri (NReference.Fix (i,recno,height))
660 NReference.reference_of_spec uri (NReference.CoFix i)
662 let status,obj = object_of_constant ~metasenv status ref bo ty in
664 | Success (ref,obj) -> i+1,status, (ref,obj)::res
665 | _ -> i+1,status, res) fs (0,status,[])
667 status, Success (dummyref,LetRec objs)
668 | NCic.Inductive (ind,leftno,il,_) ->
669 object_of_inductive status ~metasenv uri ind leftno il
671 (************************ HASKELL *************************)
673 (* -----------------------------------------------------------------------------
674 * Helper functions I can't seem to find anywhere in the OCaml stdlib?
675 * -----------------------------------------------------------------------------
685 let uncurry f (x, y) =
689 let rec char_list_of_string s =
690 let l = String.length s in
691 let rec aux buffer s =
694 | m -> aux (s.[m - 1]::buffer) s (m - 1)
699 let string_of_char_list s =
703 | x::xs -> aux (String.make 1 x ^ buffer) xs
708 (* ----------------------------------------------------------------------------
709 * Haskell name management: prettyfying valid and idiomatic Haskell identifiers
710 * and type variable names.
711 * ----------------------------------------------------------------------------
714 let remove_underscores_and_mark =
715 let rec aux char_list_buffer positions_buffer position =
717 | [] -> (string_of_char_list char_list_buffer, positions_buffer)
720 aux char_list_buffer (position::positions_buffer) position xs
722 aux (x::char_list_buffer) positions_buffer (position + 1) xs
727 let rec capitalize_marked_positions s =
731 if x < String.length s then
732 let c = Char.uppercase (String.get s x) in
733 let _ = String.set s x c in
734 capitalize_marked_positions s xs
736 capitalize_marked_positions s xs
739 let contract_underscores_and_capitalise =
740 char_list_of_string |>
741 remove_underscores_and_mark |>
742 uncurry capitalize_marked_positions
745 let idiomatic_haskell_type_name_of_string =
746 contract_underscores_and_capitalise |>
750 let idiomatic_haskell_term_name_of_string =
751 contract_underscores_and_capitalise |>
755 (*CSC: code to be changed soon when we implement constructors and
756 we fix the code for term application *)
757 let classify_reference status ref =
758 if ReferenceMap.mem ref status#extraction_db then
761 let NReference.Ref (_,ref) = ref in
763 NReference.Con _ -> `Constructor
764 | NReference.Ind _ -> assert false
768 let capitalize classification name =
769 match classification with
771 | `TypeName -> idiomatic_haskell_type_name_of_string name
774 | `FunctionName -> idiomatic_haskell_term_name_of_string name
777 let pp_ref status ref =
778 capitalize (classify_reference status ref)
779 (NCicPp.r2s status true ref)
781 (* cons avoid duplicates *)
782 let rec (@:::) name l =
783 if name <> "" (* propositional things *) && name.[0] = '_' then
784 let name = String.sub name 1 (String.length name - 1) in
785 let name = if name = "" then "a" else name in
787 else if List.mem name l then (name ^ "'") @::: l
791 let (@::) x l = let x,l = x @::: l in x::l;;
793 let rec pretty_print_type status ctxt =
795 | Var n -> List.nth ctxt (n-1)
797 | Top -> assert false (* ??? *)
798 | TConst ref -> pp_ref status ref
800 bracket size_of_type (pretty_print_type status ctxt) t1 ^ " -> " ^
801 pretty_print_type status ("_"::ctxt) t2
802 | TSkip t -> pretty_print_type status ("_"::ctxt) t
803 | Forall (name, kind, t) ->
804 (*CSC: BUG HERE: avoid clashes due to uncapitalisation*)
805 let name = capitalize `TypeVariable name in
806 let name,ctxt = name@:::ctxt in
807 if size_of_kind kind > 1 then
808 "forall (" ^ name ^ " :: " ^ pretty_print_kind kind ^ "). " ^ pretty_print_type status (name::ctxt) t
810 "forall " ^ name ^ ". " ^ pretty_print_type status (name::ctxt) t
811 | TAppl tl -> String.concat " " (List.map (pretty_print_type status ctxt) tl)
813 let pretty_print_term_context status ctx1 ctx2 =
814 let name_context, rev_res =
816 (fun el (ctx1,rev_res) ->
818 None -> ""@::ctx1,rev_res
819 | Some (name,`OfKind _) -> name@::ctx1,rev_res
820 | Some (name,`OfType typ) ->
821 let name,ctx1 = name@:::ctx1 in
823 ("(" ^ name ^ " :: " ^ pretty_print_type status ctx1 typ ^ ")")::rev_res
825 name_context, String.concat " " (List.rev rev_res)
827 let rec pretty_print_term status ctxt =
829 | Rel n -> List.nth ctxt (n-1)
831 | Const ref -> pp_ref status ref
833 let name = capitalize `BoundVariable name in
834 let name,ctxt = name@:::ctxt in
835 "\\" ^ name ^ " -> " ^ pretty_print_term status (name::ctxt) t
836 | Appl tl -> String.concat " " (List.map (bracket size_of_term (pretty_print_term status ctxt)) tl)
837 | LetIn (name,s,t) ->
838 let name = capitalize `BoundVariable name in
839 let name,ctxt = name@:::ctxt in
840 "let " ^ name ^ " = " ^ pretty_print_term status ctxt s ^ " in " ^
841 pretty_print_term status (name::ctxt) t
843 "error \"Unreachable code\""
845 "unsafeCoerce " ^ bracket size_of_term (pretty_print_term status ctxt) t
846 | Match (r,matched,pl) ->
848 "error \"Case analysis over empty type\""
850 "case " ^ pretty_print_term status ctxt matched ^ " of\n" ^
853 (fun (bound_names,rhs) i ->
854 let ref = NReference.mk_constructor (i+1) r in
855 let name = pp_ref status ref in
856 let ctxt,bound_names =
857 pretty_print_term_context status ctxt bound_names in
859 pretty_print_term status ctxt rhs
861 " " ^ name ^ " " ^ bound_names ^ " -> " ^ body
863 | Skip t -> pretty_print_term status ("[[skipped]]"@::ctxt) t
864 | TLambda (name,t) ->
865 let name = capitalize `TypeVariable name in
866 pretty_print_term status (name@::ctxt) t
867 | Inst t -> pretty_print_term status ctxt t
870 let rec pp_obj status (ref,obj_kind) =
871 let pretty_print_context ctx =
872 String.concat " " (List.rev (snd
874 (fun (x,kind) (l,res) ->
876 if size_of_kind kind > 1 then
877 x::l,("(" ^ x ^ " :: " ^ pretty_print_kind kind ^ ")")::res
880 (HExtlib.filter_map (fun x -> x) ctx) ([],[]))))
882 let namectx_of_ctx ctx =
883 List.fold_right (@::)
884 (List.map (function None -> "" | Some (x,_) -> x) ctx) [] in
886 TypeDeclaration (ctx,_) ->
887 (* data?? unsure semantics: inductive type without constructor, but
888 not matchable apparently *)
889 if List.length ctx = 0 then
890 "data " ^ pp_ref status ref
892 "data " ^ pp_ref status ref ^ " " ^ pretty_print_context ctx
893 | TypeDefinition ((ctx, _),ty) ->
894 let namectx = namectx_of_ctx ctx in
895 if List.length ctx = 0 then
896 "type " ^ pp_ref status ref ^ " = " ^ pretty_print_type status namectx ty
898 "type " ^ pp_ref status ref ^ " " ^ pretty_print_context ctx ^ " = " ^ pretty_print_type status namectx ty
899 | TermDeclaration (ctx,ty) ->
900 let name = pp_ref status ref in
901 name ^ " :: " ^ pretty_print_type status [] (glue_ctx_typ ctx ty) ^ "\n" ^
902 name ^ " = error \"The declaration `" ^ name ^ "' has yet to be defined.\""
903 | TermDefinition ((ctx,ty),bo) ->
904 let name = pp_ref status ref in
905 let namectx = namectx_of_ctx ctx in
907 name ^ " :: " ^ pretty_print_type status namectx (glue_ctx_typ ctx ty) ^ "\n" ^
908 name ^ " = " ^ pretty_print_term status namectx bo
910 String.concat "\n" (List.map (pp_obj status) l)
914 (fun ref,left,right,cl ->
915 "data " ^ pp_ref status ref ^ " " ^
916 pretty_print_context (right@left) ^ " where\n " ^
917 String.concat "\n " (List.map
919 let namectx = namectx_of_ctx left in
920 pp_ref status ref ^ " :: " ^
921 pretty_print_type status namectx tys
924 (* inductive and records missing *)
926 let haskell_of_obj status (uri,_,_,_,_ as obj) =
927 let status, obj = object_of status obj in
930 Erased -> "-- [?] " ^ NUri.name_of_uri uri ^ " erased due to term being propositionally irrelevant.\n"
931 | OutsideTheory -> "-- [?] " ^ NUri.name_of_uri uri ^ " erased due to image of term under extraction residing outside Fω.\n"
932 | Failure msg -> "-- [?] " ^ NUri.name_of_uri uri ^ " FAILURE: " ^ msg ^ "\n"
933 | Success o -> pp_obj status o ^ "\n"