1 (************************************************************************)
2 (* v * The Coq Proof Assistant / The Coq Development Team *)
3 (* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2011 *)
4 (* \VV/ **************************************************************)
5 (* // * This file is distributed under the terms of the *)
6 (* * GNU Lesser General Public License Version 2.1 *)
7 (************************************************************************)
9 (*i $Id: common.ml 14641 2011-11-06 11:59:10Z herbelin $ i*)
12 open OcamlExtractionTable
16 (*s Some pretty-print utility functions. *)
18 let pp_par par st = if par then str "(" ++ st ++ str ")" else st
20 let pp_apply st par args = match args with
22 | _ -> hov 2 (pp_par par (st ++ spc () ++ prlist_with_sep spc identity args))
24 let pr_binding = function
26 | l -> str " " ++ prlist_with_sep (fun () -> str " ") pr_id l
28 (** By default, in module Format, you can do horizontal placing of blocks
29 even if they include newlines, as long as the number of chars in the
30 blocks are less that a line length. To avoid this awkward situation,
31 we attach a big virtual size to [fnl] newlines. *)
33 let fnl () = stras (1000000,"") ++ fnl ()
35 let fnl2 () = fnl () ++ fnl ()
37 let space_if = function true -> str " " | false -> mt ()
40 match s.[0] with 'a' .. 'z' | 'A' .. 'Z' -> false | _ -> true
42 let rec lowercase_id id =
43 if id = "" then "x" else
44 if id.[0] = '_' then lowercase_id (String.sub id 1 (String.length id - 1)) else
45 if is_invalid_id id then lowercase_id ("x" ^ id) else
46 String.uncapitalize id
48 let rec uppercase_id id =
49 if id = "" then "T" else
50 if id.[0] = '_' then uppercase_id (String.sub id 1 (String.length id - 1)) else
51 if is_invalid_id id then uppercase_id ("x" ^ id) else
54 type kind = Term | Type | Cons
56 let upperkind = function
61 let kindcase_id k id =
62 if upperkind k then uppercase_id id else lowercase_id id
64 (*s de Bruijn environments for programs *)
66 type env = identifier list * Idset.t
68 (*s Generic renaming issues for local variable names. *)
70 let rec rename_id id avoid =
71 if Idset.mem id avoid then rename_id (lift_subscript id) avoid else id
73 let rec rename_vars avoid = function
76 | id :: idl when id == dummy_name ->
77 (* we don't rename dummy binders *)
78 let (idl', avoid') = rename_vars avoid idl in
81 let (idl, avoid) = rename_vars avoid idl in
82 let id = rename_id (lowercase_id id) avoid in
83 (id :: idl, Idset.add id avoid)
85 let rename_tvars avoid l =
86 let rec rename avoid = function
89 let id = rename_id (lowercase_id id) avoid in
90 let idl, avoid = rename (Idset.add id avoid) idl in
94 let push_vars ids (db,avoid) =
95 let ids',avoid' = rename_vars avoid ids in
96 ids', (ids' @ db, avoid')
98 let get_db_name n (db,_) =
99 let id = List.nth db (pred n) in
100 if id = dummy_name then "__" else id
102 let empty_env status = [], get_global_ids status
104 let fake_spec = NReference.Fix (0,-1,-1)
106 let safe_name_of_reference status r =
108 NReference.Ref (uri, spec) when spec = fake_spec ->
109 (* The field of a record *)
111 | _ -> NCicPp.r2s status true r
113 let maybe_capitalize b n = if b then String.capitalize n else n
115 let modname_of_filename status capitalize name =
117 let name = modname_of_filename status name in
118 status, maybe_capitalize capitalize name
120 let globs = Idset.elements (get_modnames status) in
121 let s = next_ident_away (String.uncapitalize name) globs in
122 let status = add_modname status s in
123 let status = add_modname_for_filename status name s in
124 status, maybe_capitalize capitalize s
126 let ref_renaming status (k,r) =
128 let rec ref_renaming status (k,r) =
129 try status,name_of_reference status r
131 if is_projection status r then
132 (* The reference for the projection and the field of a record are different
133 and they would be assigned different names (name clash!). So we normalize
134 the projection reference into the field reference *)
135 let NReference.Ref (uri,_) = r in
136 let fieldref = NReference.reference_of_spec uri fake_spec in
137 ref_renaming status (k,fieldref)
139 let name = safe_name_of_reference status r in
140 let globs = Idset.elements (get_global_ids status) in
141 let s = next_ident_away (kindcase_id k name) globs in
142 let status = add_global_ids status s in
143 let status = add_name_for_reference status r s in
146 ref_renaming status (k,r)
148 let baseuri = Filename.dirname (NReference.string_of_reference r) in
149 if current_baseuri status = baseuri then
152 let modname = Filename.basename (Filename.dirname (NReference.string_of_reference r)) in
153 let status,modname = modname_of_filename status true modname in
154 status, modname ^ "." ^ s
156 (* Main name printing function for a reference *)
158 let pp_global status k r = ref_renaming status (k,r)