genpy.ml 76 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205
  1. (*
  2. * Copyright (C)2005-2014 Haxe Foundation
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a
  5. * copy of this software and associated documentation files (the "Software"),
  6. * to deal in the Software without restriction, including without limitation
  7. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8. * and/or sell copies of the Software, and to permit persons to whom the
  9. * Software is furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice shall be included in
  12. * all copies or substantial portions of the Software.
  13. *
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  20. * DEALINGS IN THE SOFTWARE.
  21. *)
  22. open Ast
  23. open Type
  24. open Common
  25. module Utils = struct
  26. let class_of_module_type mt = match mt with
  27. | TClassDecl c -> c
  28. | _ -> failwith ("Not a class: " ^ (s_type_path (t_infos mt).mt_path))
  29. let find_type com path =
  30. try
  31. List.find (fun mt -> match mt with
  32. | TAbstractDecl _ -> false
  33. | _ -> (t_infos mt).mt_path = path
  34. ) com.types
  35. with Not_found ->
  36. error (Printf.sprintf "Could not find type %s\n" (s_type_path path)) null_pos
  37. let mk_static_field c cf p =
  38. let ta = TAnon { a_fields = c.cl_statics; a_status = ref (Statics c) } in
  39. let ethis = mk (TTypeExpr (TClassDecl c)) ta p in
  40. let t = monomorphs cf.cf_params cf.cf_type in
  41. mk (TField (ethis,(FStatic (c,cf)))) t p
  42. let mk_static_call c cf el p =
  43. let ef = mk_static_field c cf p in
  44. let tr = match follow ef.etype with
  45. | TFun(args,tr) -> tr
  46. | _ -> assert false
  47. in
  48. mk (TCall(ef,el)) tr p
  49. let resolve_static_field c n =
  50. try
  51. PMap.find n c.cl_statics
  52. with Not_found ->
  53. failwith (Printf.sprintf "Class %s has no field %s" (s_type_path c.cl_path) n)
  54. let mk_static_field_2 c n p =
  55. mk_static_field c (resolve_static_field c n) p
  56. let mk_static_call_2 c n el p =
  57. mk_static_call c (resolve_static_field c n) el p
  58. end
  59. module KeywordHandler = struct
  60. let kwds =
  61. let h = Hashtbl.create 0 in
  62. List.iter (fun s -> Hashtbl.add h s ()) [
  63. "and"; "as"; "assert"; "break"; "class"; "continue"; "def"; "del"; "elif"; "else"; "except"; "exec"; "finally"; "for";
  64. "from"; "global"; "if"; "import"; "in"; "is"; "lambda"; "not"; "or"; "pass"; "print";" raise"; "return"; "try"; "while";
  65. "with"; "yield"; "float"; "None"; "list"; "True"; "False"
  66. ];
  67. h
  68. let handle_keywords s =
  69. let l = String.length s in
  70. if Hashtbl.mem kwds s then
  71. "_hx_" ^ s
  72. (*
  73. handle special __ underscore behaviour (creates private fields for objects) for fields but only if the field doesn't
  74. end with at least one underscores like __iter__ because these are special fields
  75. *)
  76. else if l > 2 && String.sub s 0 2 = "__" && String.sub s (l - 1) 1 <> "_" then
  77. "_hx_" ^ s
  78. else s
  79. end
  80. module Transformer = struct
  81. type adjusted_expr = {
  82. a_expr : texpr;
  83. a_blocks : texpr list;
  84. a_next_id : unit -> string;
  85. a_is_value : bool;
  86. }
  87. let como = ref None
  88. let t_bool = ref t_dynamic
  89. let t_void = ref t_dynamic
  90. let t_string = ref t_dynamic
  91. let t_int = ref t_dynamic
  92. let c_reflect = ref null_class
  93. let init com =
  94. como := Some com;
  95. t_bool := com.basic.tbool;
  96. t_void := com.basic.tvoid;
  97. t_string := com.basic.tstring;
  98. t_int := com.basic.tint;
  99. c_reflect := Utils.class_of_module_type (Utils.find_type com ([],"Reflect"))
  100. and debug_expr e =
  101. let s_type = Type.s_type (print_context()) in
  102. let s = Type.s_expr_pretty "\t" s_type e in
  103. Printf.printf "%s\n" s
  104. let new_counter () =
  105. let n = ref (-1) in
  106. (fun () ->
  107. incr n;
  108. Printf.sprintf "_hx_local_%i" !n
  109. )
  110. let to_expr ae =
  111. match ae.a_blocks with
  112. | [] ->
  113. ae.a_expr
  114. | el ->
  115. match ae.a_expr.eexpr with
  116. | TBlock el2 ->
  117. { ae.a_expr with eexpr = TBlock (el @ el2) }
  118. | _ ->
  119. { ae.a_expr with eexpr = TBlock (el @ [ae.a_expr])}
  120. let lift_expr ?(is_value = false) ?(next_id = None) ?(blocks = []) e =
  121. let next_id = match next_id with
  122. | None ->
  123. new_counter()
  124. | Some f ->
  125. f
  126. in
  127. {
  128. a_expr = e;
  129. a_blocks = blocks;
  130. a_next_id = next_id;
  131. a_is_value = is_value
  132. }
  133. let lift_expr1 is_value next_id blocks e =
  134. lift_expr ~is_value:is_value ~next_id:(Some next_id) ~blocks:blocks e
  135. let to_tvar ?(capture = false) n t =
  136. { v_name = n; v_type = t; v_id = 0; v_capture = capture; v_extra = None; v_meta = [] }
  137. let create_non_local n pos =
  138. let s = "nonlocal " ^ (KeywordHandler.handle_keywords n) in
  139. (* TODO: this is a hack... *)
  140. let id = mk (TLocal (to_tvar "python_Syntax._pythonCode" t_dynamic ) ) !t_void pos in
  141. let id2 = mk (TLocal( to_tvar s t_dynamic )) !t_void pos in
  142. mk (TCall(id, [id2])) t_dynamic pos
  143. let to_tlocal_expr ?(capture = false) n t p =
  144. mk (TLocal (to_tvar ~capture:capture n t)) t p
  145. let check_unification e t = match follow e.etype,follow t with
  146. | TAnon an1, TAnon an2 ->
  147. PMap.iter (fun s cf ->
  148. if not (PMap.mem s an1.a_fields) then an1.a_fields <- PMap.add s cf an1.a_fields
  149. ) an2.a_fields;
  150. e
  151. | _ ->
  152. e
  153. let dynamic_field_read e s =
  154. Utils.mk_static_call_2 !c_reflect "field" [e;mk (TConst (TString s)) !t_string e.epos] e.epos
  155. let dynamic_field_write e1 s e2 =
  156. Utils.mk_static_call_2 !c_reflect "setField" [e1;mk (TConst (TString s)) !t_string e1.epos;e2] e1.epos
  157. let dynamic_field_read_write next_id e1 s op e2 =
  158. let id = next_id() in
  159. let temp_var = to_tvar id e1.etype in
  160. let temp_var_def = mk (TVar(temp_var,Some e1)) e1.etype e1.epos in
  161. let temp_local = mk (TLocal temp_var) e1.etype e1.epos in
  162. let e_field = dynamic_field_read temp_local s in
  163. let e_op = mk (TBinop(op,e_field,e2)) e_field.etype e_field.epos in
  164. let e_set_field = dynamic_field_write temp_local s e_op in
  165. mk (TBlock [
  166. temp_var_def;
  167. e_set_field;
  168. ]) e_set_field.etype e_set_field.epos
  169. let add_non_locals_to_func e = match e.eexpr with
  170. | TFunction tf ->
  171. let cur = ref PMap.empty in
  172. let save () =
  173. let prev = !cur in
  174. (fun () ->
  175. cur := prev
  176. )
  177. in
  178. let declare v =
  179. cur := PMap.add v.v_id v !cur;
  180. in
  181. List.iter (fun (v,_) -> declare v) tf.tf_args;
  182. let non_locals = Hashtbl.create 0 in
  183. let rec it e = match e.eexpr with
  184. | TVar(v,e1) ->
  185. begin match e1 with
  186. | Some e ->
  187. maybe_continue e
  188. | None ->
  189. ()
  190. end;
  191. declare v;
  192. | TTry(e1,catches) ->
  193. it e1;
  194. List.iter (fun (v,e) ->
  195. let restore = save() in
  196. declare v;
  197. it e;
  198. restore()
  199. ) catches;
  200. | TBinop( (OpAssign | OpAssignOp(_)), { eexpr = TLocal v }, e2) ->
  201. if not (PMap.mem v.v_id !cur) then
  202. Hashtbl.add non_locals v.v_id v;
  203. maybe_continue e2;
  204. | TFunction _ ->
  205. ()
  206. | _ ->
  207. Type.iter it e
  208. and maybe_continue e = match e.eexpr with
  209. | TFunction _ ->
  210. ()
  211. | _ ->
  212. it e
  213. in
  214. it tf.tf_expr;
  215. let el = Hashtbl.fold (fun k v acc ->
  216. (create_non_local v.v_name e.epos) :: acc
  217. ) non_locals [] in
  218. let el = tf.tf_expr :: el in
  219. let tf = { tf with tf_expr = { tf.tf_expr with eexpr = TBlock(List.rev el)}} in
  220. {e with eexpr = TFunction tf}
  221. | _ ->
  222. assert false
  223. let rec transform_function tf ae is_value =
  224. let p = tf.tf_expr.epos in
  225. let assigns = List.fold_left (fun acc (v,value) -> match value with
  226. | None | Some TNull ->
  227. acc
  228. | Some ct ->
  229. let a_local = mk (TLocal v) v.v_type p in
  230. let a_null = mk (TConst TNull) v.v_type p in
  231. let a_cmp = mk (TBinop(OpEq,a_local,a_null)) !t_bool p in
  232. let a_value = mk (TConst(ct)) v.v_type p in
  233. let a_assign = mk (TBinop(OpAssign,a_local,a_value)) v.v_type p in
  234. let a_if = mk (TIf(a_cmp,a_assign,None)) !t_void p in
  235. a_if :: acc
  236. ) [] tf.tf_args in
  237. let body = match assigns with
  238. | [] ->
  239. tf.tf_expr
  240. | _ ->
  241. let eb = mk (TBlock (List.rev assigns)) t_dynamic p in
  242. Type.concat eb tf.tf_expr
  243. in
  244. let e1 = to_expr (transform_expr ~next_id:(Some ae.a_next_id) body) in
  245. let fn = mk (TFunction({
  246. tf_expr = e1;
  247. tf_args = tf.tf_args;
  248. tf_type = tf.tf_type;
  249. })) ae.a_expr.etype p in
  250. let fn = add_non_locals_to_func fn in
  251. if is_value then begin
  252. let new_name = ae.a_next_id() in
  253. let new_var = alloc_var new_name tf.tf_type in
  254. let new_local = mk (TLocal new_var) fn.etype p in
  255. let def = mk (TVar(new_var,Some fn)) fn.etype p in
  256. lift_expr1 false ae.a_next_id [def] new_local
  257. end else
  258. lift_expr fn
  259. and transform_var_expr ae eo v =
  260. let b,new_expr = match eo with
  261. | None ->
  262. [],None
  263. | Some e1 ->
  264. let f = transform_expr1 true ae.a_next_id [] e1 in
  265. let b = f.a_blocks in
  266. b,Some(f.a_expr)
  267. in
  268. let e = mk (TVar(v,new_expr)) ae.a_expr.etype ae.a_expr.epos in
  269. lift_expr ~next_id:(Some ae.a_next_id) ~blocks:b e
  270. and transform_expr ?(is_value = false) ?(next_id = None) ?(blocks = []) (e : texpr) : adjusted_expr =
  271. transform1 (lift_expr ~is_value ~next_id ~blocks e)
  272. and transform_expr1 is_value next_id blocks e =
  273. transform_expr ~is_value ~next_id:(Some next_id) ~blocks e
  274. and transform_exprs_to_block el tb is_value p next_id =
  275. match el with
  276. | [e] ->
  277. transform_expr ~is_value ~next_id:(Some next_id) e
  278. | _ ->
  279. let size = List.length el in
  280. let res = DynArray.create () in
  281. ExtList.List.iteri (fun i e ->
  282. (* this removes Builtin.len(x) calls which are reproduced by the inlined return
  283. of Array.push even if the value is not used *)
  284. let is_removable_statement e = (not is_value || i < size-1) &&
  285. match e.eexpr with
  286. | TCall({ eexpr = TField(_, FStatic({cl_path = ["python";"internal"],"HxBuiltin"},{ cf_name = "len" }))}, [_]) -> true
  287. | _ -> false
  288. in
  289. if not (is_removable_statement e) then
  290. let ae = transform_expr ~is_value ~next_id:(Some next_id) e in
  291. List.iter (DynArray.add res) ae.a_blocks;
  292. DynArray.add res ae.a_expr
  293. else
  294. ()
  295. ) el;
  296. lift_expr (mk (TBlock (DynArray.to_list res)) tb p)
  297. and transform_switch ae is_value e1 cases edef =
  298. let case_functions = ref [] in
  299. let case_to_if (el,e) eelse =
  300. let val_reversed = List.rev el in
  301. let mk_eq e = mk (TBinop(OpEq,e1,e)) !t_bool (punion e1.epos e.epos) in
  302. let cond = match val_reversed with
  303. | [] ->
  304. assert false
  305. | [e] ->
  306. mk_eq e
  307. | e :: el ->
  308. List.fold_left (fun eelse e -> mk (TBinop(OpBoolOr,eelse,mk_eq e)) !t_bool (punion eelse.epos e.epos)) (mk_eq e) el
  309. in
  310. let eif = if is_value then begin
  311. let name = ae.a_next_id() in
  312. let func = exprs_to_func [e] name ae in
  313. case_functions := !case_functions @ func.a_blocks;
  314. let call = func.a_expr in
  315. mk (TIf(cond,call,eelse)) ae.a_expr.etype ae.a_expr.epos
  316. end else
  317. mk (TIf(cond,e,eelse)) ae.a_expr.etype e.epos
  318. in
  319. eif
  320. in
  321. let rev_cases = List.rev cases in
  322. let edef = Some (match edef with
  323. | None ->
  324. mk (TBlock []) ae.a_expr.etype ae.a_expr.epos
  325. | Some e ->
  326. e)
  327. in
  328. let res = match rev_cases,edef with
  329. | [],Some edef ->
  330. edef
  331. | [],None ->
  332. (* I don't think that can happen? *)
  333. assert false
  334. | [case],_ ->
  335. case_to_if case edef
  336. | case :: cases,_ ->
  337. List.fold_left (fun acc case -> case_to_if case (Some acc)) (case_to_if case edef) cases
  338. in
  339. let res = if is_value then
  340. mk (TBlock ((List.rev (res :: !case_functions)))) res.etype res.epos
  341. else
  342. res
  343. in
  344. forward_transform res ae
  345. and transform_string_switch ae is_value e1 cases edef =
  346. let length_map = Hashtbl.create 0 in
  347. List.iter (fun (el,e) ->
  348. List.iter (fun es ->
  349. match es.eexpr with
  350. | TConst (TString s) ->
  351. let l = String.length s in
  352. let sl = try
  353. Hashtbl.find length_map l
  354. with Not_found ->
  355. let sl = ref [] in
  356. Hashtbl.replace length_map l sl;
  357. sl
  358. in
  359. sl := ([es],e) :: !sl;
  360. | _ ->
  361. ()
  362. ) el
  363. ) cases;
  364. if Hashtbl.length length_map < 2 then
  365. transform_switch ae is_value e1 cases edef
  366. else
  367. let mk_eq e1 e2 = mk (TBinop(OpEq,e1,e2)) !t_bool (punion e1.epos e2.epos) in
  368. let mk_or e1 e2 = mk (TBinop(OpOr,e1,e2)) !t_bool (punion e1.epos e2.epos) in
  369. let mk_if (el,e) eo =
  370. let eif = List.fold_left (fun eacc e -> mk_or eacc (mk_eq e1 e)) (mk_eq e1 (List.hd el)) (List.tl el) in
  371. mk (TIf(Codegen.mk_parent eif,e,eo)) e.etype e.epos
  372. in
  373. let cases = Hashtbl.fold (fun i el acc ->
  374. let eint = mk (TConst (TInt (Int32.of_int i))) !t_int e1.epos in
  375. let fs = match List.fold_left (fun eacc ec -> Some (mk_if ec eacc)) edef !el with Some e -> e | None -> assert false in
  376. ([eint],fs) :: acc
  377. ) length_map [] in
  378. let c_string = match !t_string with TInst(c,_) -> c | _ -> assert false in
  379. let cf_length = PMap.find "length" c_string.cl_fields in
  380. let ef = mk (TField(e1,FInstance(c_string,[],cf_length))) !t_int e1.epos in
  381. let res_var = alloc_var (ae.a_next_id()) ef.etype in
  382. let res_local = {ef with eexpr = TLocal res_var} in
  383. let var_expr = {ef with eexpr = TVar(res_var,Some ef)} in
  384. let e = mk (TBlock [
  385. var_expr;
  386. mk (TSwitch(res_local,cases,edef)) ae.a_expr.etype e1.epos
  387. ]) ae.a_expr.etype e1.epos in
  388. forward_transform e ae
  389. and transform_op_assign_op ae e1 op one is_value post =
  390. let e1_ = transform_expr e1 ~is_value:true ~next_id:(Some ae.a_next_id) in
  391. let handle_as_local temp_local =
  392. let ex = ae.a_expr in
  393. let res_var = alloc_var (ae.a_next_id()) ex.etype in
  394. let res_local = {ex with eexpr = TLocal res_var} in
  395. let plus = {ex with eexpr = TBinop(op,temp_local,one)} in
  396. let var_expr = {ex with eexpr = TVar(res_var,Some temp_local)} in
  397. let assign_expr = {ex with eexpr = TBinop(OpAssign,e1_.a_expr,plus)} in
  398. let blocks = if post then
  399. [var_expr;assign_expr;res_local]
  400. else
  401. [assign_expr;temp_local]
  402. in
  403. (* TODO: block is ignored in the else case? *)
  404. let block = e1_.a_blocks @ blocks in
  405. if is_value then begin
  406. let f = exprs_to_func block (ae.a_next_id()) ae in
  407. lift_expr f.a_expr ~is_value:true ~next_id:(Some ae.a_next_id) ~blocks:f.a_blocks
  408. end else begin
  409. let block = e1_.a_blocks @ [assign_expr] in
  410. transform_exprs_to_block block ex.etype false ex.epos ae.a_next_id
  411. end
  412. in
  413. match e1_.a_expr.eexpr with
  414. | TArray({eexpr = TLocal _},{eexpr = TLocal _})
  415. | TField({eexpr = TLocal _},_)
  416. | TLocal _ ->
  417. handle_as_local e1_.a_expr
  418. | TArray(e1,e2) ->
  419. let id = ae.a_next_id() in
  420. let temp_var_l = alloc_var id e1.etype in
  421. let temp_local_l = {e1 with eexpr = TLocal temp_var_l} in
  422. let temp_var_l = {e1 with eexpr = TVar(temp_var_l,Some e1)} in
  423. let id = ae.a_next_id() in
  424. let temp_var_r = alloc_var id e2.etype in
  425. let temp_local_r = {e2 with eexpr = TLocal temp_var_r} in
  426. let temp_var_r = {e2 with eexpr = TVar(temp_var_r,Some e2)} in
  427. let id = ae.a_next_id() in
  428. let temp_var = alloc_var id e1_.a_expr.etype in
  429. let temp_local = {e1_.a_expr with eexpr = TLocal temp_var} in
  430. let temp_var_expr = {e1_.a_expr with eexpr = TArray(temp_local_l,temp_local_r)} in
  431. let temp_var = {e1_.a_expr with eexpr = TVar(temp_var,Some temp_var_expr)} in
  432. let plus = {ae.a_expr with eexpr = TBinop(op,temp_local,one)} in
  433. let assign_expr = {ae.a_expr with eexpr = TBinop(OpAssign,temp_var_expr,plus)} in
  434. let block = e1_.a_blocks @ [temp_var_l;temp_var_r;temp_var;assign_expr;if post then temp_local else temp_var_expr] in
  435. if is_value then begin
  436. let f = exprs_to_func block (ae.a_next_id()) ae in
  437. lift_expr f.a_expr ~is_value:true ~next_id:(Some ae.a_next_id) ~blocks:f.a_blocks
  438. end else
  439. transform_exprs_to_block block ae.a_expr.etype false ae.a_expr.epos ae.a_next_id
  440. | TField(e1,fa) ->
  441. let temp_var_l = alloc_var (ae.a_next_id()) e1.etype in
  442. let temp_local_l = {e1 with eexpr = TLocal temp_var_l} in
  443. let temp_var_l = {e1 with eexpr = TVar(temp_var_l,Some e1)} in
  444. let temp_var = alloc_var (ae.a_next_id()) e1_.a_expr.etype in
  445. let temp_local = {e1_.a_expr with eexpr = TLocal temp_var} in
  446. let temp_var_expr = {e1_.a_expr with eexpr = TField(temp_local_l,fa)} in
  447. let temp_var = {e1_.a_expr with eexpr = TVar(temp_var,Some temp_var_expr)} in
  448. let plus = {ae.a_expr with eexpr = TBinop(op,temp_local,one)} in
  449. let assign_expr = {ae.a_expr with eexpr = TBinop(OpAssign,temp_var_expr,plus)} in
  450. let block = e1_.a_blocks @ [temp_var_l;temp_var;assign_expr;if post then temp_local else temp_var_expr] in
  451. if is_value then begin
  452. let f = exprs_to_func block (ae.a_next_id()) ae in
  453. lift_expr f.a_expr ~is_value:true ~next_id:(Some ae.a_next_id) ~blocks:f.a_blocks
  454. end else
  455. transform_exprs_to_block block ae.a_expr.etype false ae.a_expr.epos ae.a_next_id
  456. | _ ->
  457. debug_expr e1_.a_expr;
  458. assert false
  459. and var_to_treturn_expr ?(capture = false) n t p =
  460. let x = mk (TLocal (to_tvar ~capture:capture n t)) t p in
  461. mk (TReturn (Some x)) t p
  462. and exprs_to_func exprs name base =
  463. let convert_return_expr (expr:texpr) =
  464. match expr.eexpr with
  465. | TWhile(_,_,_) ->
  466. let ret = { expr with eexpr = TReturn (None) } in
  467. [expr; ret]
  468. | TFunction(f) ->
  469. let ret = var_to_treturn_expr name f.tf_type f.tf_expr.epos in
  470. [expr;ret]
  471. | TBinop(OpAssign, l, r) ->
  472. let r = { l with eexpr = TReturn(Some l) } in
  473. [expr; r]
  474. | x ->
  475. let ret_expr = { expr with eexpr = TReturn( Some(expr) )} in
  476. [ret_expr]
  477. in
  478. let def =
  479. (let ex = match exprs with
  480. | [] -> assert false
  481. | [x] ->
  482. (let exs = convert_return_expr x in
  483. match exs with
  484. | [] -> assert false
  485. | [x] -> x
  486. | x ->
  487. match List.rev x with
  488. | x::xs ->
  489. mk (TBlock exs) x.etype base.a_expr.epos
  490. | _ -> assert false)
  491. | x ->
  492. match List.rev x with
  493. | x::xs ->
  494. (let ret = x in
  495. let tail = List.rev xs in
  496. let block = tail @ (convert_return_expr ret) in
  497. match List.rev block with
  498. | x::_ ->
  499. mk (TBlock block) x.etype base.a_expr.epos
  500. | _ -> assert false)
  501. | _ -> assert false
  502. in
  503. let f1 = { tf_args = []; tf_type = TFun([],ex.etype); tf_expr = ex} in
  504. let fexpr = mk (TFunction f1) ex.etype ex.epos in
  505. let fvar = to_tvar name fexpr.etype in
  506. let f = add_non_locals_to_func fexpr in
  507. let assign = { ex with eexpr = TVar(fvar, Some(f))} in
  508. let call_expr = (mk (TLocal fvar) fexpr.etype ex.epos ) in
  509. let substitute = mk (TCall(call_expr, [])) ex.etype ex.epos in
  510. lift_expr ~blocks:[assign] substitute)
  511. in
  512. match exprs with
  513. | [{ eexpr = TFunction({ tf_args = []} as f) } as x] ->
  514. let l = to_tlocal_expr name f.tf_type f.tf_expr.epos in
  515. let substitute = mk (TCall(l, [])) f.tf_type f.tf_expr.epos in
  516. lift_expr ~blocks:[x] substitute
  517. | _ -> def
  518. and transform_call is_value e params ae =
  519. let trans is_value blocks e = transform_expr1 is_value ae.a_next_id blocks e in
  520. let trans1 e params =
  521. let e = trans true [] e in
  522. let blocks = e.a_blocks @ (List.flatten (List.map (fun (p) -> p.a_blocks) params)) in
  523. let params = List.map (fun (p) -> p.a_expr) params in
  524. let e = { ae.a_expr with eexpr = TCall(e.a_expr, params) } in
  525. lift_expr ~blocks:blocks e
  526. in
  527. match e, params with
  528. (* the foreach block should not be handled as a value *)
  529. | ({ eexpr = TField(_, FStatic({cl_path = ["python";],"Syntax"},{ cf_name = "_foreach" }))} as e, [e1;e2;e3]) ->
  530. trans1 e [trans true [] e1; trans true [] e2; trans false [] e3]
  531. | (e, params) ->
  532. trans1 e (List.map (trans true []) params)
  533. and transform1 ae : adjusted_expr =
  534. let trans is_value blocks e = transform_expr1 is_value ae.a_next_id blocks e in
  535. let lift is_value blocks e = lift_expr1 is_value ae.a_next_id blocks e in
  536. let a_expr = ae.a_expr in
  537. match ae.a_is_value,ae.a_expr.eexpr with
  538. | (is_value,TBlock [x]) ->
  539. trans is_value [] x
  540. | (false,TBlock []) ->
  541. lift_expr a_expr
  542. | (true,TBlock []) ->
  543. lift_expr (mk (TConst TNull) ae.a_expr.etype ae.a_expr.epos)
  544. | (false,TBlock el) ->
  545. transform_exprs_to_block el ae.a_expr.etype false ae.a_expr.epos ae.a_next_id
  546. | (true,TBlock el) ->
  547. let name = ae.a_next_id() in
  548. let block,tr = match List.rev el with
  549. | e :: el ->
  550. List.rev ((mk (TReturn (Some e)) t_dynamic e.epos) :: el),e.etype
  551. | [] ->
  552. assert false
  553. in
  554. let my_block = transform_exprs_to_block block tr false ae.a_expr.epos ae.a_next_id in
  555. let fn = mk (TFunction {
  556. tf_args = [];
  557. tf_type = tr;
  558. tf_expr = my_block.a_expr;
  559. }) ae.a_expr.etype ae.a_expr.epos in
  560. let t_var = alloc_var name ae.a_expr.etype in
  561. let f = add_non_locals_to_func fn in
  562. let fn_assign = mk (TVar (t_var,Some f)) ae.a_expr.etype ae.a_expr.epos in
  563. let ev = mk (TLocal t_var) ae.a_expr.etype ae.a_expr.epos in
  564. let substitute = mk (TCall(ev,[])) ae.a_expr.etype ae.a_expr.epos in
  565. lift_expr ~blocks:[fn_assign] substitute
  566. | (is_value,TFunction(f)) ->
  567. transform_function f ae is_value
  568. | (_,TVar(v,None)) ->
  569. transform_var_expr ae None v
  570. | (false, TVar(v,Some({ eexpr = TUnop((Increment | Decrement as unop),post_fix,({eexpr = TLocal _ | TField({eexpr = TConst TThis},_)} as ve))} as e1))) ->
  571. let one = {e1 with eexpr = TConst (TInt (Int32.of_int 1))} in
  572. let op = if unop = Increment then OpAdd else OpSub in
  573. let inc = {e1 with eexpr = TBinop(op,ve,one)} in
  574. let inc_assign = {e1 with eexpr = TBinop(OpAssign,ve,inc)} in
  575. let var_assign = {e1 with eexpr = TVar(v,Some ve)} in
  576. if post_fix = Postfix then
  577. lift true [var_assign] inc_assign
  578. else
  579. lift true [inc_assign] var_assign
  580. | (_,TVar(v,eo)) ->
  581. transform_var_expr ae eo v
  582. | (_,TFor(v,e1,e2)) ->
  583. let a1 = trans true [] e1 in
  584. let a2 = to_expr (trans false [] e2) in
  585. let name = (ae.a_next_id ()) in
  586. let t_var = alloc_var name e1.etype in
  587. let mk_local v p = { eexpr = TLocal v; etype = v.v_type; epos = p } in
  588. let ev = mk_local t_var e1.epos in
  589. let ehasnext = mk (TField(ev,quick_field e1.etype "hasNext")) (tfun [] (!t_bool) ) e1.epos in
  590. let ehasnext = mk (TCall(ehasnext,[])) ehasnext.etype ehasnext.epos in
  591. let enext = mk (TField(ev,quick_field e1.etype "next")) (tfun [] v.v_type) e1.epos in
  592. let enext = mk (TCall(enext,[])) v.v_type e1.epos in
  593. let var_assign = mk (TVar (v,Some enext)) v.v_type a_expr.epos in
  594. let ebody = Type.concat var_assign (a2) in
  595. let var_decl = mk (TVar (t_var,Some a1.a_expr)) (!t_void) e1.epos in
  596. let twhile = mk (TWhile((mk (TParenthesis ehasnext) ehasnext.etype ehasnext.epos),ebody,NormalWhile)) (!t_void) e1.epos in
  597. let blocks = a1.a_blocks @ [var_decl] in
  598. lift_expr ~blocks: blocks twhile
  599. | (_,TReturn None) ->
  600. ae
  601. | (_,TReturn (Some ({eexpr = TFunction f} as ef))) ->
  602. let n = ae.a_next_id() in
  603. let e1 = to_expr (trans false [] f.tf_expr) in
  604. let f = mk (TFunction {
  605. tf_args = f.tf_args;
  606. tf_type = f.tf_type;
  607. tf_expr = e1;
  608. }) ef.etype ef.epos in
  609. let f1 = add_non_locals_to_func f in
  610. let var_n = alloc_var n ef.etype in
  611. let f1_assign = mk (TVar(var_n,Some f1)) !t_void f1.epos in
  612. let var_local = mk (TLocal var_n) ef.etype f1.epos in
  613. let er = mk (TReturn (Some var_local)) t_dynamic ae.a_expr.epos in
  614. lift true [f1_assign] er
  615. | (_,TReturn Some(x)) ->
  616. let x1 = trans true [] x in
  617. (match x1.a_blocks with
  618. | [] ->
  619. lift true [] { ae.a_expr with eexpr = TReturn(Some x1.a_expr) }
  620. | blocks ->
  621. let f = exprs_to_func (blocks @ [x1.a_expr]) (ae.a_next_id()) ae in
  622. lift true f.a_blocks {a_expr with eexpr = TReturn (Some f.a_expr)})
  623. | (_, TParenthesis(e1)) ->
  624. let e1 = trans true [] e1 in
  625. let p = { ae.a_expr with eexpr = TParenthesis(e1.a_expr)} in
  626. lift true e1.a_blocks p
  627. | (_, TEnumParameter(e1,ef,i)) ->
  628. let e1 = trans true [] e1 in
  629. let p = { ae.a_expr with eexpr = TEnumParameter(e1.a_expr,ef,i)} in
  630. lift true e1.a_blocks p
  631. | (true, TIf(econd, eif, eelse)) ->
  632. (let econd1 = trans true [] econd in
  633. let eif1 = trans true [] eif in
  634. let eelse1 = match eelse with
  635. | Some x -> Some(trans true [] x)
  636. | None -> None
  637. in
  638. let blocks = [] in
  639. let eif2, blocks =
  640. match eif1.a_blocks with
  641. | [] -> eif1.a_expr, blocks
  642. | x ->
  643. let regular =
  644. let fname = eif1.a_next_id () in
  645. let f = exprs_to_func (List.append eif1.a_blocks [eif1.a_expr]) fname ae in
  646. f.a_expr, List.append blocks f.a_blocks
  647. in
  648. match eif1.a_blocks with
  649. | [{ eexpr = TVar(_, Some({ eexpr = TFunction(_)}))} as b] ->
  650. eif1.a_expr, List.append blocks [b]
  651. | _ -> regular
  652. in
  653. let eelse2, blocks =
  654. match eelse1 with
  655. | None -> None, blocks
  656. | Some({ a_blocks = []} as x) -> Some(x.a_expr), blocks
  657. | Some({ a_blocks = b} as eelse1) ->
  658. let regular =
  659. let fname = eelse1.a_next_id () in
  660. let f = exprs_to_func (List.append eelse1.a_blocks [eelse1.a_expr]) fname ae in
  661. Some(f.a_expr), List.append blocks f.a_blocks
  662. in
  663. match b with
  664. | [{ eexpr = TVar(_, Some({ eexpr = TFunction(f)}))} as b] ->
  665. Some(eelse1.a_expr), List.append blocks [b]
  666. | _ -> regular
  667. in
  668. let blocks = List.append econd1.a_blocks blocks in
  669. let new_if = { ae.a_expr with eexpr = TIf(econd1.a_expr, eif2, eelse2) } in
  670. match blocks with
  671. | [] ->
  672. let meta = Meta.Custom(":ternaryIf"), [], ae.a_expr.epos in
  673. let ternary = { ae.a_expr with eexpr = TMeta(meta, new_if) } in
  674. lift_expr ~blocks:blocks ternary
  675. | b ->
  676. let f = exprs_to_func (List.append blocks [new_if]) (ae.a_next_id ()) ae in
  677. lift_expr ~blocks:f.a_blocks f.a_expr)
  678. | (false, TIf(econd, eif, eelse)) ->
  679. let econd = trans true [] econd in
  680. let eif = to_expr (trans false [] eif) in
  681. let eelse = match eelse with
  682. | Some(x) -> Some(to_expr (trans false [] x))
  683. | None -> None
  684. in
  685. let new_if = { ae.a_expr with eexpr = TIf(econd.a_expr, eif, eelse) } in
  686. lift false econd.a_blocks new_if
  687. | (false, TWhile(econd, e1, NormalWhile)) ->
  688. let econd1 = trans true [] econd in
  689. let e11 = to_expr (trans false [] e1) in
  690. let new_while = mk (TWhile(econd1.a_expr,e11,NormalWhile)) a_expr.etype a_expr.epos in
  691. lift false econd1.a_blocks new_while
  692. | (true, TWhile(econd, ebody, NormalWhile)) ->
  693. let econd = trans true [] econd in
  694. let ebody = to_expr (trans false [] ebody) in
  695. let ewhile = { ae.a_expr with eexpr = TWhile(econd.a_expr, ebody, NormalWhile) } in
  696. let eval = { ae.a_expr with eexpr = TConst(TNull) } in
  697. let f = exprs_to_func (List.append econd.a_blocks [ewhile; eval]) (ae.a_next_id ()) ae in
  698. lift true f.a_blocks f.a_expr
  699. | (false, TWhile(econd, ebody, DoWhile)) ->
  700. let not_expr = { econd with eexpr = TUnop(Not, Prefix, econd) } in
  701. let break_expr = mk TBreak !t_void econd.epos in
  702. let if_expr = mk (TIf(not_expr, break_expr, None)) (!t_void) econd.epos in
  703. let new_e = match ebody.eexpr with
  704. | TBlock(exprs) -> { econd with eexpr = TBlock( List.append exprs [if_expr]) }
  705. | _ -> { econd with eexpr = TBlock( List.append [ebody] [if_expr]) }
  706. in
  707. let true_expr = mk (TConst(TBool(true))) econd.etype ae.a_expr.epos in
  708. let new_expr = { ae.a_expr with eexpr = TWhile( true_expr, new_e, NormalWhile) } in
  709. forward_transform new_expr ae
  710. | (is_value, TSwitch(e, cases, edef)) ->
  711. begin match follow e.etype with
  712. | TInst({cl_path = [],"String"},_) ->
  713. transform_string_switch ae is_value e cases edef
  714. | _ ->
  715. transform_switch ae is_value e cases edef
  716. end
  717. (* anon field access on optional params *)
  718. | (is_value, TField(e,FAnon cf)) when Meta.has Meta.Optional cf.cf_meta ->
  719. let e = dynamic_field_read e cf.cf_name in
  720. transform_expr ~is_value:is_value e
  721. | (is_value, TBinop(OpAssign,{eexpr = TField(e1,FAnon cf)},e2)) when Meta.has Meta.Optional cf.cf_meta ->
  722. let e = dynamic_field_write e1 cf.cf_name e2 in
  723. transform_expr ~is_value:is_value e
  724. | (is_value, TBinop(OpAssignOp op,{eexpr = TField(e1,FAnon cf)},e2)) when Meta.has Meta.Optional cf.cf_meta ->
  725. let e = dynamic_field_read_write ae.a_next_id e1 cf.cf_name op e2 in
  726. transform_expr ~is_value:is_value e
  727. (* TODO we need to deal with Increment, Decrement too!
  728. | (_, TUnop( (Increment | Decrement) as unop, op,{eexpr = TField(e1,FAnon cf)})) when Meta.has Meta.Optional cf.cf_meta ->
  729. let = dynamic_field_read e cf.cf_name in
  730. let e = dynamic_field_read_write_unop ae.a_next_id e1 cf.cf_name unop op in
  731. Printf.printf "dyn read write\n";
  732. transform_expr e
  733. *)
  734. (*
  735. anon field access with non optional members like iterator, length, split must be handled too, we need to Reflect on them too when it's a runtime method
  736. *)
  737. | (is_value, TUnop( (Increment | Decrement) as unop, op, e)) ->
  738. let one = { ae.a_expr with eexpr = TConst(TInt(Int32.of_int(1)))} in
  739. let is_postfix = match op with
  740. | Postfix -> true
  741. | Prefix -> false in
  742. let op = match unop with
  743. | Increment -> OpAdd
  744. | Decrement -> OpSub
  745. | _ -> assert false in
  746. transform_op_assign_op ae e op one is_value is_postfix
  747. | (_, TUnop(op, Prefix, e)) ->
  748. let e1 = trans true [] e in
  749. let r = { a_expr with eexpr = TUnop(op, Prefix, e1.a_expr) } in
  750. lift_expr ~blocks:e1.a_blocks r
  751. | (is_value, TField(e,FDynamic s)) ->
  752. let e = dynamic_field_read e s in
  753. transform_expr ~is_value:is_value e
  754. | (is_value, TBinop(OpAssign,{eexpr = TField(e1,FDynamic s)},e2)) ->
  755. let e = dynamic_field_write e1 s e2 in
  756. transform_expr ~is_value:is_value e
  757. | (is_value, TBinop(OpAssignOp op,{eexpr = TField(e1,FDynamic s)},e2)) ->
  758. let e = dynamic_field_read_write ae.a_next_id e1 s op e2 in
  759. transform_expr ~is_value:is_value e
  760. | (is_value, TField(e1, FClosure(Some ({cl_path = [],("String" | "list")},_),cf))) ->
  761. let e = dynamic_field_read e1 cf.cf_name in
  762. transform_expr ~is_value:is_value e
  763. | (is_value, TBinop(OpAssign, left, right))->
  764. (let left = trans true [] left in
  765. let right = trans true [] right in
  766. let r = { a_expr with eexpr = TBinop(OpAssign, left.a_expr, right.a_expr)} in
  767. if is_value then
  768. (let blocks = List.concat [left.a_blocks; right.a_blocks; [r]] in
  769. let f = exprs_to_func blocks (ae.a_next_id ()) ae in
  770. lift true f.a_blocks f.a_expr)
  771. else
  772. lift false (List.append left.a_blocks right.a_blocks) r)
  773. | (is_value, TBinop(OpAssignOp(x), left, right)) ->
  774. let right = trans true [] right in
  775. let v = right.a_expr in
  776. let res = transform_op_assign_op ae left x v is_value false in
  777. lift true (List.append right.a_blocks res.a_blocks) res.a_expr
  778. | (_, TBinop(op, left, right))->
  779. (let left = trans true [] left in
  780. let right = trans true [] right in
  781. let r = { a_expr with eexpr = TBinop(op, left.a_expr, right.a_expr)} in
  782. lift false (List.append left.a_blocks right.a_blocks) r)
  783. | (true, TThrow(x)) ->
  784. let block = TBlock([a_expr; { a_expr with eexpr = TConst(TNull) }]) in
  785. let r = { a_expr with eexpr = block } in
  786. forward_transform r ae
  787. | (false, TThrow(x)) ->
  788. let x = trans true [] x in
  789. let r = { a_expr with eexpr = TThrow(x.a_expr)} in
  790. lift false x.a_blocks r
  791. | (_, TNew(c, tp, params)) ->
  792. let params = List.map (trans true []) params in
  793. let blocks = List.flatten (List.map (fun (p) -> p.a_blocks) params) in
  794. let params = List.map (fun (p) -> p.a_expr) params in
  795. let e = { a_expr with eexpr = TNew(c, tp, params) } in
  796. lift false blocks e
  797. | (is_value, TCall(e,params)) ->
  798. transform_call is_value e params ae
  799. | (_, TArray(e1, e2)) ->
  800. let e1 = trans true [] e1 in
  801. let e2 = trans true [] e2 in
  802. let r = { a_expr with eexpr = TArray(e1.a_expr, e2.a_expr)} in
  803. let blocks = List.append e1.a_blocks e2.a_blocks in
  804. lift_expr ~blocks:blocks r
  805. | (false, TTry(etry, catches)) ->
  806. let etry = trans false [] etry in
  807. let catches = List.map (fun(v,e) -> v, trans false [] e) catches in
  808. let blocks = List.flatten (List.map (fun (_,e) -> e.a_blocks) catches) in
  809. let catches = List.map (fun(v,e) -> v, e.a_expr) catches in
  810. let r = { a_expr with eexpr = TTry(etry.a_expr, catches)} in
  811. let blocks = List.append etry.a_blocks blocks in
  812. lift false blocks r
  813. | (true, TTry(etry, catches)) ->
  814. let id = ae.a_next_id () in
  815. let temp_var = to_tvar id a_expr.etype in
  816. let temp_var_def = { a_expr with eexpr = TVar(temp_var, None) } in
  817. let temp_local = { a_expr with eexpr = TLocal(temp_var)} in
  818. let mk_temp_assign right = { a_expr with eexpr = TBinop(OpAssign, temp_local, right)} in
  819. let etry = mk_temp_assign etry in
  820. let catches = List.map (fun (v,e)-> v, mk_temp_assign e) catches in
  821. let new_try = { a_expr with eexpr = TTry(etry, catches)} in
  822. let block = [temp_var_def; new_try; temp_local] in
  823. let new_block = { a_expr with eexpr = TBlock(block)} in
  824. forward_transform new_block ae
  825. | (_, TObjectDecl(fields)) ->
  826. let fields = List.map (fun (name,ex) -> name, trans true [] ex) fields in
  827. let blocks = List.flatten (List.map (fun (_,ex) -> ex.a_blocks) fields) in
  828. let fields = List.map (fun (name,ex) -> name, ex.a_expr) fields in
  829. let r = { a_expr with eexpr = (TObjectDecl(fields) )} in
  830. lift_expr ~blocks r
  831. | (_, TArrayDecl(values)) ->
  832. let values = List.map (trans true []) values in
  833. let blocks = List.flatten (List.map (fun (v) -> v.a_blocks) values) in
  834. let exprs = List.map (fun (v) -> v.a_expr) values in
  835. let r = { a_expr with eexpr = TArrayDecl exprs } in
  836. lift_expr ~blocks:blocks r
  837. | (is_value, TCast(e1,Some mt)) ->
  838. let e = Codegen.default_cast ~vtmp:(ae.a_next_id()) (match !como with Some com -> com | None -> assert false) e1 mt ae.a_expr.etype ae.a_expr.epos in
  839. transform_expr ~is_value:is_value e
  840. | (is_value, TCast(e,None)) ->
  841. let e = trans is_value [] e in
  842. let r = { a_expr with eexpr = TCast(e.a_expr, None)} in
  843. lift_expr ~blocks:e.a_blocks r
  844. | (_, TField(e,f)) ->
  845. let e = trans true [] e in
  846. let r = { a_expr with eexpr = TField(e.a_expr, f) } in
  847. lift_expr ~blocks:e.a_blocks r
  848. | (is_value, TMeta(m, e)) ->
  849. let e = trans is_value [] e in
  850. let r = { a_expr with eexpr = TMeta(m, e.a_expr); etype = e.a_expr.etype } in
  851. lift_expr ~blocks:e.a_blocks r
  852. | ( _, TLocal _ ) -> lift_expr a_expr
  853. | ( _, TConst _ ) -> lift_expr a_expr
  854. | ( _, TTypeExpr _ ) -> lift_expr a_expr
  855. | ( _, TUnop _ ) -> assert false
  856. | ( true, TWhile(econd, ebody, DoWhile) ) ->
  857. let new_expr = trans false [] a_expr in
  858. let f = exprs_to_func (new_expr.a_blocks @ [new_expr.a_expr]) (ae.a_next_id()) ae in
  859. lift_expr ~is_value:true ~blocks:f.a_blocks f.a_expr
  860. | ( _, TBreak ) | ( _, TContinue ) ->
  861. lift_expr a_expr
  862. and transform e =
  863. to_expr (transform1 (lift_expr e))
  864. and forward_transform e base =
  865. transform1 (lift_expr1 base.a_is_value base.a_next_id base.a_blocks e)
  866. let transform_to_value e =
  867. to_expr (transform1 (lift_expr e ~is_value:true))
  868. end
  869. module Printer = struct
  870. type print_context = {
  871. pc_indent : string;
  872. pc_next_anon_func : unit -> string;
  873. pc_debug : bool;
  874. }
  875. let create_context =
  876. let n = ref (-1) in
  877. (fun indent debug -> {
  878. pc_indent = indent;
  879. pc_next_anon_func = (fun () -> incr n; Printf.sprintf "anon_%i" !n);
  880. pc_debug = debug;
  881. }
  882. )
  883. let tabs = ref ""
  884. let opt o f s = match o with
  885. | None -> ""
  886. | Some v -> s ^ (f v)
  887. (* TODO: both of these are crazy *)
  888. let is_type p t =
  889. (fun r ->
  890. let x = t_infos r in
  891. (String.concat "." (fst x.mt_path)) = p && (snd x.mt_path) = t
  892. )
  893. let is_type1 p s =
  894. (fun t -> match follow t with
  895. | TInst(c,_) -> (is_type p s)(TClassDecl c)
  896. | TAbstract(a,_) -> (is_type p s)(TAbstractDecl a)
  897. | TEnum(en,_) -> (is_type p s)(TEnumDecl en)
  898. | _ -> false
  899. )
  900. let is_underlying_string t = match follow t with
  901. | TAbstract(a,tl) -> (is_type1 "" "String")(Abstract.get_underlying_type a tl)
  902. | _ -> false
  903. let is_underlying_array t = match follow t with
  904. | TAbstract(a,tl) -> (is_type1 "" "list")(Abstract.get_underlying_type a tl)
  905. | _ -> false
  906. let rec is_anon_or_dynamic t = match follow t with
  907. | TAbstract(a,tl) ->
  908. is_anon_or_dynamic (Abstract.get_underlying_type a tl)
  909. | TAnon _ | TDynamic _ -> true
  910. | _ -> false
  911. let handle_keywords s =
  912. KeywordHandler.handle_keywords s
  913. let print_unop = function
  914. | Increment | Decrement -> assert false
  915. | Not -> "not "
  916. | Neg -> "-";
  917. | NegBits -> "~"
  918. let print_binop = function
  919. | OpAdd -> "+"
  920. | OpSub -> "-"
  921. | OpMult -> "*"
  922. | OpDiv -> "/"
  923. | OpAssign -> "="
  924. | OpEq -> "=="
  925. | OpNotEq -> "!="
  926. | OpGt -> ">"
  927. | OpGte -> ">="
  928. | OpLt -> "<"
  929. | OpLte -> "<="
  930. | OpAnd -> "&"
  931. | OpOr -> "|"
  932. | OpXor -> "^"
  933. | OpBoolAnd -> "and"
  934. | OpBoolOr -> "or"
  935. | OpShl -> "<<"
  936. | OpShr -> ">>"
  937. | OpUShr -> ">>"
  938. | OpMod -> "%"
  939. | OpInterval | OpArrow | OpAssignOp _ -> assert false
  940. let print_string s =
  941. Printf.sprintf "\"%s\"" (Ast.s_escape s)
  942. let print_constant = function
  943. | TThis -> "self"
  944. | TNull -> "None"
  945. | TBool(true) -> "True"
  946. | TBool(false) -> "False"
  947. | TString(s) -> print_string s
  948. | TInt(i) -> Int32.to_string i
  949. | TFloat s -> s
  950. | TSuper -> "super"
  951. let print_base_type tp =
  952. try
  953. begin match Meta.get Meta.Native tp.mt_meta with
  954. | _,[EConst(String s),_],_ -> s
  955. | _ -> raise Not_found
  956. end
  957. with Not_found ->
  958. let pack,name = tp.mt_path in
  959. (String.concat "_" pack) ^ (if pack = [] then name else "_" ^ name)
  960. let print_module_type mt = print_base_type (t_infos mt)
  961. let print_metadata (name,_,_) =
  962. Printf.sprintf "@%s" name
  963. let print_args args p =
  964. let had_value = ref false in
  965. let had_var_args = ref false in
  966. let had_kw_args = ref false in
  967. let sl = List.map (fun (v,cto) ->
  968. let check_err () = if !had_var_args || !had_kw_args then error "Arguments after KwArgs/VarArgs are not allowed" p in
  969. let name = handle_keywords v.v_name in
  970. match follow v.v_type with
  971. | TAbstract({a_path = ["python"],"KwArgs"},_) ->
  972. if !had_kw_args then error "Arguments after KwArgs are not allowed" p;
  973. had_kw_args := true;
  974. "**" ^ name
  975. | TAbstract({a_path = ["python"],"VarArgs"},_) ->
  976. check_err ();
  977. had_var_args := true;
  978. "*" ^ name
  979. | _ ->
  980. check_err ();
  981. name ^ match cto with
  982. | None when !had_value -> " = None"
  983. | None -> ""
  984. | Some ct ->
  985. had_value := true;
  986. Printf.sprintf " = %s" (print_constant ct)
  987. ) args in
  988. String.concat "," sl
  989. let rec print_op_assign_right pctx e =
  990. match e.eexpr with
  991. | TIf({eexpr = TParenthesis econd},eif,Some eelse)
  992. | TIf(econd,eif,Some eelse) ->
  993. Printf.sprintf "%s if %s else %s" (print_expr pctx eif) (print_expr pctx econd) (print_expr pctx eelse)
  994. | _ ->
  995. print_expr pctx e
  996. and print_var pctx v eo =
  997. match eo with
  998. | Some ({eexpr = TFunction tf} as e) ->
  999. print_function pctx tf (Some v.v_name) e.epos
  1000. | _ ->
  1001. let s_init = match eo with
  1002. | None -> "None"
  1003. | Some e -> print_op_assign_right pctx e
  1004. in
  1005. Printf.sprintf "%s = %s" (handle_keywords v.v_name) s_init
  1006. and print_function pctx tf name p =
  1007. let s_name = match name with
  1008. | None -> pctx.pc_next_anon_func()
  1009. | Some s -> handle_keywords s
  1010. in
  1011. let s_args = print_args tf.tf_args p in
  1012. let s_expr = print_expr {pctx with pc_indent = "\t" ^ pctx.pc_indent} tf.tf_expr in
  1013. Printf.sprintf "def %s(%s):\n%s\t%s" s_name s_args pctx.pc_indent s_expr
  1014. and print_tarray_list pctx e1 e2 =
  1015. let s1 = (print_expr pctx e1) in
  1016. let s2 = (print_expr pctx e2) in
  1017. let default = Printf.sprintf "python_internal_ArrayImpl._get(%s, %s)" s1 s2 in
  1018. let handle_index =
  1019. match e2.eexpr with
  1020. | TConst TInt index ->
  1021. if Int32.to_int index >= 0 then
  1022. Printf.sprintf "(%s[%s] if %s < python_lib_Builtin.len(%s) else None)" s1 s2 s2 s1
  1023. else
  1024. "None"
  1025. | TLocal _ ->
  1026. Printf.sprintf "(%s[%s] if %s >= 0 and %s < python_lib_Builtin.len(%s) else None)" s1 s2 s2 s2 s1
  1027. | _ ->
  1028. default
  1029. in
  1030. match e1.eexpr with
  1031. | TLocal _ -> handle_index
  1032. | TField ({eexpr=(TConst TThis | TLocal _)},_) -> handle_index
  1033. | _ -> default
  1034. and print_expr pctx e =
  1035. let indent = pctx.pc_indent in
  1036. let print_expr_indented e = print_expr {pctx with pc_indent = "\t" ^ pctx.pc_indent} e in
  1037. match e.eexpr with
  1038. | TConst ct ->
  1039. print_constant ct
  1040. | TTypeExpr mt ->
  1041. print_module_type mt
  1042. | TLocal v ->
  1043. handle_keywords v.v_name
  1044. | TEnumParameter(e1,_,index) ->
  1045. Printf.sprintf "%s.params[%i]" (print_expr pctx e1) index
  1046. | TArray(e1,e2) when (is_type1 "" "list")(e1.etype) || is_underlying_array e1.etype ->
  1047. print_tarray_list pctx e1 e2
  1048. | TArray({etype = t} as e1,e2) when is_anon_or_dynamic t ->
  1049. Printf.sprintf "HxOverrides.arrayGet(%s, %s)" (print_expr pctx e1) (print_expr pctx e2)
  1050. | TArray(e1,e2) ->
  1051. Printf.sprintf "%s[%s]" (print_expr pctx e1) (print_expr pctx e2)
  1052. | TBinop(OpAssign, {eexpr = TArray(e1,e2)}, e3) when (is_type1 "" "list")(e1.etype) || is_underlying_array e1.etype ->
  1053. Printf.sprintf "python_internal_ArrayImpl._set(%s, %s, %s)" (print_expr pctx e1) (print_expr pctx e2) (print_expr pctx e3)
  1054. | TBinop(OpAssign,{eexpr = TArray({etype = t} as e1,e2)},e3) when is_anon_or_dynamic t ->
  1055. Printf.sprintf "HxOverrides.arraySet(%s,%s,%s)" (print_expr pctx e1) (print_expr pctx e2) (print_expr pctx e3)
  1056. | TBinop(OpAssign,{eexpr = TArray(e1,e2)},e3) ->
  1057. Printf.sprintf "%s[%s] = %s" (print_expr pctx e1) (print_expr pctx e2) (print_expr pctx e3)
  1058. | TBinop(OpAssign,{eexpr = TField(ef1,fa)},e2) ->
  1059. Printf.sprintf "%s = %s" (print_field pctx ef1 fa true) (print_op_assign_right pctx e2)
  1060. | TBinop(OpAssign,e1,e2) ->
  1061. Printf.sprintf "%s = %s" (print_expr pctx e1) (print_expr pctx e2)
  1062. | TBinop(op,e1,({eexpr = TBinop(_,_,_)} as e2)) ->
  1063. print_expr pctx { e with eexpr = TBinop(op, e1, { e2 with eexpr = TParenthesis(e2) })}
  1064. | TBinop(OpEq,{eexpr = TCall({eexpr = TLocal {v_name = "__typeof__"}},[e1])},e2) ->
  1065. begin match e2.eexpr with
  1066. | TConst(TString s) ->
  1067. begin match s with
  1068. | "string" -> Printf.sprintf "Std._hx_is(%s, python_lib_Builtin.str)" (print_expr pctx e1)
  1069. | "boolean" -> Printf.sprintf "Std._hx_is(%s, python_lib_Builtin.bool)" (print_expr pctx e1)
  1070. | "number" -> Printf.sprintf "Std._hx_is(%s, python_lib_Builtin.float)" (print_expr pctx e1)
  1071. | _ -> assert false
  1072. end
  1073. | _ ->
  1074. assert false
  1075. end
  1076. | TBinop(OpEq,e1,({eexpr = TConst TNull} as e2)) ->
  1077. Printf.sprintf "(%s is %s)" (print_expr pctx e1) (print_expr pctx e2)
  1078. | TBinop(OpNotEq,e1,({eexpr = TConst TNull} as e2)) ->
  1079. Printf.sprintf "(%s is not %s)" (print_expr pctx e1) (print_expr pctx e2)
  1080. | TBinop(OpEq|OpNotEq as op,e1, e2) ->
  1081. let ops = match op with
  1082. | OpEq -> "is", "==", "HxOverrides.eq"
  1083. | OpNotEq -> "is not", "!=", "not HxOverrides.eq"
  1084. | _ -> assert false
  1085. in
  1086. let third (_,_,x) = x in
  1087. let fst (x,_,_) = x in
  1088. let snd (_,x,_) = x in
  1089. let is_list_or_anon x = begin match x with
  1090. | TInst({cl_path = [],("list")},_) -> true
  1091. | TAnon _ -> true
  1092. | _ -> false
  1093. end in
  1094. let is_const_byte x =
  1095. match x.eexpr with
  1096. | TConst TInt x ->
  1097. let x = Int32.to_int x in
  1098. x >= 0 && x <= 256
  1099. | _ -> false
  1100. in
  1101. (match follow e1.etype, follow e2.etype with
  1102. | TAbstract({a_path = [],("Int")}, _),TAbstract({a_path = [],("Int")}, _) when is_const_byte e2 || is_const_byte e1 ->
  1103. Printf.sprintf "(%s %s %s)" (print_expr pctx e1) (snd ops) (print_expr pctx e2)
  1104. (* the following optimization causes a problem with polygonal unit tests
  1105. see: https://github.com/HaxeFoundation/haxe/issues/2952
  1106. *)
  1107. (* Printf.sprintf "(%s %s %s)" (print_expr pctx e1) (fst ops) (print_expr pctx e2) *)
  1108. | TAbstract({a_path = [],("String")}, []),TAbstract({a_path = [],("String")}, []) when (is_type1 "" "String") (e.etype)->
  1109. Printf.sprintf "(%s %s %s)" (print_expr pctx e1) (fst ops) (print_expr pctx e2)
  1110. | TInst({cl_path = [],("list")},_), _ ->
  1111. Printf.sprintf "(%s %s %s)" (print_expr pctx e1) (fst ops) (print_expr pctx e2)
  1112. | TDynamic _, TDynamic _ ->
  1113. Printf.sprintf "%s(%s,%s)" (third ops) (print_expr pctx e1) (print_expr pctx e2)
  1114. | TDynamic _, x | x, TDynamic _ when is_list_or_anon x ->
  1115. Printf.sprintf "%s(%s,%s)" (third ops) (print_expr pctx e1) (print_expr pctx e2)
  1116. | _,_ -> Printf.sprintf "(%s %s %s)" (print_expr pctx e1) (snd ops) (print_expr pctx e2))
  1117. | TBinop(OpMod,e1,e2) when (is_type1 "" "Int")(e1.etype) && (is_type1 "" "Int")(e2.etype) ->
  1118. Printf.sprintf "(%s %% %s)" (print_expr pctx e1) (print_expr pctx e2)
  1119. | TBinop(OpMod,e1,e2) ->
  1120. Printf.sprintf "HxOverrides.modf(%s, %s)" (print_expr pctx e1) (print_expr pctx e2)
  1121. | TBinop(OpUShr,e1,e2) ->
  1122. Printf.sprintf "HxOverrides.rshift(%s, %s)" (print_expr pctx e1) (print_expr pctx e2)
  1123. | TBinop(OpAdd,e1,e2) when (is_type1 "" "String")(e.etype) || is_underlying_string e.etype ->
  1124. let follow_parens e = match e.eexpr with
  1125. | TParenthesis e -> e
  1126. | _ -> e
  1127. in
  1128. let rec is_safe_string x =
  1129. match (follow_parens x).eexpr with
  1130. | TBinop(OpAdd, e1, e2) -> is_safe_string e1 && is_safe_string e2
  1131. | TCall (e1,_) ->
  1132. let id = print_expr pctx (follow_parens e1) in
  1133. (match id with
  1134. | "Std.string" -> true
  1135. | _ -> false)
  1136. | TConst (TString s) -> true
  1137. | _ -> false
  1138. in
  1139. let rec safe_string ex =
  1140. match ex.eexpr, ex.etype with
  1141. | e, _ when is_safe_string ex -> print_expr pctx ex
  1142. | TBinop(OpAdd, e1, e2), x when (is_type1 "" "String")(x) -> Printf.sprintf "(%s + %s)" (safe_string e1) (safe_string e2)
  1143. | _,x when (is_type1 "" "String")(x) -> Printf.sprintf "HxOverrides.stringOrNull(%s)" (print_expr pctx ex)
  1144. | _,_ -> Printf.sprintf "Std.string(%s)" (print_expr pctx ex)
  1145. in
  1146. let e1_str = safe_string e1 in
  1147. let e2_str = safe_string e2 in
  1148. Printf.sprintf "(%s + %s)" e1_str e2_str
  1149. | TBinop(OpAdd,e1,e2) when (match follow e.etype with TDynamic _ -> true | _ -> false) ->
  1150. Printf.sprintf "python_Boot._add_dynamic(%s,%s)" (print_expr pctx e1) (print_expr pctx e2);
  1151. | TBinop(op,e1,e2) ->
  1152. Printf.sprintf "(%s %s %s)" (print_expr pctx e1) (print_binop op) (print_expr pctx e2)
  1153. | TField(e1,fa) ->
  1154. print_field pctx e1 fa false
  1155. | TParenthesis e1 ->
  1156. Printf.sprintf "(%s)" (print_expr pctx e1)
  1157. | TObjectDecl fl ->
  1158. let fl2 = ref fl in
  1159. begin match follow e.etype with
  1160. | TAnon an ->
  1161. PMap.iter (fun s cf ->
  1162. if not (List.mem_assoc s fl) then fl2 := (s,null cf.cf_type cf.cf_pos) :: !fl2
  1163. ) an.a_fields
  1164. | _ ->
  1165. ()
  1166. end;
  1167. Printf.sprintf "_hx_AnonObject(%s)" (print_exprs_named pctx ", " !fl2)
  1168. | TArrayDecl el ->
  1169. Printf.sprintf "[%s]" (print_exprs pctx ", " el)
  1170. | TCall(e1,el) ->
  1171. print_call pctx e1 el
  1172. | TNew(c,_,el) ->
  1173. let id = print_base_type (t_infos (TClassDecl c)) in
  1174. Printf.sprintf "%s(%s)" id (print_exprs pctx ", " el)
  1175. | TUnop(Not,Prefix,e1) ->
  1176. Printf.sprintf "(%s%s)" (print_unop Not) (print_expr pctx e1)
  1177. | TUnop(op,Prefix,e1) ->
  1178. Printf.sprintf "%s%s" (print_unop op) (print_expr pctx e1)
  1179. | TFunction tf ->
  1180. print_function pctx tf None e.epos
  1181. | TVar (v,eo) ->
  1182. print_var pctx v eo
  1183. | TBlock [] ->
  1184. Printf.sprintf "pass"
  1185. | TBlock [{ eexpr = TBlock _} as b] ->
  1186. print_expr pctx b
  1187. | TBlock el ->
  1188. let old = !tabs in
  1189. tabs := pctx.pc_indent;
  1190. let s = print_block_exprs pctx ("\n" ^ !tabs) pctx.pc_debug el in
  1191. tabs := old;
  1192. Printf.sprintf "%s" s
  1193. | TIf(econd,eif,(Some {eexpr = TIf _} as eelse)) ->
  1194. print_if_else pctx econd eif eelse true
  1195. | TIf(econd,eif,eelse) ->
  1196. print_if_else pctx econd eif eelse false
  1197. | TWhile(econd,e1,NormalWhile) ->
  1198. Printf.sprintf "while %s:\n%s\t%s" (print_expr pctx econd) indent (print_expr_indented e1)
  1199. | TWhile(econd,e1,DoWhile) ->
  1200. error "Currently not supported" e.epos
  1201. | TTry(e1,catches) ->
  1202. print_try pctx e1 catches
  1203. | TReturn eo ->
  1204. Printf.sprintf "return%s" (opt eo (print_op_assign_right pctx) " ")
  1205. | TBreak ->
  1206. "break"
  1207. | TContinue ->
  1208. "continue"
  1209. | TThrow e1 ->
  1210. let rec is_native_exception t =
  1211. match Abstract.follow_with_abstracts t with
  1212. | TInst ({ cl_path = [],"BaseException" }, _) ->
  1213. true
  1214. | TInst ({ cl_super = Some csup }, _) ->
  1215. is_native_exception (TInst(fst csup, snd csup))
  1216. | _ ->
  1217. false
  1218. in
  1219. if is_native_exception e1.etype then
  1220. Printf.sprintf "raise %s" (print_expr pctx e1)
  1221. else
  1222. Printf.sprintf "raise _HxException(%s)" (print_expr pctx e1)
  1223. | TCast(e1,None) ->
  1224. print_expr pctx e1
  1225. | TMeta((Meta.Custom ":ternaryIf",_,_),{eexpr = TIf(econd,eif,Some eelse)}) ->
  1226. Printf.sprintf "(%s if %s else %s)" (print_expr pctx eif) (print_expr pctx econd) (print_expr pctx eelse)
  1227. | TMeta(_,e1) ->
  1228. print_expr pctx e1
  1229. | TSwitch _ | TCast(_, Some _) | TFor _ | TUnop(_,Postfix,_) ->
  1230. assert false
  1231. and print_if_else pctx econd eif eelse as_elif =
  1232. let econd1 = match econd.eexpr with
  1233. | TParenthesis e -> e
  1234. | _ -> econd
  1235. in
  1236. let if_str = print_expr {pctx with pc_indent = "\t" ^ pctx.pc_indent} eif in
  1237. let indent = pctx.pc_indent in
  1238. let else_str = if as_elif then
  1239. opt eelse (print_expr pctx) "el"
  1240. else
  1241. opt eelse (print_expr {pctx with pc_indent = "\t" ^ pctx.pc_indent}) (Printf.sprintf "else:\n%s\t" indent)
  1242. in
  1243. let else_str = if else_str = "" then "" else "\n" ^ indent ^ else_str in
  1244. Printf.sprintf "if %s:\n%s\t%s%s" (print_expr pctx econd1) indent if_str else_str
  1245. and print_field pctx e1 fa is_assign =
  1246. let obj = match e1.eexpr with
  1247. | TConst TSuper -> "super()"
  1248. | _ -> print_expr pctx e1
  1249. in
  1250. let name = field_name fa in
  1251. let is_extern = (match fa with
  1252. | FInstance(c,_,_) -> c.cl_extern
  1253. | FStatic(c,_) -> c.cl_extern
  1254. | _ -> false)
  1255. in
  1256. let do_default () =
  1257. Printf.sprintf "%s.%s" obj (if is_extern then name else (handle_keywords name))
  1258. in
  1259. let call_override s =
  1260. match s with
  1261. | "iterator" | "toUpperCase" | "toLowerCase" | "pop" | "shift" | "join" | "push" | "map" | "filter" -> true
  1262. | _ -> false
  1263. in
  1264. match fa with
  1265. (* we need to get rid of these cases in the transformer, how is this handled in js *)
  1266. | FInstance(c,_,{cf_name = "length" | "get_length"}) when (is_type "" "list")(TClassDecl c) ->
  1267. Printf.sprintf "python_lib_Builtin.len(%s)" (print_expr pctx e1)
  1268. | FInstance(c,_,{cf_name = "length"}) when (is_type "" "String")(TClassDecl c) ->
  1269. Printf.sprintf "python_lib_Builtin.len(%s)" (print_expr pctx e1)
  1270. | FStatic(c,{cf_name = "fromCharCode"}) when (is_type "" "String")(TClassDecl c) ->
  1271. Printf.sprintf "HxString.fromCharCode"
  1272. | FInstance _ | FStatic _ ->
  1273. do_default ()
  1274. | FAnon cf when is_assign && call_override(name) ->
  1275. begin match follow cf.cf_type with
  1276. | TFun([],_) ->
  1277. Printf.sprintf "python_lib_FuncTools.partial(HxOverrides.%s, %s)" name obj
  1278. | _ ->
  1279. do_default()
  1280. end
  1281. | _ ->
  1282. do_default()
  1283. and print_try pctx e1 catches =
  1284. let has_catch_all = List.exists (fun (v,_) -> match v.v_type with
  1285. | TDynamic _ -> true
  1286. | _ -> false
  1287. ) catches in
  1288. let has_only_catch_all = has_catch_all && begin match catches with
  1289. | [_] -> true
  1290. | _ -> false
  1291. end in
  1292. let print_catch pctx i (v,e) =
  1293. let is_empty_expr = begin match e.eexpr with
  1294. | TBlock [] -> true
  1295. | _ -> false
  1296. end in
  1297. let indent = pctx.pc_indent in
  1298. (* Don't generate assignment to catch variable when catch expression is an empty block *)
  1299. let assign = if is_empty_expr then "" else Printf.sprintf "%s = _hx_e1\n%s" v.v_name indent in
  1300. let handle_base_type bt =
  1301. let t = print_base_type bt in
  1302. let res = if t = "String" then
  1303. Printf.sprintf "if python_lib_Builtin.isinstance(_hx_e1, str):\n%s\t%s\t%s" indent assign (print_expr {pctx with pc_indent = "\t" ^ pctx.pc_indent} e)
  1304. else
  1305. Printf.sprintf "if python_lib_Builtin.isinstance(_hx_e1, %s):\n%s\t%s\t%s" t indent assign (print_expr {pctx with pc_indent = "\t" ^ pctx.pc_indent} e)
  1306. in
  1307. if i > 0 then
  1308. indent ^ "el" ^ res
  1309. else
  1310. res
  1311. in
  1312. match follow v.v_type with
  1313. | TDynamic _ ->
  1314. begin if has_only_catch_all then
  1315. Printf.sprintf "%s%s" assign (print_expr pctx e)
  1316. else
  1317. (* Dynamic is always the last block *)
  1318. Printf.sprintf "%selse:\n\t%s%s\t%s" indent indent assign (print_expr {pctx with pc_indent = "\t" ^ pctx.pc_indent} e)
  1319. end
  1320. | TInst(c,_) ->
  1321. handle_base_type (t_infos (TClassDecl c))
  1322. | TEnum(en,_) ->
  1323. handle_base_type (t_infos (TEnumDecl en))
  1324. | _ ->
  1325. assert false
  1326. in
  1327. let indent = pctx.pc_indent in
  1328. let print_expr_indented e = print_expr {pctx with pc_indent = "\t" ^ pctx.pc_indent} e in
  1329. let try_str = Printf.sprintf "try:\n%s\t%s\n%s" indent (print_expr_indented e1) indent in
  1330. let except = Printf.sprintf "except Exception as _hx_e:\n%s\t_hx_e1 = _hx_e.val if isinstance(_hx_e, _HxException) else _hx_e\n%s\t" indent indent in
  1331. let catch_str = String.concat (Printf.sprintf "\n") (ExtList.List.mapi (fun i catch -> print_catch {pctx with pc_indent = "\t" ^ pctx.pc_indent} i catch) catches) in
  1332. let except_end = if not has_catch_all then Printf.sprintf "\n%s\telse:\n%s\t\traise _hx_e" indent indent else "" in
  1333. Printf.sprintf "%s%s%s%s" try_str except catch_str except_end
  1334. and print_call2 pctx e1 el =
  1335. let id = print_expr pctx e1 in
  1336. match id,el with
  1337. | "super",_ ->
  1338. let s_el = print_exprs pctx ", " el in
  1339. Printf.sprintf "super().__init__(%s)" s_el
  1340. | ("python_Syntax._pythonCode"),[({ eexpr = TConst (TString code) } as ecode); {eexpr = TArrayDecl tl}] ->
  1341. let exprs = Array.of_list tl in
  1342. let i = ref 0 in
  1343. let err msg =
  1344. let pos = { ecode.epos with pmin = ecode.epos.pmin + !i } in
  1345. error msg pos
  1346. in
  1347. let regex = Str.regexp "[{}]" in
  1348. let rec loop m = match m with
  1349. | [] -> ""
  1350. | Str.Text txt :: tl ->
  1351. i := !i + String.length txt;
  1352. txt ^ (loop tl)
  1353. | Str.Delim a :: Str.Delim b :: tl when a = b ->
  1354. i := !i + 2;
  1355. a ^ (loop tl)
  1356. | Str.Delim "{" :: Str.Text n :: Str.Delim "}" :: tl ->
  1357. (try
  1358. let expr = Array.get exprs (int_of_string n) in
  1359. let txt = print_expr pctx expr in
  1360. i := !i + 2 + String.length n;
  1361. txt ^ (loop tl)
  1362. with | Failure "int_of_string" ->
  1363. err ("Index expected. Got " ^ n)
  1364. | Invalid_argument _ ->
  1365. err ("Out-of-bounds pythonCode special parameter: " ^ n))
  1366. | Str.Delim x :: _ ->
  1367. err ("Unexpected " ^ x)
  1368. in
  1369. loop (Str.full_split regex code)
  1370. | ("python_Syntax._pythonCode"), [e] ->
  1371. print_expr pctx e
  1372. | "python_Syntax._callNamedUntyped",el ->
  1373. let res,fields = match List.rev el with
  1374. | {eexpr = TObjectDecl fields} :: el ->
  1375. List.rev el,fields
  1376. | _ ->
  1377. assert false
  1378. in
  1379. begin match res with
  1380. | e1 :: [] ->
  1381. Printf.sprintf "%s(%s)" (print_expr pctx e1) (print_params_named pctx ", " fields)
  1382. | e1 :: el ->
  1383. Printf.sprintf "%s(%s, %s)" (print_expr pctx e1) (print_exprs pctx ", " el) (print_params_named pctx ", " fields)
  1384. | [] ->
  1385. Printf.sprintf "%s(%s)" (print_expr pctx e1) (print_params_named pctx ", " fields)
  1386. end
  1387. | "python_Syntax.varArgs",[e1] ->
  1388. "*" ^ (print_expr pctx e1)
  1389. | "python_Syntax.call" ,e1 :: [{eexpr = TArrayDecl el}]->
  1390. Printf.sprintf "%s(%s)" (print_expr pctx e1) (print_exprs pctx ", " el)
  1391. | "python_Syntax.field",[e1;{eexpr = TConst(TString id)}] ->
  1392. Printf.sprintf "%s.%s" (print_expr pctx e1) id
  1393. | "python_Syntax._tuple", [{eexpr = TArrayDecl el}] ->
  1394. Printf.sprintf "(%s)" (print_exprs pctx ", " el)
  1395. | "python_Syntax._arrayAccess", e1 :: {eexpr = TArrayDecl el} :: etrail ->
  1396. let trailing_colon = match etrail with
  1397. | [{eexpr = TConst(TBool(true))}] -> true
  1398. | _ -> false
  1399. in
  1400. Printf.sprintf "%s[%s%s]" (print_expr pctx e1) (print_exprs pctx ":" el) (if trailing_colon then ":" else "")
  1401. | "python_Syntax.isIn",[e1;e2] ->
  1402. Printf.sprintf "%s in %s" (print_expr pctx e1) (print_expr pctx e2)
  1403. | "python_Syntax.delete",[e1] ->
  1404. Printf.sprintf "del %s" (print_expr pctx e1)
  1405. | "python_Syntax.binop",[e0;{eexpr = TConst(TString id)};e2] ->
  1406. Printf.sprintf "(%s %s %s)" (print_expr pctx e0) id (print_expr pctx e2)
  1407. | "python_Syntax.assign",[e0;e1] ->
  1408. Printf.sprintf "%s = %s" (print_expr pctx e0) (print_expr pctx e1)
  1409. | "python_Syntax.arraySet",[e1;e2;e3] ->
  1410. Printf.sprintf "%s[%s] = %s" (print_expr pctx e1) (print_expr pctx e2) (print_expr pctx e3)
  1411. | "python_Syntax._newInstance", e1 :: [{eexpr = TArrayDecl el}] ->
  1412. Printf.sprintf "%s(%s)" (print_expr pctx e1) (print_exprs pctx ", " el)
  1413. | "python_Syntax.opPow", [e1;e2] ->
  1414. Printf.sprintf "(%s ** %s)" (print_expr pctx e1) (print_expr pctx e2)
  1415. | "python_Syntax._foreach",[e1;e2;e3] ->
  1416. let pctx = {pctx with pc_indent = "\t" ^ pctx.pc_indent} in
  1417. let i = pctx.pc_indent in
  1418. Printf.sprintf "for %s in %s:\n%s%s" (print_expr pctx e1) (print_expr pctx e2) i (print_expr pctx e3)
  1419. | _,el ->
  1420. Printf.sprintf "%s(%s)" id (print_call_args pctx e1 el)
  1421. and print_call pctx e1 el =
  1422. match e1.eexpr, el with
  1423. | TField(e1,((FAnon {cf_name = (("join" | "push" | "map" | "filter") as s)}) | FDynamic (("join" | "push" | "map" | "filter") as s))), [x] ->
  1424. Printf.sprintf "HxOverrides.%s(%s, %s)" s (print_expr pctx e1) (print_expr pctx x)
  1425. | TField(e1,((FAnon {cf_name = (("iterator" | "toUpperCase" | "toLowerCase" | "pop" | "shift") as s)}) | FDynamic (("iterator" | "toUpperCase" | "toLowerCase" | "pop" | "shift") as s))), [] ->
  1426. Printf.sprintf "HxOverrides.%s(%s)" s (print_expr pctx e1)
  1427. | _,_ ->
  1428. print_call2 pctx e1 el
  1429. and print_call_args pctx e1 el =
  1430. let print_arg pctx i x =
  1431. let e = match x.eexpr, follow x.etype with
  1432. | TConst TNull, TAbstract({a_path = ["python"],"KwArgs"},_) -> "{}"
  1433. | TConst TNull, TAbstract({a_path = ["python"],"VarArgs"},_) -> "[]"
  1434. | _ -> (print_expr pctx x)
  1435. in
  1436. let prefix = match e1.eexpr, follow x.etype with
  1437. (* the should not apply for the instance methods of the abstract itself *)
  1438. | TField(_, FStatic({cl_path = ["python"; "_KwArgs"],"KwArgs_Impl_"},f)), _ when i == 0 && Meta.has Meta.Impl f.cf_meta -> ""
  1439. | TField(_, FStatic({cl_path = ["python"; "_VarArgs"],"VarArgs_Impl_"},f)), _ when i == 0 && Meta.has Meta.Impl f.cf_meta -> ""
  1440. | _, TAbstract({a_path = ["python"],"KwArgs"},_) -> "**"
  1441. | _, TAbstract({a_path = ["python"],"VarArgs"},_) -> "*"
  1442. | _, _ -> ""
  1443. in
  1444. prefix ^ e
  1445. in
  1446. String.concat "," (ExtList.List.mapi (print_arg pctx) el)
  1447. and print_exprs pctx sep el =
  1448. String.concat sep (List.map (print_expr pctx) el)
  1449. and print_block_exprs pctx sep print_debug_comment el =
  1450. if print_debug_comment then begin
  1451. let el = List.fold_left (fun acc e ->
  1452. let line = Lexer.get_error_line e.epos in
  1453. (print_expr pctx e) :: (Printf.sprintf "# %s:%i" e.epos.pfile line) :: acc
  1454. ) [] el in
  1455. String.concat sep (List.rev el)
  1456. end else
  1457. print_exprs pctx sep el
  1458. and print_exprs_named pctx sep fl =
  1459. let args = String.concat sep (List.map (fun (s,e) -> Printf.sprintf "'%s': %s" (handle_keywords s) (print_expr pctx e)) fl) in
  1460. Printf.sprintf "{%s}" args
  1461. and print_params_named pctx sep fl =
  1462. let args = String.concat sep (List.map (fun (s,e) -> Printf.sprintf "%s= %s" (handle_keywords s) (print_expr pctx e)) fl) in
  1463. Printf.sprintf "%s" args
  1464. let handle_keywords s =
  1465. KeywordHandler.handle_keywords s
  1466. end
  1467. module Generator = struct
  1468. type context = {
  1469. com : Common.context;
  1470. buf : Buffer.t;
  1471. packages : (string,int) Hashtbl.t;
  1472. mutable static_inits : (unit -> unit) list;
  1473. mutable class_inits : (unit -> unit) list;
  1474. mutable indent_count : int;
  1475. transform_time : float;
  1476. print_time : float;
  1477. }
  1478. type class_field_infos = {
  1479. cfd_fields : string list;
  1480. cfd_props : string list;
  1481. cfd_methods : string list;
  1482. }
  1483. type import_type =
  1484. | IModule of string
  1485. | IObject of string * string
  1486. let mk_context com = {
  1487. com = com;
  1488. buf = Buffer.create 16000;
  1489. packages = Hashtbl.create 0;
  1490. static_inits = [];
  1491. class_inits = [];
  1492. indent_count = 0;
  1493. transform_time = 0.;
  1494. print_time = 0.;
  1495. }
  1496. (* Transformer interface *)
  1497. let transform_expr e =
  1498. (* let e = Codegen.UnificationCallback.run Transformer.check_unification e in *)
  1499. Transformer.transform e
  1500. let transform_to_value e =
  1501. (* let e = Codegen.UnificationCallback.run Transformer.check_unification e in *)
  1502. Transformer.transform_to_value e
  1503. (* Printer interface *)
  1504. let get_path mt =
  1505. Printer.print_base_type mt
  1506. let tfunc_str f pctx name p =
  1507. Printer.print_function pctx f name p
  1508. let texpr_str e pctx =
  1509. Printer.print_expr pctx e
  1510. let handle_keywords s =
  1511. Printer.handle_keywords s
  1512. (* Helper *)
  1513. let get_full_name mt =
  1514. (* TODO: haxe source is crazy *)
  1515. s_type_path mt.mt_path
  1516. let collect_class_field_data cfl =
  1517. let fields = DynArray.create () in
  1518. let props = DynArray.create () in
  1519. let methods = DynArray.create () in
  1520. List.iter (fun cf ->
  1521. match cf.cf_kind with
  1522. | Var({v_read = AccResolve}) ->
  1523. ()
  1524. | Var _ when is_extern_field cf ->
  1525. ()
  1526. | Var({v_read = AccCall}) ->
  1527. if Meta.has Meta.IsVar cf.cf_meta then
  1528. DynArray.add fields cf.cf_name
  1529. else
  1530. DynArray.add props cf.cf_name
  1531. | Var _ ->
  1532. DynArray.add fields cf.cf_name
  1533. | _ ->
  1534. DynArray.add methods cf.cf_name
  1535. ) cfl;
  1536. {
  1537. cfd_fields = DynArray.to_list fields;
  1538. cfd_props = DynArray.to_list props;
  1539. cfd_methods = DynArray.to_list methods;
  1540. }
  1541. let collect_class_statics_data cfl =
  1542. let fields = DynArray.create () in
  1543. List.iter (fun cf ->
  1544. if not (is_extern_field cf) then
  1545. DynArray.add fields cf.cf_name
  1546. ) cfl;
  1547. DynArray.to_list fields
  1548. let filter_py_metas metas =
  1549. List.filter (fun (n,_,_) -> match n with Meta.Custom ":python" -> true | _ -> false) metas
  1550. let get_members_with_init_expr c =
  1551. List.filter (fun cf -> match cf.cf_kind with
  1552. | Var _ when is_extern_field cf -> false
  1553. | Var _ when cf.cf_expr = None -> true
  1554. | _ -> false
  1555. ) c.cl_ordered_fields
  1556. (* Printing *)
  1557. let spr ctx s =
  1558. Buffer.add_string ctx.buf s
  1559. let spr_line ctx s =
  1560. Buffer.add_string ctx.buf s;
  1561. Buffer.add_string ctx.buf "\n"
  1562. let print ctx =
  1563. Printf.kprintf (fun s -> begin
  1564. Buffer.add_string ctx.buf s
  1565. end)
  1566. let newline ctx =
  1567. spr ctx "\n"
  1568. (* Generating functions *)
  1569. let gen_pre_code_meta ctx metadata =
  1570. try
  1571. begin match Meta.get (Meta.Custom ":preCode") metadata with
  1572. | _,[(EConst(String s)),_],_ ->
  1573. newline ctx;
  1574. spr ctx s
  1575. | _ ->
  1576. raise Not_found
  1577. end
  1578. with Not_found ->
  1579. ()
  1580. let gen_py_metas ctx metas indent =
  1581. List.iter (fun (n,el,_) ->
  1582. match el with
  1583. | [EConst(String s),_] ->
  1584. print ctx "%s@%s\n" indent s
  1585. | _ ->
  1586. assert false
  1587. ) metas
  1588. let gen_expr ctx e field indent =
  1589. let pctx = Printer.create_context ("\t" ^ indent) ctx.com.debug in
  1590. let e = match e.eexpr with
  1591. | TFunction(f) ->
  1592. {e with eexpr = TBlock [e]}
  1593. | _ ->
  1594. e
  1595. in
  1596. let expr2 = transform_to_value e in
  1597. let name = "_hx_init_" ^ (String.concat "_" (ExtString.String.nsplit field ".")) in
  1598. let maybe_split_expr expr2 = match expr2.eexpr with
  1599. | TBlock es when es <> [] && field <> "" ->
  1600. begin match List.rev es with
  1601. | e_last :: el ->
  1602. let new_last = {e_last with eexpr = TReturn (Some e_last)} in
  1603. let new_block = {expr2 with eexpr = TBlock (List.rev (new_last :: el))} in
  1604. let v_name = alloc_var name (tfun [] e_last.etype) in
  1605. let f_name = mk (TLocal v_name) v_name.v_type e_last.epos in
  1606. let call_f = mk (TCall(f_name,[])) e_last.etype e_last.epos in
  1607. Some new_block,call_f
  1608. | _ ->
  1609. assert false
  1610. end
  1611. | _ ->
  1612. None,expr2
  1613. in
  1614. let r = maybe_split_expr expr2 in
  1615. match r with
  1616. | Some e1,e2 ->
  1617. let expr_string_1 = texpr_str e1 pctx in
  1618. let expr_string_2 = texpr_str e2 pctx in
  1619. print ctx "%sdef %s():\n\t%s" indent name expr_string_1;
  1620. newline ctx;
  1621. print ctx "%s%s = %s" indent field expr_string_2;
  1622. | None,e2 ->
  1623. let expr_string_2 = texpr_str e2 pctx in
  1624. if field = "" then
  1625. spr ctx expr_string_2
  1626. else
  1627. print ctx "%s%s = %s" indent field expr_string_2
  1628. let gen_func_expr ctx e c name metas extra_args indent stat p =
  1629. let pctx = Printer.create_context indent ctx.com.debug in
  1630. let e = match e.eexpr with
  1631. | TFunction(f) ->
  1632. let args = List.map (fun s ->
  1633. alloc_var s t_dynamic,None
  1634. ) extra_args in
  1635. {e with eexpr = TFunction {f with tf_args = args @ f.tf_args}}
  1636. | _ ->
  1637. e
  1638. in
  1639. if stat then begin
  1640. newline ctx;
  1641. spr ctx indent;
  1642. spr ctx "@staticmethod\n"
  1643. end;
  1644. let expr1 = transform_expr e in
  1645. let expr_string = match expr1.eexpr with
  1646. | TFunction f ->
  1647. tfunc_str f pctx (Some name) p
  1648. | _ ->
  1649. Printf.sprintf "%s = %s" name (texpr_str expr1 pctx)
  1650. in
  1651. gen_py_metas ctx metas indent;
  1652. spr ctx indent;
  1653. spr ctx expr_string
  1654. let gen_class_constructor ctx c cf =
  1655. let member_inits = get_members_with_init_expr c in
  1656. let py_metas = filter_py_metas cf.cf_meta in
  1657. begin match member_inits,cf.cf_expr with
  1658. | _,Some ({eexpr = TFunction f} as ef) ->
  1659. let ethis = mk (TConst TThis) (TInst(c,List.map snd c.cl_params)) cf.cf_pos in
  1660. let member_data = List.map (fun cf ->
  1661. let ef = mk (TField(ethis,FInstance(c,[],cf))) cf.cf_type cf.cf_pos in (* TODO *)
  1662. mk (TBinop(OpAssign,ef,null ef.etype ef.epos)) ef.etype ef.epos
  1663. ) member_inits in
  1664. let e = {f.tf_expr with eexpr = TBlock (member_data @ [f.tf_expr])} in
  1665. cf.cf_expr <- Some {ef with eexpr = TFunction {f with tf_expr = e}};
  1666. | _ ->
  1667. (* TODO: is this correct? *)
  1668. ()
  1669. end;
  1670. newline ctx;
  1671. newline ctx;
  1672. gen_func_expr ctx (match cf.cf_expr with None -> assert false | Some e -> e) c "__init__" py_metas ["self"] "\t" false cf.cf_pos
  1673. let gen_class_field ctx c p cf =
  1674. let field = handle_keywords cf.cf_name in
  1675. begin match cf.cf_expr with
  1676. | None ->
  1677. ()(* print ctx "\t# var %s" field *)
  1678. | Some e ->
  1679. newline ctx;
  1680. newline ctx;
  1681. begin match cf.cf_kind with
  1682. | Method _ ->
  1683. let py_metas = filter_py_metas cf.cf_meta in
  1684. gen_func_expr ctx e c field py_metas ["self"] "\t" false cf.cf_pos;
  1685. | _ ->
  1686. gen_expr ctx e (Printf.sprintf "# var %s" field) "\t";
  1687. end
  1688. end
  1689. let gen_class_register ctx c cfd p_super p_interfaces p p_name =
  1690. print ctx "@_hx_classes.registerClass(\"%s\"" p_name;
  1691. let add_names_arg lst arg_name =
  1692. match lst with
  1693. | [] -> ()
  1694. | l ->
  1695. let s = String.concat "," (List.map (fun s -> "\"" ^ s ^ "\"") l) in
  1696. print ctx ", %s=[%s]" arg_name s
  1697. in
  1698. add_names_arg cfd.cfd_fields "fields";
  1699. add_names_arg cfd.cfd_props "props";
  1700. add_names_arg cfd.cfd_methods "methods";
  1701. (* TODO: It seems strange to have a separation for member fields but a plain _hx_statics for static ones *)
  1702. add_names_arg (collect_class_statics_data c.cl_ordered_statics) "statics";
  1703. (match p_interfaces with
  1704. | [] -> ()
  1705. | l -> print ctx ", interfaces=[%s]" (String.concat "," p_interfaces)
  1706. );
  1707. (match p_super with
  1708. | None -> ()
  1709. | Some ps -> print ctx ", superClass=%s" ps);
  1710. print ctx ")\n"
  1711. let gen_class_empty_constructor ctx p cfl =
  1712. newline ctx;
  1713. newline ctx;
  1714. print ctx "\t@staticmethod\n\tdef _hx_empty_init(_hx_o):";
  1715. let found_fields = ref false in
  1716. List.iter (fun cf -> match cf.cf_kind with
  1717. | Var ({v_read = AccResolve | AccCall}) ->
  1718. ()
  1719. | Var _ ->
  1720. found_fields := true;
  1721. newline ctx;
  1722. print ctx "\t\t_hx_o.%s = None" (handle_keywords cf.cf_name)
  1723. | _ ->
  1724. ()
  1725. ) cfl;
  1726. if not !found_fields then
  1727. spr ctx "\t\tpass"
  1728. let gen_class_statics ctx c p =
  1729. let methods, other = List.partition (fun cf ->
  1730. match cf.cf_kind with
  1731. | Method _ -> (match cf.cf_expr with Some _ -> true | _ -> false)
  1732. | _ -> false
  1733. ) c.cl_ordered_statics in
  1734. (* generate non methods *)
  1735. let has_empty_static_vars = ref false in
  1736. List.iter (fun cf ->
  1737. let p = get_path (t_infos (TClassDecl c)) in
  1738. let field = handle_keywords cf.cf_name in
  1739. match cf.cf_expr with
  1740. | None ->
  1741. has_empty_static_vars := true;
  1742. newline ctx;
  1743. print ctx "\t%s = None" field
  1744. | Some e ->
  1745. (let f = fun () ->
  1746. newline ctx;
  1747. gen_expr ctx e (Printf.sprintf "%s.%s" p field) "";
  1748. in
  1749. ctx.static_inits <- f :: ctx.static_inits)
  1750. ) other;
  1751. (* generate static methods *)
  1752. let has_static_methods = ref false in
  1753. List.iter (fun cf ->
  1754. has_static_methods := true;
  1755. let field = handle_keywords cf.cf_name in
  1756. let py_metas = filter_py_metas cf.cf_meta in
  1757. let e = match cf.cf_expr with Some e -> e | _ -> assert false in
  1758. newline ctx;
  1759. gen_func_expr ctx e c field py_metas [] "\t" true cf.cf_pos;
  1760. ) methods;
  1761. !has_static_methods || !has_empty_static_vars
  1762. let gen_class_init ctx c =
  1763. match c.cl_init with
  1764. | None ->
  1765. ()
  1766. | Some e ->
  1767. let f = fun () ->
  1768. let e = transform_expr e in
  1769. newline ctx;
  1770. spr ctx (texpr_str e (Printer.create_context "" ctx.com.debug));
  1771. in
  1772. ctx.class_inits <- f :: ctx.class_inits
  1773. let gen_import ctx path meta =
  1774. gen_pre_code_meta ctx meta;
  1775. if Meta.has Meta.PythonImport meta && is_directly_used ctx.com meta then begin
  1776. let _, args, mp = Meta.get Meta.PythonImport meta in
  1777. let class_name = match path with
  1778. | [],name -> name
  1779. | path,name -> (ExtString.String.join "_" path) ^ "_" ^ name
  1780. in
  1781. let import_type,ignore_error = match args with
  1782. | [(EConst(String(module_name)), _)]
  1783. | [(EConst(String(module_name)), _); (EBinop(OpAssign, (EConst(Ident("ignoreError")),_), (EConst(Ident("false")),_)),_)] ->
  1784. IModule module_name, false
  1785. | [(EConst(String(module_name)), _); (EBinop(OpAssign, (EConst(Ident("ignoreError")),_), (EConst(Ident("true")),_)),_)] ->
  1786. IModule module_name,true
  1787. | [(EConst(String(module_name)), _); (EConst(String(object_name)), _)]
  1788. | [(EConst(String(module_name)), _); (EConst(String(object_name)), _); (EBinop(OpAssign, (EConst(Ident("ignoreError")),_), (EConst(Ident("false")),_)),_)] ->
  1789. IObject (module_name,object_name), false
  1790. | [(EConst(String(module_name)), _); (EConst(String(object_name)), _); (EBinop(OpAssign, (EConst(Ident("ignoreError")),_), (EConst(Ident("true")),_)),_)] ->
  1791. IObject (module_name,object_name), true
  1792. | _ ->
  1793. error "Unsupported @:pythonImport format" mp
  1794. in
  1795. let import = match import_type with
  1796. | IModule module_name ->
  1797. (* importing whole module *)
  1798. "import " ^ module_name ^ " as " ^ class_name
  1799. | IObject (module_name,object_name) ->
  1800. if String.contains object_name '.' then
  1801. (* importing nested class *)
  1802. "import " ^ module_name ^ " as _hx_temp_import; " ^ class_name ^ " = _hx_temp_import." ^ object_name ^ "; del _hx_temp_import"
  1803. else
  1804. (* importing a class from a module *)
  1805. "from " ^ module_name ^ " import " ^ object_name ^ " as " ^ class_name
  1806. in
  1807. if ignore_error then begin
  1808. spr_line ctx "try:";
  1809. spr ctx "\t";
  1810. spr_line ctx import;
  1811. spr_line ctx "except:\n\tpass"
  1812. end else
  1813. spr_line ctx import
  1814. end
  1815. let gen_class ctx c =
  1816. gen_pre_code_meta ctx c.cl_meta;
  1817. (* print ctx "# print %s.%s\n" (s_type_path c.cl_module.m_path) (snd c.cl_path); *)
  1818. if not c.cl_extern then begin
  1819. newline ctx;
  1820. newline ctx;
  1821. let mt = (t_infos (TClassDecl c)) in
  1822. let p = get_path mt in
  1823. let p_name = get_full_name mt in
  1824. let x = collect_class_field_data c.cl_ordered_fields in
  1825. let p_super = match c.cl_super with
  1826. | None ->
  1827. None
  1828. | Some (csup,_) ->
  1829. Some (get_path (t_infos (TClassDecl csup)))
  1830. in
  1831. let p_interfaces = List.map (fun (c,tl) ->
  1832. get_path (t_infos (TClassDecl c))
  1833. ) c.cl_implements in
  1834. newline ctx;
  1835. if not (Meta.has Meta.NativeGen c.cl_meta) then
  1836. gen_class_register ctx c x p_super p_interfaces p p_name;
  1837. print ctx "class %s" p;
  1838. (match p_super with Some p -> print ctx "(%s)" p | _ -> ());
  1839. spr ctx ":";
  1840. begin match c.cl_constructor with
  1841. | Some cf -> gen_class_constructor ctx c cf;
  1842. | None -> ()
  1843. end;
  1844. List.iter (fun cf -> gen_class_field ctx c p cf) c.cl_ordered_fields;
  1845. let has_inner_static = gen_class_statics ctx c p in
  1846. let has_empty_constructor = match ((Meta.has Meta.NativeGen c.cl_meta) || c.cl_interface), c.cl_ordered_fields with
  1847. | true,_
  1848. | _, [] ->
  1849. false
  1850. | _ ->
  1851. gen_class_empty_constructor ctx p c.cl_ordered_fields;
  1852. true
  1853. in
  1854. let use_pass = (not has_inner_static) && (not has_empty_constructor) && match x.cfd_methods with
  1855. | [] -> c.cl_constructor = None
  1856. | _ -> c.cl_interface
  1857. in
  1858. if use_pass then begin
  1859. newline ctx;
  1860. spr ctx "\tpass";
  1861. end
  1862. end;
  1863. gen_class_init ctx c
  1864. let gen_enum_metadata ctx en p =
  1865. let meta = Codegen.build_metadata ctx.com (TEnumDecl en) in
  1866. match meta with
  1867. | None ->
  1868. ()
  1869. | Some e ->
  1870. newline ctx;
  1871. print ctx "%s.__meta__ = " p;
  1872. gen_expr ctx e "" ""
  1873. let gen_enum ctx en =
  1874. let mt = (t_infos (TEnumDecl en)) in
  1875. let p = get_path mt in
  1876. let p_name = get_full_name mt in
  1877. let enum_constructs = PMap.foldi (fun k ef acc -> ef :: acc) en.e_constrs [] in
  1878. let enum_constructs = List.sort (fun a b -> if a.ef_index < b.ef_index then -1 else if a.ef_index > b.ef_index then 1 else 0) enum_constructs in
  1879. let fix = match enum_constructs with [] -> "" | _ -> "\"" in
  1880. let enum_constructs_str = fix ^ (String.concat ("\",\"") (List.map (fun ef -> ef.ef_name) enum_constructs)) ^ fix in
  1881. newline ctx;
  1882. newline ctx;
  1883. print ctx "@_hx_classes.registerEnum(\"%s\", [%s])\n" p_name enum_constructs_str;
  1884. print ctx "class %s(Enum):\n" p;
  1885. spr ctx "\tdef __init__(self, t, i, p):\n";
  1886. print ctx "\t\tsuper(%s,self).__init__(t, i, p)" p;
  1887. let const_constructors,param_constructors = List.partition (fun ef ->
  1888. match follow ef.ef_type with
  1889. | TFun(_,_) -> false
  1890. | _ -> true
  1891. ) enum_constructs in
  1892. List.iter (fun ef ->
  1893. match follow ef.ef_type with
  1894. | TFun(args, _) ->
  1895. let print_args args =
  1896. let had_optional = ref false in
  1897. let sl = List.map (fun (n,o,_) ->
  1898. let name = handle_keywords n in
  1899. let arg_value = if !had_optional then
  1900. "= None"
  1901. else if o then begin
  1902. had_optional := true;
  1903. " = None"
  1904. end else
  1905. ""
  1906. in
  1907. Printf.sprintf "%s%s" name arg_value
  1908. ) args in
  1909. String.concat "," sl
  1910. in
  1911. let f = handle_keywords ef.ef_name in
  1912. let param_str = print_args args in
  1913. let args_str = String.concat "," (List.map (fun (n,_,_) -> handle_keywords n) args) in
  1914. newline ctx;
  1915. newline ctx;
  1916. print ctx "\t@staticmethod\n\tdef %s(%s):\n" f param_str;
  1917. print ctx "\t\treturn %s(\"%s\", %i, [%s])" p ef.ef_name ef.ef_index args_str;
  1918. | _ -> assert false
  1919. ) param_constructors;
  1920. List.iter (fun ef ->
  1921. (* TODO: haxe source has api.quoteString for ef.ef_name *)
  1922. let f = handle_keywords ef.ef_name in
  1923. newline ctx;
  1924. print ctx "%s.%s = %s(\"%s\", %i, list())" p f p ef.ef_name ef.ef_index
  1925. ) const_constructors;
  1926. gen_enum_metadata ctx en p
  1927. let gen_abstract ctx a =
  1928. gen_pre_code_meta ctx a.a_meta;
  1929. (* print ctx "# print %s.%s\n" (s_type_path a.a_module.m_path) (snd a.a_path); *)
  1930. newline ctx;
  1931. newline ctx;
  1932. newline ctx;
  1933. let mt = (t_infos (TAbstractDecl a)) in
  1934. let p = get_path mt in
  1935. let p_name = get_full_name mt in
  1936. print ctx "@_hx_classes.registerAbstract(\"%s\")\n" p_name;
  1937. print ctx "class %s" p;
  1938. spr ctx ":";
  1939. match a.a_impl with
  1940. | Some c ->
  1941. List.iter (fun cf ->
  1942. if cf.cf_name = "_new" then
  1943. gen_class_constructor ctx c cf
  1944. else
  1945. gen_class_field ctx c p cf
  1946. ) c.cl_ordered_statics
  1947. | None ->
  1948. spr ctx "\n\tpass"
  1949. let gen_type ctx mt = match mt with
  1950. | TClassDecl c -> gen_class ctx c
  1951. | TEnumDecl en when not en.e_extern -> gen_enum ctx en
  1952. | TAbstractDecl {a_path = [],"UInt"} -> ()
  1953. | TAbstractDecl a when Meta.has Meta.CoreType a.a_meta -> gen_abstract ctx a
  1954. | _ -> ()
  1955. (* Generator parts *)
  1956. let gen_resources ctx =
  1957. if Hashtbl.length ctx.com.resources > 0 then begin
  1958. spr ctx "def _hx_resources__():\n\treturn {";
  1959. let first = ref true in
  1960. Hashtbl.iter (fun k v ->
  1961. let prefix = if !first then begin
  1962. first := false;
  1963. "";
  1964. end else
  1965. ","
  1966. in
  1967. let k_enc = Base64.str_encode k in
  1968. print ctx "%s\"%s\": open('%%s.%%s'%%(__file__,'%s'),'rb').read()" prefix (Ast.s_escape k) k_enc;
  1969. Std.output_file (ctx.com.file ^ "." ^ k_enc) v
  1970. ) ctx.com.resources;
  1971. spr ctx "}"
  1972. end
  1973. let gen_imports ctx =
  1974. List.iter (fun mt ->
  1975. match mt with
  1976. | TClassDecl c when c.cl_extern -> gen_import ctx c.cl_path c.cl_meta
  1977. | TEnumDecl e when e.e_extern -> gen_import ctx e.e_path e.e_meta
  1978. | _ -> ()
  1979. ) ctx.com.types;
  1980. newline ctx
  1981. let gen_types ctx =
  1982. let used_paths = Hashtbl.create 0 in
  1983. let find_type path =
  1984. Hashtbl.add used_paths path true;
  1985. Utils.find_type ctx.com path
  1986. in
  1987. gen_type ctx (find_type ([],"_hx_ClassRegistry"));
  1988. gen_type ctx (find_type ([],"_hx_AnonObject"));
  1989. gen_type ctx (find_type (["python"],"Boot"));
  1990. gen_type ctx (find_type ([],"Enum"));
  1991. gen_type ctx (find_type ([],"HxOverrides"));
  1992. List.iter (fun mt ->
  1993. if not (Hashtbl.mem used_paths (t_infos mt).mt_path) then
  1994. gen_type ctx mt
  1995. ) ctx.com.types
  1996. let gen_static_inits ctx =
  1997. List.iter (fun f -> f()) (List.rev ctx.static_inits)
  1998. let gen_class_inits ctx =
  1999. List.iter (fun f -> f()) (List.rev ctx.class_inits)
  2000. let gen_main ctx =
  2001. match ctx.com.main with
  2002. | None ->
  2003. ()
  2004. | Some e ->
  2005. newline ctx;
  2006. gen_expr ctx e "" ""
  2007. (* Entry point *)
  2008. let run com =
  2009. Transformer.init com;
  2010. let ctx = mk_context com in
  2011. gen_imports ctx;
  2012. gen_resources ctx;
  2013. gen_types ctx;
  2014. gen_class_inits ctx;
  2015. gen_static_inits ctx;
  2016. gen_main ctx;
  2017. mkdir_from_path com.file;
  2018. let ch = open_out_bin com.file in
  2019. output_string ch (Buffer.contents ctx.buf);
  2020. close_out ch
  2021. end
  2022. let generate com =
  2023. Generator.run com