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
129 TypeDeclaration of typ_former_decl
130 | TypeDefinition of typ_former_def
131 | TermDeclaration of term_former_decl
132 | TermDefinition of term_former_def
133 | LetRec of (NReference.reference * obj_kind) list
134 (* reference, left, right, constructors *)
135 | Algebraic of (NReference.reference * typ_context * typ_context * (NReference.reference * typ) list) list
137 type obj = NReference.reference * obj_kind
139 (* For LetRec and Algebraic blocks *)
141 NReference.reference_of_string "cic:/matita/dummy/dummy.ind(1,1,1)"
143 type not_term = [`Kind | `KindOrType | `PropKind | `Proposition | `Type];;
145 let max_not_term t1 t2 =
148 | _,`KindOrType -> `KindOrType
154 | _,`PropKind -> `PropKind
155 | `Proposition,`Proposition -> `Proposition
157 let sup = List.fold_left max_not_term `Proposition
159 let rec classify_not_term status context t =
160 match NCicReduction.whd status ~subst:[] context t with
164 | NCic.Type [`CProp,_] -> `PropKind
165 | NCic.Type [`Type,_] -> `Kind
166 | NCic.Type _ -> assert false)
167 | NCic.Prod (b,s,t) ->
168 (*CSC: using invariant on "_" *)
169 classify_not_term status ((b,NCic.Decl s)::context) t
172 | NCic.Const (NReference.Ref (_,NReference.CoFix _))
174 assert false (* NOT POSSIBLE *)
175 | NCic.Lambda (n,s,t) ->
176 (* Lambdas can me met in branches of matches, expecially when the
177 output type is a product *)
178 classify_not_term status ((n,NCic.Decl s)::context) t
179 | NCic.Match (r,_,_,pl) ->
180 let classified_pl = List.map (classify_not_term status context) pl in
182 | NCic.Const (NReference.Ref (_,NReference.Fix _)) ->
183 assert false (* IMPOSSIBLE *)
184 | NCic.Meta _ -> assert false (* TODO *)
185 | NCic.Appl (NCic.Const (NReference.Ref (_,NReference.Fix (i,_,_)) as r)::_)->
186 let l,_,_ = NCicEnvironment.get_checked_fixes_or_cofixes status r in
187 let _,_,_,_,bo = List.nth l i in
188 classify_not_term status [] bo
189 | NCic.Appl (he::_) -> classify_not_term status context he
191 let rec find_sort typ =
192 match NCicReduction.whd status ~subst:[] context (NCicSubstitution.lift status n typ) with
193 NCic.Sort NCic.Prop -> `Proposition
194 | NCic.Sort (NCic.Type [`CProp,_]) -> `Proposition
195 | NCic.Sort (NCic.Type [`Type,_]) ->
196 (*CSC: we could be more precise distinguishing the user provided
197 minimal elements of the hierarchies and classify these
200 | NCic.Sort (NCic.Type _) -> assert false (* ALGEBRAIC *)
201 | NCic.Prod (_,_,t) ->
202 (* we skipped arguments of applications, so here we need to skip
205 | _ -> assert false (* NOT A SORT *)
207 (match List.nth context (n-1) with
208 _,NCic.Decl typ -> find_sort typ
209 | _,NCic.Def _ -> assert false (* IMPOSSIBLE *))
210 | NCic.Const (NReference.Ref (_,NReference.Decl) as ref) ->
211 let _,_,ty,_,_ = NCicEnvironment.get_checked_decl status ref in
212 (match classify_not_term status [] ty with
214 | `Type -> assert false (* IMPOSSIBLE *)
216 | `KindOrType -> `Type
217 | `PropKind -> `Proposition)
218 | NCic.Const (NReference.Ref (_,NReference.Ind _) as ref) ->
219 let _,_,ityl,_,i = NCicEnvironment.get_checked_indtys status ref in
220 let _,_,arity,_ = List.nth ityl i in
221 (match classify_not_term status [] arity with
224 | `KindOrType -> assert false (* IMPOSSIBLE *)
226 | `PropKind -> `Proposition)
227 | NCic.Const (NReference.Ref (_,NReference.Con _))
228 | NCic.Const (NReference.Ref (_,NReference.Def _)) ->
229 assert false (* IMPOSSIBLE *)
232 let classify status ~metasenv context t =
233 match NCicTypeChecker.typeof status ~metasenv ~subst:[] context t with
235 (classify_not_term status context t : not_term :> [> not_term])
237 let ty = fix_sorts ty in
239 (match classify_not_term status context ty with
240 | `Proposition -> `Proof
242 | `KindOrType -> `TypeFormerOrTerm
243 | `Kind -> `TypeFormer
244 | `PropKind -> `PropFormer)
248 let rec kind_of status ~metasenv context k =
249 match NCicReduction.whd status ~subst:[] context k with
250 | NCic.Sort NCic.Type _ -> Type
251 | NCic.Sort _ -> assert false (* NOT A KIND *)
252 | NCic.Prod (b,s,t) ->
253 (match classify status ~metasenv context s with
255 KArrow (kind_of status ~metasenv context s,
256 kind_of ~metasenv status ((b,NCic.Decl s)::context) t)
261 KSkip (kind_of status ~metasenv ((b,NCic.Decl s)::context) t)
262 | `Term _ -> assert false (* IMPOSSIBLE *))
264 | NCic.LetIn _ -> assert false (* IMPOSSIBLE *)
267 | NCic.Const _ -> assert false (* NOT A KIND *)
268 | NCic.Appl _ -> assert false (* TODO: when head is a match/let rec;
269 otherwise NOT A KIND *)
271 | NCic.Match (_,_,_,_) -> assert false (* TODO *)
274 let rec skip_args status ~metasenv context =
277 | [],_ -> assert false (* IMPOSSIBLE *)
278 | None::tl1,_::tl2 -> skip_args status ~metasenv context (tl1,tl2)
280 match classify status ~metasenv context arg with
283 | `Term `TypeFormer ->
284 Some arg::skip_args status ~metasenv context (tl1,tl2)
287 | `PropKind -> None::skip_args status ~metasenv context (tl1,tl2)
288 | `Term _ -> assert false (* IMPOSSIBLE *)
291 module ReferenceMap = Map.Make(struct type t = NReference.reference let compare = NReference.compare end)
293 type db = (typ_context * typ option) ReferenceMap.t
295 class type g_status =
297 method extraction_db: db
300 class virtual status =
303 val extraction_db = ReferenceMap.empty
304 method extraction_db = extraction_db
305 method set_extraction_db v = {< extraction_db = v >}
306 method set_extraction_status
307 : 'status. #g_status as 'status -> 'self
308 = fun o -> {< extraction_db = o#extraction_db >}
311 let rec split_kind_prods context =
313 | KArrow (so,ta)-> split_kind_prods (Some ("_",so)::context) ta
314 | KSkip ta -> split_kind_prods (None::context) ta
315 | Type -> context,Type
318 let rec split_typ_prods context =
320 | Arrow (so,ta)-> split_typ_prods (Some ("_",`OfType so)::context) ta
321 | Forall (name,so,ta)-> split_typ_prods (Some (name,`OfKind so)::context) ta
322 | TSkip ta -> split_typ_prods (None::context) ta
323 | _ as t -> context,t
326 let rec glue_ctx_typ ctx typ =
329 | Some (_,`OfType so)::ctx -> glue_ctx_typ ctx (Arrow (so,typ))
330 | Some (name,`OfKind so)::ctx -> glue_ctx_typ ctx (Forall (name,so,typ))
331 | None::ctx -> glue_ctx_typ ctx (TSkip typ)
334 let rec split_typ_lambdas status n ~metasenv context typ =
335 if n = 0 then context,typ
337 match NCicReduction.whd status ~delta:max_int ~subst:[] context typ with
338 | NCic.Lambda (name,s,t) ->
339 split_typ_lambdas status (n-1) ~metasenv ((name,NCic.Decl s)::context) t
341 (* eta-expansion required *)
342 let ty = NCicTypeChecker.typeof status ~metasenv ~subst:[] context t in
343 match NCicReduction.whd status ~delta:max_int ~subst:[] context ty with
344 | NCic.Prod (name,typ,_) ->
345 split_typ_lambdas status (n-1) ~metasenv
346 ((name,NCic.Decl typ)::context)
347 (NCicUntrusted.mk_appl t [NCic.Rel 1])
348 | _ -> assert false (* IMPOSSIBLE *)
352 let rev_context_of_typformer status ~metasenv context =
354 NCic.Const (NReference.Ref (_,NReference.Ind _) as ref)
355 | NCic.Const (NReference.Ref (_,NReference.Def _) as ref)
356 | NCic.Const (NReference.Ref (_,NReference.Decl) as ref)
357 | NCic.Const (NReference.Ref (_,NReference.Fix _) as ref) ->
358 (try List.rev (fst (ReferenceMap.find ref status#extraction_db))
361 (* This can happen only when we are processing the type of
362 the constructor of a small singleton type. In this case
363 we are not interested in all the type, but only in its
364 backbone. That is why we can safely return the dummy context here *)
365 let rec dummy = None::dummy in
367 | NCic.Match _ -> assert false (* TODO ???? *)
370 match List.nth context (n-1) with
371 _,NCic.Decl typ -> typ
372 | _,NCic.Def _ -> assert false (* IMPOSSIBLE *) in
373 let typ_ctx = snd (HExtlib.split_nth n context) in
374 let typ = kind_of status ~metasenv typ_ctx typ in
375 List.rev (fst (split_kind_prods [] typ))
376 | NCic.Meta _ -> assert false (* TODO *)
377 | NCic.Const (NReference.Ref (_,NReference.Con _))
378 | NCic.Const (NReference.Ref (_,NReference.CoFix _))
379 | NCic.Sort _ | NCic.Implicit _ | NCic.Lambda _ | NCic.LetIn _
380 | NCic.Appl _ | NCic.Prod _ ->
381 assert false (* IMPOSSIBLE *)
383 let rec typ_of status ~metasenv context k =
384 match NCicReduction.whd status ~delta:max_int ~subst:[] context k with
385 | NCic.Prod (b,s,t) ->
386 (* CSC: non-invariant assumed here about "_" *)
387 (match classify status ~metasenv context s with
389 Forall (b, kind_of status ~metasenv context s,
390 typ_of ~metasenv status ((b,NCic.Decl s)::context) t)
392 | `KindOrType -> (* ??? *)
393 Arrow (typ_of status ~metasenv context s,
394 typ_of status ~metasenv ((b,NCic.Decl s)::context) t)
397 TSkip (typ_of status ~metasenv ((b,NCic.Decl s)::context) t)
398 | `Term _ -> assert false (* IMPOSSIBLE *))
401 | NCic.LetIn _ -> assert false (* IMPOSSIBLE *)
402 | NCic.Lambda _ -> assert false (* LAMBDA-LIFT INNER DECLARATION *)
403 | NCic.Rel n -> Var n
404 | NCic.Const ref -> TConst ref
405 | NCic.Match (_,_,_,_)
406 | NCic.Appl (NCic.Const (NReference.Ref (_,NReference.Fix _))::_) ->
408 | NCic.Appl (he::args) ->
409 let rev_he_context= rev_context_of_typformer status ~metasenv context he in
410 TAppl (typ_of status ~metasenv context he ::
412 (function None -> Unit | Some ty -> typ_of status ~metasenv context ty)
413 (skip_args status ~metasenv context (rev_he_context,args)))
414 | NCic.Appl _ -> assert false (* TODO: when head is a match/let rec;
415 otherwise NOT A TYPE *)
416 | NCic.Meta _ -> assert false (*TODO*)
419 let rec fomega_lift_type_from n k =
421 | Var m as t -> if m < k then t else Var (m + n)
425 | Arrow (ty1,ty2) -> Arrow (fomega_lift_type_from n k ty1,fomega_lift_type_from n (k+1) ty2)
426 | TSkip t -> TSkip (fomega_lift_type_from n (k+1) t)
427 | Forall (name,kind,t) -> Forall (name,kind,fomega_lift_type_from n (k+1) t)
428 | TAppl args -> TAppl (List.map (fomega_lift_type_from n k) args)
430 let fomega_lift_type n t =
431 if n = 0 then t else fomega_lift_type_from n 0 t
433 let fomega_lift_term n t =
434 let rec fomega_lift_term n k =
436 | Rel m as t -> if m < k then t else Rel (m + n)
440 | Lambda (name,t) -> Lambda (name,fomega_lift_term n (k+1) t)
441 | TLambda (name,t) -> TLambda (name,fomega_lift_term n (k+1) t)
442 | Appl args -> Appl (List.map (fomega_lift_term n k) args)
443 | LetIn (name,m,bo) ->
444 LetIn (name, fomega_lift_term n k m, fomega_lift_term n (k+1) bo)
445 | Match (ref,t,pl) ->
447 let lift_context ctx =
448 let len = List.length ctx in
451 let j = len - i - 1 in
454 | Some (_,`OfKind _) as el -> el
455 | Some (name,`OfType t) ->
456 Some (name,`OfType (fomega_lift_type_from n (k+j) t))
459 lift_context ctx, fomega_lift_term n (k + List.length ctx) t
461 Match (ref,fomega_lift_term n k t,List.map lift_p pl)
462 | Inst t -> Inst (fomega_lift_term n k t)
463 | Skip t -> Skip (fomega_lift_term n (k+1) t)
464 | UnsafeCoerce t -> UnsafeCoerce (fomega_lift_term n k t)
466 if n = 0 then t else fomega_lift_term n 0 t
469 let rec fomega_subst k t1 =
472 if k=n then fomega_lift_type k t1
473 else if n < k then Var n
476 | TConst ref -> TConst ref
478 | Arrow (ty1,ty2) -> Arrow (fomega_subst k t1 ty1, fomega_subst (k+1) t1 ty2)
479 | TSkip t -> TSkip (fomega_subst (k+1) t1 t)
480 | Forall (n,kind,t) -> Forall (n,kind,fomega_subst (k+1) t1 t)
481 | TAppl args -> TAppl (List.map (fomega_subst k t1) args)
483 let fomega_lookup status ref = snd (ReferenceMap.find ref status#extraction_db)
485 let rec fomega_whd status ty =
488 (match fomega_lookup status r with
490 | Some ty -> fomega_whd status ty)
491 | TAppl (TConst r::args) ->
492 (match fomega_lookup status r with
494 | Some ty -> fomega_whd status (List.fold_right (fomega_subst 1) args ty))
497 let rec term_of status ~metasenv context =
501 | NCic.Prod _ -> assert false (* IMPOSSIBLE *)
502 | NCic.Lambda (b,ty,bo) ->
503 (* CSC: non-invariant assumed here about "_" *)
504 (match classify status ~metasenv context ty with
506 TLambda (b,term_of status ~metasenv ((b,NCic.Decl ty)::context) bo)
507 | `KindOrType (* ??? *)
509 Lambda (b, term_of status ~metasenv ((b,NCic.Decl ty)::context) bo)
513 Skip (term_of status ~metasenv ((b,NCic.Decl ty)::context) bo)
514 | `Term _ -> assert false (* IMPOSSIBLE *))
515 | NCic.LetIn (b,ty,t,bo) ->
516 (match classify status ~metasenv context t with
517 | `Term `TypeFormerOrTerm (* ???? *)
519 LetIn (b,term_of status ~metasenv context t,
520 term_of status ~metasenv ((b,NCic.Def (t,ty))::context) bo)
529 (* not in programming languages, we expand it *)
530 term_of status ~metasenv context
531 (NCicSubstitution.subst status ~avoid_beta_redexes:true t bo))
532 | NCic.Rel n -> Rel n
533 | NCic.Const ref -> Const ref
534 | NCic.Appl (he::args) ->
535 eat_args status metasenv
536 (term_of status ~metasenv context he) context
537 (*BUG: recomputing every time the type of the head*)
538 (typ_of status ~metasenv context
539 (NCicTypeChecker.typeof status ~metasenv ~subst:[] context he))
541 | NCic.Appl _ -> assert false (* TODO: when head is a match/let rec;
542 otherwise NOT A TYPE *)
543 | NCic.Meta _ -> assert false (* TODO *)
544 | NCic.Match (ref,_,t,pl) ->
546 let constructors, leftno =
547 let _,leftno,tys,_,n = NCicEnvironment.get_checked_indtys status ref in
548 let _,_,_,cl = List.nth tys n in
551 let rec eat_branch n ty context ctx pat =
555 | Arrow (_, t), _ when n > 0 ->
556 eat_branch (pred n) t context ctx pat
557 | _, _ when n > 0 -> assert false (*BUG: is Top possible here?*)
558 (*CSC: unify the three cases below? *)
559 | Arrow (_, t), NCic.Lambda (name, ty, t') ->
561 (Some (name,`OfType (typ_of status ~metasenv context ty)))::ctx in
562 let context = (name,NCic.Decl ty)::context in
563 eat_branch 0 t context ctx t'
564 | Forall (_,_,t),NCic.Lambda (name, ty, t') ->
566 (Some (name,`OfKind (kind_of status ~metasenv context ty)))::ctx in
567 let context = (name,NCic.Decl ty)::context in
568 eat_branch 0 t context ctx t'
569 | TSkip t,NCic.Lambda (name, ty, t') ->
570 let ctx = None::ctx in
571 let context = (name,NCic.Decl ty)::context in
572 eat_branch 0 t context ctx t'
573 | Top,_ -> assert false (* IMPOSSIBLE *)
576 | Arrow _,_ -> assert false (*BUG here, eta-expand!*)
577 | _, _ -> context,ctx, pat
581 (fun (_, name, ty) pat ->
582 (*BUG: recomputing every time the type of the constructor*)
583 let ty = typ_of status ~metasenv context ty in
584 let context,lhs,rhs = eat_branch leftno ty context [] pat in
586 (* UnsafeCoerce not always required *)
587 UnsafeCoerce (term_of status ~metasenv context rhs)
591 with Invalid_argument _ -> assert false
593 (match classify_not_term status [] (NCic.Const ref) with
596 | `Kind -> assert false (* IMPOSSIBLE *)
598 (match patterns_of pl with
600 | [lhs,rhs] -> fomega_lift_term (- List.length lhs) rhs
603 Match (ref,term_of status ~metasenv context t, patterns_of pl))
604 and eat_args status metasenv acc context tyhe =
608 match fomega_whd status tyhe with
613 | _ -> term_of status ~metasenv context arg in
614 eat_args status metasenv (mk_appl acc arg) context t tl
617 match classify status ~metasenv context arg with
626 | `Term `TypeFormerOrTerm
627 | `Term `Term -> term_of status ~metasenv context arg
629 eat_args status metasenv
630 (UnsafeCoerce (mk_appl acc (UnsafeCoerce arg)))
633 (match classify status ~metasenv context arg with
634 | `PropKind -> assert false (*TODO: same as below, coercion needed???*)
638 eat_args status metasenv (UnsafeCoerce (Inst acc))
639 context (fomega_subst 1 Unit t) tl
640 | `Term _ -> assert false (*TODO: ????*)
643 eat_args status metasenv (Inst acc)
644 context (fomega_subst 1 (typ_of status ~metasenv context arg) t)
647 eat_args status metasenv acc context t tl
648 | Unit | Var _ | TConst _ | TAppl _ -> assert false (* NOT A PRODUCT *)
658 let object_of_constant status ~metasenv ref bo ty =
659 match classify status ~metasenv [] ty with
661 let ty = kind_of status ~metasenv [] ty in
662 let ctx0,res = split_kind_prods [] ty in
664 split_typ_lambdas status ~metasenv (List.length ctx0) [] bo in
665 (match classify status ~metasenv ctx bo with
667 | `KindOrType -> (* ?? no kind formers in System F_omega *)
671 HExtlib.map_option (fun (_,k) ->
672 (*CSC: BUG here, clashes*)
673 String.uncapitalize (fst n),k) p1)
676 let bo = typ_of status ~metasenv ctx bo in
677 status#set_extraction_db
678 (ReferenceMap.add ref (nicectx,Some bo)
679 status#extraction_db),
680 Success (ref,TypeDefinition((nicectx,res),bo))
681 | `Kind -> status, Erased (* DPM: but not really, more a failure! *)
683 | `Proposition -> status, Erased
684 | `Term _ -> status, Failure "Body of type lambda classified as a term. This is a bug.")
686 | `Proposition -> status, Erased
687 | `KindOrType (* ??? *)
689 (* CSC: TO BE FINISHED, REF NON REGISTERED *)
690 let ty = typ_of status ~metasenv [] ty in
692 Success (ref, TermDefinition (split_typ_prods [] ty, term_of status ~metasenv [] bo))
693 | `Term _ -> status, Failure "Non-term classified as a term. This is a bug."
696 let object_of_inductive status ~metasenv uri ind leftno il =
697 let status,_,rev_tyl =
699 (fun (status,i,res) (_,_,arity,cl) ->
700 match classify_not_term status [] arity with
703 | `Type -> assert false (* IMPOSSIBLE *)
704 | `PropKind -> status,i+1,res
706 let arity = kind_of status ~metasenv [] arity in
707 let ctx,_ = split_kind_prods [] arity in
708 let right,left = HExtlib.split_nth (List.length ctx - leftno) ctx in
710 NReference.reference_of_spec uri (NReference.Ind (ind,i,leftno)) in
712 status#set_extraction_db
713 (ReferenceMap.add ref (ctx,None) status#extraction_db) in
718 NCicReduction.split_prods status ~subst:[] [] leftno ty in
719 let ty = typ_of status ~metasenv ctx ty in
720 NReference.mk_constructor (j+1) ref,ty
723 status,i+1,(ref,left,right,cl)::res
728 | _ -> status, Success (dummyref, Algebraic (List.rev rev_tyl))
731 let object_of status (uri,height,metasenv,subst,obj_kind) =
732 let obj_kind = apply_subst subst obj_kind in
734 | NCic.Constant (_,_,None,ty,_) ->
735 let ref = NReference.reference_of_spec uri NReference.Decl in
736 (match classify status ~metasenv [] ty with
738 let ty = kind_of status ~metasenv [] ty in
739 let ctx,_ as res = split_kind_prods [] ty in
740 status#set_extraction_db
741 (ReferenceMap.add ref (ctx,None) status#extraction_db),
742 Success (ref, TypeDeclaration res)
744 | `Proposition -> status, Erased
746 | `KindOrType (*???*) ->
747 let ty = typ_of status ~metasenv [] ty in
748 status, Success (ref, TermDeclaration (split_typ_prods [] ty))
749 | `Term _ -> status, Failure "Type classified as a term. This is a bug.")
750 | NCic.Constant (_,_,Some bo,ty,_) ->
751 let ref = NReference.reference_of_spec uri (NReference.Def height) in
752 object_of_constant status ~metasenv ref bo ty
753 | NCic.Fixpoint (fix_or_cofix,fs,_) ->
756 (fun (_,_name,recno,ty,bo) (i,status,res) ->
759 NReference.reference_of_spec
760 uri (NReference.Fix (i,recno,height))
762 NReference.reference_of_spec uri (NReference.CoFix i)
764 let status,obj = object_of_constant ~metasenv status ref bo ty in
766 | Success (ref,obj) -> i+1,status, (ref,obj)::res
767 | _ -> i+1,status, res) fs (0,status,[])
769 status, Success (dummyref,LetRec objs)
770 | NCic.Inductive (ind,leftno,il,_) ->
771 object_of_inductive status ~metasenv uri ind leftno il
773 (************************ HASKELL *************************)
775 (* -----------------------------------------------------------------------------
776 * Helper functions I can't seem to find anywhere in the OCaml stdlib?
777 * -----------------------------------------------------------------------------
787 let uncurry f (x, y) =
791 let rec char_list_of_string s =
792 let l = String.length s in
793 let rec aux buffer s =
796 | m -> aux (s.[m - 1]::buffer) s (m - 1)
801 let string_of_char_list s =
805 | x::xs -> aux (String.make 1 x ^ buffer) xs
810 (* ----------------------------------------------------------------------------
811 * Haskell name management: prettyfying valid and idiomatic Haskell identifiers
812 * and type variable names.
813 * ----------------------------------------------------------------------------
816 let remove_underscores_and_mark =
817 let rec aux char_list_buffer positions_buffer position =
819 | [] -> (string_of_char_list char_list_buffer, positions_buffer)
822 aux char_list_buffer (position::positions_buffer) position xs
824 aux (x::char_list_buffer) positions_buffer (position + 1) xs
829 let rec capitalize_marked_positions s =
833 if x < String.length s then
834 let c = Char.uppercase (String.get s x) in
835 let _ = String.set s x c in
836 capitalize_marked_positions s xs
838 capitalize_marked_positions s xs
841 let contract_underscores_and_capitalise =
842 char_list_of_string |>
843 remove_underscores_and_mark |>
844 uncurry capitalize_marked_positions
847 let idiomatic_haskell_type_name_of_string =
848 contract_underscores_and_capitalise |>
852 let idiomatic_haskell_term_name_of_string =
853 contract_underscores_and_capitalise |>
857 (*CSC: code to be changed soon when we implement constructors and
858 we fix the code for term application *)
859 let classify_reference status ref =
860 if ReferenceMap.mem ref status#extraction_db then
863 let NReference.Ref (_,r) = ref in
865 NReference.Con _ -> `Constructor
866 | NReference.Ind _ -> assert false
870 let capitalize classification name =
871 match classification with
873 | `TypeName -> idiomatic_haskell_type_name_of_string name
876 | `FunctionName -> idiomatic_haskell_term_name_of_string name
879 let pp_ref status ref =
880 capitalize (classify_reference status ref)
881 (NCicPp.r2s status true ref)
883 (* cons avoid duplicates *)
884 let rec (@:::) name l =
885 if name <> "" (* propositional things *) && name.[0] = '_' then
886 let name = String.sub name 1 (String.length name - 1) in
887 let name = if name = "" then "a" else name in
889 else if List.mem name l then (name ^ "'") @::: l
893 let (@::) x l = let x,l = x @::: l in x::l;;
895 let rec pretty_print_type status ctxt =
897 | Var n -> List.nth ctxt (n-1)
900 | TConst ref -> pp_ref status ref
902 bracket size_of_type (pretty_print_type status ctxt) t1 ^ " -> " ^
903 pretty_print_type status ("_"::ctxt) t2
904 | TSkip t -> pretty_print_type status ("_"::ctxt) t
905 | Forall (name, kind, t) ->
906 (*CSC: BUG HERE: avoid clashes due to uncapitalisation*)
907 let name = capitalize `TypeVariable name in
908 let name,ctxt = name@:::ctxt in
909 if size_of_kind kind > 1 then
910 "forall (" ^ name ^ " :: " ^ pretty_print_kind kind ^ "). " ^ pretty_print_type status (name::ctxt) t
912 "forall " ^ name ^ ". " ^ pretty_print_type status (name::ctxt) t
913 | TAppl tl -> String.concat " " (List.map (pretty_print_type status ctxt) tl)
915 let pretty_print_term_context status ctx1 ctx2 =
916 let name_context, rev_res =
918 (fun el (ctx1,rev_res) ->
920 None -> ""@::ctx1,rev_res
921 | Some (name,`OfKind _) -> name@::ctx1,rev_res
922 | Some (name,`OfType typ) ->
923 let name,ctx1 = name@:::ctx1 in
925 ("(" ^ name ^ " :: " ^ pretty_print_type status ctx1 typ ^ ")")::rev_res
927 name_context, String.concat " " (List.rev rev_res)
929 let rec pretty_print_term status ctxt =
931 | Rel n -> List.nth ctxt (n-1)
933 | Const ref -> pp_ref status ref
935 let name = capitalize `BoundVariable name in
936 let name,ctxt = name@:::ctxt in
937 "\\" ^ name ^ " -> " ^ pretty_print_term status (name::ctxt) t
938 | Appl tl -> String.concat " " (List.map (bracket size_of_term (pretty_print_term status ctxt)) tl)
939 | LetIn (name,s,t) ->
940 let name = capitalize `BoundVariable name in
941 let name,ctxt = name@:::ctxt in
942 "let " ^ name ^ " = " ^ pretty_print_term status ctxt s ^ " in " ^
943 pretty_print_term status (name::ctxt) t
945 "error \"Unreachable code\""
947 "unsafeCoerce " ^ bracket size_of_term (pretty_print_term status ctxt) t
948 | Match (r,matched,pl) ->
950 "error \"Case analysis over empty type\""
952 "case " ^ pretty_print_term status ctxt matched ^ " of\n" ^
955 (fun (bound_names,rhs) i ->
956 let ref = NReference.mk_constructor (i+1) r in
957 let name = pp_ref status ref in
958 let ctxt,bound_names =
959 pretty_print_term_context status ctxt bound_names in
961 pretty_print_term status ctxt rhs
963 " " ^ name ^ " " ^ bound_names ^ " -> " ^ body
965 | Skip t -> pretty_print_term status ("[[skipped]]"@::ctxt) t
966 | TLambda (name,t) ->
967 let name = capitalize `TypeVariable name in
968 pretty_print_term status (name@::ctxt) t
969 | Inst t -> pretty_print_term status ctxt t
972 let rec pp_obj status (ref,obj_kind) =
973 let pretty_print_context ctx =
974 String.concat " " (List.rev (snd
976 (fun (x,kind) (l,res) ->
978 if size_of_kind kind > 1 then
979 x::l,("(" ^ x ^ " :: " ^ pretty_print_kind kind ^ ")")::res
982 (HExtlib.filter_map (fun x -> x) ctx) ([],[]))))
984 let namectx_of_ctx ctx =
985 List.fold_right (@::)
986 (List.map (function None -> "" | Some (x,_) -> x) ctx) [] in
988 TypeDeclaration (ctx,_) ->
989 (* data?? unsure semantics: inductive type without constructor, but
990 not matchable apparently *)
991 if List.length ctx = 0 then
992 "data " ^ pp_ref status ref
994 "data " ^ pp_ref status ref ^ " " ^ pretty_print_context ctx
995 | TypeDefinition ((ctx, _),ty) ->
996 let namectx = namectx_of_ctx ctx in
997 if List.length ctx = 0 then
998 "type " ^ pp_ref status ref ^ " = " ^ pretty_print_type status namectx ty
1000 "type " ^ pp_ref status ref ^ " " ^ pretty_print_context ctx ^ " = " ^ pretty_print_type status namectx ty
1001 | TermDeclaration (ctx,ty) ->
1002 let name = pp_ref status ref in
1003 name ^ " :: " ^ pretty_print_type status [] (glue_ctx_typ ctx ty) ^ "\n" ^
1004 name ^ " = error \"The declaration `" ^ name ^ "' has yet to be defined.\""
1005 | TermDefinition ((ctx,ty),bo) ->
1006 let name = pp_ref status ref in
1007 let namectx = namectx_of_ctx ctx in
1009 name ^ " :: " ^ pretty_print_type status namectx (glue_ctx_typ ctx ty) ^ "\n" ^
1010 name ^ " = " ^ pretty_print_term status namectx bo
1012 String.concat "\n" (List.map (pp_obj status) l)
1016 (fun ref,left,right,cl ->
1017 "data " ^ pp_ref status ref ^ " " ^
1018 pretty_print_context (right@left) ^ " where\n " ^
1019 String.concat "\n " (List.map
1021 let namectx = namectx_of_ctx left in
1022 pp_ref status ref ^ " :: " ^
1023 pretty_print_type status namectx tys
1026 (* inductive and records missing *)
1028 let haskell_of_obj status (uri,_,_,_,_ as obj) =
1029 let status, obj = object_of status obj in
1032 Erased -> "-- [?] " ^ NUri.name_of_uri uri ^ " erased due to term being propositionally irrelevant.\n"
1033 | OutsideTheory -> "-- [?] " ^ NUri.name_of_uri uri ^ " erased due to image of term under extraction residing outside Fω.\n"
1034 | Failure msg -> "-- [?] " ^ NUri.name_of_uri uri ^ " FAILURE: " ^ msg ^ "\n"
1035 | Success o -> pp_obj status o ^ "\n"