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 type not_term = [`Kind | `KindOrType | `PropKind | `Proposition | `Type];;
147 let max_not_term t1 t2 =
150 | _,`KindOrType -> `KindOrType
156 | _,`PropKind -> `PropKind
157 | `Proposition,`Proposition -> `Proposition
159 let sup = List.fold_left max_not_term `Proposition
161 let rec classify_not_term status context t =
162 match NCicReduction.whd status ~subst:[] context t with
166 | NCic.Type [`CProp,_] -> `PropKind
167 | NCic.Type [`Type,_] -> `Kind
168 | NCic.Type _ -> assert false)
169 | NCic.Prod (b,s,t) ->
170 (*CSC: using invariant on "_" *)
171 classify_not_term status ((b,NCic.Decl s)::context) t
174 | NCic.Const (NReference.Ref (_,NReference.CoFix _))
176 assert false (* NOT POSSIBLE *)
177 | NCic.Lambda (n,s,t) ->
178 (* Lambdas can me met in branches of matches, expecially when the
179 output type is a product *)
180 classify_not_term status ((n,NCic.Decl s)::context) t
181 | NCic.Match (r,_,_,pl) ->
182 let classified_pl = List.map (classify_not_term status context) pl in
184 | NCic.Const (NReference.Ref (_,NReference.Fix _)) ->
185 (* be aware: we can be the head of an application *)
186 assert false (* TODO *)
187 | NCic.Meta _ -> assert false (* TODO *)
188 | NCic.Appl (he::_) -> classify_not_term status context he
190 let rec find_sort typ =
191 match NCicReduction.whd status ~subst:[] context (NCicSubstitution.lift status n typ) with
192 NCic.Sort NCic.Prop -> `Proposition
193 | NCic.Sort (NCic.Type [`CProp,_]) -> `Proposition
194 | NCic.Sort (NCic.Type [`Type,_]) ->
195 (*CSC: we could be more precise distinguishing the user provided
196 minimal elements of the hierarchies and classify these
199 | NCic.Sort (NCic.Type _) -> assert false (* ALGEBRAIC *)
200 | NCic.Prod (_,_,t) ->
201 (* we skipped arguments of applications, so here we need to skip
204 | _ -> assert false (* NOT A SORT *)
206 (match List.nth context (n-1) with
207 _,NCic.Decl typ -> find_sort typ
208 | _,NCic.Def _ -> assert false (* IMPOSSIBLE *))
209 | NCic.Const (NReference.Ref (_,NReference.Decl) as ref) ->
210 let _,_,ty,_,_ = NCicEnvironment.get_checked_decl status ref in
211 (match classify_not_term status [] ty with
213 | `Type -> assert false (* IMPOSSIBLE *)
215 | `KindOrType -> `Type
216 | `PropKind -> `Proposition)
217 | NCic.Const (NReference.Ref (_,NReference.Ind _) as ref) ->
218 let _,_,ityl,_,i = NCicEnvironment.get_checked_indtys status ref in
219 let _,_,arity,_ = List.nth ityl i in
220 (match classify_not_term status [] arity with
223 | `KindOrType -> assert false (* IMPOSSIBLE *)
225 | `PropKind -> `Proposition)
226 | NCic.Const (NReference.Ref (_,NReference.Con _))
227 | NCic.Const (NReference.Ref (_,NReference.Def _)) ->
228 assert false (* IMPOSSIBLE *)
231 let classify status ~metasenv context t =
232 match NCicTypeChecker.typeof status ~metasenv ~subst:[] context t with
234 (classify_not_term status context t : not_term :> [> not_term])
236 let ty = fix_sorts ty in
238 (match classify_not_term status context ty with
239 | `Proposition -> `Proof
241 | `KindOrType -> `TypeFormerOrTerm
242 | `Kind -> `TypeFormer
243 | `PropKind -> `PropFormer)
247 let rec kind_of status ~metasenv context k =
248 match NCicReduction.whd status ~subst:[] context k with
249 | NCic.Sort NCic.Type _ -> Type
250 | NCic.Sort _ -> assert false (* NOT A KIND *)
251 | NCic.Prod (b,s,t) ->
252 (match classify status ~metasenv context s with
254 KArrow (kind_of status ~metasenv context s,
255 kind_of ~metasenv status ((b,NCic.Decl s)::context) t)
260 KSkip (kind_of status ~metasenv ((b,NCic.Decl s)::context) t)
261 | `Term _ -> assert false (* IMPOSSIBLE *))
263 | NCic.LetIn _ -> assert false (* IMPOSSIBLE *)
266 | NCic.Const _ -> assert false (* NOT A KIND *)
267 | NCic.Appl _ -> assert false (* TODO: when head is a match/let rec;
268 otherwise NOT A KIND *)
270 | NCic.Match (_,_,_,_) -> assert false (* TODO *)
273 let rec skip_args status ~metasenv context =
276 | [],_ -> assert false (* IMPOSSIBLE *)
277 | None::tl1,_::tl2 -> skip_args status ~metasenv context (tl1,tl2)
279 match classify status ~metasenv context arg with
282 | `Term `TypeFormer ->
283 Some arg::skip_args status ~metasenv context (tl1,tl2)
286 | `PropKind -> None::skip_args status ~metasenv context (tl1,tl2)
287 | `Term _ -> assert false (* IMPOSSIBLE *)
290 module ReferenceMap = Map.Make(struct type t = NReference.reference let compare = NReference.compare end)
292 type db = (typ_context * typ option) ReferenceMap.t
294 class type g_status =
296 method extraction_db: db
299 class virtual status =
302 val extraction_db = ReferenceMap.empty
303 method extraction_db = extraction_db
304 method set_extraction_db v = {< extraction_db = v >}
305 method set_extraction_status
306 : 'status. #g_status as 'status -> 'self
307 = fun o -> {< extraction_db = o#extraction_db >}
310 let rec split_kind_prods context =
312 | KArrow (so,ta)-> split_kind_prods (Some ("_",so)::context) ta
313 | KSkip ta -> split_kind_prods (None::context) ta
314 | Type -> context,Type
317 let rec split_typ_prods context =
319 | Arrow (so,ta)-> split_typ_prods (Some ("_",`OfType so)::context) ta
320 | Forall (name,so,ta)-> split_typ_prods (Some (name,`OfKind so)::context) ta
321 | TSkip ta -> split_typ_prods (None::context) ta
322 | _ as t -> context,t
325 let rec glue_ctx_typ ctx typ =
328 | Some (_,`OfType so)::ctx -> glue_ctx_typ ctx (Arrow (so,typ))
329 | Some (name,`OfKind so)::ctx -> glue_ctx_typ ctx (Forall (name,so,typ))
330 | None::ctx -> glue_ctx_typ ctx (TSkip typ)
333 let rec split_typ_lambdas status n ~metasenv context typ =
334 if n = 0 then context,typ
336 match NCicReduction.whd status ~delta:max_int ~subst:[] context typ with
337 | NCic.Lambda (name,s,t) ->
338 split_typ_lambdas status (n-1) ~metasenv ((name,NCic.Decl s)::context) t
340 (* eta-expansion required *)
341 let ty = NCicTypeChecker.typeof status ~metasenv ~subst:[] context t in
342 match NCicReduction.whd status ~delta:max_int ~subst:[] context ty with
343 | NCic.Prod (name,typ,_) ->
344 split_typ_lambdas status (n-1) ~metasenv
345 ((name,NCic.Decl typ)::context)
346 (NCicUntrusted.mk_appl t [NCic.Rel 1])
347 | _ -> assert false (* IMPOSSIBLE *)
351 let rev_context_of_typformer status ~metasenv context =
353 NCic.Const (NReference.Ref (_,NReference.Ind _) as ref)
354 | NCic.Const (NReference.Ref (_,NReference.Def _) as ref)
355 | NCic.Const (NReference.Ref (_,NReference.Decl) as ref)
356 | NCic.Const (NReference.Ref (_,NReference.Fix _) as ref) ->
357 (try List.rev (fst (ReferenceMap.find ref status#extraction_db))
360 (* This can happen only when we are processing the type of
361 the constructor of a small singleton type. In this case
362 we are not interested in all the type, but only in its
363 backbone. That is why we can safely return the dummy context here *)
364 let rec dummy = None::dummy in
366 | NCic.Match _ -> assert false (* TODO ???? *)
369 match List.nth context (n-1) with
370 _,NCic.Decl typ -> typ
371 | _,NCic.Def _ -> assert false (* IMPOSSIBLE *) in
372 let typ_ctx = snd (HExtlib.split_nth n context) in
373 let typ = kind_of status ~metasenv typ_ctx typ in
374 List.rev (fst (split_kind_prods [] typ))
375 | NCic.Meta _ -> assert false (* TODO *)
376 | NCic.Const (NReference.Ref (_,NReference.Con _))
377 | NCic.Const (NReference.Ref (_,NReference.CoFix _))
378 | NCic.Sort _ | NCic.Implicit _ | NCic.Lambda _ | NCic.LetIn _
379 | NCic.Appl _ | NCic.Prod _ ->
380 assert false (* IMPOSSIBLE *)
382 let rec typ_of status ~metasenv context k =
383 match NCicReduction.whd status ~delta:max_int ~subst:[] context k with
384 | NCic.Prod (b,s,t) ->
385 (* CSC: non-invariant assumed here about "_" *)
386 (match classify status ~metasenv context s with
388 Forall (b, kind_of status ~metasenv context s,
389 typ_of ~metasenv status ((b,NCic.Decl s)::context) t)
391 | `KindOrType -> (* ??? *)
392 Arrow (typ_of status ~metasenv context s,
393 typ_of status ~metasenv ((b,NCic.Decl s)::context) t)
396 TSkip (typ_of status ~metasenv ((b,NCic.Decl s)::context) t)
397 | `Term _ -> assert false (* IMPOSSIBLE *))
400 | NCic.LetIn _ -> assert false (* IMPOSSIBLE *)
401 | NCic.Lambda _ -> assert false (* LAMBDA-LIFT INNER DECLARATION *)
402 | NCic.Rel n -> Var n
403 | NCic.Const ref -> TConst ref
404 | NCic.Appl (he::args) ->
405 let rev_he_context= rev_context_of_typformer status ~metasenv context he in
406 TAppl (typ_of status ~metasenv context he ::
408 (function None -> Unit | Some ty -> typ_of status ~metasenv context ty)
409 (skip_args status ~metasenv context (rev_he_context,args)))
410 | NCic.Appl _ -> assert false (* TODO: when head is a match/let rec;
411 otherwise NOT A TYPE *)
413 | NCic.Match (_,_,_,_) -> assert false (* TODO *)
416 let rec fomega_lift_type_from n k =
418 | Var m as t -> if m < k then t else Var (m + n)
422 | Arrow (ty1,ty2) -> Arrow (fomega_lift_type_from n k ty1,fomega_lift_type_from n (k+1) ty2)
423 | TSkip t -> TSkip (fomega_lift_type_from n (k+1) t)
424 | Forall (name,kind,t) -> Forall (name,kind,fomega_lift_type_from n (k+1) t)
425 | TAppl args -> TAppl (List.map (fomega_lift_type_from n k) args)
427 let fomega_lift_type n t =
428 if n = 0 then t else fomega_lift_type_from n 0 t
430 let fomega_lift_term n t =
431 let rec fomega_lift_term n k =
433 | Rel m as t -> if m < k then t else Rel (m + n)
437 | Lambda (name,t) -> Lambda (name,fomega_lift_term n (k+1) t)
438 | TLambda (name,t) -> TLambda (name,fomega_lift_term n (k+1) t)
439 | Appl args -> Appl (List.map (fomega_lift_term n k) args)
440 | LetIn (name,m,bo) ->
441 LetIn (name, fomega_lift_term n k m, fomega_lift_term n (k+1) bo)
442 | Match (ref,t,pl) ->
444 let lift_context ctx =
445 let len = List.length ctx in
448 let j = len - i - 1 in
451 | Some (_,`OfKind _) as el -> el
452 | Some (name,`OfType t) ->
453 Some (name,`OfType (fomega_lift_type_from n (k+j) t))
456 lift_context ctx, fomega_lift_term n (k + List.length ctx) t
458 Match (ref,fomega_lift_term n k t,List.map lift_p pl)
459 | Inst t -> Inst (fomega_lift_term n k t)
460 | Skip t -> Skip (fomega_lift_term n (k+1) t)
461 | UnsafeCoerce t -> UnsafeCoerce (fomega_lift_term n k t)
463 if n = 0 then t else fomega_lift_term n 0 t
466 let rec fomega_subst k t1 =
469 if k=n then fomega_lift_type k t1
470 else if n < k then Var n
473 | TConst ref -> TConst ref
475 | Arrow (ty1,ty2) -> Arrow (fomega_subst k t1 ty1, fomega_subst (k+1) t1 ty2)
476 | TSkip t -> TSkip (fomega_subst (k+1) t1 t)
477 | Forall (n,kind,t) -> Forall (n,kind,fomega_subst (k+1) t1 t)
478 | TAppl args -> TAppl (List.map (fomega_subst k t1) args)
480 let fomega_lookup status ref = snd (ReferenceMap.find ref status#extraction_db)
482 let rec fomega_whd status ty =
485 (match fomega_lookup status r with
487 | Some ty -> fomega_whd status ty)
488 | TAppl (TConst r::args) ->
489 (match fomega_lookup status r with
491 | Some ty -> fomega_whd status (List.fold_right (fomega_subst 1) args ty))
494 let rec term_of status ~metasenv context =
498 | NCic.Prod _ -> assert false (* IMPOSSIBLE *)
499 | NCic.Lambda (b,ty,bo) ->
500 (* CSC: non-invariant assumed here about "_" *)
501 (match classify status ~metasenv context ty with
503 TLambda (b,term_of status ~metasenv ((b,NCic.Decl ty)::context) bo)
504 | `KindOrType (* ??? *)
506 Lambda (b, term_of status ~metasenv ((b,NCic.Decl ty)::context) bo)
510 Skip (term_of status ~metasenv ((b,NCic.Decl ty)::context) bo)
511 | `Term _ -> assert false (* IMPOSSIBLE *))
512 | NCic.LetIn (b,ty,t,bo) ->
513 (match classify status ~metasenv context t with
514 | `Term `TypeFormerOrTerm (* ???? *)
516 LetIn (b,term_of status ~metasenv context t,
517 term_of status ~metasenv ((b,NCic.Def (t,ty))::context) bo)
526 (* not in programming languages, we expand it *)
527 term_of status ~metasenv context
528 (NCicSubstitution.subst status ~avoid_beta_redexes:true t bo))
529 | NCic.Rel n -> Rel n
530 | NCic.Const ref -> Const ref
531 | NCic.Appl (he::args) ->
532 eat_args status metasenv
533 (term_of status ~metasenv context he) context
534 (*BUG: recomputing every time the type of the head*)
535 (typ_of status ~metasenv context
536 (NCicTypeChecker.typeof status ~metasenv ~subst:[] context he))
538 | NCic.Appl _ -> assert false (* TODO: when head is a match/let rec;
539 otherwise NOT A TYPE *)
540 | NCic.Meta _ -> assert false (* TODO *)
541 | NCic.Match (ref,_,t,pl) ->
543 let constructors, leftno =
544 let _,leftno,tys,_,n = NCicEnvironment.get_checked_indtys status ref in
545 let _,_,_,cl = List.nth tys n in
548 let rec eat_branch n ty context ctx pat =
552 | Arrow (_, t), _ when n > 0 ->
553 eat_branch (pred n) t context ctx pat
554 | _, _ when n > 0 -> assert false (*BUG: is Top possible here?*)
555 (*CSC: unify the three cases below? *)
556 | Arrow (_, t), NCic.Lambda (name, ty, t') ->
558 (Some (name,`OfType (typ_of status ~metasenv context ty)))::ctx in
559 let context = (name,NCic.Decl ty)::context in
560 eat_branch 0 t context ctx t'
561 | Forall (_,_,t),NCic.Lambda (name, ty, t') ->
563 (Some (name,`OfKind (kind_of status ~metasenv context ty)))::ctx in
564 let context = (name,NCic.Decl ty)::context in
565 eat_branch 0 t context ctx t'
566 | TSkip t,NCic.Lambda (name, ty, t') ->
567 let ctx = None::ctx in
568 let context = (name,NCic.Decl ty)::context in
569 eat_branch 0 t context ctx t'
570 | Top,_ -> assert false (*TODO: HOW??*)
573 | Arrow _,_ -> assert false (*BUG here, eta-expand!*)
574 | _, _ -> context,ctx, pat
578 (fun (_, name, ty) pat ->
579 (*BUG: recomputing every time the type of the constructor*)
580 let ty = typ_of status ~metasenv context ty in
581 let context,lhs,rhs = eat_branch leftno ty context [] pat in
583 (* UnsafeCoerce not always required *)
584 UnsafeCoerce (term_of status ~metasenv context rhs)
588 with Invalid_argument _ -> assert false
590 (match classify_not_term status [] (NCic.Const ref) with
593 | `Kind -> assert false (* IMPOSSIBLE *)
595 (match patterns_of pl with
597 | [lhs,rhs] -> fomega_lift_term (- List.length lhs) rhs
600 Match (ref,term_of status ~metasenv context t, patterns_of pl))
601 and eat_args status metasenv acc context tyhe =
605 match fomega_whd status tyhe with
610 | _ -> term_of status ~metasenv context arg in
611 eat_args status metasenv (mk_appl acc arg) context t tl
613 (match classify status ~metasenv context arg with
614 | `PropKind -> assert false (*TODO: same as below, coercion needed???*)
618 eat_args status metasenv (UnsafeCoerce (Inst acc))
619 context (fomega_subst 1 Unit t) tl
620 | `Term _ -> assert false (*TODO: ????*)
623 eat_args status metasenv (Inst acc)
624 context (fomega_subst 1 (typ_of status ~metasenv context arg) t)
627 eat_args status metasenv acc context t tl
628 | Top -> assert false (*TODO: HOW??*)
629 | Unit | Var _ | TConst _ | TAppl _ -> assert false (* NOT A PRODUCT *)
639 let object_of_constant status ~metasenv ref bo ty =
640 match classify status ~metasenv [] ty with
642 let ty = kind_of status ~metasenv [] ty in
643 let ctx0,res = split_kind_prods [] ty in
645 split_typ_lambdas status ~metasenv (List.length ctx0) [] bo in
646 (match classify status ~metasenv ctx bo with
648 | `KindOrType -> (* ?? no kind formers in System F_omega *)
652 HExtlib.map_option (fun (_,k) ->
653 (*CSC: BUG here, clashes*)
654 String.uncapitalize (fst n),k) p1)
657 let bo = typ_of status ~metasenv ctx bo in
658 status#set_extraction_db
659 (ReferenceMap.add ref (nicectx,Some bo)
660 status#extraction_db),
661 Success (ref,TypeDefinition((nicectx,res),bo))
662 | `Kind -> status, Erased (* DPM: but not really, more a failure! *)
664 | `Proposition -> status, Erased
665 | `Term _ -> status, Failure "Body of type lambda classified as a term. This is a bug.")
667 | `Proposition -> status, Erased
668 | `KindOrType (* ??? *)
670 (* CSC: TO BE FINISHED, REF NON REGISTERED *)
671 let ty = typ_of status ~metasenv [] ty in
673 Success (ref, TermDefinition (split_typ_prods [] ty, term_of status ~metasenv [] bo))
674 | `Term _ -> status, Failure "Non-term classified as a term. This is a bug."
677 let object_of_inductive status ~metasenv uri ind leftno il =
678 let status,_,rev_tyl =
680 (fun (status,i,res) (_,_,arity,cl) ->
681 match classify_not_term status [] arity with
684 | `Type -> assert false (* IMPOSSIBLE *)
685 | `PropKind -> status,i+1,res
687 let arity = kind_of status ~metasenv [] arity in
688 let ctx,_ = split_kind_prods [] arity in
689 let right,left = HExtlib.split_nth (List.length ctx - leftno) ctx in
691 NReference.reference_of_spec uri (NReference.Ind (ind,i,leftno)) in
693 status#set_extraction_db
694 (ReferenceMap.add ref (ctx,None) status#extraction_db) in
699 NCicReduction.split_prods status ~subst:[] [] leftno ty in
700 let ty = typ_of status ~metasenv ctx ty in
701 NReference.mk_constructor (j+1) ref,ty
704 status,i+1,(ref,left,right,cl)::res
709 | _ -> status, Success (dummyref, Algebraic (List.rev rev_tyl))
712 let object_of status (uri,height,metasenv,subst,obj_kind) =
713 let obj_kind = apply_subst subst obj_kind in
715 | NCic.Constant (_,_,None,ty,_) ->
716 let ref = NReference.reference_of_spec uri NReference.Decl in
717 (match classify status ~metasenv [] ty with
719 let ty = kind_of status ~metasenv [] ty in
720 let ctx,_ as res = split_kind_prods [] ty in
721 status#set_extraction_db
722 (ReferenceMap.add ref (ctx,None) status#extraction_db),
723 Success (ref, TypeDeclaration res)
725 | `Proposition -> status, Erased
727 | `KindOrType (*???*) ->
728 let ty = typ_of status ~metasenv [] ty in
729 status, Success (ref, TermDeclaration (split_typ_prods [] ty))
730 | `Term _ -> status, Failure "Type classified as a term. This is a bug.")
731 | NCic.Constant (_,_,Some bo,ty,_) ->
732 let ref = NReference.reference_of_spec uri (NReference.Def height) in
733 object_of_constant status ~metasenv ref bo ty
734 | NCic.Fixpoint (fix_or_cofix,fs,_) ->
737 (fun (_,_name,recno,ty,bo) (i,status,res) ->
740 NReference.reference_of_spec
741 uri (NReference.Fix (i,recno,height))
743 NReference.reference_of_spec uri (NReference.CoFix i)
745 let status,obj = object_of_constant ~metasenv status ref bo ty in
747 | Success (ref,obj) -> i+1,status, (ref,obj)::res
748 | _ -> i+1,status, res) fs (0,status,[])
750 status, Success (dummyref,LetRec objs)
751 | NCic.Inductive (ind,leftno,il,_) ->
752 object_of_inductive status ~metasenv uri ind leftno il
754 (************************ HASKELL *************************)
756 (* -----------------------------------------------------------------------------
757 * Helper functions I can't seem to find anywhere in the OCaml stdlib?
758 * -----------------------------------------------------------------------------
768 let uncurry f (x, y) =
772 let rec char_list_of_string s =
773 let l = String.length s in
774 let rec aux buffer s =
777 | m -> aux (s.[m - 1]::buffer) s (m - 1)
782 let string_of_char_list s =
786 | x::xs -> aux (String.make 1 x ^ buffer) xs
791 (* ----------------------------------------------------------------------------
792 * Haskell name management: prettyfying valid and idiomatic Haskell identifiers
793 * and type variable names.
794 * ----------------------------------------------------------------------------
797 let remove_underscores_and_mark =
798 let rec aux char_list_buffer positions_buffer position =
800 | [] -> (string_of_char_list char_list_buffer, positions_buffer)
803 aux char_list_buffer (position::positions_buffer) position xs
805 aux (x::char_list_buffer) positions_buffer (position + 1) xs
810 let rec capitalize_marked_positions s =
814 if x < String.length s then
815 let c = Char.uppercase (String.get s x) in
816 let _ = String.set s x c in
817 capitalize_marked_positions s xs
819 capitalize_marked_positions s xs
822 let contract_underscores_and_capitalise =
823 char_list_of_string |>
824 remove_underscores_and_mark |>
825 uncurry capitalize_marked_positions
828 let idiomatic_haskell_type_name_of_string =
829 contract_underscores_and_capitalise |>
833 let idiomatic_haskell_term_name_of_string =
834 contract_underscores_and_capitalise |>
838 (*CSC: code to be changed soon when we implement constructors and
839 we fix the code for term application *)
840 let classify_reference status ref =
841 if ReferenceMap.mem ref status#extraction_db then
844 let NReference.Ref (_,ref) = ref in
846 NReference.Con _ -> `Constructor
847 | NReference.Ind _ -> assert false
851 let capitalize classification name =
852 match classification with
854 | `TypeName -> idiomatic_haskell_type_name_of_string name
857 | `FunctionName -> idiomatic_haskell_term_name_of_string name
860 let pp_ref status ref =
861 capitalize (classify_reference status ref)
862 (NCicPp.r2s status true ref)
864 (* cons avoid duplicates *)
865 let rec (@:::) name l =
866 if name <> "" (* propositional things *) && name.[0] = '_' then
867 let name = String.sub name 1 (String.length name - 1) in
868 let name = if name = "" then "a" else name in
870 else if List.mem name l then (name ^ "'") @::: l
874 let (@::) x l = let x,l = x @::: l in x::l;;
876 let rec pretty_print_type status ctxt =
878 | Var n -> List.nth ctxt (n-1)
880 | Top -> assert false (* ??? *)
881 | TConst ref -> pp_ref status ref
883 bracket size_of_type (pretty_print_type status ctxt) t1 ^ " -> " ^
884 pretty_print_type status ("_"::ctxt) t2
885 | TSkip t -> pretty_print_type status ("_"::ctxt) t
886 | Forall (name, kind, t) ->
887 (*CSC: BUG HERE: avoid clashes due to uncapitalisation*)
888 let name = capitalize `TypeVariable name in
889 let name,ctxt = name@:::ctxt in
890 if size_of_kind kind > 1 then
891 "forall (" ^ name ^ " :: " ^ pretty_print_kind kind ^ "). " ^ pretty_print_type status (name::ctxt) t
893 "forall " ^ name ^ ". " ^ pretty_print_type status (name::ctxt) t
894 | TAppl tl -> String.concat " " (List.map (pretty_print_type status ctxt) tl)
896 let pretty_print_term_context status ctx1 ctx2 =
897 let name_context, rev_res =
899 (fun el (ctx1,rev_res) ->
901 None -> ""@::ctx1,rev_res
902 | Some (name,`OfKind _) -> name@::ctx1,rev_res
903 | Some (name,`OfType typ) ->
904 let name,ctx1 = name@:::ctx1 in
906 ("(" ^ name ^ " :: " ^ pretty_print_type status ctx1 typ ^ ")")::rev_res
908 name_context, String.concat " " (List.rev rev_res)
910 let rec pretty_print_term status ctxt =
912 | Rel n -> List.nth ctxt (n-1)
914 | Const ref -> pp_ref status ref
916 let name = capitalize `BoundVariable name in
917 let name,ctxt = name@:::ctxt in
918 "\\" ^ name ^ " -> " ^ pretty_print_term status (name::ctxt) t
919 | Appl tl -> String.concat " " (List.map (bracket size_of_term (pretty_print_term status ctxt)) tl)
920 | LetIn (name,s,t) ->
921 let name = capitalize `BoundVariable name in
922 let name,ctxt = name@:::ctxt in
923 "let " ^ name ^ " = " ^ pretty_print_term status ctxt s ^ " in " ^
924 pretty_print_term status (name::ctxt) t
926 "error \"Unreachable code\""
928 "unsafeCoerce " ^ bracket size_of_term (pretty_print_term status ctxt) t
929 | Match (r,matched,pl) ->
931 "error \"Case analysis over empty type\""
933 "case " ^ pretty_print_term status ctxt matched ^ " of\n" ^
936 (fun (bound_names,rhs) i ->
937 let ref = NReference.mk_constructor (i+1) r in
938 let name = pp_ref status ref in
939 let ctxt,bound_names =
940 pretty_print_term_context status ctxt bound_names in
942 pretty_print_term status ctxt rhs
944 " " ^ name ^ " " ^ bound_names ^ " -> " ^ body
946 | Skip t -> pretty_print_term status ("[[skipped]]"@::ctxt) t
947 | TLambda (name,t) ->
948 let name = capitalize `TypeVariable name in
949 pretty_print_term status (name@::ctxt) t
950 | Inst t -> pretty_print_term status ctxt t
953 let rec pp_obj status (ref,obj_kind) =
954 let pretty_print_context ctx =
955 String.concat " " (List.rev (snd
957 (fun (x,kind) (l,res) ->
959 if size_of_kind kind > 1 then
960 x::l,("(" ^ x ^ " :: " ^ pretty_print_kind kind ^ ")")::res
963 (HExtlib.filter_map (fun x -> x) ctx) ([],[]))))
965 let namectx_of_ctx ctx =
966 List.fold_right (@::)
967 (List.map (function None -> "" | Some (x,_) -> x) ctx) [] in
969 TypeDeclaration (ctx,_) ->
970 (* data?? unsure semantics: inductive type without constructor, but
971 not matchable apparently *)
972 if List.length ctx = 0 then
973 "data " ^ pp_ref status ref
975 "data " ^ pp_ref status ref ^ " " ^ pretty_print_context ctx
976 | TypeDefinition ((ctx, _),ty) ->
977 let namectx = namectx_of_ctx ctx in
978 if List.length ctx = 0 then
979 "type " ^ pp_ref status ref ^ " = " ^ pretty_print_type status namectx ty
981 "type " ^ pp_ref status ref ^ " " ^ pretty_print_context ctx ^ " = " ^ pretty_print_type status namectx ty
982 | TermDeclaration (ctx,ty) ->
983 let name = pp_ref status ref in
984 name ^ " :: " ^ pretty_print_type status [] (glue_ctx_typ ctx ty) ^ "\n" ^
985 name ^ " = error \"The declaration `" ^ name ^ "' has yet to be defined.\""
986 | TermDefinition ((ctx,ty),bo) ->
987 let name = pp_ref status ref in
988 let namectx = namectx_of_ctx ctx in
990 name ^ " :: " ^ pretty_print_type status namectx (glue_ctx_typ ctx ty) ^ "\n" ^
991 name ^ " = " ^ pretty_print_term status namectx bo
993 String.concat "\n" (List.map (pp_obj status) l)
997 (fun ref,left,right,cl ->
998 "data " ^ pp_ref status ref ^ " " ^
999 pretty_print_context (right@left) ^ " where\n " ^
1000 String.concat "\n " (List.map
1002 let namectx = namectx_of_ctx left in
1003 pp_ref status ref ^ " :: " ^
1004 pretty_print_type status namectx tys
1007 (* inductive and records missing *)
1009 let haskell_of_obj status (uri,_,_,_,_ as obj) =
1010 let status, obj = object_of status obj in
1013 Erased -> "-- [?] " ^ NUri.name_of_uri uri ^ " erased due to term being propositionally irrelevant.\n"
1014 | OutsideTheory -> "-- [?] " ^ NUri.name_of_uri uri ^ " erased due to image of term under extraction residing outside Fω.\n"
1015 | Failure msg -> "-- [?] " ^ NUri.name_of_uri uri ^ " FAILURE: " ^ msg ^ "\n"
1016 | Success o -> pp_obj status o ^ "\n"