PageRenderTime 79ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/contrib/extraction/ocaml.ml

http://github.com/mzp/coq-ruby
OCaml | 731 lines | 623 code | 73 blank | 35 comment | 74 complexity | f0f18f3d3df9b5e2a2866df44936e3e1 MD5 | raw file
Possible License(s): LGPL-2.1, LGPL-2.0
  1. (************************************************************************)
  2. (* v * The Coq Proof Assistant / The Coq Development Team *)
  3. (* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *)
  4. (* \VV/ **************************************************************)
  5. (* // * This file is distributed under the terms of the *)
  6. (* * GNU Lesser General Public License Version 2.1 *)
  7. (************************************************************************)
  8. (*i $Id: ocaml.ml 11559 2008-11-07 22:03:34Z letouzey $ i*)
  9. (*s Production of Ocaml syntax. *)
  10. open Pp
  11. open Util
  12. open Names
  13. open Nameops
  14. open Libnames
  15. open Table
  16. open Miniml
  17. open Mlutil
  18. open Modutil
  19. open Common
  20. open Declarations
  21. (*s Some utility functions. *)
  22. let pp_tvar id =
  23. let s = string_of_id id in
  24. if String.length s < 2 || s.[1]<>'\''
  25. then str ("'"^s)
  26. else str ("' "^s)
  27. let pp_tuple_light f = function
  28. | [] -> mt ()
  29. | [x] -> f true x
  30. | l ->
  31. pp_par true (prlist_with_sep (fun () -> str "," ++ spc ()) (f false) l)
  32. let pp_tuple f = function
  33. | [] -> mt ()
  34. | [x] -> f x
  35. | l -> pp_par true (prlist_with_sep (fun () -> str "," ++ spc ()) f l)
  36. let pp_boxed_tuple f = function
  37. | [] -> mt ()
  38. | [x] -> f x
  39. | l -> pp_par true (hov 0 (prlist_with_sep (fun () -> str "," ++ spc ()) f l))
  40. let pp_abst = function
  41. | [] -> mt ()
  42. | l ->
  43. str "fun " ++ prlist_with_sep (fun () -> str " ") pr_id l ++
  44. str " ->" ++ spc ()
  45. let pp_parameters l =
  46. (pp_boxed_tuple pp_tvar l ++ space_if (l<>[]))
  47. let pp_string_parameters l =
  48. (pp_boxed_tuple str l ++ space_if (l<>[]))
  49. (*s Ocaml renaming issues. *)
  50. let keywords =
  51. List.fold_right (fun s -> Idset.add (id_of_string s))
  52. [ "and"; "as"; "assert"; "begin"; "class"; "constraint"; "do";
  53. "done"; "downto"; "else"; "end"; "exception"; "external"; "false";
  54. "for"; "fun"; "function"; "functor"; "if"; "in"; "include";
  55. "inherit"; "initializer"; "lazy"; "let"; "match"; "method";
  56. "module"; "mutable"; "new"; "object"; "of"; "open"; "or";
  57. "parser"; "private"; "rec"; "sig"; "struct"; "then"; "to"; "true";
  58. "try"; "type"; "val"; "virtual"; "when"; "while"; "with"; "mod";
  59. "land"; "lor"; "lxor"; "lsl"; "lsr"; "asr" ; "unit" ; "_" ; "__" ]
  60. Idset.empty
  61. let pp_open mp = str ("open "^ string_of_modfile mp ^"\n")
  62. let preamble _ used_modules usf =
  63. prlist pp_open used_modules ++
  64. (if used_modules = [] then mt () else fnl ()) ++
  65. (if usf.tdummy || usf.tunknown then str "type __ = Obj.t\n" else mt()) ++
  66. (if usf.mldummy then
  67. str "let __ = let rec f _ = Obj.repr f in Obj.repr f\n"
  68. else mt ()) ++
  69. (if usf.tdummy || usf.tunknown || usf.mldummy then fnl () else mt ())
  70. let sig_preamble _ used_modules usf =
  71. prlist pp_open used_modules ++
  72. (if used_modules = [] then mt () else fnl ()) ++
  73. (if usf.tdummy || usf.tunknown then str "type __ = Obj.t\n\n" else mt())
  74. (*s The pretty-printer for Ocaml syntax*)
  75. (* Beware of the side-effects of [pp_global] and [pp_modname].
  76. They are used to update table of content for modules. Many [let]
  77. below should not be altered since they force evaluation order.
  78. *)
  79. let pp_global k r =
  80. if is_inline_custom r then str (find_custom r)
  81. else str (Common.pp_global k r)
  82. let pp_modname mp = str (Common.pp_module mp)
  83. let is_infix r =
  84. is_inline_custom r &&
  85. (let s = find_custom r in
  86. let l = String.length s in
  87. l >= 2 && s.[0] = '(' && s.[l-1] = ')')
  88. let get_infix r =
  89. let s = find_custom r in
  90. String.sub s 1 (String.length s - 2)
  91. exception NoRecord
  92. let find_projections = function Record l -> l | _ -> raise NoRecord
  93. (*s Pretty-printing of types. [par] is a boolean indicating whether parentheses
  94. are needed or not. *)
  95. let kn_sig =
  96. let specif = MPfile (dirpath_of_string "Coq.Init.Specif") in
  97. make_kn specif empty_dirpath (mk_label "sig")
  98. let rec pp_type par vl t =
  99. let rec pp_rec par = function
  100. | Tmeta _ | Tvar' _ | Taxiom -> assert false
  101. | Tvar i -> (try pp_tvar (List.nth vl (pred i))
  102. with _ -> (str "'a" ++ int i))
  103. | Tglob (r,[a1;a2]) when is_infix r ->
  104. pp_par par
  105. (pp_rec true a1 ++ spc () ++ str (get_infix r) ++ spc () ++
  106. pp_rec true a2)
  107. | Tglob (r,[]) -> pp_global Type r
  108. | Tglob (r,l) ->
  109. if r = IndRef (kn_sig,0) then
  110. pp_tuple_light pp_rec l
  111. else
  112. pp_tuple_light pp_rec l ++ spc () ++ pp_global Type r
  113. | Tarr (t1,t2) ->
  114. pp_par par
  115. (pp_rec true t1 ++ spc () ++ str "->" ++ spc () ++ pp_rec false t2)
  116. | Tdummy _ -> str "__"
  117. | Tunknown -> str "__"
  118. in
  119. hov 0 (pp_rec par t)
  120. (*s Pretty-printing of expressions. [par] indicates whether
  121. parentheses are needed or not. [env] is the list of names for the
  122. de Bruijn variables. [args] is the list of collected arguments
  123. (already pretty-printed). *)
  124. let is_ifthenelse = function
  125. | [|(r1,[],_);(r2,[],_)|] ->
  126. (try (find_custom r1 = "true") && (find_custom r2 = "false")
  127. with Not_found -> false)
  128. | _ -> false
  129. let expr_needs_par = function
  130. | MLlam _ -> true
  131. | MLcase (_,_,[|_|]) -> false
  132. | MLcase (_,_,pv) -> not (is_ifthenelse pv)
  133. | _ -> false
  134. let rec pp_expr par env args =
  135. let par' = args <> [] || par
  136. and apply st = pp_apply st par args in
  137. function
  138. | MLrel n ->
  139. let id = get_db_name n env in apply (pr_id id)
  140. | MLapp (f,args') ->
  141. let stl = List.map (pp_expr true env []) args' in
  142. pp_expr par env (stl @ args) f
  143. | MLlam _ as a ->
  144. let fl,a' = collect_lams a in
  145. let fl,env' = push_vars fl env in
  146. let st = (pp_abst (List.rev fl) ++ pp_expr false env' [] a') in
  147. apply (pp_par par' st)
  148. | MLletin (id,a1,a2) ->
  149. let i,env' = push_vars [id] env in
  150. let pp_id = pr_id (List.hd i)
  151. and pp_a1 = pp_expr false env [] a1
  152. and pp_a2 = pp_expr (not par && expr_needs_par a2) env' [] a2 in
  153. hv 0
  154. (apply
  155. (pp_par par'
  156. (hv 0
  157. (hov 2
  158. (str "let " ++ pp_id ++ str " =" ++ spc () ++ pp_a1) ++
  159. spc () ++ str "in") ++
  160. spc () ++ hov 0 pp_a2)))
  161. | MLglob r ->
  162. (try
  163. let args = list_skipn (projection_arity r) args in
  164. let record = List.hd args in
  165. pp_apply (record ++ str "." ++ pp_global Term r) par (List.tl args)
  166. with _ -> apply (pp_global Term r))
  167. | MLcons (Coinductive,r,[]) ->
  168. assert (args=[]);
  169. pp_par par (str "lazy " ++ pp_global Cons r)
  170. | MLcons (Coinductive,r,args') ->
  171. assert (args=[]);
  172. let tuple = pp_tuple (pp_expr true env []) args' in
  173. pp_par par (str "lazy (" ++ pp_global Cons r ++ spc() ++ tuple ++str ")")
  174. | MLcons (_,r,[]) ->
  175. assert (args=[]);
  176. pp_global Cons r
  177. | MLcons (Record projs, r, args') ->
  178. assert (args=[]);
  179. pp_record_pat (projs, List.map (pp_expr true env []) args')
  180. | MLcons (_,r,[arg1;arg2]) when is_infix r ->
  181. assert (args=[]);
  182. pp_par par
  183. ((pp_expr true env [] arg1) ++ spc () ++ str (get_infix r) ++
  184. spc () ++ (pp_expr true env [] arg2))
  185. | MLcons (_,r,args') ->
  186. assert (args=[]);
  187. let tuple = pp_tuple (pp_expr true env []) args' in
  188. pp_par par (pp_global Cons r ++ spc () ++ tuple)
  189. | MLcase ((i,factors), t, pv) ->
  190. let expr = if i = Coinductive then
  191. (str "Lazy.force" ++ spc () ++ pp_expr true env [] t)
  192. else
  193. (pp_expr false env [] t)
  194. in
  195. (try
  196. let projs = find_projections i in
  197. let (_, ids, c) = pv.(0) in
  198. let n = List.length ids in
  199. match c with
  200. | MLrel i when i <= n ->
  201. apply (pp_par par' (pp_expr true env [] t ++ str "." ++
  202. pp_global Term (List.nth projs (n-i))))
  203. | MLapp (MLrel i, a) when i <= n ->
  204. if List.exists (ast_occurs_itvl 1 n) a
  205. then raise NoRecord
  206. else
  207. let ids,env' = push_vars (List.rev ids) env in
  208. (pp_apply
  209. (pp_expr true env [] t ++ str "." ++
  210. pp_global Term (List.nth projs (n-i)))
  211. par ((List.map (pp_expr true env' []) a) @ args))
  212. | _ -> raise NoRecord
  213. with NoRecord ->
  214. if Array.length pv = 1 then
  215. let s1,s2 = pp_one_pat env i pv.(0) in
  216. apply
  217. (hv 0
  218. (pp_par par'
  219. (hv 0
  220. (hov 2 (str "let " ++ s1 ++ str " =" ++ spc () ++ expr)
  221. ++ spc () ++ str "in") ++
  222. spc () ++ hov 0 s2)))
  223. else
  224. apply
  225. (pp_par par'
  226. (try pp_ifthenelse par' env expr pv
  227. with Not_found ->
  228. v 0 (str "match " ++ expr ++ str " with" ++ fnl () ++
  229. str " | " ++ pp_pat env (i,factors) pv))))
  230. | MLfix (i,ids,defs) ->
  231. let ids',env' = push_vars (List.rev (Array.to_list ids)) env in
  232. pp_fix par env' i (Array.of_list (List.rev ids'),defs) args
  233. | MLexn s ->
  234. (* An [MLexn] may be applied, but I don't really care. *)
  235. pp_par par (str "assert false" ++ spc () ++ str ("(* "^s^" *)"))
  236. | MLdummy ->
  237. str "__" (* An [MLdummy] may be applied, but I don't really care. *)
  238. | MLmagic a ->
  239. pp_apply (str "Obj.magic") par (pp_expr true env [] a :: args)
  240. | MLaxiom ->
  241. pp_par par (str "failwith \"AXIOM TO BE REALIZED\"")
  242. and pp_record_pat (projs, args) =
  243. str "{ " ++
  244. prlist_with_sep (fun () -> str ";" ++ spc ())
  245. (fun (r,a) -> pp_global Term r ++ str " =" ++ spc () ++ a)
  246. (List.combine projs args) ++
  247. str " }"
  248. and pp_ifthenelse par env expr pv = match pv with
  249. | [|(tru,[],the);(fal,[],els)|] when
  250. (find_custom tru = "true") && (find_custom fal = "false")
  251. ->
  252. hv 0 (hov 2 (str "if " ++ expr) ++ spc () ++
  253. hov 2 (str "then " ++
  254. hov 2 (pp_expr (expr_needs_par the) env [] the)) ++ spc () ++
  255. hov 2 (str "else " ++
  256. hov 2 (pp_expr (expr_needs_par els) env [] els)))
  257. | _ -> raise Not_found
  258. and pp_one_pat env i (r,ids,t) =
  259. let ids,env' = push_vars (List.rev ids) env in
  260. let expr = pp_expr (expr_needs_par t) env' [] t in
  261. try
  262. let projs = find_projections i in
  263. pp_record_pat (projs, List.rev_map pr_id ids), expr
  264. with NoRecord ->
  265. (match List.rev ids with
  266. | [i1;i2] when is_infix r ->
  267. pr_id i1 ++ str " " ++ str (get_infix r) ++ str " " ++ pr_id i2
  268. | [] -> pp_global Cons r
  269. | ids -> pp_global Cons r ++ str " " ++ pp_boxed_tuple pr_id ids),
  270. expr
  271. and pp_pat env (info,factors) pv =
  272. prvecti
  273. (fun i x -> if List.mem i factors then mt () else
  274. let s1,s2 = pp_one_pat env info x in
  275. hov 2 (s1 ++ str " ->" ++ spc () ++ s2) ++
  276. (if factors = [] && i = Array.length pv-1 then mt ()
  277. else fnl () ++ str " | ")) pv
  278. ++
  279. match factors with
  280. | [] -> mt ()
  281. | i::_ ->
  282. let (_,ids,t) = pv.(i) in
  283. let t = ast_lift (-List.length ids) t in
  284. hov 2 (str "_ ->" ++ spc () ++ pp_expr (expr_needs_par t) env [] t)
  285. and pp_function env t =
  286. let bl,t' = collect_lams t in
  287. let bl,env' = push_vars bl env in
  288. match t' with
  289. | MLcase(i,MLrel 1,pv) when fst i=Standard ->
  290. if not (ast_occurs 1 (MLcase(i,MLdummy,pv))) then
  291. pr_binding (List.rev (List.tl bl)) ++
  292. str " = function" ++ fnl () ++
  293. v 0 (str " | " ++ pp_pat env' i pv)
  294. else
  295. pr_binding (List.rev bl) ++
  296. str " = match " ++ pr_id (List.hd bl) ++ str " with" ++ fnl () ++
  297. v 0 (str " | " ++ pp_pat env' i pv)
  298. | _ ->
  299. pr_binding (List.rev bl) ++
  300. str " =" ++ fnl () ++ str " " ++
  301. hov 2 (pp_expr false env' [] t')
  302. (*s names of the functions ([ids]) are already pushed in [env],
  303. and passed here just for convenience. *)
  304. and pp_fix par env i (ids,bl) args =
  305. pp_par par
  306. (v 0 (str "let rec " ++
  307. prvect_with_sep
  308. (fun () -> fnl () ++ str "and ")
  309. (fun (fi,ti) -> pr_id fi ++ pp_function env ti)
  310. (array_map2 (fun id b -> (id,b)) ids bl) ++
  311. fnl () ++
  312. hov 2 (str "in " ++ pp_apply (pr_id ids.(i)) false args)))
  313. let pp_val e typ =
  314. hov 4 (str "(** val " ++ e ++ str " :" ++ spc () ++ pp_type false [] typ ++
  315. str " **)") ++ fnl2 ()
  316. (*s Pretty-printing of [Dfix] *)
  317. let pp_Dfix (rv,c,t) =
  318. let names = Array.map
  319. (fun r -> if is_inline_custom r then mt () else pp_global Term r) rv
  320. in
  321. let rec pp sep letand i =
  322. if i >= Array.length rv then mt ()
  323. else if is_inline_custom rv.(i) then pp sep letand (i+1)
  324. else
  325. let def =
  326. if is_custom rv.(i) then str " = " ++ str (find_custom rv.(i))
  327. else pp_function (empty_env ()) c.(i)
  328. in
  329. sep () ++ pp_val names.(i) t.(i) ++
  330. str letand ++ names.(i) ++ def ++ pp fnl2 "and " (i+1)
  331. in pp mt "let rec " 0
  332. (*s Pretty-printing of inductive types declaration. *)
  333. let pp_equiv param_list name = function
  334. | NoEquiv, _ -> mt ()
  335. | Equiv kn, i ->
  336. str " = " ++ pp_parameters param_list ++ pp_global Type (IndRef (kn,i))
  337. | RenEquiv ren, _ ->
  338. str " = " ++ pp_parameters param_list ++ str (ren^".") ++ name
  339. let pp_comment s = str "(* " ++ s ++ str " *)"
  340. let pp_one_ind prefix ip_equiv pl name cnames ctyps =
  341. let pl = rename_tvars keywords pl in
  342. let pp_constructor i typs =
  343. (if i=0 then mt () else fnl ()) ++
  344. hov 5 (str " | " ++ cnames.(i) ++
  345. (if typs = [] then mt () else str " of ") ++
  346. prlist_with_sep
  347. (fun () -> spc () ++ str "* ") (pp_type true pl) typs)
  348. in
  349. pp_parameters pl ++ str prefix ++ name ++
  350. pp_equiv pl name ip_equiv ++ str " =" ++
  351. if Array.length ctyps = 0 then str " unit (* empty inductive *)"
  352. else fnl () ++ v 0 (prvecti pp_constructor ctyps)
  353. let pp_logical_ind packet =
  354. pp_comment (pr_id packet.ip_typename ++ str " : logical inductive") ++
  355. fnl () ++
  356. pp_comment (str "with constructors : " ++
  357. prvect_with_sep spc pr_id packet.ip_consnames) ++
  358. fnl ()
  359. let pp_singleton kn packet =
  360. let name = pp_global Type (IndRef (kn,0)) in
  361. let l = rename_tvars keywords packet.ip_vars in
  362. hov 2 (str "type " ++ pp_parameters l ++ name ++ str " =" ++ spc () ++
  363. pp_type false l (List.hd packet.ip_types.(0)) ++ fnl () ++
  364. pp_comment (str "singleton inductive, whose constructor was " ++
  365. pr_id packet.ip_consnames.(0)))
  366. let pp_record kn projs ip_equiv packet =
  367. let name = pp_global Type (IndRef (kn,0)) in
  368. let projnames = List.map (pp_global Term) projs in
  369. let l = List.combine projnames packet.ip_types.(0) in
  370. let pl = rename_tvars keywords packet.ip_vars in
  371. str "type " ++ pp_parameters pl ++ name ++
  372. pp_equiv pl name ip_equiv ++ str " = { "++
  373. hov 0 (prlist_with_sep (fun () -> str ";" ++ spc ())
  374. (fun (p,t) -> p ++ str " : " ++ pp_type true pl t) l)
  375. ++ str " }"
  376. let pp_coind pl name =
  377. let pl = rename_tvars keywords pl in
  378. pp_parameters pl ++ name ++ str " = " ++
  379. pp_parameters pl ++ str "__" ++ name ++ str " Lazy.t" ++
  380. fnl() ++ str "and "
  381. let pp_ind co kn ind =
  382. let prefix = if co then "__" else "" in
  383. let some = ref false in
  384. let init= ref (str "type ") in
  385. let names =
  386. Array.mapi (fun i p -> if p.ip_logical then mt () else
  387. pp_global Type (IndRef (kn,i)))
  388. ind.ind_packets
  389. in
  390. let cnames =
  391. Array.mapi
  392. (fun i p -> if p.ip_logical then [||] else
  393. Array.mapi (fun j _ -> pp_global Cons (ConstructRef ((kn,i),j+1)))
  394. p.ip_types)
  395. ind.ind_packets
  396. in
  397. let rec pp i =
  398. if i >= Array.length ind.ind_packets then mt ()
  399. else
  400. let ip = (kn,i) in
  401. let ip_equiv = ind.ind_equiv, i in
  402. let p = ind.ind_packets.(i) in
  403. if is_custom (IndRef ip) then pp (i+1)
  404. else begin
  405. some := true;
  406. if p.ip_logical then pp_logical_ind p ++ pp (i+1)
  407. else
  408. let s = !init in
  409. begin
  410. init := (fnl () ++ str "and ");
  411. s ++
  412. (if co then pp_coind p.ip_vars names.(i) else mt ()) ++
  413. pp_one_ind
  414. prefix ip_equiv p.ip_vars names.(i) cnames.(i) p.ip_types ++
  415. pp (i+1)
  416. end
  417. end
  418. in
  419. let st = pp 0 in if !some then st else failwith "empty phrase"
  420. (*s Pretty-printing of a declaration. *)
  421. let pp_mind kn i =
  422. match i.ind_info with
  423. | Singleton -> pp_singleton kn i.ind_packets.(0)
  424. | Coinductive -> pp_ind true kn i
  425. | Record projs ->
  426. pp_record kn projs (i.ind_equiv,0) i.ind_packets.(0)
  427. | Standard -> pp_ind false kn i
  428. let pp_decl = function
  429. | Dtype (r,_,_) when is_inline_custom r -> failwith "empty phrase"
  430. | Dterm (r,_,_) when is_inline_custom r -> failwith "empty phrase"
  431. | Dind (kn,i) -> pp_mind kn i
  432. | Dtype (r, l, t) ->
  433. let name = pp_global Type r in
  434. let l = rename_tvars keywords l in
  435. let ids, def =
  436. try
  437. let ids,s = find_type_custom r in
  438. pp_string_parameters ids, str "=" ++ spc () ++ str s
  439. with Not_found ->
  440. pp_parameters l,
  441. if t = Taxiom then str "(* AXIOM TO BE REALIZED *)"
  442. else str "=" ++ spc () ++ pp_type false l t
  443. in
  444. hov 2 (str "type " ++ ids ++ name ++ spc () ++ def)
  445. | Dterm (r, a, t) ->
  446. let def =
  447. if is_custom r then str (" = " ^ find_custom r)
  448. else if is_projection r then
  449. (prvect str (Array.make (projection_arity r) " _")) ++
  450. str " x = x."
  451. else pp_function (empty_env ()) a
  452. in
  453. let name = pp_global Term r in
  454. let postdef = if is_projection r then name else mt () in
  455. pp_val name t ++ hov 0 (str "let " ++ name ++ def ++ postdef)
  456. | Dfix (rv,defs,typs) ->
  457. pp_Dfix (rv,defs,typs)
  458. let pp_alias_decl ren = function
  459. | Dind (kn,i) -> pp_mind kn { i with ind_equiv = RenEquiv ren }
  460. | Dtype (r, l, _) ->
  461. let name = pp_global Type r in
  462. let l = rename_tvars keywords l in
  463. let ids = pp_parameters l in
  464. hov 2 (str "type " ++ ids ++ name ++ str " =" ++ spc () ++ ids ++
  465. str (ren^".") ++ name)
  466. | Dterm (r, a, t) ->
  467. let name = pp_global Term r in
  468. hov 2 (str "let " ++ name ++ str (" = "^ren^".") ++ name)
  469. | Dfix (rv, _, _) ->
  470. prvecti (fun i r -> if is_inline_custom r then mt () else
  471. let name = pp_global Term r in
  472. hov 2 (str "let " ++ name ++ str (" = "^ren^".") ++ name) ++
  473. fnl ())
  474. rv
  475. let pp_spec = function
  476. | Sval (r,_) when is_inline_custom r -> failwith "empty phrase"
  477. | Stype (r,_,_) when is_inline_custom r -> failwith "empty phrase"
  478. | Sind (kn,i) -> pp_mind kn i
  479. | Sval (r,t) ->
  480. let def = pp_type false [] t in
  481. let name = pp_global Term r in
  482. hov 2 (str "val " ++ name ++ str " :" ++ spc () ++ def)
  483. | Stype (r,vl,ot) ->
  484. let name = pp_global Type r in
  485. let l = rename_tvars keywords vl in
  486. let ids, def =
  487. try
  488. let ids, s = find_type_custom r in
  489. pp_string_parameters ids, str "= " ++ str s
  490. with Not_found ->
  491. let ids = pp_parameters l in
  492. match ot with
  493. | None -> ids, mt ()
  494. | Some Taxiom -> ids, str "(* AXIOM TO BE REALIZED *)"
  495. | Some t -> ids, str "=" ++ spc () ++ pp_type false l t
  496. in
  497. hov 2 (str "type " ++ ids ++ name ++ spc () ++ def)
  498. let pp_alias_spec ren = function
  499. | Sind (kn,i) -> pp_mind kn { i with ind_equiv = RenEquiv ren }
  500. | Stype (r,l,_) ->
  501. let name = pp_global Type r in
  502. let l = rename_tvars keywords l in
  503. let ids = pp_parameters l in
  504. hov 2 (str "type " ++ ids ++ name ++ str " =" ++ spc () ++ ids ++
  505. str (ren^".") ++ name)
  506. | Sval _ -> assert false
  507. let rec pp_specif = function
  508. | (_,Spec (Sval _ as s)) -> pp_spec s
  509. | (l,Spec s) ->
  510. (try
  511. let ren = Common.check_duplicate (top_visible_mp ()) l in
  512. hov 1 (str ("module "^ren^" : sig ") ++ fnl () ++ pp_spec s) ++
  513. fnl () ++ str "end" ++ fnl () ++
  514. pp_alias_spec ren s
  515. with Not_found -> pp_spec s)
  516. | (l,Smodule mt) ->
  517. let def = pp_module_type (Some l) mt in
  518. let def' = pp_module_type (Some l) mt in
  519. let name = pp_modname (MPdot (top_visible_mp (), l)) in
  520. hov 1 (str "module " ++ name ++ str " : " ++ fnl () ++ def) ++
  521. (try
  522. let ren = Common.check_duplicate (top_visible_mp ()) l in
  523. fnl () ++ hov 1 (str ("module "^ren^" : ") ++ fnl () ++ def')
  524. with Not_found -> Pp.mt ())
  525. | (l,Smodtype mt) ->
  526. let def = pp_module_type None mt in
  527. let name = pp_modname (MPdot (top_visible_mp (), l)) in
  528. hov 1 (str "module type " ++ name ++ str " = " ++ fnl () ++ def) ++
  529. (try
  530. let ren = Common.check_duplicate (top_visible_mp ()) l in
  531. fnl () ++ str ("module type "^ren^" = ") ++ name
  532. with Not_found -> Pp.mt ())
  533. and pp_module_type ol = function
  534. | MTident kn ->
  535. pp_modname kn
  536. | MTfunsig (mbid, mt, mt') ->
  537. let typ = pp_module_type None mt in
  538. let name = pp_modname (MPbound mbid) in
  539. let def = pp_module_type None mt' in
  540. str "functor (" ++ name ++ str ":" ++ typ ++ str ") ->" ++ fnl () ++ def
  541. | MTsig (msid, sign) ->
  542. let tvm = top_visible_mp () in
  543. let mp = match ol with None -> MPself msid | Some l -> MPdot (tvm,l) in
  544. (* References in [sign] are in short form (relative to [msid]).
  545. In push_visible, [msid-->mp] is added to the current subst. *)
  546. push_visible mp (Some msid);
  547. let l = map_succeed pp_specif sign in
  548. pop_visible ();
  549. str "sig " ++ fnl () ++
  550. v 1 (str " " ++ prlist_with_sep fnl2 identity l) ++
  551. fnl () ++ str "end"
  552. | MTwith(mt,ML_With_type(idl,vl,typ)) ->
  553. let ids = pp_parameters (rename_tvars keywords vl) in
  554. let mp_mt = msid_of_mt mt in
  555. let l,idl' = list_sep_last idl in
  556. let mp_w =
  557. List.fold_left (fun mp l -> MPdot(mp,label_of_id l)) mp_mt idl'
  558. in
  559. let r = ConstRef (make_con mp_w empty_dirpath (label_of_id l))
  560. in
  561. push_visible mp_mt None;
  562. let s =
  563. pp_module_type None mt ++ str " with type " ++
  564. pp_global Type r ++ ids
  565. in
  566. pop_visible();
  567. s ++ str "=" ++ spc () ++ pp_type false vl typ
  568. | MTwith(mt,ML_With_module(idl,mp)) ->
  569. let mp_mt = msid_of_mt mt in
  570. let mp_w =
  571. List.fold_left (fun mp id -> MPdot(mp,label_of_id id)) mp_mt idl
  572. in
  573. push_visible mp_mt None;
  574. let s =
  575. pp_module_type None mt ++ str " with module " ++ pp_modname mp_w
  576. in
  577. pop_visible ();
  578. s ++ str " = " ++ pp_modname mp
  579. let is_short = function MEident _ | MEapply _ -> true | _ -> false
  580. let rec pp_structure_elem = function
  581. | (l,SEdecl d) ->
  582. (try
  583. let ren = Common.check_duplicate (top_visible_mp ()) l in
  584. hov 1 (str ("module "^ren^" = struct ") ++ fnl () ++ pp_decl d) ++
  585. fnl () ++ str "end" ++ fnl () ++
  586. pp_alias_decl ren d
  587. with Not_found -> pp_decl d)
  588. | (l,SEmodule m) ->
  589. let typ =
  590. (* virtual printing of the type, in order to have a correct mli later*)
  591. if Common.get_phase () = Pre then
  592. str ": " ++ pp_module_type (Some l) m.ml_mod_type
  593. else mt ()
  594. in
  595. let def = pp_module_expr (Some l) m.ml_mod_expr in
  596. let name = pp_modname (MPdot (top_visible_mp (), l)) in
  597. hov 1
  598. (str "module " ++ name ++ typ ++ str " = " ++
  599. (if (is_short m.ml_mod_expr) then mt () else fnl ()) ++ def) ++
  600. (try
  601. let ren = Common.check_duplicate (top_visible_mp ()) l in
  602. fnl () ++ str ("module "^ren^" = ") ++ name
  603. with Not_found -> mt ())
  604. | (l,SEmodtype m) ->
  605. let def = pp_module_type None m in
  606. let name = pp_modname (MPdot (top_visible_mp (), l)) in
  607. hov 1 (str "module type " ++ name ++ str " = " ++ fnl () ++ def) ++
  608. (try
  609. let ren = Common.check_duplicate (top_visible_mp ()) l in
  610. fnl () ++ str ("module type "^ren^" = ") ++ name
  611. with Not_found -> mt ())
  612. and pp_module_expr ol = function
  613. | MEident mp' -> pp_modname mp'
  614. | MEfunctor (mbid, mt, me) ->
  615. let name = pp_modname (MPbound mbid) in
  616. let typ = pp_module_type None mt in
  617. let def = pp_module_expr None me in
  618. str "functor (" ++ name ++ str ":" ++ typ ++ str ") ->" ++ fnl () ++ def
  619. | MEapply (me, me') ->
  620. pp_module_expr None me ++ str "(" ++ pp_module_expr None me' ++ str ")"
  621. | MEstruct (msid, sel) ->
  622. let tvm = top_visible_mp () in
  623. let mp = match ol with None -> MPself msid | Some l -> MPdot (tvm,l) in
  624. (* No need to update the subst with [Some msid] below : names are
  625. already in long form (see [subst_structure] in [Extract_env]). *)
  626. push_visible mp None;
  627. let l = map_succeed pp_structure_elem sel in
  628. pop_visible ();
  629. str "struct " ++ fnl () ++
  630. v 1 (str " " ++ prlist_with_sep fnl2 identity l) ++
  631. fnl () ++ str "end"
  632. let do_struct f s =
  633. let pp s = try f s ++ fnl2 () with Failure "empty phrase" -> mt ()
  634. in
  635. let ppl (mp,sel) =
  636. push_visible mp None;
  637. let p = prlist_strict pp sel in
  638. (* for monolithic extraction, we try to simulate the unavailability
  639. of [MPfile] in names by artificially nesting these [MPfile] *)
  640. (if modular () then pop_visible ()); p
  641. in
  642. let p = prlist_strict ppl s in
  643. (if not (modular ()) then repeat (List.length s) pop_visible ());
  644. p
  645. let pp_struct s = do_struct pp_structure_elem s
  646. let pp_signature s = do_struct pp_specif s
  647. let pp_decl d = try pp_decl d with Failure "empty phrase" -> mt ()
  648. let ocaml_descr = {
  649. keywords = keywords;
  650. file_suffix = ".ml";
  651. capital_file = false;
  652. preamble = preamble;
  653. pp_struct = pp_struct;
  654. sig_suffix = Some ".mli";
  655. sig_preamble = sig_preamble;
  656. pp_sig = pp_signature;
  657. pp_decl = pp_decl;
  658. }