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 (* be aware: we can be the head of an application *)
184 assert false (* TODO *)
185 | NCic.Meta _ -> assert false (* TODO *)
186 | NCic.Appl (he::_) -> classify_not_term status context he
188 let rec find_sort typ =
189 match NCicReduction.whd status ~subst:[] context (NCicSubstitution.lift status n typ) with
190 NCic.Sort NCic.Prop -> `Proposition
191 | NCic.Sort (NCic.Type [`CProp,_]) -> `Proposition
192 | NCic.Sort (NCic.Type [`Type,_]) ->
193 (*CSC: we could be more precise distinguishing the user provided
194 minimal elements of the hierarchies and classify these
197 | NCic.Sort (NCic.Type _) -> assert false (* ALGEBRAIC *)
198 | NCic.Prod (_,_,t) ->
199 (* we skipped arguments of applications, so here we need to skip
202 | _ -> assert false (* NOT A SORT *)
204 (match List.nth context (n-1) with
205 _,NCic.Decl typ -> find_sort typ
206 | _,NCic.Def _ -> assert false (* IMPOSSIBLE *))
207 | NCic.Const (NReference.Ref (_,NReference.Decl) as ref) ->
208 let _,_,ty,_,_ = NCicEnvironment.get_checked_decl status ref in
209 (match classify_not_term status [] ty with
211 | `Type -> assert false (* IMPOSSIBLE *)
213 | `KindOrType -> `Type
214 | `PropKind -> `Proposition)
215 | NCic.Const (NReference.Ref (_,NReference.Ind _) as ref) ->
216 let _,_,ityl,_,i = NCicEnvironment.get_checked_indtys status ref in
217 let _,_,arity,_ = List.nth ityl i in
218 (match classify_not_term status [] arity with
221 | `KindOrType -> assert false (* IMPOSSIBLE *)
223 | `PropKind -> `Proposition)
224 | NCic.Const (NReference.Ref (_,NReference.Con _))
225 | NCic.Const (NReference.Ref (_,NReference.Def _)) ->
226 assert false (* IMPOSSIBLE *)
229 let classify status ~metasenv context t =
230 match NCicTypeChecker.typeof status ~metasenv ~subst:[] context t with
232 (classify_not_term status context t : not_term :> [> not_term])
234 let ty = fix_sorts ty in
236 (match classify_not_term status context ty with
237 | `Proposition -> `Proof
239 | `KindOrType -> `TypeFormerOrTerm
240 | `Kind -> `TypeFormer
241 | `PropKind -> `PropFormer)
245 let rec kind_of status ~metasenv context k =
246 match NCicReduction.whd status ~subst:[] context k with
247 | NCic.Sort NCic.Type _ -> Type
248 | NCic.Sort _ -> assert false (* NOT A KIND *)
249 | NCic.Prod (b,s,t) ->
250 (match classify status ~metasenv context s with
252 KArrow (kind_of status ~metasenv context s,
253 kind_of ~metasenv status ((b,NCic.Decl s)::context) t)
258 KSkip (kind_of status ~metasenv ((b,NCic.Decl s)::context) t)
259 | `Term _ -> assert false (* IMPOSSIBLE *))
261 | NCic.LetIn _ -> assert false (* IMPOSSIBLE *)
264 | NCic.Const _ -> assert false (* NOT A KIND *)
265 | NCic.Appl _ -> assert false (* TODO: when head is a match/let rec;
266 otherwise NOT A KIND *)
268 | NCic.Match (_,_,_,_) -> assert false (* TODO *)
271 let rec skip_args status ~metasenv context =
274 | [],_ -> assert false (* IMPOSSIBLE *)
275 | None::tl1,_::tl2 -> skip_args status ~metasenv context (tl1,tl2)
277 match classify status ~metasenv context arg with
280 | `Term `TypeFormer ->
281 Some arg::skip_args status ~metasenv context (tl1,tl2)
284 | `PropKind -> None::skip_args status ~metasenv context (tl1,tl2)
285 | `Term _ -> assert false (* IMPOSSIBLE *)
288 module ReferenceMap = Map.Make(struct type t = NReference.reference let compare = NReference.compare end)
290 type db = (typ_context * typ option) ReferenceMap.t
292 class type g_status =
294 method extraction_db: db
297 class virtual status =
300 val extraction_db = ReferenceMap.empty
301 method extraction_db = extraction_db
302 method set_extraction_db v = {< extraction_db = v >}
303 method set_extraction_status
304 : 'status. #g_status as 'status -> 'self
305 = fun o -> {< extraction_db = o#extraction_db >}
308 let rec split_kind_prods context =
310 | KArrow (so,ta)-> split_kind_prods (Some ("_",so)::context) ta
311 | KSkip ta -> split_kind_prods (None::context) ta
312 | Type -> context,Type
315 let rec split_typ_prods context =
317 | Arrow (so,ta)-> split_typ_prods (Some ("_",`OfType so)::context) ta
318 | Forall (name,so,ta)-> split_typ_prods (Some (name,`OfKind so)::context) ta
319 | TSkip ta -> split_typ_prods (None::context) ta
320 | _ as t -> context,t
323 let rec glue_ctx_typ ctx typ =
326 | Some (_,`OfType so)::ctx -> glue_ctx_typ ctx (Arrow (so,typ))
327 | Some (name,`OfKind so)::ctx -> glue_ctx_typ ctx (Forall (name,so,typ))
328 | None::ctx -> glue_ctx_typ ctx (TSkip typ)
331 let rec split_typ_lambdas status n ~metasenv context typ =
332 if n = 0 then context,typ
334 match NCicReduction.whd status ~delta:max_int ~subst:[] context typ with
335 | NCic.Lambda (name,s,t) ->
336 split_typ_lambdas status (n-1) ~metasenv ((name,NCic.Decl s)::context) t
338 (* eta-expansion required *)
339 let ty = NCicTypeChecker.typeof status ~metasenv ~subst:[] context t in
340 match NCicReduction.whd status ~delta:max_int ~subst:[] context ty with
341 | NCic.Prod (name,typ,_) ->
342 split_typ_lambdas status (n-1) ~metasenv
343 ((name,NCic.Decl typ)::context)
344 (NCicUntrusted.mk_appl t [NCic.Rel 1])
345 | _ -> assert false (* IMPOSSIBLE *)
349 let rev_context_of_typformer status ~metasenv context =
351 NCic.Const (NReference.Ref (_,NReference.Ind _) as ref)
352 | NCic.Const (NReference.Ref (_,NReference.Def _) as ref)
353 | NCic.Const (NReference.Ref (_,NReference.Decl) as ref)
354 | NCic.Const (NReference.Ref (_,NReference.Fix _) as ref) ->
355 (try List.rev (fst (ReferenceMap.find ref status#extraction_db))
358 (* This can happen only when we are processing the type of
359 the constructor of a small singleton type. In this case
360 we are not interested in all the type, but only in its
361 backbone. That is why we can safely return the dummy context here *)
362 let rec dummy = None::dummy in
364 | NCic.Match _ -> assert false (* TODO ???? *)
367 match List.nth context (n-1) with
368 _,NCic.Decl typ -> typ
369 | _,NCic.Def _ -> assert false (* IMPOSSIBLE *) in
370 let typ_ctx = snd (HExtlib.split_nth n context) in
371 let typ = kind_of status ~metasenv typ_ctx typ in
372 List.rev (fst (split_kind_prods [] typ))
373 | NCic.Meta _ -> assert false (* TODO *)
374 | NCic.Const (NReference.Ref (_,NReference.Con _))
375 | NCic.Const (NReference.Ref (_,NReference.CoFix _))
376 | NCic.Sort _ | NCic.Implicit _ | NCic.Lambda _ | NCic.LetIn _
377 | NCic.Appl _ | NCic.Prod _ ->
378 assert false (* IMPOSSIBLE *)
380 let rec typ_of status ~metasenv context k =
381 match NCicReduction.whd status ~delta:max_int ~subst:[] context k with
382 | NCic.Prod (b,s,t) ->
383 (* CSC: non-invariant assumed here about "_" *)
384 (match classify status ~metasenv context s with
386 Forall (b, kind_of status ~metasenv context s,
387 typ_of ~metasenv status ((b,NCic.Decl s)::context) t)
389 | `KindOrType -> (* ??? *)
390 Arrow (typ_of status ~metasenv context s,
391 typ_of status ~metasenv ((b,NCic.Decl s)::context) t)
394 TSkip (typ_of status ~metasenv ((b,NCic.Decl s)::context) t)
395 | `Term _ -> assert false (* IMPOSSIBLE *))
398 | NCic.LetIn _ -> assert false (* IMPOSSIBLE *)
399 | NCic.Lambda _ -> assert false (* LAMBDA-LIFT INNER DECLARATION *)
400 | NCic.Rel n -> Var n
401 | NCic.Const ref -> TConst ref
402 | NCic.Appl (he::args) ->
403 let rev_he_context= rev_context_of_typformer status ~metasenv context he in
404 TAppl (typ_of status ~metasenv context he ::
406 (function None -> Unit | Some ty -> typ_of status ~metasenv context ty)
407 (skip_args status ~metasenv context (rev_he_context,args)))
408 | NCic.Appl _ -> assert false (* TODO: when head is a match/let rec;
409 otherwise NOT A TYPE *)
411 | NCic.Match (_,_,_,_) -> Top
414 let rec fomega_lift_type_from n k =
416 | Var m as t -> if m < k then t else Var (m + n)
420 | Arrow (ty1,ty2) -> Arrow (fomega_lift_type_from n k ty1,fomega_lift_type_from n (k+1) ty2)
421 | TSkip t -> TSkip (fomega_lift_type_from n (k+1) t)
422 | Forall (name,kind,t) -> Forall (name,kind,fomega_lift_type_from n (k+1) t)
423 | TAppl args -> TAppl (List.map (fomega_lift_type_from n k) args)
425 let fomega_lift_type n t =
426 if n = 0 then t else fomega_lift_type_from n 0 t
428 let fomega_lift_term n t =
429 let rec fomega_lift_term n k =
431 | Rel m as t -> if m < k then t else Rel (m + n)
435 | Lambda (name,t) -> Lambda (name,fomega_lift_term n (k+1) t)
436 | TLambda (name,t) -> TLambda (name,fomega_lift_term n (k+1) t)
437 | Appl args -> Appl (List.map (fomega_lift_term n k) args)
438 | LetIn (name,m,bo) ->
439 LetIn (name, fomega_lift_term n k m, fomega_lift_term n (k+1) bo)
440 | Match (ref,t,pl) ->
442 let lift_context ctx =
443 let len = List.length ctx in
446 let j = len - i - 1 in
449 | Some (_,`OfKind _) as el -> el
450 | Some (name,`OfType t) ->
451 Some (name,`OfType (fomega_lift_type_from n (k+j) t))
454 lift_context ctx, fomega_lift_term n (k + List.length ctx) t
456 Match (ref,fomega_lift_term n k t,List.map lift_p pl)
457 | Inst t -> Inst (fomega_lift_term n k t)
458 | Skip t -> Skip (fomega_lift_term n (k+1) t)
459 | UnsafeCoerce t -> UnsafeCoerce (fomega_lift_term n k t)
461 if n = 0 then t else fomega_lift_term n 0 t
464 let rec fomega_subst k t1 =
467 if k=n then fomega_lift_type k t1
468 else if n < k then Var n
471 | TConst ref -> TConst ref
473 | Arrow (ty1,ty2) -> Arrow (fomega_subst k t1 ty1, fomega_subst (k+1) t1 ty2)
474 | TSkip t -> TSkip (fomega_subst (k+1) t1 t)
475 | Forall (n,kind,t) -> Forall (n,kind,fomega_subst (k+1) t1 t)
476 | TAppl args -> TAppl (List.map (fomega_subst k t1) args)
478 let fomega_lookup status ref = snd (ReferenceMap.find ref status#extraction_db)
480 let rec fomega_whd status ty =
483 (match fomega_lookup status r with
485 | Some ty -> fomega_whd status ty)
486 | TAppl (TConst r::args) ->
487 (match fomega_lookup status r with
489 | Some ty -> fomega_whd status (List.fold_right (fomega_subst 1) args ty))
492 let rec term_of status ~metasenv context =
496 | NCic.Prod _ -> assert false (* IMPOSSIBLE *)
497 | NCic.Lambda (b,ty,bo) ->
498 (* CSC: non-invariant assumed here about "_" *)
499 (match classify status ~metasenv context ty with
501 TLambda (b,term_of status ~metasenv ((b,NCic.Decl ty)::context) bo)
502 | `KindOrType (* ??? *)
504 Lambda (b, term_of status ~metasenv ((b,NCic.Decl ty)::context) bo)
508 Skip (term_of status ~metasenv ((b,NCic.Decl ty)::context) bo)
509 | `Term _ -> assert false (* IMPOSSIBLE *))
510 | NCic.LetIn (b,ty,t,bo) ->
511 (match classify status ~metasenv context t with
512 | `Term `TypeFormerOrTerm (* ???? *)
514 LetIn (b,term_of status ~metasenv context t,
515 term_of status ~metasenv ((b,NCic.Def (t,ty))::context) bo)
524 (* not in programming languages, we expand it *)
525 term_of status ~metasenv context
526 (NCicSubstitution.subst status ~avoid_beta_redexes:true t bo))
527 | NCic.Rel n -> Rel n
528 | NCic.Const ref -> Const ref
529 | NCic.Appl (he::args) ->
530 eat_args status metasenv
531 (term_of status ~metasenv context he) context
532 (*BUG: recomputing every time the type of the head*)
533 (typ_of status ~metasenv context
534 (NCicTypeChecker.typeof status ~metasenv ~subst:[] context he))
536 | NCic.Appl _ -> assert false (* TODO: when head is a match/let rec;
537 otherwise NOT A TYPE *)
538 | NCic.Meta _ -> assert false (* TODO *)
539 | NCic.Match (ref,_,t,pl) ->
541 let constructors, leftno =
542 let _,leftno,tys,_,n = NCicEnvironment.get_checked_indtys status ref in
543 let _,_,_,cl = List.nth tys n in
546 let rec eat_branch n ty context ctx pat =
550 | Arrow (_, t), _ when n > 0 ->
551 eat_branch (pred n) t context ctx pat
552 | _, _ when n > 0 -> assert false (*BUG: is Top possible here?*)
553 (*CSC: unify the three cases below? *)
554 | Arrow (_, t), NCic.Lambda (name, ty, t') ->
556 (Some (name,`OfType (typ_of status ~metasenv context ty)))::ctx in
557 let context = (name,NCic.Decl ty)::context in
558 eat_branch 0 t context ctx t'
559 | Forall (_,_,t),NCic.Lambda (name, ty, t') ->
561 (Some (name,`OfKind (kind_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 | TSkip t,NCic.Lambda (name, ty, t') ->
565 let ctx = None::ctx in
566 let context = (name,NCic.Decl ty)::context in
567 eat_branch 0 t context ctx t'
568 | Top,_ -> assert false (* IMPOSSIBLE *)
571 | Arrow _,_ -> assert false (*BUG here, eta-expand!*)
572 | _, _ -> context,ctx, pat
576 (fun (_, name, ty) pat ->
577 (*BUG: recomputing every time the type of the constructor*)
578 let ty = typ_of status ~metasenv context ty in
579 let context,lhs,rhs = eat_branch leftno ty context [] pat in
581 (* UnsafeCoerce not always required *)
582 UnsafeCoerce (term_of status ~metasenv context rhs)
586 with Invalid_argument _ -> assert false
588 (match classify_not_term status [] (NCic.Const ref) with
591 | `Kind -> assert false (* IMPOSSIBLE *)
593 (match patterns_of pl with
595 | [lhs,rhs] -> fomega_lift_term (- List.length lhs) rhs
598 Match (ref,term_of status ~metasenv context t, patterns_of pl))
599 and eat_args status metasenv acc context tyhe =
603 match fomega_whd status tyhe with
608 | _ -> term_of status ~metasenv context arg in
609 eat_args status metasenv (mk_appl acc arg) context t tl
612 match classify status ~metasenv context arg with
621 | `Term `TypeFormerOrTerm
622 | `Term `Term -> term_of status ~metasenv context arg
624 eat_args status metasenv (UnsafeCoerce (mk_appl acc arg))
627 (match classify status ~metasenv context arg with
628 | `PropKind -> assert false (*TODO: same as below, coercion needed???*)
632 eat_args status metasenv (UnsafeCoerce (Inst acc))
633 context (fomega_subst 1 Unit t) tl
634 | `Term _ -> assert false (*TODO: ????*)
637 eat_args status metasenv (Inst acc)
638 context (fomega_subst 1 (typ_of status ~metasenv context arg) t)
641 eat_args status metasenv acc context t tl
642 | Unit | Var _ | TConst _ | TAppl _ -> assert false (* NOT A PRODUCT *)
652 let object_of_constant status ~metasenv ref bo ty =
653 match classify status ~metasenv [] ty with
655 let ty = kind_of status ~metasenv [] ty in
656 let ctx0,res = split_kind_prods [] ty in
658 split_typ_lambdas status ~metasenv (List.length ctx0) [] bo in
659 (match classify status ~metasenv ctx bo with
661 | `KindOrType -> (* ?? no kind formers in System F_omega *)
665 HExtlib.map_option (fun (_,k) ->
666 (*CSC: BUG here, clashes*)
667 String.uncapitalize (fst n),k) p1)
670 let bo = typ_of status ~metasenv ctx bo in
671 status#set_extraction_db
672 (ReferenceMap.add ref (nicectx,Some bo)
673 status#extraction_db),
674 Success (ref,TypeDefinition((nicectx,res),bo))
675 | `Kind -> status, Erased (* DPM: but not really, more a failure! *)
677 | `Proposition -> status, Erased
678 | `Term _ -> status, Failure "Body of type lambda classified as a term. This is a bug.")
680 | `Proposition -> status, Erased
681 | `KindOrType (* ??? *)
683 (* CSC: TO BE FINISHED, REF NON REGISTERED *)
684 let ty = typ_of status ~metasenv [] ty in
686 Success (ref, TermDefinition (split_typ_prods [] ty, term_of status ~metasenv [] bo))
687 | `Term _ -> status, Failure "Non-term classified as a term. This is a bug."
690 let object_of_inductive status ~metasenv uri ind leftno il =
691 let status,_,rev_tyl =
693 (fun (status,i,res) (_,_,arity,cl) ->
694 match classify_not_term status [] arity with
697 | `Type -> assert false (* IMPOSSIBLE *)
698 | `PropKind -> status,i+1,res
700 let arity = kind_of status ~metasenv [] arity in
701 let ctx,_ = split_kind_prods [] arity in
702 let right,left = HExtlib.split_nth (List.length ctx - leftno) ctx in
704 NReference.reference_of_spec uri (NReference.Ind (ind,i,leftno)) in
706 status#set_extraction_db
707 (ReferenceMap.add ref (ctx,None) status#extraction_db) in
712 NCicReduction.split_prods status ~subst:[] [] leftno ty in
713 let ty = typ_of status ~metasenv ctx ty in
714 NReference.mk_constructor (j+1) ref,ty
717 status,i+1,(ref,left,right,cl)::res
722 | _ -> status, Success (dummyref, Algebraic (List.rev rev_tyl))
725 let object_of status (uri,height,metasenv,subst,obj_kind) =
726 let obj_kind = apply_subst subst obj_kind in
728 | NCic.Constant (_,_,None,ty,_) ->
729 let ref = NReference.reference_of_spec uri NReference.Decl in
730 (match classify status ~metasenv [] ty with
732 let ty = kind_of status ~metasenv [] ty in
733 let ctx,_ as res = split_kind_prods [] ty in
734 status#set_extraction_db
735 (ReferenceMap.add ref (ctx,None) status#extraction_db),
736 Success (ref, TypeDeclaration res)
738 | `Proposition -> status, Erased
740 | `KindOrType (*???*) ->
741 let ty = typ_of status ~metasenv [] ty in
742 status, Success (ref, TermDeclaration (split_typ_prods [] ty))
743 | `Term _ -> status, Failure "Type classified as a term. This is a bug.")
744 | NCic.Constant (_,_,Some bo,ty,_) ->
745 let ref = NReference.reference_of_spec uri (NReference.Def height) in
746 object_of_constant status ~metasenv ref bo ty
747 | NCic.Fixpoint (fix_or_cofix,fs,_) ->
750 (fun (_,_name,recno,ty,bo) (i,status,res) ->
753 NReference.reference_of_spec
754 uri (NReference.Fix (i,recno,height))
756 NReference.reference_of_spec uri (NReference.CoFix i)
758 let status,obj = object_of_constant ~metasenv status ref bo ty in
760 | Success (ref,obj) -> i+1,status, (ref,obj)::res
761 | _ -> i+1,status, res) fs (0,status,[])
763 status, Success (dummyref,LetRec objs)
764 | NCic.Inductive (ind,leftno,il,_) ->
765 object_of_inductive status ~metasenv uri ind leftno il
767 (************************ HASKELL *************************)
769 (* -----------------------------------------------------------------------------
770 * Helper functions I can't seem to find anywhere in the OCaml stdlib?
771 * -----------------------------------------------------------------------------
781 let uncurry f (x, y) =
785 let rec char_list_of_string s =
786 let l = String.length s in
787 let rec aux buffer s =
790 | m -> aux (s.[m - 1]::buffer) s (m - 1)
795 let string_of_char_list s =
799 | x::xs -> aux (String.make 1 x ^ buffer) xs
804 (* ----------------------------------------------------------------------------
805 * Haskell name management: prettyfying valid and idiomatic Haskell identifiers
806 * and type variable names.
807 * ----------------------------------------------------------------------------
810 let remove_underscores_and_mark =
811 let rec aux char_list_buffer positions_buffer position =
813 | [] -> (string_of_char_list char_list_buffer, positions_buffer)
816 aux char_list_buffer (position::positions_buffer) position xs
818 aux (x::char_list_buffer) positions_buffer (position + 1) xs
823 let rec capitalize_marked_positions s =
827 if x < String.length s then
828 let c = Char.uppercase (String.get s x) in
829 let _ = String.set s x c in
830 capitalize_marked_positions s xs
832 capitalize_marked_positions s xs
835 let contract_underscores_and_capitalise =
836 char_list_of_string |>
837 remove_underscores_and_mark |>
838 uncurry capitalize_marked_positions
841 let idiomatic_haskell_type_name_of_string =
842 contract_underscores_and_capitalise |>
846 let idiomatic_haskell_term_name_of_string =
847 contract_underscores_and_capitalise |>
851 (*CSC: code to be changed soon when we implement constructors and
852 we fix the code for term application *)
853 let classify_reference status ref =
854 if ReferenceMap.mem ref status#extraction_db then
857 let NReference.Ref (_,ref) = ref in
859 NReference.Con _ -> `Constructor
860 | NReference.Ind _ -> assert false
864 let capitalize classification name =
865 match classification with
867 | `TypeName -> idiomatic_haskell_type_name_of_string name
870 | `FunctionName -> idiomatic_haskell_term_name_of_string name
873 let pp_ref status ref =
874 capitalize (classify_reference status ref)
875 (NCicPp.r2s status true ref)
877 (* cons avoid duplicates *)
878 let rec (@:::) name l =
879 if name <> "" (* propositional things *) && name.[0] = '_' then
880 let name = String.sub name 1 (String.length name - 1) in
881 let name = if name = "" then "a" else name in
883 else if List.mem name l then (name ^ "'") @::: l
887 let (@::) x l = let x,l = x @::: l in x::l;;
889 let rec pretty_print_type status ctxt =
891 | Var n -> List.nth ctxt (n-1)
894 | TConst ref -> pp_ref status ref
896 bracket size_of_type (pretty_print_type status ctxt) t1 ^ " -> " ^
897 pretty_print_type status ("_"::ctxt) t2
898 | TSkip t -> pretty_print_type status ("_"::ctxt) t
899 | Forall (name, kind, t) ->
900 (*CSC: BUG HERE: avoid clashes due to uncapitalisation*)
901 let name = capitalize `TypeVariable name in
902 let name,ctxt = name@:::ctxt in
903 if size_of_kind kind > 1 then
904 "forall (" ^ name ^ " :: " ^ pretty_print_kind kind ^ "). " ^ pretty_print_type status (name::ctxt) t
906 "forall " ^ name ^ ". " ^ pretty_print_type status (name::ctxt) t
907 | TAppl tl -> String.concat " " (List.map (pretty_print_type status ctxt) tl)
909 let pretty_print_term_context status ctx1 ctx2 =
910 let name_context, rev_res =
912 (fun el (ctx1,rev_res) ->
914 None -> ""@::ctx1,rev_res
915 | Some (name,`OfKind _) -> name@::ctx1,rev_res
916 | Some (name,`OfType typ) ->
917 let name,ctx1 = name@:::ctx1 in
919 ("(" ^ name ^ " :: " ^ pretty_print_type status ctx1 typ ^ ")")::rev_res
921 name_context, String.concat " " (List.rev rev_res)
923 let rec pretty_print_term status ctxt =
925 | Rel n -> List.nth ctxt (n-1)
927 | Const ref -> pp_ref status ref
929 let name = capitalize `BoundVariable name in
930 let name,ctxt = name@:::ctxt in
931 "\\" ^ name ^ " -> " ^ pretty_print_term status (name::ctxt) t
932 | Appl tl -> String.concat " " (List.map (bracket size_of_term (pretty_print_term status ctxt)) tl)
933 | LetIn (name,s,t) ->
934 let name = capitalize `BoundVariable name in
935 let name,ctxt = name@:::ctxt in
936 "let " ^ name ^ " = " ^ pretty_print_term status ctxt s ^ " in " ^
937 pretty_print_term status (name::ctxt) t
939 "error \"Unreachable code\""
941 "unsafeCoerce " ^ bracket size_of_term (pretty_print_term status ctxt) t
942 | Match (r,matched,pl) ->
944 "error \"Case analysis over empty type\""
946 "case " ^ pretty_print_term status ctxt matched ^ " of\n" ^
949 (fun (bound_names,rhs) i ->
950 let ref = NReference.mk_constructor (i+1) r in
951 let name = pp_ref status ref in
952 let ctxt,bound_names =
953 pretty_print_term_context status ctxt bound_names in
955 pretty_print_term status ctxt rhs
957 " " ^ name ^ " " ^ bound_names ^ " -> " ^ body
959 | Skip t -> pretty_print_term status ("[[skipped]]"@::ctxt) t
960 | TLambda (name,t) ->
961 let name = capitalize `TypeVariable name in
962 pretty_print_term status (name@::ctxt) t
963 | Inst t -> pretty_print_term status ctxt t
966 let rec pp_obj status (ref,obj_kind) =
967 let pretty_print_context ctx =
968 String.concat " " (List.rev (snd
970 (fun (x,kind) (l,res) ->
972 if size_of_kind kind > 1 then
973 x::l,("(" ^ x ^ " :: " ^ pretty_print_kind kind ^ ")")::res
976 (HExtlib.filter_map (fun x -> x) ctx) ([],[]))))
978 let namectx_of_ctx ctx =
979 List.fold_right (@::)
980 (List.map (function None -> "" | Some (x,_) -> x) ctx) [] in
982 TypeDeclaration (ctx,_) ->
983 (* data?? unsure semantics: inductive type without constructor, but
984 not matchable apparently *)
985 if List.length ctx = 0 then
986 "data " ^ pp_ref status ref
988 "data " ^ pp_ref status ref ^ " " ^ pretty_print_context ctx
989 | TypeDefinition ((ctx, _),ty) ->
990 let namectx = namectx_of_ctx ctx in
991 if List.length ctx = 0 then
992 "type " ^ pp_ref status ref ^ " = " ^ pretty_print_type status namectx ty
994 "type " ^ pp_ref status ref ^ " " ^ pretty_print_context ctx ^ " = " ^ pretty_print_type status namectx ty
995 | TermDeclaration (ctx,ty) ->
996 let name = pp_ref status ref in
997 name ^ " :: " ^ pretty_print_type status [] (glue_ctx_typ ctx ty) ^ "\n" ^
998 name ^ " = error \"The declaration `" ^ name ^ "' has yet to be defined.\""
999 | TermDefinition ((ctx,ty),bo) ->
1000 let name = pp_ref status ref in
1001 let namectx = namectx_of_ctx ctx in
1003 name ^ " :: " ^ pretty_print_type status namectx (glue_ctx_typ ctx ty) ^ "\n" ^
1004 name ^ " = " ^ pretty_print_term status namectx bo
1006 String.concat "\n" (List.map (pp_obj status) l)
1010 (fun ref,left,right,cl ->
1011 "data " ^ pp_ref status ref ^ " " ^
1012 pretty_print_context (right@left) ^ " where\n " ^
1013 String.concat "\n " (List.map
1015 let namectx = namectx_of_ctx left in
1016 pp_ref status ref ^ " :: " ^
1017 pretty_print_type status namectx tys
1020 (* inductive and records missing *)
1022 let haskell_of_obj status (uri,_,_,_,_ as obj) =
1023 let status, obj = object_of status obj in
1026 Erased -> "-- [?] " ^ NUri.name_of_uri uri ^ " erased due to term being propositionally irrelevant.\n"
1027 | OutsideTheory -> "-- [?] " ^ NUri.name_of_uri uri ^ " erased due to image of term under extraction residing outside Fω.\n"
1028 | Failure msg -> "-- [?] " ^ NUri.name_of_uri uri ^ " FAILURE: " ^ msg ^ "\n"
1029 | Success o -> pp_obj status o ^ "\n"