summaryrefslogtreecommitdiff
path: root/parsing/prettyp.ml
diff options
context:
space:
mode:
Diffstat (limited to 'parsing/prettyp.ml')
-rw-r--r--parsing/prettyp.ml605
1 files changed, 605 insertions, 0 deletions
diff --git a/parsing/prettyp.ml b/parsing/prettyp.ml
new file mode 100644
index 00000000..169eff94
--- /dev/null
+++ b/parsing/prettyp.ml
@@ -0,0 +1,605 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+(* $Id: prettyp.ml,v 1.50.2.1 2004/07/16 19:30:40 herbelin Exp $ *)
+
+open Pp
+open Util
+open Names
+open Nameops
+open Term
+open Termops
+open Declarations
+open Inductive
+open Inductiveops
+open Sign
+open Reduction
+open Environ
+open Instantiate
+open Declare
+open Impargs
+open Libobject
+open Printer
+open Printmod
+open Libnames
+open Nametab
+
+(*********************)
+(** Basic printing *)
+
+let print_basename sp = pr_global (ConstRef sp)
+
+let print_closed_sections = ref false
+
+(********************************)
+(** Printing implicit arguments *)
+
+let print_impl_args_by_pos = function
+ | [] -> mt ()
+ | [i] -> str"Position [" ++ int i ++ str"] is implicit" ++ fnl()
+ | l ->
+ str"Positions [" ++
+ prlist_with_sep (fun () -> str "; ") int l ++
+ str"] are implicit" ++ fnl()
+
+let print_impl_args_by_name = function
+ | [] -> mt ()
+ | [i] -> str"Argument " ++ pr_id (name_of_implicit i) ++ str" is implicit" ++
+ fnl()
+ | l ->
+ str"Arguments " ++
+ prlist_with_sep (fun () -> str ", ")
+ (fun imp -> pr_id (name_of_implicit imp)) l ++
+ str" are implicit" ++ fnl()
+
+let print_impl_args l =
+ if !Options.v7 then print_impl_args_by_pos (positions_of_implicits l)
+ else print_impl_args_by_name (List.filter is_status_implicit l)
+
+(*********************)
+(** Printing Scopes *)
+
+let print_ref reduce ref =
+ let typ = Global.type_of_global ref in
+ let typ =
+ if reduce then
+ let ctx,ccl = Reductionops.splay_prod_assum (Global.env()) Evd.empty typ
+ in it_mkProd_or_LetIn ccl ctx
+ else typ in
+ hov 0 (pr_global ref ++ str " :" ++ spc () ++ prtype typ) ++ fnl ()
+
+let print_argument_scopes = function
+ | [Some sc] -> str"Argument scope is [" ++ str sc ++ str"]" ++ fnl()
+ | l when not (List.for_all ((=) None) l) ->
+ hov 2 (str"Argument scopes are" ++ spc() ++
+ str "[" ++
+ prlist_with_sep spc (function Some sc -> str sc | None -> str "_") l ++
+ str "]") ++ fnl()
+ | _ -> mt()
+
+let need_expansion impl ref =
+ let typ = Global.type_of_global ref in
+ let ctx = fst (decompose_prod_assum typ) in
+ let nprods = List.length (List.filter (fun (_,b,_) -> b=None) ctx) in
+ impl <> [] & let _,lastimpl = list_chop nprods impl in
+ List.filter is_status_implicit lastimpl <> []
+
+let print_name_infos ref =
+ let impl = implicits_of_global ref in
+ let scopes = Symbols.find_arguments_scope ref in
+ let type_for_implicit =
+ if need_expansion impl ref then
+ (* Need to reduce since implicits are computed with products flattened *)
+ str "Expanded type for implicit arguments" ++ fnl () ++
+ print_ref true ref ++ fnl()
+ else mt() in
+ (if (List.filter is_status_implicit impl<>[])
+ or not (List.for_all ((=) None) scopes)
+ then fnl()
+ else mt())
+ ++ type_for_implicit
+ ++ print_impl_args impl ++ print_argument_scopes scopes
+
+let print_id_args_data test pr id l =
+ if List.exists test l then
+ str"For " ++ pr_id id ++ str": " ++ pr l
+ else
+ mt()
+
+let print_args_data_of_inductive_ids get test pr sp mipv =
+ prvecti
+ (fun i mip ->
+ print_id_args_data test pr mip.mind_typename (get (IndRef (sp,i))) ++
+ prvecti
+ (fun j idc ->
+ print_id_args_data test pr idc (get (ConstructRef ((sp,i),j+1))))
+ mip.mind_consnames)
+ mipv
+
+let print_inductive_implicit_args =
+ print_args_data_of_inductive_ids
+ implicits_of_global is_status_implicit print_impl_args
+
+let print_inductive_argument_scopes =
+ print_args_data_of_inductive_ids
+ Symbols.find_arguments_scope ((<>) None) print_argument_scopes
+
+(*********************)
+(* "Locate" commands *)
+
+type logical_name =
+ | Term of global_reference
+ | Dir of global_dir_reference
+ | Syntactic of kernel_name
+ | ModuleType of qualid * kernel_name
+ | Undefined of qualid
+
+let locate_any_name ref =
+ let module N = Nametab in
+ let (loc,qid) = qualid_of_reference ref in
+ try Term (N.locate qid)
+ with Not_found ->
+ try Syntactic (N.locate_syntactic_definition qid)
+ with Not_found ->
+ try Dir (N.locate_dir qid)
+ with Not_found ->
+ try ModuleType (qid, N.locate_modtype qid)
+ with Not_found -> Undefined qid
+
+let pr_located_qualid = function
+ | Term ref ->
+ let ref_str = match ref with
+ ConstRef _ -> "Constant"
+ | IndRef _ -> "Inductive"
+ | ConstructRef _ -> "Constructor"
+ | VarRef _ -> "Variable" in
+ str ref_str ++ spc () ++ pr_sp (Nametab.sp_of_global ref)
+ | Syntactic kn ->
+ str (if !Options.v7 then "Syntactic Definition" else "Notation") ++
+ spc () ++ pr_sp (Nametab.sp_of_syntactic_definition kn)
+ | Dir dir ->
+ let s,dir = match dir with
+ | DirOpenModule (dir,_) -> "Open Module", dir
+ | DirOpenModtype (dir,_) -> "Open Module Type", dir
+ | DirOpenSection (dir,_) -> "Open Section", dir
+ | DirModule (dir,_) -> "Module", dir
+ | DirClosedSection dir -> "Closed Section", dir
+ in
+ str s ++ spc () ++ pr_dirpath dir
+ | ModuleType (qid,_) ->
+ str "Module Type" ++ spc () ++ pr_sp (Nametab.full_name_modtype qid)
+ | Undefined qid ->
+ pr_qualid qid ++ str " is not a defined object"
+
+let print_located_qualid ref =
+ let (loc,qid) = qualid_of_reference ref in
+ let module N = Nametab in
+ let expand = function
+ | TrueGlobal ref -> Term ref, N.shortest_qualid_of_global Idset.empty ref
+ | SyntacticDef kn -> Syntactic kn, N.shortest_qualid_of_syndef kn in
+ match List.map expand (N.extended_locate_all qid) with
+ | [] ->
+ let (dir,id) = repr_qualid qid in
+ if dir = empty_dirpath then
+ str "No object of basename " ++ pr_id id
+ else
+ str "No object of suffix " ++ pr_qualid qid
+ | l ->
+ prlist_with_sep fnl
+ (fun (o,oqid) ->
+ hov 2 (pr_located_qualid o ++
+ (if oqid <> qid then
+ spc() ++ str "(visible as " ++ pr_qualid oqid ++ str")"
+ else
+ mt ()))) l
+
+(******************************************)
+(**** Printing declarations and judgments *)
+
+let print_typed_value_in_env env (trm,typ) =
+ (prterm_env env trm ++ fnl () ++
+ str " : " ++ prtype_env env typ ++ fnl ())
+
+let print_typed_value x = print_typed_value_in_env (Global.env ()) x
+
+let print_judgment env {uj_val=trm;uj_type=typ} =
+ print_typed_value_in_env env (trm, typ)
+
+let print_safe_judgment env j =
+ let trm = Safe_typing.j_val j in
+ let typ = Safe_typing.j_type j in
+ print_typed_value_in_env env (trm, typ)
+
+(* To be improved; the type should be used to provide the types in the
+ abstractions. This should be done recursively inside prterm, so that
+ the pretty-print of a proposition (P:(nat->nat)->Prop)(P [u]u)
+ synthesizes the type nat of the abstraction on u *)
+
+let print_named_def name body typ =
+ let pbody = prterm body in
+ let ptyp = prtype typ in
+ (str "*** [" ++ str name ++ str " " ++
+ hov 0 (str ":=" ++ brk (1,2) ++ pbody ++ spc () ++
+ str ":" ++ brk (1,2) ++ ptyp) ++
+ str "]" ++ fnl ())
+
+let print_named_assum name typ =
+ (str "*** [" ++ str name ++ str " : " ++ prtype typ ++ str "]" ++ fnl ())
+
+let print_named_decl (id,c,typ) =
+ let s = string_of_id id in
+ match c with
+ | Some body -> print_named_def s body typ
+ | None -> print_named_assum s typ
+
+let assumptions_for_print lna =
+ List.fold_right (fun na env -> add_name na env) lna empty_names_context
+
+(*********************)
+(* *)
+
+let print_params env params =
+ if List.length params = 0 then
+ (mt ())
+ else
+ if !Options.v7 then
+ (str "[" ++ pr_rel_context env params ++ str "]" ++ brk(1,2))
+ else
+ (pr_rel_context env params ++ brk(1,2))
+
+let print_constructors envpar names types =
+ let pc =
+ prlist_with_sep (fun () -> brk(1,0) ++ str "| ")
+ (fun (id,c) -> pr_id id ++ str " : " ++ prterm_env envpar c)
+ (Array.to_list (array_map2 (fun n t -> (n,t)) names types))
+ in
+ hv 0 (str " " ++ pc)
+
+let build_inductive sp tyi =
+ let (mib,mip) = Global.lookup_inductive (sp,tyi) in
+ let params = mip.mind_params_ctxt in
+ let args = extended_rel_list 0 params in
+ let env = Global.env() in
+ let arity = hnf_prod_applist env mip.mind_user_arity args in
+ let cstrtypes = arities_of_constructors env (sp,tyi) in
+ let cstrtypes =
+ Array.map (fun c -> hnf_prod_applist env c args) cstrtypes in
+ let cstrnames = mip.mind_consnames in
+ (IndRef (sp,tyi), params, arity, cstrnames, cstrtypes)
+
+let print_one_inductive (sp,tyi) =
+ let (ref, params, arity, cstrnames, cstrtypes) = build_inductive sp tyi in
+ let env = Global.env () in
+ let envpar = push_rel_context params env in
+ hov 0 (
+ pr_global (IndRef (sp,tyi)) ++ brk(1,4) ++ print_params env params ++
+ str ": " ++ prterm_env envpar arity ++ str " :=") ++
+ brk(0,2) ++ print_constructors envpar cstrnames cstrtypes
+
+let pr_mutual_inductive finite indl =
+ hov 0 (
+ str (if finite then "Inductive " else "CoInductive ") ++
+ prlist_with_sep (fun () -> fnl () ++ str" with ")
+ print_one_inductive indl) ++
+ fnl ()
+
+let print_mutual sp =
+ let (mib,mip) = Global.lookup_inductive (sp,0) in
+ let mipv = mib.mind_packets in
+ let names = list_tabulate (fun x -> (sp,x)) (Array.length mipv) in
+ pr_mutual_inductive mib.mind_finite names ++
+ print_inductive_implicit_args sp mipv ++
+ print_inductive_argument_scopes sp mipv
+
+let print_section_variable sp =
+ let d = get_variable sp in
+ print_named_decl d ++
+ print_name_infos (VarRef sp)
+
+let print_body = function
+ | Some lc -> prterm (Declarations.force lc)
+ | None -> (str"<no body>")
+
+let print_typed_body (val_0,typ) =
+ (print_body val_0 ++ fnl () ++ str " : " ++ prtype typ ++ fnl ())
+
+let print_constant with_values sep sp =
+ let cb = Global.lookup_constant sp in
+ let val_0 = cb.const_body in
+ let typ = cb.const_type in
+ hov 0 (
+ match val_0 with
+ | None ->
+ str"*** [ " ++
+ print_basename sp ++ str " : " ++ cut () ++ prtype typ ++
+ str" ]" ++ fnl ()
+ | _ ->
+ print_basename sp ++ str sep ++ cut () ++
+ (if with_values then print_typed_body (val_0,typ) else prtype typ) ++
+ fnl ())
+
+let print_constant_with_infos sp =
+ print_constant true " = " sp ++ print_name_infos (ConstRef sp)
+
+let print_inductive sp = (print_mutual sp)
+
+let print_syntactic_def sep kn =
+ let qid = Nametab.shortest_qualid_of_syndef kn in
+ let c = Syntax_def.search_syntactic_definition dummy_loc kn in
+ (str (if !Options.v7 then "Syntactic Definition " else "Notation ")
+ ++ pr_qualid qid ++ str sep ++
+ Constrextern.without_symbols pr_rawterm c ++ fnl ())
+
+let print_leaf_entry with_values sep ((sp,kn as oname),lobj) =
+ let tag = object_tag lobj in
+ match (oname,tag) with
+ | (_,"VARIABLE") ->
+ Some (print_section_variable (basename sp))
+ | (_,"CONSTANT") ->
+ Some (print_constant with_values sep kn)
+ | (_,"INDUCTIVE") ->
+ Some (print_inductive kn)
+ | (_,"MODULE") ->
+ let (mp,_,l) = repr_kn kn in
+ Some (print_module with_values (MPdot (mp,l)))
+ | (_,"MODULE TYPE") ->
+ Some (print_modtype kn)
+ | (_,("AUTOHINT"|"GRAMMAR"|"SYNTAXCONSTANT"|"PPSYNTAX"|"TOKEN"|"CLASS"|
+ "COERCION"|"REQUIRE"|"END-SECTION"|"STRUCTURE")) -> None
+ (* To deal with forgotten cases... *)
+ | (_,s) -> None
+(*
+ | (_,s) ->
+ (str(string_of_path sp) ++ str" : " ++
+ str"Unrecognized object " ++ str s ++ fnl ())
+*)
+
+let rec print_library_entry with_values ent =
+ let sep = if with_values then " = " else " : " in
+ let pr_name (sp,_) = pr_id (basename sp) in
+ match ent with
+ | (oname,Lib.Leaf lobj) ->
+ print_leaf_entry with_values sep (oname,lobj)
+ | (oname,Lib.OpenedSection (dir,_)) ->
+ Some (str " >>>>>>> Section " ++ pr_name oname)
+ | (oname,Lib.ClosedSection _) ->
+ Some (str " >>>>>>> Closed Section " ++ pr_name oname)
+ | (_,Lib.CompilingLibrary (dir,_)) ->
+ Some (str " >>>>>>> Library " ++ pr_dirpath dir)
+ | (oname,Lib.OpenedModule _) ->
+ Some (str " >>>>>>> Module " ++ pr_name oname)
+ | (oname,Lib.OpenedModtype _) ->
+ Some (str " >>>>>>> Module Type " ++ pr_name oname)
+ | (_,Lib.FrozenState _) ->
+ None
+
+let print_context with_values =
+ let rec prec n = function
+ | h::rest when n = None or out_some n > 0 ->
+ (match print_library_entry with_values h with
+ | None -> prec n rest
+ | Some pp -> prec (option_app ((+) (-1)) n) rest ++ pp ++ fnl ())
+ | _ -> mt ()
+ in
+ prec
+
+let print_full_context () =
+ print_context true None (Lib.contents_after None)
+
+let print_full_context_typ () =
+ print_context false None (Lib.contents_after None)
+
+(* For printing an inductive definition with
+ its constructors and elimination,
+ assume that the declaration of constructors and eliminations
+ follows the definition of the inductive type *)
+
+let list_filter_vec f vec =
+ let rec frec n lf =
+ if n < 0 then lf
+ else if f vec.(n) then
+ frec (n-1) (vec.(n)::lf)
+ else
+ frec (n-1) lf
+ in
+ frec (Array.length vec -1) []
+
+(* This is designed to print the contents of an opened section *)
+let read_sec_context r =
+ let loc,qid = qualid_of_reference r in
+ let dir =
+ try Nametab.locate_section qid
+ with Not_found ->
+ user_err_loc (loc,"read_sec_context", str "Unknown section") in
+ let rec get_cxt in_cxt = function
+ | ((_,Lib.OpenedSection ((dir',_),_)) as hd)::rest ->
+ if dir = dir' then (hd::in_cxt) else get_cxt (hd::in_cxt) rest
+ | ((_,Lib.ClosedSection (_,_,ctxt)) as hd)::rest ->
+ error "Cannot print the contents of a closed section"
+ | [] -> []
+ | hd::rest -> get_cxt (hd::in_cxt) rest
+ in
+ let cxt = (Lib.contents_after None) in
+ List.rev (get_cxt [] cxt)
+
+let print_sec_context sec =
+ print_context true None (read_sec_context sec)
+
+let print_sec_context_typ sec =
+ print_context false None (read_sec_context sec)
+
+let print_eval red_fun env {uj_val=trm;uj_type=typ} =
+ let ntrm = red_fun env Evd.empty trm in
+ (str " = " ++ print_judgment env {uj_val = ntrm; uj_type = typ})
+
+let print_name ref =
+ match locate_any_name ref with
+ | Term (ConstRef sp) -> print_constant_with_infos sp
+ | Term (IndRef (sp,_)) -> print_inductive sp
+ | Term (ConstructRef ((sp,_),_)) -> print_inductive sp
+ | Term (VarRef sp) -> print_section_variable sp
+ | Syntactic kn -> print_syntactic_def " := " kn
+ | Dir (DirModule(dirpath,(mp,_))) -> print_module (printable_body dirpath) mp
+ | Dir _ -> mt ()
+ | ModuleType (_,kn) -> print_modtype kn
+ | Undefined qid ->
+ try (* Var locale de but, pas var de section... donc pas d'implicits *)
+ let dir,str = repr_qualid qid in
+ if (repr_dirpath dir) <> [] then raise Not_found;
+ let (_,c,typ) = Global.lookup_named str in
+ (print_named_decl (str,c,typ))
+ with Not_found ->
+ try
+ let sp = Nametab.locate_obj qid in
+ let (oname,lobj) =
+ let (oname,entry) =
+ List.find (fun en -> (fst (fst en)) = sp) (Lib.contents_after None)
+ in
+ match entry with
+ | Lib.Leaf obj -> (oname,obj)
+ | _ -> raise Not_found
+ in
+ match print_leaf_entry true " = " (oname,lobj) with
+ | None -> mt ()
+ | Some pp -> pp ++ fnl()
+ with Not_found ->
+ errorlabstrm
+ "print_name" (pr_qualid qid ++ spc () ++ str "not a defined object")
+
+let print_opaque_name qid =
+ let sigma = Evd.empty in
+ let env = Global.env () in
+ let sign = Global.named_context () in
+ match global qid with
+ | ConstRef cst ->
+ let cb = Global.lookup_constant cst in
+ if cb.const_body <> None then
+ print_constant_with_infos cst
+ else
+ error "not a defined constant"
+ | IndRef (sp,_) ->
+ print_mutual sp
+ | ConstructRef cstr ->
+ let ty = Inductive.type_of_constructor env cstr in
+ print_typed_value (mkConstruct cstr, ty)
+ | VarRef id ->
+ let (_,c,ty) = lookup_named id env in
+ print_named_decl (id,c,ty)
+
+let print_about ref =
+ let sigma = Evd.empty in
+ let k = locate_any_name ref in
+ begin match k with
+ | Term ref -> print_ref false ref ++ print_name_infos ref
+ | Syntactic kn -> print_syntactic_def " := " kn
+ | Dir _ | ModuleType _ | Undefined _ -> mt () end
+ ++
+ hov 0 (str "Expands to: " ++ pr_located_qualid k)
+
+let print_impargs ref =
+ let ref = Nametab.global ref in
+ let impl = implicits_of_global ref in
+ let has_impl = List.filter is_status_implicit impl <> [] in
+ (* Need to reduce since implicits are computed with products flattened *)
+ print_ref (need_expansion impl ref) ref ++ fnl() ++
+ (if has_impl then print_impl_args impl
+ else (str "No implicit arguments" ++ fnl ()))
+
+let print_local_context () =
+ let env = Lib.contents_after None in
+ let rec print_var_rec = function
+ | [] -> (mt ())
+ | (oname,Lib.Leaf lobj)::rest ->
+ if "VARIABLE" = object_tag lobj then
+ let d = get_variable (basename (fst oname)) in
+ (print_var_rec rest ++
+ print_named_decl d)
+ else
+ print_var_rec rest
+ | _::rest -> print_var_rec rest
+
+ and print_last_const = function
+ | (oname,Lib.Leaf lobj)::rest ->
+ (match object_tag lobj with
+ | "CONSTANT" ->
+ let kn = snd oname in
+ let {const_body=val_0;const_type=typ} =
+ Global.lookup_constant kn in
+ (print_last_const rest ++
+ print_basename kn ++str" = " ++
+ print_typed_body (val_0,typ))
+ | "INDUCTIVE" ->
+ let kn = snd oname in
+ (print_last_const rest ++print_mutual kn ++ fnl ())
+ | "VARIABLE" -> (mt ())
+ | _ -> print_last_const rest)
+ | _ -> (mt ())
+ in
+ (print_var_rec env ++ print_last_const env)
+
+let unfold_head_fconst =
+ let rec unfrec k = match kind_of_term k with
+ | Const cst -> constant_value (Global.env ()) cst
+ | Lambda (na,t,b) -> mkLambda (na,t,unfrec b)
+ | App (f,v) -> appvect (unfrec f,v)
+ | _ -> k
+ in
+ unfrec
+
+(* for debug *)
+let inspect depth =
+ print_context false (Some depth) (Lib.contents_after None)
+
+
+(*************************************************************************)
+(* Pretty-printing functions coming from classops.ml *)
+
+open Classops
+
+let print_coercion_value v = prterm (get_coercion_value v)
+
+let print_class i =
+ let cl,_ = class_info_from_index i in
+ pr_class cl
+
+let print_path ((i,j),p) =
+ (str"[" ++
+ prlist_with_sep pr_semicolon print_coercion_value p ++
+ str"] : " ++ print_class i ++ str" >-> " ++
+ print_class j)
+
+let _ = Classops.install_path_printer print_path
+
+let print_graph () =
+ prlist_with_sep pr_fnl print_path (inheritance_graph())
+
+let print_classes () =
+ prlist_with_sep pr_spc pr_class (classes())
+
+let print_coercions () =
+ prlist_with_sep pr_spc print_coercion_value (coercions())
+
+let index_of_class cl =
+ try
+ fst (class_info cl)
+ with _ ->
+ errorlabstrm "index_of_class" (pr_class cl ++ str" is not a defined class")
+
+let print_path_between cls clt =
+ let i = index_of_class cls in
+ let j = index_of_class clt in
+ let p =
+ try
+ lookup_path_between (i,j)
+ with _ ->
+ errorlabstrm "index_cl_of_id"
+ (str"No path between " ++ pr_class cls ++ str" and " ++ pr_class clt)
+ in
+ print_path ((i,j),p)
+
+(*************************************************************************)