genxml.ml 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558
  1. (*
  2. The Haxe Compiler
  3. Copyright (C) 2005-2015 Haxe Foundation
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  15. *)
  16. open Ast
  17. open Type
  18. open Common
  19. open ExtString
  20. type xml =
  21. | Node of string * (string * string) list * xml list
  22. | PCData of string
  23. | CData of string
  24. let tag name = Node (name,[],[])
  25. let xml name att = Node (name,att,[])
  26. let node name att childs = Node (name,att,childs)
  27. let pcdata s = PCData s
  28. let cdata s = CData s
  29. let pmap f m =
  30. PMap.fold (fun x acc -> f x :: acc) m []
  31. let gen_path (p,n) priv =
  32. ("path",String.concat "." (p @ [n]))
  33. let gen_string s =
  34. if String.contains s '<' || String.contains s '>' || String.contains s '&' then cdata s else pcdata s
  35. let gen_doc s =
  36. (* remove trailing space and convert newlines *)
  37. let s = ExtString.String.strip s in
  38. let s = String.concat "\n" (ExtString.String.nsplit (String.concat "\n" (ExtString.String.nsplit s "\r\n")) "\r") in
  39. node "haxe_doc" [] [gen_string s]
  40. let gen_doc_opt d =
  41. match d with
  42. | None -> []
  43. | Some s -> [gen_doc s]
  44. let gen_arg_name (name,opt,_) =
  45. (if opt then "?" else "") ^ name
  46. let real_path path meta =
  47. let rec loop = function
  48. | [] -> path
  49. | (Meta.RealPath,[(Ast.EConst (Ast.String s),_)],_) :: _ -> parse_path s
  50. | _ :: l -> loop l
  51. in
  52. loop meta
  53. let tpath t =
  54. let i = t_infos t in
  55. real_path i.mt_path i.mt_meta
  56. let rec follow_param t =
  57. match t with
  58. | TMono r ->
  59. (match !r with
  60. | Some t -> follow_param t
  61. | _ -> t)
  62. | TType ({ t_path = [],"Null" } as t,tl) ->
  63. follow_param (apply_params t.t_params tl t.t_type)
  64. | _ ->
  65. t
  66. let gen_meta meta =
  67. let meta = List.filter (fun (m,_,_) -> match m with Meta.Used | Meta.MaybeUsed | Meta.RealPath -> false | _ -> true) meta in
  68. match meta with
  69. | [] -> []
  70. | _ ->
  71. let nodes = List.map (fun (m,el,_) ->
  72. node "m" ["n",fst (MetaInfo.to_string m)] (List.map (fun e -> node "e" [] [gen_string (Ast.s_expr e)]) el)
  73. ) meta in
  74. [node "meta" [] nodes]
  75. let rec gen_type ?(values=None) t =
  76. match t with
  77. | TMono m -> (match !m with None -> tag "unknown" | Some t -> gen_type t)
  78. | TEnum (e,params) -> gen_type_decl "e" (TEnumDecl e) params
  79. | TInst (c,params) -> gen_type_decl "c" (TClassDecl c) params
  80. | TAbstract (a,params) -> gen_type_decl "x" (TAbstractDecl a) params
  81. | TType (t,params) -> gen_type_decl "t" (TTypeDecl t) params
  82. | TFun (args,r) ->
  83. let names = String.concat ":" (List.map gen_arg_name args) in
  84. let values = match values with
  85. | None -> []
  86. | Some values ->
  87. let has_value = ref false in
  88. let values = List.map (fun (n,_,_) ->
  89. try
  90. let e = PMap.find n values in
  91. has_value := true;
  92. let s = Ast.s_expr e in
  93. s
  94. with Not_found ->
  95. ""
  96. ) args in
  97. if !has_value then
  98. ["v",String.concat ":" values]
  99. else
  100. []
  101. in
  102. let args = List.map (fun (_,opt,t) ->
  103. if opt then follow_param t else t
  104. ) args in
  105. node "f" (("a",names) :: values) (List.map gen_type (args @ [r]))
  106. | TAnon a -> node "a" [] (pmap (fun f -> gen_field [] { f with cf_public = false }) a.a_fields)
  107. | TDynamic t2 -> node "d" [] (if t == t2 then [] else [gen_type t2])
  108. | TLazy f -> gen_type (!f())
  109. and gen_type_decl n t pl =
  110. let i = t_infos t in
  111. node n [gen_path (tpath t) i.mt_private] (List.map gen_type pl)
  112. and gen_field att f =
  113. let add_get_set acc name att =
  114. match acc with
  115. | AccNormal | AccResolve | AccRequire _ -> att
  116. | AccNo | AccNever -> (name, "null") :: att
  117. | AccCall -> (name,"accessor") :: att
  118. | AccInline -> (name,"inline") :: att
  119. in
  120. let att = (match f.cf_expr with None -> att | Some e -> ("line",string_of_int (Lexer.get_error_line e.epos)) :: att) in
  121. let att,values = (match f.cf_kind with
  122. | Var v ->
  123. let att = try
  124. begin match Meta.get Meta.Value f.cf_meta with
  125. | (_,[e],_) -> ("expr",Ast.s_expr e) :: att
  126. | _ -> att
  127. end
  128. with Not_found ->
  129. att
  130. in
  131. add_get_set v.v_read "get" (add_get_set v.v_write "set" att),PMap.empty
  132. | Method m ->
  133. let att = match m with
  134. | MethNormal | MethMacro -> ("set", "method") :: att
  135. | MethDynamic -> ("set", "dynamic") :: att
  136. | MethInline -> ("get", "inline") :: ("set","null") :: att
  137. in
  138. att,get_value_meta f.cf_meta
  139. ) in
  140. let att = (match f.cf_params with [] -> att | l -> ("params", String.concat ":" (List.map (fun (n,_) -> n) l)) :: att) in
  141. let overloads = match List.map (gen_field []) f.cf_overloads with
  142. | [] -> []
  143. | nl -> [node "overloads" [] nl]
  144. in
  145. let field_name cf =
  146. try
  147. begin match Meta.get Meta.RealPath cf.cf_meta with
  148. | _,[EConst (String (s)),_],_ -> s
  149. | _ -> raise Not_found
  150. end;
  151. with Not_found ->
  152. cf.cf_name
  153. in
  154. node (field_name f) (if f.cf_public then ("public","1") :: att else att) (gen_type ~values:(Some values) f.cf_type :: gen_meta f.cf_meta @ gen_doc_opt f.cf_doc @ overloads)
  155. let gen_constr e =
  156. let doc = gen_doc_opt e.ef_doc in
  157. let args, t = (match follow e.ef_type with
  158. | TFun (args,_) ->
  159. ["a",String.concat ":" (List.map gen_arg_name args)] ,
  160. List.map (fun (_,opt,t) -> gen_type (if opt then follow_param t else t)) args @ doc
  161. | _ ->
  162. [] , doc
  163. ) in
  164. node e.ef_name args (t @ gen_meta e.ef_meta)
  165. let gen_ordered_constr e =
  166. let rec loop el = match el with
  167. | n :: el ->
  168. gen_constr (PMap.find n e.e_constrs) :: loop el
  169. | [] ->
  170. []
  171. in
  172. loop e.e_names
  173. let gen_type_params ipos priv path params pos m =
  174. let mpriv = (if priv then [("private","1")] else []) in
  175. let mpath = (if m.m_path <> path then [("module",snd (gen_path m.m_path false))] else []) in
  176. let file = (if ipos && pos <> null_pos then [("file",pos.pfile)] else []) in
  177. gen_path path priv :: ("params", String.concat ":" (List.map fst params)) :: (file @ mpriv @ mpath)
  178. let gen_class_path name (c,pl) =
  179. node name [("path",s_type_path (tpath (TClassDecl c)))] (List.map gen_type pl)
  180. let rec exists f c =
  181. PMap.exists f.cf_name c.cl_fields ||
  182. match c.cl_super with
  183. | None -> false
  184. | Some (csup,_) -> exists f csup
  185. let rec gen_type_decl com pos t =
  186. let m = (t_infos t).mt_module in
  187. match t with
  188. | TClassDecl c ->
  189. let stats = List.filter (fun cf ->
  190. cf.cf_name <> "__meta__" && not (Meta.has Meta.GenericInstance cf.cf_meta)
  191. ) c.cl_ordered_statics in
  192. let stats = List.map (gen_field ["static","1"]) stats in
  193. let fields = List.filter (fun cf ->
  194. not (Meta.has Meta.GenericInstance cf.cf_meta)
  195. ) c.cl_ordered_fields in
  196. let fields = (match c.cl_super with
  197. | None -> List.map (fun f -> f,[]) fields
  198. | Some (csup,_) -> List.map (fun f -> if exists f csup then (f,["override","1"]) else (f,[])) fields
  199. ) in
  200. let fields = List.map (fun (f,att) -> gen_field att f) fields in
  201. let constr = (match c.cl_constructor with None -> [] | Some f -> [gen_field [] f]) in
  202. let impl = List.map (gen_class_path (if c.cl_interface then "extends" else "implements")) c.cl_implements in
  203. let tree = (match c.cl_super with
  204. | None -> impl
  205. | Some x -> gen_class_path "extends" x :: impl
  206. ) in
  207. let doc = gen_doc_opt c.cl_doc in
  208. let meta = gen_meta c.cl_meta in
  209. let ext = (if c.cl_extern then [("extern","1")] else []) in
  210. let interf = (if c.cl_interface then [("interface","1")] else []) in
  211. let dynamic = (match c.cl_dynamic with
  212. | None -> []
  213. | Some t -> [node "haxe_dynamic" [] [gen_type t]]
  214. ) in
  215. node "class" (gen_type_params pos c.cl_private (tpath t) c.cl_params c.cl_pos m @ ext @ interf) (tree @ stats @ fields @ constr @ doc @ meta @ dynamic)
  216. | TEnumDecl e ->
  217. let doc = gen_doc_opt e.e_doc in
  218. let meta = gen_meta e.e_meta in
  219. node "enum" (gen_type_params pos e.e_private (tpath t) e.e_params e.e_pos m) (gen_ordered_constr e @ doc @ meta)
  220. | TTypeDecl t ->
  221. let doc = gen_doc_opt t.t_doc in
  222. let meta = gen_meta t.t_meta in
  223. let tt = gen_type t.t_type in
  224. node "typedef" (gen_type_params pos t.t_private t.t_path t.t_params t.t_pos m) (tt :: doc @ meta)
  225. | TAbstractDecl a ->
  226. let doc = gen_doc_opt a.a_doc in
  227. let meta = gen_meta a.a_meta in
  228. let mk_cast t = node "icast" [] [gen_type t] in
  229. let mk_field_cast (t,cf) = node "icast" ["field",cf.cf_name] [gen_type t] in
  230. let sub = (match a.a_from,a.a_from_field with [],[] -> [] | l1,l2 -> [node "from" [] ((List.map mk_cast l1) @ (List.map mk_field_cast l2))]) in
  231. let super = (match a.a_to,a.a_to_field with [],[] -> [] | l1,l2 -> [node "to" [] ((List.map mk_cast l1) @ (List.map mk_field_cast l2))]) in
  232. let impl = (match a.a_impl with None -> [] | Some c -> [node "impl" [] [gen_type_decl com pos (TClassDecl c)]]) in
  233. let this = [node "this" [] [gen_type a.a_this]] in
  234. node "abstract" (gen_type_params pos a.a_private (tpath t) a.a_params a.a_pos m) (sub @ this @ super @ doc @ meta @ impl)
  235. let escape_entities s =
  236. Xml.to_string (Xml.PCData s)
  237. let att_str att =
  238. String.concat "" (List.map (fun (a,v) -> Printf.sprintf " %s=\"%s\"" a (escape_entities v)) att)
  239. let rec write_xml ch tabs x =
  240. match x with
  241. | Node (name,att,[]) ->
  242. IO.printf ch "%s<%s%s/>" tabs name (att_str att)
  243. | Node (name,att,[x]) ->
  244. IO.printf ch "%s<%s%s>" tabs name (att_str att);
  245. write_xml ch "" x;
  246. IO.printf ch "</%s>" name;
  247. | Node (name,att,childs) ->
  248. IO.printf ch "%s<%s%s>\n" tabs name (att_str att);
  249. List.iter (fun x ->
  250. write_xml ch (tabs ^ "\t") x;
  251. IO.printf ch "\n";
  252. ) childs;
  253. IO.printf ch "%s</%s>" tabs name
  254. | PCData s ->
  255. IO.printf ch "%s" s
  256. | CData s ->
  257. IO.printf ch "<![CDATA[%s]]>" s
  258. let generate com file =
  259. let t = Common.timer "construct xml" in
  260. let x = node "haxe" [] (List.map (gen_type_decl com true) (List.filter (fun t -> not (Meta.has Meta.NoDoc (t_infos t).mt_meta)) com.types)) in
  261. t();
  262. let t = Common.timer "write xml" in
  263. let ch = IO.output_channel (open_out_bin file) in
  264. write_xml ch "" x;
  265. IO.close_out ch;
  266. t()
  267. let gen_type_string ctx t =
  268. let x = gen_type_decl ctx false t in
  269. let ch = IO.output_string() in
  270. write_xml ch "" x;
  271. IO.close_out ch
  272. (* -------------------------------------------------------------------------- *)
  273. (* PRINT HX FROM TYPE *)
  274. let rec create_dir acc = function
  275. | [] -> ()
  276. | d :: l ->
  277. let path = acc ^ "/" ^ d in
  278. (try Unix.mkdir path 0o777 with _ -> ());
  279. create_dir path l
  280. let conv_path p =
  281. match List.rev (fst p) with
  282. | x :: l when x.[0] = '_' -> List.rev (("priv" ^ x) :: l), snd p
  283. | _ -> p
  284. let get_real_path meta path =
  285. try
  286. let real_path = match Meta.get Meta.RealPath meta with
  287. | (_,[(EConst(String s),_)],_) ->
  288. s
  289. | _ -> raise Not_found
  290. in
  291. match List.rev (String.nsplit real_path ".") with
  292. | name :: pack ->
  293. (List.rev pack), name
  294. | _ -> raise Not_found
  295. with | Not_found ->
  296. path
  297. let generate_type com t =
  298. let base_path = "hxclasses" in
  299. let pack, name =
  300. let info = t_infos t in
  301. get_real_path info.mt_meta info.mt_path
  302. in
  303. create_dir "." (base_path :: pack);
  304. match pack, name with
  305. | ["flash";"net"], "NetStreamPlayTransitions"
  306. | ["flash";"filters"], "BitmapFilterQuality"
  307. | ["flash";"display"], ("BitmapDataChannel" | "GraphicsPathCommand") -> ()
  308. | _ ->
  309. let f = open_out_bin (base_path ^ "/" ^ (match pack with [] -> "" | l -> String.concat "/" l ^ "/") ^ name ^ ".hx") in
  310. let ch = IO.output_channel f in
  311. let p fmt = IO.printf ch fmt in
  312. if pack <> [] then IO.printf ch "package %s;\n\n" (String.concat "." pack);
  313. let rec notnull t =
  314. match t with
  315. | TMono r ->
  316. (match !r with
  317. | None -> t
  318. | Some t -> notnull t)
  319. | TLazy f ->
  320. notnull ((!f)())
  321. | TType ({ t_path = [],"Null" },[t]) ->
  322. t
  323. | _ ->
  324. t
  325. in
  326. let rec path meta p tl =
  327. let p = conv_path (get_real_path meta p) in
  328. (if fst p = pack then snd p else s_type_path p) ^ (match tl with [] -> "" | _ -> "<" ^ String.concat "," (List.map stype tl) ^ ">")
  329. and stype t =
  330. match t with
  331. | TMono r ->
  332. (match !r with
  333. | None -> "Unknown"
  334. | Some t -> stype t)
  335. | TInst ({ cl_kind = KTypeParameter _ } as c,tl) ->
  336. path [] ([],snd c.cl_path) tl
  337. | TInst (c,tl) ->
  338. path c.cl_meta c.cl_path tl
  339. | TEnum (e,tl) ->
  340. path e.e_meta e.e_path tl
  341. | TType (t,tl) ->
  342. path t.t_meta t.t_path tl
  343. | TAbstract (a,tl) ->
  344. path a.a_meta a.a_path tl
  345. | TAnon a ->
  346. let fields = PMap.fold (fun f acc -> (f.cf_name ^ " : " ^ stype f.cf_type) :: acc) a.a_fields [] in
  347. "{" ^ String.concat ", " fields ^ "}"
  348. | TLazy f ->
  349. stype ((!f)())
  350. | TDynamic t2 ->
  351. if t == t2 then "Dynamic" else "Dynamic<" ^ stype t2 ^ ">"
  352. | TFun ([],ret) ->
  353. "Void -> " ^ ftype ret
  354. | TFun (args,ret) ->
  355. String.concat " -> " (List.map (fun (_,_,t) -> ftype t) args) ^ " -> " ^ ftype ret
  356. and ftype t =
  357. match t with
  358. | TMono r ->
  359. (match !r with
  360. | None -> stype t
  361. | Some t -> ftype t)
  362. | TLazy f ->
  363. ftype ((!f)())
  364. | TFun _ ->
  365. "(" ^ stype t ^ ")"
  366. | _ ->
  367. stype t
  368. in
  369. let sparam (n,v,t) =
  370. match v with
  371. | None ->
  372. n ^ " : " ^ stype t
  373. | Some (Ident "null") ->
  374. if is_nullable (notnull t) then
  375. "?" ^ n ^ " : " ^ stype (notnull t)
  376. else
  377. (* we have not found a default value stored in metadata, let's generate it *)
  378. n ^ " : " ^ stype t ^ " = " ^ (match follow t with
  379. | TAbstract ({ a_path = [],("Int"|"Float"|"UInt") },_) -> "0"
  380. | TAbstract ({ a_path = [],"Bool" },_) -> "false"
  381. | _ -> "null")
  382. | Some v ->
  383. n ^ " : " ^ stype t ^ " = " ^ (match s_constant v with "nan" -> "0./*NaN*/" | v -> v)
  384. in
  385. let print_meta ml =
  386. List.iter (fun (m,pl,_) ->
  387. match m with
  388. | Meta.DefParam | Meta.CoreApi | Meta.Used | Meta.MaybeUsed | Meta.FlatEnum | Meta.Value | Meta.DirectlyUsed -> ()
  389. | _ ->
  390. match pl with
  391. | [] -> p "@%s " (fst (MetaInfo.to_string m))
  392. | l -> p "@%s(%s) " (fst (MetaInfo.to_string m)) (String.concat "," (List.map Ast.s_expr pl))
  393. ) ml
  394. in
  395. let access is_read a =
  396. match a, pack with
  397. | AccNever, "flash" :: _ -> "null"
  398. | _ -> s_access is_read a
  399. in
  400. let rec print_field stat f =
  401. p "\t";
  402. print_meta f.cf_meta;
  403. if stat then p "static ";
  404. let name = try (match Meta.get Meta.RealPath f.cf_meta with
  405. | (Meta.RealPath, [EConst( String s ), _], _) ->
  406. s
  407. | _ ->
  408. raise Not_found)
  409. with Not_found ->
  410. f.cf_name
  411. in
  412. (match f.cf_kind with
  413. | Var v ->
  414. p "var %s" name;
  415. if v.v_read <> AccNormal || v.v_write <> AccNormal then p "(%s,%s)" (access true v.v_read) (access false v.v_write);
  416. p " : %s" (stype f.cf_type);
  417. | Method m ->
  418. let params, ret = (match follow f.cf_type with
  419. | TFun (args,ret) ->
  420. List.map (fun (a,o,t) ->
  421. let rec loop = function
  422. | [] -> Ident "null"
  423. | (Meta.DefParam,[(EConst (String p),_);(EConst v,_)],_) :: _ when p = a ->
  424. (match v with
  425. | Float "1.#QNAN" -> Float "0./*NaN*/"
  426. | Float "4294967295." -> Int "0xFFFFFFFF"
  427. | Int "16777215" -> Int "0xFFFFFF"
  428. | Float x ->
  429. (try
  430. let f = float_of_string x in
  431. let s = string_of_int (int_of_float f) in
  432. if s ^ "." = x then Int s else v
  433. with _ ->
  434. v)
  435. | _ -> v)
  436. | _ :: l -> loop l
  437. in
  438. a,(if o then Some (loop f.cf_meta) else None ),t
  439. ) args, ret
  440. | _ ->
  441. assert false
  442. ) in
  443. let tparams = (match f.cf_params with [] -> "" | l -> "<" ^ String.concat "," (List.map fst l) ^ ">") in
  444. p "function %s%s(%s) : %s" name tparams (String.concat ", " (List.map sparam params)) (stype ret);
  445. );
  446. p ";\n";
  447. if Meta.has Meta.Overload f.cf_meta then List.iter (fun f -> print_field stat f) f.cf_overloads
  448. in
  449. (match t with
  450. | TClassDecl c ->
  451. print_meta c.cl_meta;
  452. p "extern %s %s" (if c.cl_interface then "interface" else "class") (stype (TInst (c,List.map snd c.cl_params)));
  453. let ext = (match c.cl_super with
  454. | None -> []
  455. | Some (c,pl) -> [" extends " ^ stype (TInst (c,pl))]
  456. ) in
  457. let ext = List.fold_left (fun acc (i,pl) -> ((if c.cl_interface then " extends " else " implements ") ^ stype (TInst (i,pl))) :: acc) ext c.cl_implements in
  458. let ext = (match c.cl_dynamic with
  459. | None -> ext
  460. | Some t ->
  461. (match c.cl_path with
  462. | ["flash";"errors"], _ -> ext
  463. | _ when t == t_dynamic -> " implements Dynamic" :: ext
  464. | _ -> (" implements Dynamic<" ^ stype t ^ ">") :: ext)
  465. ) in
  466. let ext = (match c.cl_path with
  467. | ["flash";"utils"], "ByteArray" -> " implements ArrayAccess<Int>" :: ext
  468. | ["flash";"utils"], "Dictionnary" -> [" implements ArrayAccess<Dynamic>"]
  469. | ["flash";"xml"], "XML" -> [" implements Dynamic<XMLList>"]
  470. | ["flash";"xml"], "XMLList" -> [" implements ArrayAccess<XML>"]
  471. | ["flash";"display"],"MovieClip" -> [" extends Sprite #if !flash_strict implements Dynamic #end"]
  472. | ["flash";"errors"], "Error" -> [" #if !flash_strict implements Dynamic #end"]
  473. | _ -> ext
  474. ) in
  475. p "%s" (String.concat "" (List.rev ext));
  476. p " {\n";
  477. let sort l =
  478. let a = Array.of_list (List.filter (fun f -> f.cf_public && not (List.memq f c.cl_overrides)) l) in
  479. let name = function "new" -> "" | n -> n in
  480. Array.sort (fun f1 f2 ->
  481. match f1.cf_kind, f2.cf_kind with
  482. | Var _, Var _ | Method _ , Method _ -> compare (name f1.cf_name) (name f2.cf_name)
  483. | Var _, _ -> -1
  484. | _ -> 1
  485. ) a;
  486. Array.to_list a
  487. in
  488. List.iter (print_field false) (sort (match c.cl_constructor with None -> c.cl_ordered_fields | Some f -> f :: c.cl_ordered_fields));
  489. List.iter (print_field true) (sort c.cl_ordered_statics);
  490. p "}\n";
  491. | TEnumDecl e ->
  492. print_meta e.e_meta;
  493. p "extern enum %s {\n" (stype (TEnum(e,List.map snd e.e_params)));
  494. let sort l =
  495. let a = Array.of_list l in
  496. Array.sort compare a;
  497. Array.to_list a
  498. in
  499. List.iter (fun n ->
  500. let c = PMap.find n e.e_constrs in
  501. p "\t%s" c.ef_name;
  502. (match follow c.ef_type with
  503. | TFun (args,_) -> p "(%s)" (String.concat ", " (List.map sparam (List.map (fun (a,o,t) -> a,(if o then Some (Ident "null") else None),t) args)))
  504. | _ -> ());
  505. p ";\n";
  506. ) (if Meta.has Meta.FakeEnum e.e_meta then sort e.e_names else e.e_names);
  507. p "}\n"
  508. | TTypeDecl t ->
  509. print_meta t.t_meta;
  510. p "typedef %s = " (stype (TType (t,List.map snd t.t_params)));
  511. p "%s" (stype t.t_type);
  512. p "\n";
  513. | TAbstractDecl a ->
  514. print_meta a.a_meta;
  515. p "abstract %s {}" (stype (TAbstract (a,List.map snd a.a_params)));
  516. );
  517. IO.close_out ch
  518. let generate_hx com =
  519. List.iter (generate_type com) com.types