prebuild.ml 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. open Json
  2. exception Prebuild_error of string
  3. type parsed_warning = {
  4. w_name : string;
  5. w_doc : string;
  6. w_parent : string option;
  7. w_generic : bool;
  8. }
  9. let as_string = function
  10. | JString s -> Some s
  11. | _ -> None
  12. let as_int = function
  13. | JInt i -> Some i
  14. | _ -> None
  15. let as_params = function
  16. | JArray s -> Some (List.map (function
  17. | JString s -> s
  18. | _ -> raise (Prebuild_error "parameter description should be a string")
  19. ) s)
  20. | _ -> None
  21. let as_platforms = function
  22. | JArray s -> Some (List.map (function
  23. | JString "cross" -> "Cross"
  24. | JString "js" -> "Js"
  25. | JString "lua" -> "Lua"
  26. | JString "neko" -> "Neko"
  27. | JString "flash" -> "Flash"
  28. | JString "php" -> "Php"
  29. | JString "cpp" -> "Cpp"
  30. | JString "cs" -> "Cs"
  31. | JString "java" -> "Java"
  32. | JString "python" -> "Python"
  33. | JString "hl" -> "Hl"
  34. | JString "eval" -> "Eval"
  35. | _ -> raise (Prebuild_error "invalid platform")
  36. ) s)
  37. | _ -> None
  38. let as_targets = function
  39. | JArray s -> Some (List.map (function
  40. | JString "TClass" -> "TClass"
  41. | JString "TClassField" -> "TClassField"
  42. | JString "TAbstract" -> "TAbstract"
  43. | JString "TAbstractField" -> "TAbstractField"
  44. | JString "TEnum" -> "TEnum"
  45. | JString "TTypedef" -> "TTypedef"
  46. | JString "TAnyField" -> "TAnyField"
  47. | JString "TExpr" -> "TExpr"
  48. | JString "TTypeParameter" -> "TTypeParameter"
  49. | _ -> raise (Prebuild_error "invalid metadata target")
  50. ) s)
  51. | _ -> None
  52. let as_bool = function
  53. | JBool b -> Some b
  54. | _ -> None
  55. let as_links = function
  56. | JArray s -> Some (List.map (function
  57. | JString s -> s
  58. | _ -> raise (Prebuild_error "link should be a string")
  59. ) s)
  60. | _ -> None
  61. let get_optional_field name map default fields =
  62. try
  63. let field = List.find (fun (n, _) -> n = name) fields in
  64. let value = map (snd field) in
  65. match value with
  66. | None -> raise (Prebuild_error ("field `" ^ name ^ "` has invalid data"))
  67. | Some v -> v
  68. with Not_found -> default
  69. let get_optional_field2 name map fields =
  70. try
  71. let field = List.find (fun (n, _) -> n = name) fields in
  72. let value = map (snd field) in
  73. match value with
  74. | None -> raise (Prebuild_error ("field `" ^ name ^ "` has invalid data"))
  75. | Some v -> Some v
  76. with Not_found ->
  77. None
  78. let get_field name map fields =
  79. let field = try List.find (fun (n, _) -> n = name) fields with Not_found -> raise (Prebuild_error ("no `" ^ name ^ "` field")) in
  80. let value = map (snd field) in
  81. match value with
  82. | None -> raise (Prebuild_error ("field `" ^ name ^ "` has invalid data"))
  83. | Some v -> v
  84. let parse_define json =
  85. let fields = match json with
  86. | JObject fl -> fl
  87. | _ -> raise (Prebuild_error "not an object")
  88. in
  89. (* name *) get_field "name" as_string fields,
  90. (* define *) get_field "define" as_string fields,
  91. (* doc *) get_field "doc" as_string fields,
  92. (* params *) get_optional_field "params" as_params [] fields,
  93. (* platforms *) get_optional_field "platforms" as_platforms [] fields,
  94. (* links *) get_optional_field "links" as_links [] fields,
  95. (* deprecated *) get_optional_field2 "deprecated" as_string fields
  96. let parse_meta json =
  97. let fields = match json with
  98. | JObject fl -> fl
  99. | _ -> raise (Prebuild_error "not an object")
  100. in
  101. (* name *) get_field "name" as_string fields,
  102. (* metadata *) get_field "metadata" as_string fields,
  103. (* doc *) get_field "doc" as_string fields,
  104. (* params *) get_optional_field "params" as_params [] fields,
  105. (* platforms *) get_optional_field "platforms" as_platforms [] fields,
  106. (* targets *) get_optional_field "targets" as_targets [] fields,
  107. (* internal *) get_optional_field "internal" as_bool false fields,
  108. (* links *) get_optional_field "links" as_links [] fields
  109. let parse_warning json =
  110. let fields = match json with
  111. | JObject fl -> fl
  112. | _ -> raise (Prebuild_error "not an object")
  113. in
  114. {
  115. w_name = get_field "name" as_string fields;
  116. w_doc = get_field "doc" as_string fields;
  117. w_parent = get_optional_field2 "parent" as_string fields;
  118. w_generic = get_optional_field "generic" as_bool false fields;
  119. }
  120. let parse_file_array path map =
  121. let file = open_in path in
  122. let data = Std.input_all file in
  123. let open Json.Reader in
  124. let lexbuf = Sedlexing.Utf8.from_string data in
  125. let json = read_json lexbuf in
  126. match json with
  127. | JArray s -> List.map map s
  128. | _ -> raise (Prebuild_error "not an array")
  129. let s_escape ?(hex=true) s =
  130. let b = Buffer.create (String.length s) in
  131. for i = 0 to (String.length s) - 1 do
  132. match s.[i] with
  133. | '\n' -> Buffer.add_string b "\\n"
  134. | '\t' -> Buffer.add_string b "\\t"
  135. | '\r' -> Buffer.add_string b "\\r"
  136. | '"' -> Buffer.add_string b "\\\""
  137. | '\\' -> Buffer.add_string b "\\\\"
  138. | c when int_of_char c < 32 && hex -> Buffer.add_string b (Printf.sprintf "\\x%.2X" (int_of_char c))
  139. | c -> Buffer.add_char b c
  140. done;
  141. Buffer.contents b
  142. let gen_platforms = function
  143. | [] -> []
  144. | platforms -> ["Platforms [" ^ (String.concat ";" platforms) ^ "]"]
  145. let gen_params = List.map (function param -> "HasParam \"" ^ param ^ "\"" )
  146. let gen_links = List.map (function link -> "Link \"" ^ link ^ "\"" )
  147. let gen_define_type defines =
  148. String.concat "\n" (List.map (function (name, _, _, _, _, _, _) -> "\t| " ^ name) defines)
  149. let gen_option f = function
  150. | None -> "None"
  151. | Some x -> Printf.sprintf "Some(%s)" (f x)
  152. let gen_define_info defines =
  153. let deprecations = DynArray.create() in
  154. let define_str = List.map (function
  155. (name, define, doc, params, platforms, links, deprecated) ->
  156. let platforms_str = gen_platforms platforms in
  157. let params_str = gen_params params in
  158. let links_str = gen_links links in
  159. let define = String.concat "_" (ExtString.String.nsplit define "-") in
  160. let deprecated = match deprecated with
  161. | None ->
  162. []
  163. | Some x ->
  164. let quoted = Printf.sprintf "%S" x in
  165. DynArray.add deprecations (Printf.sprintf "\t(%S,%S)" define x);
  166. [Printf.sprintf "Deprecated(%s)" quoted]
  167. in
  168. "\t| " ^ name ^ " -> \"" ^ define ^ "\",(" ^ (Printf.sprintf "%S" doc) ^ ",[" ^ (String.concat "; " (platforms_str @ params_str @ links_str @ deprecated)) ^ "])"
  169. ) defines in
  170. String.concat "\n" define_str,String.concat ";\n" (DynArray.to_list deprecations)
  171. let gen_meta_type metas =
  172. String.concat "\n" (List.map (function
  173. | ("InlineConstructorArgument", _, _, _, _, _, _, _) -> "\t| InlineConstructorArgument of int * int"
  174. | (name, _, _, _, _, _, _, _) -> "\t| " ^ name
  175. ) metas)
  176. let gen_meta_info metas =
  177. let meta_str = List.map (function
  178. (name, metadata, doc, params, platforms, targets, internal, links) ->
  179. let platforms_str = gen_platforms platforms in
  180. let params_str = gen_params params in
  181. let targets_str = (match targets with
  182. | [] -> []
  183. | targets -> ["UsedOn [" ^ (String.concat ";" targets) ^ "]"]
  184. ) in
  185. let internal_str = if internal then ["UsedInternally"] else [] in
  186. let links_str = gen_links links in
  187. let name = (match name with
  188. (* this is a hacky, I know *)
  189. | "InlineConstructorArgument" -> "InlineConstructorArgument _"
  190. | _ -> name
  191. ) in
  192. "\t| " ^ name ^ " -> \"" ^ metadata ^ "\",(" ^ (Printf.sprintf "%S" doc) ^ ",[" ^ (String.concat "; " (platforms_str @ params_str @ targets_str @ internal_str @ links_str)) ^ "])"
  193. ) metas in
  194. String.concat "\n" meta_str
  195. let gen_warning_type warnings =
  196. let warning_str = List.map (function
  197. w ->
  198. Printf.sprintf "\t| %s" w.w_name
  199. ) warnings in
  200. String.concat "\n" warning_str
  201. let gen_warning_parse warnings =
  202. let warning_str = List.map (function
  203. w ->
  204. Printf.sprintf "\t| \"%s\" -> %s" w.w_name w.w_name
  205. ) warnings in
  206. let warning_str = warning_str @ ["\t| _ -> raise Exit"] in
  207. String.concat "\n" warning_str
  208. let gen_warning_obj warnings =
  209. let warning_str = List.map (fun w ->
  210. let w_parent = match w.w_parent with
  211. | None -> if w.w_name = "WAll" then "None" else "Some WAll"
  212. | Some w -> Printf.sprintf "Some %s" w
  213. in
  214. Printf.sprintf "\t| %s -> {w_name = \"%s\"; w_doc = \"%s\"; w_generic = %b; w_parent = %s}" w.w_name w.w_name (s_escape w.w_doc) w.w_generic w_parent
  215. ) warnings in
  216. String.concat "\n" warning_str
  217. let autogen_header = "(* This file is auto-generated using prebuild from files in src-json *)
  218. (* Do not edit manually! *)
  219. "
  220. let define_header = autogen_header ^ "
  221. open Globals
  222. type define_parameter =
  223. | HasParam of string
  224. | Platforms of platform list
  225. | Link of string
  226. | Deprecated of string
  227. "
  228. let meta_header = autogen_header ^ "
  229. open Globals
  230. type meta_usage =
  231. | TClass
  232. | TClassField
  233. | TAbstract
  234. | TAbstractField
  235. | TEnum
  236. | TTypedef
  237. | TAnyField
  238. | TExpr
  239. | TTypeParameter
  240. | TVariable
  241. let parse_meta_usage = function
  242. | \"TClass\" -> TClass
  243. | \"TClassField\" -> TClassField
  244. | \"TAbstract\" -> TAbstract
  245. | \"TAbstractField\" -> TAbstractField
  246. | \"TEnum\" -> TEnum
  247. | \"TTypedef\" -> TTypedef
  248. | \"TAnyField\" -> TAnyField
  249. | \"TExpr\" -> TExpr
  250. | \"TTypeParameter\" -> TTypeParameter
  251. | \"TVariable\" -> TVariable
  252. | t -> raise (failwith (\"invalid metadata target \" ^ t))
  253. let print_meta_usage = function
  254. | TClass -> \"TClass\"
  255. | TClassField -> \"TClassField\"
  256. | TAbstract -> \"TAbstract\"
  257. | TAbstractField -> \"TAbstractField\"
  258. | TEnum -> \"TEnum\"
  259. | TTypedef -> \"TTypedef\"
  260. | TAnyField -> \"TAnyField\"
  261. | TExpr -> \"TExpr\"
  262. | TTypeParameter -> \"TTypeParameter\"
  263. | TVariable -> \"TVariable\"
  264. type meta_parameter =
  265. | HasParam of string
  266. | Platforms of platform list
  267. | UsedOn of meta_usage list
  268. | UsedInternally
  269. | Link of string
  270. "
  271. ;;
  272. match Array.to_list (Sys.argv) with
  273. | [_; "define"; define_path]->
  274. let defines = parse_file_array define_path parse_define in
  275. Printf.printf "%s" define_header;
  276. Printf.printf "type strict_defined =\n";
  277. Printf.printf "%s" (gen_define_type defines);
  278. Printf.printf "\n\t| Last\n\t| Custom of string\n\n";
  279. let infos,deprecations = gen_define_info defines in
  280. Printf.printf "let infos = function\n";
  281. Printf.printf "%s" infos;
  282. Printf.printf "\n\t| Last -> die \"\" __LOC__\n\t| Custom s -> s,(\"\",[])\n";
  283. Printf.printf "\nlet deprecated_defines = [\n%s\n]\n" deprecations;
  284. | [_; "meta"; meta_path]->
  285. let metas = parse_file_array meta_path parse_meta in
  286. Printf.printf "%s" meta_header;
  287. Printf.printf "type strict_meta =\n";
  288. Printf.printf "%s" (gen_meta_type metas);
  289. Printf.printf "\n\t| Last\n\t| Dollar of string\n\t| Custom of string\n\n";
  290. Printf.printf "let get_info = function\n";
  291. Printf.printf "%s" (gen_meta_info metas);
  292. Printf.printf "\n\t| Last -> die \"\" __LOC__\n\t| Dollar s -> \"$\" ^ s,(\"\",[])\n\t| Custom s -> s,(\"\",[])\n"
  293. | [_; "warning"; warning_path]->
  294. let warnings = parse_file_array warning_path parse_warning in
  295. print_endline "type warning =";
  296. print_endline (gen_warning_type warnings);
  297. print_endline "";
  298. print_endline "type warning_obj = {";
  299. print_endline "\tw_name : string;";
  300. print_endline "\tw_doc : string;";
  301. print_endline "\tw_generic : bool;";
  302. print_endline "\tw_parent : warning option;";
  303. print_endline "}";
  304. print_endline "";
  305. print_endline "let warning_obj = function";
  306. print_endline (gen_warning_obj warnings);
  307. print_endline "";
  308. print_endline "let from_string = function";
  309. print_endline (gen_warning_parse warnings);
  310. | _ :: "libparams" :: params ->
  311. Printf.printf "(%s)" (String.concat " " (List.map (fun s -> Printf.sprintf "\"%s\"" s) params))
  312. | [_ ;"version";add_revision;branch;sha] ->
  313. begin match add_revision with
  314. | "0" | "" ->
  315. print_endline "let version_extra = None"
  316. | _ ->
  317. Printf.printf "let version_extra = Some (\"git build %s\",\"%s\")" branch sha
  318. end
  319. | args ->
  320. print_endline (String.concat ", " args)