genpy.ml 62 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810
  1. open Ast
  2. open Type
  3. open Common
  4. module Utils = struct
  5. let class_of_module_type mt = match mt with
  6. | TClassDecl c -> c
  7. | _ -> failwith ("Not a class: " ^ (s_type_path (t_infos mt).mt_path))
  8. let find_type com path =
  9. try
  10. List.find (fun mt -> match mt with
  11. | TAbstractDecl _ -> false
  12. | _ -> (t_infos mt).mt_path = path
  13. ) com.types
  14. with Not_found ->
  15. error (Printf.sprintf "Could not find type %s\n" (s_type_path path)) null_pos
  16. let mk_static_field c cf p =
  17. let ta = TAnon { a_fields = c.cl_statics; a_status = ref (Statics c) } in
  18. let ethis = mk (TTypeExpr (TClassDecl c)) ta p in
  19. let t = monomorphs cf.cf_params cf.cf_type in
  20. mk (TField (ethis,(FStatic (c,cf)))) t p
  21. let mk_static_call c cf el p =
  22. let ef = mk_static_field c cf p in
  23. let tr = match follow ef.etype with
  24. | TFun(args,tr) -> tr
  25. | _ -> assert false
  26. in
  27. mk (TCall(ef,el)) tr p
  28. let resolve_static_field c n =
  29. try
  30. PMap.find n c.cl_statics
  31. with Not_found ->
  32. failwith (Printf.sprintf "Class %s has no field %s" (s_type_path c.cl_path) n)
  33. let mk_static_field_2 c n p =
  34. mk_static_field c (resolve_static_field c n) p
  35. let mk_static_call_2 c n el p =
  36. mk_static_call c (resolve_static_field c n) el p
  37. end
  38. module KeywordHandler = struct
  39. let kwds =
  40. let h = Hashtbl.create 0 in
  41. List.iter (fun s -> Hashtbl.add h s ()) [
  42. "and"; "as"; "assert"; "break"; "class"; "continue"; "def"; "del"; "elif"; "else"; "except"; "exec"; "finally"; "for";
  43. "from"; "global"; "if"; "import"; "in"; "is"; "lambda"; "not"; "or"; "pass"; "print";" raise"; "return"; "try"; "while";
  44. "with"; "yield"; "float"; "None"; "list"; "True"; "False"
  45. ;"__b" (* TODO: hack to deal with haxe.Utf8 error *)
  46. ];
  47. h
  48. let handle_keywords s =
  49. if Hashtbl.mem kwds s then "_hx_" ^ s else s
  50. let unhandle_keywords s =
  51. if String.length s > 4 && String.sub s 0 4 = "_hx_" then
  52. String.sub s 4 (String.length s - 4)
  53. else
  54. s
  55. end
  56. module Transformer = struct
  57. type adjusted_expr = {
  58. a_expr : texpr;
  59. a_blocks : texpr list;
  60. a_next_id : unit -> string;
  61. a_is_value : bool;
  62. }
  63. let como = ref None
  64. let t_bool = ref t_dynamic
  65. let t_void = ref t_dynamic
  66. let t_string= ref t_dynamic
  67. let c_reflect = ref null_class
  68. let init com =
  69. como := Some com;
  70. t_bool := com.basic.tbool;
  71. t_void := com.basic.tvoid;
  72. t_string := com.basic.tstring;
  73. c_reflect := Utils.class_of_module_type (Utils.find_type com ([],"Reflect"))
  74. and debug_expr e =
  75. let s_type = Type.s_type (print_context()) in
  76. let s = Type.s_expr_pretty "\t" s_type e in
  77. Printf.printf "%s\n" s
  78. let new_counter () =
  79. let n = ref (-1) in
  80. (fun () ->
  81. incr n;
  82. Printf.sprintf "_hx_local_%i" !n
  83. )
  84. let to_expr ae =
  85. match ae.a_blocks with
  86. | [] ->
  87. ae.a_expr
  88. | el ->
  89. match ae.a_expr.eexpr with
  90. | TBlock el2 ->
  91. { ae.a_expr with eexpr = TBlock (el @ el2) }
  92. | _ ->
  93. { ae.a_expr with eexpr = TBlock (el @ [ae.a_expr])}
  94. let lift_expr ?(is_value = false) ?(next_id = None) ?(blocks = []) e =
  95. let next_id = match next_id with
  96. | None ->
  97. new_counter()
  98. | Some f ->
  99. f
  100. in
  101. {
  102. a_expr = e;
  103. a_blocks = blocks;
  104. a_next_id = next_id;
  105. a_is_value = is_value
  106. }
  107. let lift_expr1 is_value next_id blocks e =
  108. lift_expr ~is_value:is_value ~next_id:(Some next_id) ~blocks:blocks e
  109. let to_tvar ?(capture = false) n t =
  110. { v_name = n; v_type = t; v_id = 0; v_capture = capture; v_extra = None; v_meta = [] }
  111. let create_non_local n pos =
  112. let s = "nonlocal " ^ n in
  113. (* TODO: this is a hack... *)
  114. let id = mk (TLocal (to_tvar "python_Syntax.pythonCode" t_dynamic ) ) !t_void pos in
  115. let id2 = mk (TLocal( to_tvar s t_dynamic )) !t_void pos in
  116. mk (TCall(id, [id2])) t_dynamic pos
  117. let to_tlocal_expr ?(capture = false) n t p =
  118. mk (TLocal (to_tvar ~capture:capture n t)) t p
  119. let check_unification e t = match follow e.etype,follow t with
  120. | TAnon an1, TAnon an2 ->
  121. PMap.iter (fun s cf ->
  122. if not (PMap.mem s an1.a_fields) then an1.a_fields <- PMap.add s cf an1.a_fields
  123. ) an2.a_fields;
  124. e
  125. | _ ->
  126. e
  127. let dynamic_field_read e s =
  128. Utils.mk_static_call_2 !c_reflect "field" [e;mk (TConst (TString s)) !t_string e.epos] e.epos
  129. let dynamic_field_write e1 s e2 =
  130. Utils.mk_static_call_2 !c_reflect "setField" [e1;mk (TConst (TString s)) !t_string e1.epos;e2] e1.epos
  131. let dynamic_field_read_write next_id e1 s op e2 =
  132. let id = next_id() in
  133. let temp_var = to_tvar id e1.etype in
  134. let temp_var_def = mk (TVar(temp_var,Some e1)) e1.etype e1.epos in
  135. let temp_local = mk (TLocal temp_var) e1.etype e1.epos in
  136. let e_field = dynamic_field_read temp_local s in
  137. let e_op = mk (TBinop(op,e_field,e2)) e_field.etype e_field.epos in
  138. let e_set_field = dynamic_field_write temp_local s e_op in
  139. mk (TBlock [
  140. temp_var_def;
  141. e_set_field;
  142. ]) e_set_field.etype e_set_field.epos
  143. let add_non_locals_to_func e =
  144. match e.eexpr with
  145. | TFunction f ->
  146. let local_vars =
  147. let h = Hashtbl.create 0 in
  148. let fn (tvar, _) =
  149. let x = tvar.v_name in
  150. Hashtbl.add h x x;
  151. in
  152. List.iter fn f.tf_args;
  153. h
  154. in
  155. let non_locals = Hashtbl.create 0 in
  156. let rec it lv e =
  157. let maybe_continue x =
  158. match x.eexpr with
  159. | TFunction(_) -> ()
  160. | _ ->
  161. Type.iter (it (Hashtbl.copy lv)) x;
  162. ()
  163. in
  164. match e.eexpr with
  165. | TVar(v,expr) ->
  166. (match expr with
  167. | Some x -> maybe_continue x; ()
  168. | None -> ());
  169. Hashtbl.add lv v.v_name v.v_name;
  170. ()
  171. | TBinop( (OpAssign | OpAssignOp(_)) , { eexpr = TLocal( { v_name = x })}, e2) ->
  172. if not (Hashtbl.mem lv x) then
  173. Hashtbl.add non_locals x x;
  174. maybe_continue e2;
  175. ()
  176. | TFunction(_) -> ()
  177. | _ -> Type.iter (it (Hashtbl.copy lv)) e; ()
  178. in
  179. Type.iter (it local_vars) f.tf_expr;
  180. let keys = Hashtbl.fold (fun k _ acc -> k :: acc) non_locals [] in
  181. let non_local_exprs = List.map (fun (k) -> create_non_local k f.tf_expr.epos) keys in
  182. let new_exprs = List.append non_local_exprs [f.tf_expr] in
  183. let f = { f with tf_expr = { f.tf_expr with eexpr = TBlock(new_exprs)}} in
  184. {e with eexpr = TFunction f }
  185. | _ -> assert false
  186. let rec transform_function tf ae is_value =
  187. let p = tf.tf_expr.epos in
  188. let assigns = List.fold_left (fun acc (v,value) -> match value with
  189. | None ->
  190. acc
  191. | Some ct ->
  192. let a_local = mk (TLocal v) v.v_type p in
  193. let a_null = mk (TConst TNull) v.v_type p in
  194. let a_cmp = mk (TBinop(OpEq,a_local,a_null)) !t_bool p in
  195. let a_value = mk (TConst(ct)) v.v_type p in
  196. let a_assign = mk (TBinop(OpAssign,a_local,a_value)) v.v_type p in
  197. let a_if = mk (TIf(a_cmp,a_assign,None)) !t_void p in
  198. a_if :: acc
  199. ) [] tf.tf_args in
  200. let body = match assigns with
  201. | [] ->
  202. tf.tf_expr
  203. | _ ->
  204. let eb = mk (TBlock (List.rev assigns)) t_dynamic p in
  205. Type.concat eb tf.tf_expr
  206. in
  207. let e1 = to_expr (transform_expr ~next_id:(Some ae.a_next_id) body) in
  208. let fn = mk (TFunction({
  209. tf_expr = e1;
  210. tf_args = tf.tf_args;
  211. tf_type = tf.tf_type;
  212. })) ae.a_expr.etype p in
  213. let fn = add_non_locals_to_func fn in
  214. if is_value then begin
  215. let new_name = ae.a_next_id() in
  216. let new_var = alloc_var new_name tf.tf_type in
  217. let new_local = mk (TLocal new_var) fn.etype p in
  218. let def = mk (TVar(new_var,Some fn)) fn.etype p in
  219. lift_expr1 false ae.a_next_id [def] new_local
  220. end else
  221. lift_expr fn
  222. and transform_var_expr ae eo v =
  223. let b,new_expr = match eo with
  224. | None ->
  225. [],None
  226. | Some e1 ->
  227. let f = transform_expr1 true ae.a_next_id [] e1 in
  228. let b = f.a_blocks in
  229. b,Some(f.a_expr)
  230. in
  231. let e = mk (TVar(v,new_expr)) ae.a_expr.etype ae.a_expr.epos in
  232. lift_expr ~next_id:(Some ae.a_next_id) ~blocks:b e
  233. and transform_expr ?(is_value = false) ?(next_id = None) ?(blocks = []) (e : texpr) : adjusted_expr =
  234. transform1 (lift_expr ~is_value ~next_id ~blocks e)
  235. and transform_expr1 is_value next_id blocks e =
  236. transform_expr ~is_value ~next_id:(Some next_id) ~blocks e
  237. and transform_exprs_to_block el tb is_value p next_id =
  238. match el with
  239. | [e] ->
  240. transform_expr ~is_value ~next_id:(Some next_id) e
  241. | _ ->
  242. let res = DynArray.create () in
  243. List.iter (fun e ->
  244. let ae = transform_expr ~is_value ~next_id:(Some next_id) e in
  245. List.iter (DynArray.add res) ae.a_blocks;
  246. DynArray.add res ae.a_expr
  247. ) el;
  248. lift_expr (mk (TBlock (DynArray.to_list res)) tb p)
  249. and transform_switch ae is_value e1 cases edef =
  250. let case_functions = ref [] in
  251. let case_to_if (el,e) eelse =
  252. let val_reversed = List.rev el in
  253. let mk_eq e = mk (TBinop(OpEq,e1,e)) !t_bool (punion e1.epos e.epos) in
  254. let cond = match val_reversed with
  255. | [] ->
  256. assert false
  257. | [e] ->
  258. mk_eq e
  259. | e :: el ->
  260. List.fold_left (fun eelse e -> mk (TBinop(OpBoolOr,eelse,mk_eq e)) !t_bool (punion eelse.epos e.epos)) (mk_eq e) el
  261. in
  262. let eif = if is_value then begin
  263. let name = ae.a_next_id() in
  264. let func = exprs_to_func [e] name ae in
  265. case_functions := !case_functions @ func.a_blocks;
  266. let call = func.a_expr in
  267. mk (TIf(cond,call,eelse)) ae.a_expr.etype ae.a_expr.epos
  268. end else
  269. mk (TIf(cond,e,eelse)) ae.a_expr.etype e.epos
  270. in
  271. eif
  272. in
  273. let rev_cases = List.rev cases in
  274. let edef = Some (match edef with
  275. | None ->
  276. mk (TBlock []) ae.a_expr.etype ae.a_expr.epos
  277. | Some e ->
  278. e)
  279. in
  280. let res = match rev_cases,edef with
  281. | [],Some edef ->
  282. edef
  283. | [],None ->
  284. (* I don't think that can happen? *)
  285. assert false
  286. | [case],_ ->
  287. case_to_if case edef
  288. | case :: cases,_ ->
  289. List.fold_left (fun acc case -> case_to_if case (Some acc)) (case_to_if case edef) cases
  290. in
  291. let res = if is_value then
  292. mk (TBlock ((List.rev (res :: !case_functions)))) res.etype res.epos
  293. else
  294. res
  295. in
  296. forward_transform res ae
  297. and transform_op_assign_op ae e1 op one is_value post =
  298. let e1_ = transform_expr e1 ~is_value:true ~next_id:(Some ae.a_next_id) in
  299. let handle_as_local temp_local =
  300. let ex = ae.a_expr in
  301. let res_var = alloc_var (ae.a_next_id()) ex.etype in
  302. let res_local = {ex with eexpr = TLocal res_var} in
  303. let plus = {ex with eexpr = TBinop(op,temp_local,one)} in
  304. let var_expr = {ex with eexpr = TVar(res_var,Some temp_local)} in
  305. let assign_expr = {ex with eexpr = TBinop(OpAssign,e1_.a_expr,plus)} in
  306. let blocks = if post then
  307. [var_expr;assign_expr;res_local]
  308. else
  309. [assign_expr;temp_local]
  310. in
  311. (* TODO: block is ignored in the else case? *)
  312. let block = e1_.a_blocks @ blocks in
  313. if is_value then begin
  314. let f = exprs_to_func block (ae.a_next_id()) ae in
  315. lift_expr f.a_expr ~is_value:true ~next_id:(Some ae.a_next_id) ~blocks:f.a_blocks
  316. end else begin
  317. let block = e1_.a_blocks @ [assign_expr] in
  318. transform_exprs_to_block block ex.etype false ex.epos ae.a_next_id
  319. end
  320. in
  321. match e1_.a_expr.eexpr with
  322. | TArray({eexpr = TLocal _},{eexpr = TLocal _})
  323. | TField({eexpr = TLocal _},_)
  324. | TLocal _ ->
  325. handle_as_local e1_.a_expr
  326. | TArray(e1,e2) ->
  327. let id = ae.a_next_id() in
  328. let temp_var_l = alloc_var id e1.etype in
  329. let temp_local_l = {e1 with eexpr = TLocal temp_var_l} in
  330. let temp_var_l = {e1 with eexpr = TVar(temp_var_l,Some e1)} in
  331. let id = ae.a_next_id() in
  332. let temp_var_r = alloc_var id e2.etype in
  333. let temp_local_r = {e2 with eexpr = TLocal temp_var_r} in
  334. let temp_var_r = {e2 with eexpr = TVar(temp_var_r,Some e2)} in
  335. let id = ae.a_next_id() in
  336. let temp_var = alloc_var id e1_.a_expr.etype in
  337. let temp_local = {e1_.a_expr with eexpr = TLocal temp_var} in
  338. let temp_var_expr = {e1_.a_expr with eexpr = TArray(temp_local_l,temp_local_r)} in
  339. let temp_var = {e1_.a_expr with eexpr = TVar(temp_var,Some temp_var_expr)} in
  340. let plus = {ae.a_expr with eexpr = TBinop(op,temp_local,one)} in
  341. let assign_expr = {ae.a_expr with eexpr = TBinop(OpAssign,temp_var_expr,plus)} in
  342. 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
  343. if is_value then begin
  344. let f = exprs_to_func block (ae.a_next_id()) ae in
  345. lift_expr f.a_expr ~is_value:true ~next_id:(Some ae.a_next_id) ~blocks:f.a_blocks
  346. end else
  347. transform_exprs_to_block block ae.a_expr.etype false ae.a_expr.epos ae.a_next_id
  348. | TField(e1,fa) ->
  349. let temp_var_l = alloc_var (ae.a_next_id()) e1.etype in
  350. let temp_local_l = {e1 with eexpr = TLocal temp_var_l} in
  351. let temp_var_l = {e1 with eexpr = TVar(temp_var_l,Some e1)} in
  352. let temp_var = alloc_var (ae.a_next_id()) e1_.a_expr.etype in
  353. let temp_local = {e1_.a_expr with eexpr = TLocal temp_var} in
  354. let temp_var_expr = {e1_.a_expr with eexpr = TField(temp_local_l,fa)} in
  355. let temp_var = {e1_.a_expr with eexpr = TVar(temp_var,Some temp_var_expr)} in
  356. let plus = {ae.a_expr with eexpr = TBinop(op,temp_local,one)} in
  357. let assign_expr = {ae.a_expr with eexpr = TBinop(OpAssign,temp_var_expr,plus)} in
  358. let block = e1_.a_blocks @ [temp_var_l;temp_var;assign_expr;if post then temp_local else temp_var_expr] in
  359. if is_value then begin
  360. let f = exprs_to_func block (ae.a_next_id()) ae in
  361. lift_expr f.a_expr ~is_value:true ~next_id:(Some ae.a_next_id) ~blocks:f.a_blocks
  362. end else
  363. transform_exprs_to_block block ae.a_expr.etype false ae.a_expr.epos ae.a_next_id
  364. | _ ->
  365. debug_expr e1_.a_expr;
  366. assert false
  367. and var_to_treturn_expr ?(capture = false) n t p =
  368. let x = mk (TLocal (to_tvar ~capture:capture n t)) t p in
  369. mk (TReturn (Some x)) t p
  370. and exprs_to_func exprs name base =
  371. let convert_return_expr (expr:texpr) =
  372. match expr.eexpr with
  373. | TWhile(_,_,_) ->
  374. let ret = { expr with eexpr = TReturn (None) } in
  375. [expr; ret]
  376. | TFunction(f) ->
  377. let ret = var_to_treturn_expr name f.tf_type f.tf_expr.epos in
  378. [expr;ret]
  379. | TBinop(OpAssign, l, r) ->
  380. let r = { l with eexpr = TReturn(Some l) } in
  381. [expr; r]
  382. | x ->
  383. let ret_expr = { expr with eexpr = TReturn( Some(expr) )} in
  384. [ret_expr]
  385. in
  386. let def =
  387. (let ex = match exprs with
  388. | [] -> assert false
  389. | [x] ->
  390. (let exs = convert_return_expr x in
  391. match exs with
  392. | [] -> assert false
  393. | [x] -> x
  394. | x ->
  395. match List.rev x with
  396. | x::xs ->
  397. mk (TBlock exs) x.etype base.a_expr.epos
  398. | _ -> assert false)
  399. | x ->
  400. match List.rev x with
  401. | x::xs ->
  402. (let ret = x in
  403. let tail = List.rev xs in
  404. let block = tail @ (convert_return_expr ret) in
  405. match List.rev block with
  406. | x::_ ->
  407. mk (TBlock block) x.etype base.a_expr.epos
  408. | _ -> assert false)
  409. | _ -> assert false
  410. in
  411. let f1 = { tf_args = []; tf_type = TFun([],ex.etype); tf_expr = ex} in
  412. let fexpr = mk (TFunction f1) ex.etype ex.epos in
  413. let fvar = to_tvar name fexpr.etype in
  414. let f = add_non_locals_to_func fexpr in
  415. let assign = { ex with eexpr = TVar(fvar, Some(f))} in
  416. let call_expr = (mk (TLocal fvar) fexpr.etype ex.epos ) in
  417. let substitute = mk (TCall(call_expr, [])) ex.etype ex.epos in
  418. lift_expr ~blocks:[assign] substitute)
  419. in
  420. match exprs with
  421. | [{ eexpr = TFunction({ tf_args = []} as f) } as x] ->
  422. let l = to_tlocal_expr name f.tf_type f.tf_expr.epos in
  423. let substitute = mk (TCall(l, [])) f.tf_type f.tf_expr.epos in
  424. lift_expr ~blocks:[x] substitute
  425. | _ -> def
  426. and transform1 ae : adjusted_expr =
  427. let trans is_value blocks e = transform_expr1 is_value ae.a_next_id blocks e in
  428. let lift is_value blocks e = lift_expr1 is_value ae.a_next_id blocks e in
  429. let a_expr = ae.a_expr in
  430. match ae.a_is_value,ae.a_expr.eexpr with
  431. | (is_value,TBlock [x]) ->
  432. trans is_value [] x
  433. | (_,TBlock []) ->
  434. lift_expr (mk (TConst TNull) ae.a_expr.etype ae.a_expr.epos)
  435. | (false,TBlock el) ->
  436. transform_exprs_to_block el ae.a_expr.etype false ae.a_expr.epos ae.a_next_id
  437. | (true,TBlock el) ->
  438. let name = ae.a_next_id() in
  439. let block,tr = match List.rev el with
  440. | e :: el ->
  441. List.rev ((mk (TReturn (Some e)) t_dynamic e.epos) :: el),e.etype
  442. | [] ->
  443. assert false
  444. in
  445. let my_block = transform_exprs_to_block block tr false ae.a_expr.epos ae.a_next_id in
  446. let fn = mk (TFunction {
  447. tf_args = [];
  448. tf_type = tr;
  449. tf_expr = my_block.a_expr;
  450. }) ae.a_expr.etype ae.a_expr.epos in
  451. let t_var = alloc_var name ae.a_expr.etype in
  452. let f = add_non_locals_to_func fn in
  453. let fn_assign = mk (TVar (t_var,Some f)) ae.a_expr.etype ae.a_expr.epos in
  454. let ev = mk (TLocal t_var) ae.a_expr.etype ae.a_expr.epos in
  455. let substitute = mk (TCall(ev,[])) ae.a_expr.etype ae.a_expr.epos in
  456. lift_expr ~blocks:[fn_assign] substitute
  457. | (is_value,TFunction(f)) ->
  458. transform_function f ae is_value
  459. | (_,TVar(v,None)) ->
  460. transform_var_expr ae None v
  461. | (false, TVar(v,Some({ eexpr = TUnop((Increment | Decrement as unop),post_fix,({eexpr = TLocal _ | TField({eexpr = TConst TThis},_)} as ve))} as e1))) ->
  462. let one = {e1 with eexpr = TConst (TInt (Int32.of_int 1))} in
  463. let op = if unop = Increment then OpAdd else OpSub in
  464. let inc = {e1 with eexpr = TBinop(op,ve,one)} in
  465. let inc_assign = {e1 with eexpr = TBinop(OpAssign,ve,inc)} in
  466. let var_assign = {e1 with eexpr = TVar(v,Some ve)} in
  467. if post_fix = Postfix then
  468. lift true [var_assign] inc_assign
  469. else
  470. lift true [inc_assign] var_assign
  471. | (_,TVar(v,eo)) ->
  472. transform_var_expr ae eo v
  473. | (_,TFor(v,e1,e2)) ->
  474. let e1 = trans true [] e1 in
  475. let e2 = to_expr (trans false [] e2) in
  476. let new_expr = mk (TFor(v,e1.a_expr,e2)) ae.a_expr.etype ae.a_expr.epos in
  477. lift_expr ~blocks: e1.a_blocks new_expr
  478. | (_,TReturn None) ->
  479. ae
  480. | (_,TReturn (Some ({eexpr = TFunction f} as ef))) ->
  481. let n = ae.a_next_id() in
  482. let e1 = to_expr (trans false [] f.tf_expr) in
  483. let f = mk (TFunction {
  484. tf_args = f.tf_args;
  485. tf_type = f.tf_type;
  486. tf_expr = e1;
  487. }) ef.etype ef.epos in
  488. let f1 = add_non_locals_to_func f in
  489. let var_n = alloc_var n ef.etype in
  490. let f1_assign = mk (TVar(var_n,Some f1)) !t_void f1.epos in
  491. let var_local = mk (TLocal var_n) ef.etype f1.epos in
  492. let er = mk (TReturn (Some var_local)) t_dynamic ae.a_expr.epos in
  493. lift true [f1_assign] er
  494. | (_,TReturn Some(x)) ->
  495. let x1 = trans true [] x in
  496. (match x1.a_blocks with
  497. | [] ->
  498. lift true [] { ae.a_expr with eexpr = TReturn(Some x1.a_expr) }
  499. | blocks ->
  500. let f = exprs_to_func (blocks @ [x1.a_expr]) (ae.a_next_id()) ae in
  501. lift true f.a_blocks {a_expr with eexpr = TReturn (Some f.a_expr)})
  502. | (_, TParenthesis(e1)) ->
  503. let e1 = trans true [] e1 in
  504. let p = { ae.a_expr with eexpr = TParenthesis(e1.a_expr)} in
  505. lift true e1.a_blocks p
  506. | (true, TIf(econd, eif, eelse)) ->
  507. (let econd1 = trans true [] econd in
  508. let eif1 = trans true [] eif in
  509. let eelse1 = match eelse with
  510. | Some x -> Some(trans true [] x)
  511. | None -> None
  512. in
  513. let blocks = [] in
  514. let eif2, blocks =
  515. match eif1.a_blocks with
  516. | [] -> eif1.a_expr, blocks
  517. | x ->
  518. let regular =
  519. let fname = eif1.a_next_id () in
  520. let f = exprs_to_func (List.append eif1.a_blocks [eif1.a_expr]) fname ae in
  521. f.a_expr, List.append blocks f.a_blocks
  522. in
  523. match eif1.a_blocks with
  524. | [{ eexpr = TVar(_, Some({ eexpr = TFunction(_)}))} as b] ->
  525. eif1.a_expr, List.append blocks [b]
  526. | _ -> regular
  527. in
  528. let eelse2, blocks =
  529. match eelse1 with
  530. | None -> None, blocks
  531. | Some({ a_blocks = []} as x) -> Some(x.a_expr), blocks
  532. | Some({ a_blocks = b} as eelse1) ->
  533. let regular =
  534. let fname = eelse1.a_next_id () in
  535. let f = exprs_to_func (List.append eelse1.a_blocks [eelse1.a_expr]) fname ae in
  536. Some(f.a_expr), List.append blocks f.a_blocks
  537. in
  538. match b with
  539. | [{ eexpr = TVar(_, Some({ eexpr = TFunction(f)}))} as b] ->
  540. Some(eelse1.a_expr), List.append blocks [b]
  541. | _ -> regular
  542. in
  543. let blocks = List.append econd1.a_blocks blocks in
  544. let new_if = { ae.a_expr with eexpr = TIf(econd1.a_expr, eif2, eelse2) } in
  545. match blocks with
  546. | [] ->
  547. let meta = Meta.Custom(":ternaryIf"), [], ae.a_expr.epos in
  548. let ternary = { ae.a_expr with eexpr = TMeta(meta, new_if) } in
  549. lift_expr ~blocks:blocks ternary
  550. | b ->
  551. let f = exprs_to_func (List.append blocks [new_if]) (ae.a_next_id ()) ae in
  552. lift_expr ~blocks:f.a_blocks f.a_expr)
  553. | (false, TIf(econd, eif, eelse)) ->
  554. let econd = trans true [] econd in
  555. let eif = to_expr (trans false [] eif) in
  556. let eelse = match eelse with
  557. | Some(x) -> Some(to_expr (trans false [] x))
  558. | None -> None
  559. in
  560. let new_if = { ae.a_expr with eexpr = TIf(econd.a_expr, eif, eelse) } in
  561. lift false econd.a_blocks new_if
  562. | (false, TWhile(econd, e1, NormalWhile)) ->
  563. let econd1 = trans true [] econd in
  564. let e11 = to_expr (trans false [] e1) in
  565. let new_while = mk (TWhile(econd1.a_expr,e11,NormalWhile)) a_expr.etype a_expr.epos in
  566. lift false econd1.a_blocks new_while
  567. | (true, TWhile(econd, ebody, NormalWhile)) ->
  568. let econd = trans true [] econd in
  569. let ebody = to_expr (trans false [] ebody) in
  570. let ewhile = { ae.a_expr with eexpr = TWhile(econd.a_expr, ebody, NormalWhile) } in
  571. let eval = { ae.a_expr with eexpr = TConst(TNull) } in
  572. let f = exprs_to_func (List.append econd.a_blocks [ewhile; eval]) (ae.a_next_id ()) ae in
  573. lift true f.a_blocks f.a_expr
  574. | (false, TWhile(econd, ebody, DoWhile)) ->
  575. let not_expr = { econd with eexpr = TUnop(Not, Prefix, econd) } in
  576. let break_expr = mk TBreak !t_void econd.epos in
  577. let if_expr = mk (TIf(not_expr, break_expr, None)) (!t_void) econd.epos in
  578. let new_e = match ebody.eexpr with
  579. | TBlock(exprs) -> { econd with eexpr = TBlock( List.append exprs [if_expr]) }
  580. | _ -> { econd with eexpr = TBlock( List.append [ebody] [if_expr]) }
  581. in
  582. let true_expr = mk (TConst(TBool(true))) econd.etype ae.a_expr.epos in
  583. let new_expr = { ae.a_expr with eexpr = TWhile( true_expr, new_e, NormalWhile) } in
  584. forward_transform new_expr ae
  585. | (is_value, TSwitch(e, cases, edef)) ->
  586. transform_switch ae is_value e cases edef
  587. (* anon field access on optional params *)
  588. | (_, TField(e,FAnon cf)) when Meta.has Meta.Optional cf.cf_meta ->
  589. let e = dynamic_field_read e cf.cf_name in
  590. transform_expr e
  591. | (_, TBinop(OpAssign,{eexpr = TField(e1,FAnon cf)},e2)) when Meta.has Meta.Optional cf.cf_meta ->
  592. let e = dynamic_field_write e1 cf.cf_name e2 in
  593. transform_expr e
  594. | (_, TBinop(OpAssignOp op,{eexpr = TField(e1,FAnon cf)},e2)) when Meta.has Meta.Optional cf.cf_meta ->
  595. let e = dynamic_field_read_write ae.a_next_id e1 cf.cf_name op e2 in
  596. transform_expr e
  597. (* TODO we need to deal with Increment, Decrement too!
  598. | (_, TUnop( (Increment | Decrement) as unop, op,{eexpr = TField(e1,FAnon cf)})) when Meta.has Meta.Optional cf.cf_meta ->
  599. let = dynamic_field_read e cf.cf_name in
  600. let e = dynamic_field_read_write_unop ae.a_next_id e1 cf.cf_name unop op in
  601. Printf.printf "dyn read write\n";
  602. transform_expr e
  603. *)
  604. (*
  605. 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
  606. *)
  607. | (is_value, TUnop( (Increment | Decrement) as unop, op, e)) ->
  608. let one = { ae.a_expr with eexpr = TConst(TInt(Int32.of_int(1)))} in
  609. let is_postfix = match op with
  610. | Postfix -> true
  611. | Prefix -> false in
  612. let op = match unop with
  613. | Increment -> OpAdd
  614. | Decrement -> OpSub
  615. | _ -> assert false in
  616. transform_op_assign_op ae e op one is_value is_postfix
  617. | (_, TUnop(op, Prefix, e)) ->
  618. let e1 = trans true [] e in
  619. let r = { a_expr with eexpr = TUnop(op, Prefix, e1.a_expr) } in
  620. lift_expr ~blocks:e1.a_blocks r
  621. | (_, TField(e,FDynamic s)) ->
  622. let e = dynamic_field_read e s in
  623. transform_expr e
  624. | (_, TBinop(OpAssign,{eexpr = TField(e1,FDynamic s)},e2)) ->
  625. let e = dynamic_field_write e1 s e2 in
  626. transform_expr e
  627. | (_, TBinop(OpAssignOp op,{eexpr = TField(e1,FDynamic s)},e2)) ->
  628. let e = dynamic_field_read_write ae.a_next_id e1 s op e2 in
  629. transform_expr e
  630. | (_, TField(e1, FClosure(Some {cl_path = [],("String" | "list")},cf))) ->
  631. let e = dynamic_field_read e1 cf.cf_name in
  632. transform_expr e
  633. | (is_value, TBinop(OpAssign, left, right))->
  634. (let left = trans true [] left in
  635. let right = trans true [] right in
  636. let r = { a_expr with eexpr = TBinop(OpAssign, left.a_expr, right.a_expr)} in
  637. if is_value then
  638. (let blocks = List.concat [left.a_blocks; right.a_blocks; [r]] in
  639. let f = exprs_to_func blocks (ae.a_next_id ()) ae in
  640. lift true f.a_blocks f.a_expr)
  641. else
  642. lift false (List.append left.a_blocks right.a_blocks) r)
  643. | (is_value, TBinop(OpAssignOp(x), left, right)) ->
  644. let right = trans true [] right in
  645. let v = right.a_expr in
  646. let res = transform_op_assign_op ae left x v is_value false in
  647. lift true (List.append right.a_blocks res.a_blocks) res.a_expr
  648. | (_, TBinop(op, left, right))->
  649. (let left = trans true [] left in
  650. let right = trans true [] right in
  651. let r = { a_expr with eexpr = TBinop(op, left.a_expr, right.a_expr)} in
  652. lift false (List.append left.a_blocks right.a_blocks) r)
  653. | (true, TThrow(x)) ->
  654. let block = TBlock([a_expr; { a_expr with eexpr = TConst(TNull) }]) in
  655. let r = { a_expr with eexpr = block } in
  656. forward_transform r ae
  657. | (false, TThrow(x)) ->
  658. let x = trans true [] x in
  659. let r = { a_expr with eexpr = TThrow(x.a_expr)} in
  660. lift false x.a_blocks r
  661. | (_, TNew(c, tp, params)) ->
  662. let params = List.map (trans true []) params in
  663. let blocks = List.flatten (List.map (fun (p) -> p.a_blocks) params) in
  664. let params = List.map (fun (p) -> p.a_expr) params in
  665. let e = { a_expr with eexpr = TNew(c, tp, params) } in
  666. lift false blocks e
  667. (* | (_, TCall({ eexpr = TLocal({v_name = "__python_for__" })} as x, [param])) ->
  668. let param = trans false [] param in
  669. let call = { a_expr with eexpr = TCall(x, [param.a_expr])} in
  670. lift_expr call *)
  671. | (_, TCall(e, params)) ->
  672. let e = trans true [] e in
  673. let params = List.map (trans true []) params in
  674. let blocks = e.a_blocks @ (List.flatten (List.map (fun (p) -> p.a_blocks) params)) in
  675. let params = List.map (fun (p) -> p.a_expr) params in
  676. let e = { a_expr with eexpr = TCall(e.a_expr, params) } in
  677. lift_expr ~blocks:blocks e
  678. | (_, TArray(e1, e2)) ->
  679. let e1 = trans true [] e1 in
  680. let e2 = trans true [] e2 in
  681. let r = { a_expr with eexpr = TArray(e1.a_expr, e2.a_expr)} in
  682. let blocks = List.append e1.a_blocks e2.a_blocks in
  683. lift_expr ~blocks:blocks r
  684. | (false, TTry(etry, catches)) ->
  685. let etry = trans false [] etry in
  686. let catches = List.map (fun(v,e) -> v, trans false [] e) catches in
  687. let blocks = List.flatten (List.map (fun (_,e) -> e.a_blocks) catches) in
  688. let catches = List.map (fun(v,e) -> v, e.a_expr) catches in
  689. let r = { a_expr with eexpr = TTry(etry.a_expr, catches)} in
  690. let blocks = List.append etry.a_blocks blocks in
  691. lift false blocks r
  692. | (true, TTry(etry, catches)) ->
  693. let id = ae.a_next_id () in
  694. let temp_var = to_tvar id a_expr.etype in
  695. let temp_var_def = { a_expr with eexpr = TVar(temp_var, None) } in
  696. let temp_local = { a_expr with eexpr = TLocal(temp_var)} in
  697. let mk_temp_assign right = { a_expr with eexpr = TBinop(OpAssign, temp_local, right)} in
  698. let etry = mk_temp_assign etry in
  699. let catches = List.map (fun (v,e)-> v, mk_temp_assign e) catches in
  700. let new_try = { a_expr with eexpr = TTry(etry, catches)} in
  701. let block = [temp_var_def; new_try; temp_local] in
  702. let new_block = { a_expr with eexpr = TBlock(block)} in
  703. forward_transform new_block ae
  704. | (_, TObjectDecl(fields)) ->
  705. let fields = List.map (fun (name,ex) -> name, trans true [] ex) fields in
  706. let blocks = List.flatten (List.map (fun (_,ex) -> ex.a_blocks) fields) in
  707. let fields = List.map (fun (name,ex) -> name, ex.a_expr) fields in
  708. let r = { a_expr with eexpr = (TObjectDecl(fields) )} in
  709. lift_expr ~blocks r
  710. | (_, TArrayDecl(values)) ->
  711. let values = List.map (trans true []) values in
  712. let blocks = List.flatten (List.map (fun (v) -> v.a_blocks) values) in
  713. let exprs = List.map (fun (v) -> v.a_expr) values in
  714. let r = { a_expr with eexpr = TArrayDecl exprs } in
  715. lift_expr ~blocks:blocks r
  716. | (is_value, TCast(e1,Some mt)) ->
  717. 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
  718. transform_expr e
  719. | (is_value, TCast(e,t)) ->
  720. let e = trans is_value [] e in
  721. let r = { a_expr with eexpr = e.a_expr.eexpr } in
  722. lift_expr ~blocks:e.a_blocks r
  723. | (_, TField(e,f)) ->
  724. let e = trans true [] e in
  725. let r = { a_expr with eexpr = TField(e.a_expr, f) } in
  726. lift_expr ~blocks:e.a_blocks r
  727. | (is_value, TMeta(m,e)) ->
  728. let e = trans is_value [] e in
  729. let r = { a_expr with eexpr = TMeta(m, e.a_expr) } in
  730. lift_expr ~blocks:e.a_blocks r
  731. | ( _, TPatMatch _ ) -> assert false
  732. | ( _, TLocal _ ) -> lift_expr a_expr
  733. | ( _, TConst _ ) -> lift_expr a_expr
  734. | ( _, TTypeExpr _ ) -> lift_expr a_expr
  735. | ( _, TEnumParameter _ ) -> lift_expr a_expr
  736. | ( _, TUnop _ ) -> assert false
  737. | ( true, TWhile(econd, ebody, DoWhile) ) ->
  738. let new_expr = trans false [] a_expr in
  739. let f = exprs_to_func (new_expr.a_blocks @ [new_expr.a_expr]) (ae.a_next_id()) ae in
  740. lift_expr ~is_value:true ~blocks:f.a_blocks f.a_expr
  741. | ( _, TBreak ) | ( _, TContinue ) ->
  742. lift_expr a_expr
  743. and transform e =
  744. to_expr (transform1 (lift_expr e))
  745. and forward_transform e base =
  746. transform1 (lift_expr1 base.a_is_value base.a_next_id base.a_blocks e)
  747. let transform_to_value e =
  748. to_expr (transform1 (lift_expr e ~is_value:true))
  749. end
  750. module Printer = struct
  751. type print_context = {
  752. pc_indent : string;
  753. pc_next_anon_func : unit -> string;
  754. }
  755. let create_context =
  756. let n = ref (-1) in
  757. (fun indent -> {
  758. pc_indent = indent;
  759. pc_next_anon_func = (fun () -> incr n; Printf.sprintf "anon_%i" !n);
  760. }
  761. )
  762. let tabs = ref ""
  763. let opt o f s = match o with
  764. | None -> ""
  765. | Some v -> s ^ (f v)
  766. (* TODO: both of these are crazy *)
  767. let is_type p t =
  768. (fun r ->
  769. let x = t_infos r in
  770. (String.concat "." (fst x.mt_path)) = p && (snd x.mt_path) = t
  771. )
  772. let is_type1 p s =
  773. (fun t -> match follow t with
  774. | TInst(c,_) -> (is_type p s)(TClassDecl c)
  775. | TAbstract(a,_) -> (is_type p s)(TAbstractDecl a)
  776. | TEnum(en,_) -> (is_type p s)(TEnumDecl en)
  777. | _ -> false
  778. )
  779. let is_underlying_string t = match follow t with
  780. | TAbstract(a,tl) -> (is_type1 "" "String")(Codegen.Abstract.get_underlying_type a tl)
  781. | _ -> false
  782. let handle_keywords s =
  783. KeywordHandler.handle_keywords s
  784. let print_unop = function
  785. | Increment | Decrement -> assert false
  786. | Not -> "not "
  787. | Neg -> "-";
  788. | NegBits -> "~"
  789. let print_binop = function
  790. | OpAdd -> "+"
  791. | OpSub -> "-"
  792. | OpMult -> "*"
  793. | OpDiv -> "/"
  794. | OpAssign -> "="
  795. | OpEq -> "=="
  796. | OpNotEq -> "!="
  797. | OpGt -> ">"
  798. | OpGte -> ">="
  799. | OpLt -> "<"
  800. | OpLte -> "<="
  801. | OpAnd -> "&"
  802. | OpOr -> "|"
  803. | OpXor -> "^"
  804. | OpBoolAnd -> "and"
  805. | OpBoolOr -> "or"
  806. | OpShl -> "<<"
  807. | OpShr -> ">>"
  808. | OpUShr -> ">>"
  809. | OpMod -> "%"
  810. | OpInterval | OpArrow | OpAssignOp _ -> assert false
  811. let print_string s =
  812. Printf.sprintf "\"%s\"" (Ast.s_escape s)
  813. let print_constant = function
  814. | TThis -> "self"
  815. | TNull -> "None"
  816. | TBool(true) -> "True"
  817. | TBool(false) -> "False"
  818. | TString(s) -> print_string s
  819. | TInt(i) -> Int32.to_string i
  820. | TFloat s -> s
  821. | TSuper -> "super"
  822. let print_base_type tp =
  823. try
  824. begin match Meta.get Meta.Native tp.mt_meta with
  825. | _,[EConst(String s),_],_ -> s
  826. | _ -> raise Not_found
  827. end
  828. with Not_found ->
  829. let pack,name = tp.mt_path in
  830. (String.concat "_" pack) ^ (if pack = [] then name else "_" ^ name)
  831. let print_module_type mt = print_base_type (t_infos mt)
  832. let print_metadata (name,_,_) =
  833. Printf.sprintf "@%s" name
  834. let print_args args =
  835. let had_value = ref false in
  836. let sl = List.map (fun (v,cto) ->
  837. let name = handle_keywords v.v_name in
  838. let arg_string = match follow v.v_type with
  839. | TAbstract({a_path = [],"KwdArgs"},_) -> "**" ^ name
  840. | _ -> name
  841. in
  842. let arg_value = match cto with
  843. | None when !had_value -> " = None"
  844. | None -> ""
  845. | Some ct ->
  846. had_value := true;
  847. Printf.sprintf " = %s" (print_constant ct)
  848. in
  849. Printf.sprintf "%s%s" arg_string arg_value
  850. ) args in
  851. String.concat "," sl
  852. let rec print_op_assign_right pctx e =
  853. match e.eexpr with
  854. | TIf({eexpr = TParenthesis econd},eif,Some eelse)
  855. | TIf(econd,eif,Some eelse) ->
  856. Printf.sprintf "%s if %s else %s" (print_expr pctx eif) (print_expr pctx econd) (print_expr pctx eelse)
  857. | _ ->
  858. print_expr pctx e
  859. and print_var pctx v eo =
  860. match eo with
  861. | Some {eexpr = TFunction tf} ->
  862. print_function pctx tf (Some v.v_name)
  863. | _ ->
  864. let s_init = match eo with
  865. | None -> "None"
  866. | Some e -> print_op_assign_right pctx e
  867. in
  868. Printf.sprintf "%s = %s" (handle_keywords v.v_name) s_init
  869. and print_function pctx tf name =
  870. let s_name = match name with
  871. | None -> pctx.pc_next_anon_func()
  872. | Some s -> handle_keywords s
  873. in
  874. let s_args = print_args tf.tf_args in
  875. let s_expr = print_expr {pctx with pc_indent = "\t" ^ pctx.pc_indent} tf.tf_expr in
  876. Printf.sprintf "def %s(%s):\n%s\t%s" s_name s_args pctx.pc_indent s_expr
  877. and print_expr pctx e =
  878. let indent = pctx.pc_indent in
  879. let print_expr_indented e = print_expr {pctx with pc_indent = "\t" ^ pctx.pc_indent} e in
  880. match e.eexpr with
  881. | TConst ct ->
  882. print_constant ct
  883. | TTypeExpr mt ->
  884. print_module_type mt
  885. | TLocal v ->
  886. handle_keywords v.v_name
  887. | TEnumParameter(e1,_,index) ->
  888. Printf.sprintf "%s.params[%i]" (print_expr pctx e1) index
  889. | TArray(e1,e2) ->
  890. Printf.sprintf "HxOverrides.arrayGet(%s, %s)" (print_expr pctx e1) (print_expr pctx e2)
  891. | TBinop(OpAssign,{eexpr = TArray(e1,e2)},e3) ->
  892. Printf.sprintf "HxOverrides.arraySet(%s,%s,%s)" (print_expr pctx e1) (print_expr pctx e2) (print_expr pctx e3)
  893. | TBinop(OpAssign,{eexpr = TField(ef1,fa)},e2) ->
  894. Printf.sprintf "%s = %s" (print_field pctx ef1 fa true) (print_op_assign_right pctx e2)
  895. | TBinop(OpAssign,e1,e2) ->
  896. Printf.sprintf "%s = %s" (print_expr pctx e1) (print_expr pctx e2)
  897. | TBinop(op,e1,({eexpr = TBinop(_,_,_)} as e2)) ->
  898. print_expr pctx { e with eexpr = TBinop(op, e1, { e2 with eexpr = TParenthesis(e2) })}
  899. | TBinop(OpEq,{eexpr = TCall({eexpr = TLocal {v_name = "__typeof__"}},[e1])},e2) ->
  900. begin match e2.eexpr with
  901. | TConst(TString s) ->
  902. begin match s with
  903. | "string" -> Printf.sprintf "_hx_c.Std._hx_is(%s, _hx_builtin.str)" (print_expr pctx e1)
  904. | "boolean" -> Printf.sprintf "_hx_c.Std._hx_is(%s, _hx_builtin.bool)" (print_expr pctx e1)
  905. | "number" -> Printf.sprintf "_hx_c.Std._hx_is(%s, _hx_builtin.float)" (print_expr pctx e1)
  906. | _ -> assert false
  907. end
  908. | _ ->
  909. assert false
  910. end
  911. | TBinop(OpEq,e1,({eexpr = TConst TNull} as e2)) ->
  912. Printf.sprintf "%s is %s" (print_expr pctx e1) (print_expr pctx e2)
  913. | TBinop(OpNotEq,e1,({eexpr = TConst TNull} as e2)) ->
  914. Printf.sprintf "%s is not %s" (print_expr pctx e1) (print_expr pctx e2)
  915. | TBinop(OpMod,e1,e2) when (is_type1 "" "Int")(e1.etype) && (is_type1 "" "Int")(e2.etype) ->
  916. Printf.sprintf "%s %% %s" (print_expr pctx e1) (print_expr pctx e2)
  917. | TBinop(OpMod,e1,e2) ->
  918. Printf.sprintf "HxOverrides.modf(%s, %s)" (print_expr pctx e1) (print_expr pctx e2)
  919. | TBinop(OpUShr,e1,e2) ->
  920. Printf.sprintf "HxOverrides.rshift(%s, %s)" (print_expr pctx e1) (print_expr pctx e2)
  921. | TBinop(OpAdd,e1,e2) when (is_type1 "" "String")(e.etype) || is_underlying_string e.etype ->
  922. let safe_string ex =
  923. match ex.eexpr with
  924. | TConst(TString _) -> print_expr pctx ex
  925. | _ -> Printf.sprintf "Std.string(%s)" (print_expr pctx ex)
  926. in
  927. let e1_str = safe_string e1 in
  928. let e2_str = safe_string e2 in
  929. Printf.sprintf "%s + %s" e1_str e2_str
  930. | TBinop(OpAdd,e1,e2) when (match follow e.etype with TDynamic _ -> true | _ -> false) ->
  931. Printf.sprintf "python_Boot._add_dynamic(%s,%s)" (print_expr pctx e1) (print_expr pctx e2);
  932. | TBinop(op,e1,e2) ->
  933. Printf.sprintf "%s %s %s" (print_expr pctx e1) (print_binop op) (print_expr pctx e2)
  934. | TField(e1,fa) ->
  935. print_field pctx e1 fa false
  936. | TParenthesis e1 ->
  937. Printf.sprintf "(%s)" (print_expr pctx e1)
  938. | TObjectDecl fl ->
  939. let fl2 = ref fl in
  940. begin match follow e.etype with
  941. | TAnon an ->
  942. PMap.iter (fun s cf ->
  943. if not (List.mem_assoc s fl) then fl2 := (s,null cf.cf_type cf.cf_pos) :: !fl2
  944. ) an.a_fields
  945. | _ ->
  946. ()
  947. end;
  948. Printf.sprintf "_hx_c._hx_AnonObject(%s)" (print_exprs_named pctx ", " !fl2)
  949. | TArrayDecl el ->
  950. Printf.sprintf "[%s]" (print_exprs pctx ", " el)
  951. | TCall(e1,el) ->
  952. print_call pctx e1 el
  953. | TNew(c,_,el) ->
  954. let id = print_base_type (t_infos (TClassDecl c)) in
  955. Printf.sprintf "%s(%s)" id (print_exprs pctx ", " el)
  956. | TUnop(op,Postfix,e1) ->
  957. Printf.sprintf "%s%s" (print_expr pctx e1) (print_unop op)
  958. | TUnop(Not,Prefix,e1) ->
  959. Printf.sprintf "(%s%s)" (print_unop Not) (print_expr pctx e1)
  960. | TUnop(op,Prefix,e1) ->
  961. Printf.sprintf "%s%s" (print_unop op) (print_expr pctx e1)
  962. | TFunction tf ->
  963. print_function pctx tf None
  964. | TVar (v,eo) ->
  965. print_var pctx v eo
  966. | TBlock [] ->
  967. Printf.sprintf "pass\n%s" indent
  968. | TBlock [{ eexpr = TBlock _} as b] ->
  969. print_expr pctx b
  970. | TBlock el ->
  971. let old = !tabs in
  972. tabs := pctx.pc_indent;
  973. let s = print_exprs pctx ("\n" ^ !tabs) el in
  974. tabs := old;
  975. Printf.sprintf "%s\n" s
  976. | TFor(v,e1,e2) ->
  977. let pctx2 = {pctx with pc_indent = "\t" ^ pctx.pc_indent} in
  978. let ind1 = pctx.pc_indent in
  979. let ind2 = pctx2.pc_indent in
  980. Printf.sprintf "_it = %s\n%swhile _it.hasNext():\n%s%s = _it.next()\n%s%s" (print_expr pctx e1) ind1 ind2 v.v_name ind2 (print_expr pctx2 e2)
  981. | TIf(econd,eif,(Some {eexpr = TIf _} as eelse)) ->
  982. print_if_else pctx econd eif eelse true
  983. | TIf(econd,eif,eelse) ->
  984. print_if_else pctx econd eif eelse false
  985. | TWhile(econd,e1,NormalWhile) ->
  986. Printf.sprintf "while %s:\n%s\t%s" (print_expr pctx econd) indent (print_expr_indented e1)
  987. | TWhile(econd,e1,DoWhile) ->
  988. error "Currently not supported" e.epos
  989. | TTry(e1,catches) ->
  990. print_try pctx e1 catches
  991. | TReturn eo ->
  992. Printf.sprintf "return%s" (opt eo (print_op_assign_right pctx) " ")
  993. | TBreak ->
  994. "break"
  995. | TContinue ->
  996. "continue"
  997. | TThrow e1 ->
  998. Printf.sprintf "raise _HxException(%s)" (print_expr pctx e1)
  999. | TCast(e1,None) ->
  1000. print_expr pctx e1
  1001. | TMeta((Meta.Custom ":ternaryIf",_,_),{eexpr = TIf(econd,eif,Some eelse)}) ->
  1002. Printf.sprintf "%s if %s else %s" (print_expr pctx eif) (print_expr pctx econd) (print_expr pctx eelse)
  1003. | TMeta(_,e1) ->
  1004. print_expr pctx e1
  1005. | TPatMatch _ | TSwitch _ | TCast(_, Some _) ->
  1006. assert false
  1007. and print_if_else pctx econd eif eelse as_elif =
  1008. let econd1 = match econd.eexpr with
  1009. | TParenthesis e -> e
  1010. | _ -> econd
  1011. in
  1012. let if_str = print_expr {pctx with pc_indent = "\t" ^ pctx.pc_indent} eif in
  1013. let indent = pctx.pc_indent in
  1014. let else_str = if as_elif then
  1015. opt eelse (print_expr pctx) "el"
  1016. else
  1017. opt eelse (print_expr {pctx with pc_indent = "\t" ^ pctx.pc_indent}) (Printf.sprintf "else:\n%s\t" indent)
  1018. in
  1019. Printf.sprintf "if %s:\n%s\t%s\n%s%s" (print_expr pctx econd1) indent if_str indent else_str
  1020. and print_field pctx e1 fa is_assign =
  1021. let obj = match e1.eexpr with
  1022. | TConst TSuper -> "super()"
  1023. | _ -> print_expr pctx e1
  1024. in
  1025. let name = field_name fa in
  1026. let is_extern = (match fa with
  1027. | FInstance(c,_) -> c.cl_extern
  1028. | FStatic(c,_) -> c.cl_extern
  1029. | _ -> false)
  1030. in
  1031. let do_default () =
  1032. Printf.sprintf "%s.%s" obj (if is_extern then name else (handle_keywords name))
  1033. in
  1034. match fa with
  1035. (* we need to get rid of these cases in the transformer, how is this handled in js *)
  1036. | FInstance(c,{cf_name = "length" | "get_length"}) when (is_type "" "list")(TClassDecl c) ->
  1037. Printf.sprintf "_hx_builtin.len(%s)" (print_expr pctx e1)
  1038. | FInstance(c,{cf_name = "length"}) when (is_type "" "String")(TClassDecl c) ->
  1039. Printf.sprintf "_hx_builtin.len(%s)" (print_expr pctx e1)
  1040. | FStatic(c,{cf_name = "fromCharCode"}) when (is_type "" "String")(TClassDecl c) ->
  1041. Printf.sprintf "HxString.fromCharCode"
  1042. | FInstance _ | FStatic _ ->
  1043. do_default ()
  1044. | FAnon cf when name = "iterator" && not is_assign ->
  1045. begin match follow cf.cf_type with
  1046. | TFun([],_) ->
  1047. Printf.sprintf "_hx_functools.partial(HxOverrides.iterator, %s)" obj
  1048. | _ ->
  1049. do_default()
  1050. end
  1051. | FAnon cf when name = "shift" && not is_assign ->
  1052. begin match follow cf.cf_type with
  1053. | TFun([],_) ->
  1054. Printf.sprintf "_hx_functools.partial(HxOverrides.shift, %s)" obj
  1055. | _ ->
  1056. do_default()
  1057. end
  1058. | _ ->
  1059. do_default()
  1060. and print_try pctx e1 catches =
  1061. let print_catch pctx i (v,e) =
  1062. let indent = pctx.pc_indent in
  1063. let handle_base_type bt =
  1064. let t = print_base_type bt in
  1065. let res = if t = "String" then
  1066. Printf.sprintf "if _hx_builtin.isinstance(_hx_e1, str):\n%s\t%s = _hx_e1\n%s\t%s" indent v.v_name indent (print_expr {pctx with pc_indent = "\t" ^ pctx.pc_indent} e)
  1067. else
  1068. Printf.sprintf "if _hx_builtin.isinstance(_hx_e1, %s):\n%s\t%s = _hx_e1\n%s\t%s" t indent v.v_name indent (print_expr {pctx with pc_indent = "\t" ^ pctx.pc_indent} e)
  1069. in
  1070. if i > 0 then
  1071. indent ^ "el" ^ res
  1072. else
  1073. res
  1074. in
  1075. match follow v.v_type with
  1076. | TDynamic _ ->
  1077. Printf.sprintf "%sif True:\n%s\t%s = _hx_e1\n%s\t%s" (if i > 0 then indent else "") indent v.v_name indent (print_expr {pctx with pc_indent = "\t" ^ pctx.pc_indent} e)
  1078. | TInst(c,_) ->
  1079. handle_base_type (t_infos (TClassDecl c))
  1080. | TEnum(en,_) ->
  1081. handle_base_type (t_infos (TEnumDecl en))
  1082. | _ ->
  1083. assert false
  1084. in
  1085. let indent = pctx.pc_indent in
  1086. let print_expr_indented e = print_expr {pctx with pc_indent = "\t" ^ pctx.pc_indent} e in
  1087. let try_str = Printf.sprintf "try:\n%s\t%s\n%s" indent (print_expr_indented e1) indent in
  1088. 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
  1089. let catch_str = String.concat (Printf.sprintf "\n%s\n" indent) (ExtList.List.mapi (fun i catch -> print_catch {pctx with pc_indent = "\t" ^ pctx.pc_indent} i catch) catches) in
  1090. let except_end = Printf.sprintf "\n%s\telse:\n%s\t\traise _hx_e" indent indent in
  1091. Printf.sprintf "%s%s%s%s" try_str except catch_str except_end
  1092. and print_call2 pctx e1 el =
  1093. let id = print_expr pctx e1 in
  1094. match id,el with
  1095. | "super",_ ->
  1096. let s_el = print_exprs pctx ", " el in
  1097. Printf.sprintf "super().__init__(%s)" s_el
  1098. | ("python_Syntax.pythonCode"),[e1] ->
  1099. begin match e1.eexpr with
  1100. | TConst (TString s) -> s
  1101. | e -> print_expr pctx e1
  1102. end
  1103. | "python_Syntax._callNamedUntyped",el ->
  1104. let res,fields = match List.rev el with
  1105. | {eexpr = TObjectDecl fields} :: el ->
  1106. List.rev el,fields
  1107. | _ ->
  1108. assert false
  1109. in
  1110. begin match res with
  1111. | e1 :: [] ->
  1112. Printf.sprintf "%s(%s)" (print_expr pctx e1) (print_params_named pctx ", " fields)
  1113. | e1 :: el ->
  1114. Printf.sprintf "%s(%s, %s)" (print_expr pctx e1) (print_exprs pctx ", " el) (print_params_named pctx ", " fields)
  1115. | [] ->
  1116. Printf.sprintf "%s(%s)" (print_expr pctx e1) (print_params_named pctx ", " fields)
  1117. end
  1118. | "python_Syntax.varArgs",[e1] ->
  1119. "*" ^ (print_expr pctx e1)
  1120. | "python_Syntax.call" ,e1 :: [{eexpr = TArrayDecl el}]->
  1121. Printf.sprintf "%s(%s)" (print_expr pctx e1) (print_exprs pctx ", " el)
  1122. | "python_Syntax.field",[e1;{eexpr = TConst(TString id)}] ->
  1123. Printf.sprintf "%s.%s" (print_expr pctx e1) id
  1124. | "python_Syntax.tuple", [{eexpr = TArrayDecl el}] ->
  1125. Printf.sprintf "(%s)" (print_exprs pctx ", " el)
  1126. | "python_Syntax._arrayAccess", e1 :: {eexpr = TArrayDecl el} :: etrail ->
  1127. let trailing_colon = match etrail with
  1128. | [{eexpr = TConst(TBool(true))}] -> true
  1129. | _ -> false
  1130. in
  1131. Printf.sprintf "%s[%s%s]" (print_expr pctx e1) (print_exprs pctx ":" el) (if trailing_colon then ":" else "")
  1132. | "python_Syntax.isIn",[e1;e2] ->
  1133. Printf.sprintf "%s in %s" (print_expr pctx e1) (print_expr pctx e2)
  1134. | "python_Syntax.delete",[e1] ->
  1135. Printf.sprintf "del %s" (print_expr pctx e1)
  1136. | "python_Syntax.binop",[e0;{eexpr = TConst(TString id)};e2] ->
  1137. Printf.sprintf "(%s %s %s)" (print_expr pctx e0) id (print_expr pctx e2)
  1138. | "python_Syntax.assign",[e0;e1] ->
  1139. Printf.sprintf "%s = %s" (print_expr pctx e0) (print_expr pctx e1)
  1140. | "python_Syntax.arraySet",[e1;e2;e3] ->
  1141. Printf.sprintf "%s[%s] = %s" (print_expr pctx e1) (print_expr pctx e2) (print_expr pctx e3)
  1142. | "python_Syntax._newInstance", e1 :: [{eexpr = TArrayDecl el}] ->
  1143. Printf.sprintf "%s(%s)" (print_expr pctx e1) (print_exprs pctx ", " el)
  1144. | "python_Syntax.opPow", [e1;e2] ->
  1145. Printf.sprintf "(%s ** %s)" (print_expr pctx e1) (print_expr pctx e2)
  1146. (* | "__python_for__",[{eexpr = TBlock [{eexpr = TVar(v1,_)};e2;block]}] ->
  1147. let f1 = v1.v_name in
  1148. let pctx = {pctx with pc_indent = "\t" ^ pctx.pc_indent} in
  1149. let i = pctx.pc_indent in
  1150. Printf.sprintf "for %s in %s:\n%s%s" f1 (print_expr pctx e2) i (print_expr pctx block) *)
  1151. (* | "__new_named__",e1::el ->
  1152. Printf.sprintf "new %s(%s)" (print_expr pctx e1) (print_exprs pctx ", " el) *)
  1153. (* | "__python_kwargs__",[e1] ->
  1154. "**" ^ (print_expr pctx e1) *)
  1155. (* | "__named_arg__",[{eexpr = TConst (TString name)};e2] ->
  1156. Printf.sprintf "%s=%s" name (print_expr pctx e2) *)
  1157. (* | "__assert__",el ->
  1158. Printf.sprintf "assert(%s)" (print_exprs pctx ", " el) *)
  1159. (* | "__call_global__",{eexpr = TConst(TString s)} :: el ->
  1160. Printf.sprintf "%s(%s)" s (print_exprs pctx ", " el) *)
  1161. (* | "__is__",[e1;e2] ->
  1162. Printf.sprintf "%s is %s" (print_expr pctx e1) (print_expr pctx e2) *)
  1163. (* | "__as__",[e1;e2] ->
  1164. Printf.sprintf "%s as %s" (print_expr pctx e1) (print_expr pctx e2) *)
  1165. (* | "__int_parse__",[e1] ->
  1166. Printf.sprintf "int.parse(%s)" (print_expr pctx e1) *)
  1167. (* | "__double_parse__",[e1] ->
  1168. Printf.sprintf "double.parse(%s)" (print_expr pctx e1) *)
  1169. (* | "__instanceof__",[e1;e2] ->
  1170. Printf.sprintf "_hx_c.Std._hx_is%s,%s" (print_expr pctx e1) (print_expr pctx e2) *)
  1171. (* | "__strict_eq__",[e2;e3] ->
  1172. let e2 = match e2.eexpr with
  1173. | TBinop(OpOr,a,_) -> a
  1174. | _ -> e2
  1175. in
  1176. print_expr pctx {e1 with eexpr = TBinop(OpEq,e2,e3)} *)
  1177. | _,el ->
  1178. Printf.sprintf "%s(%s)" id (print_exprs pctx ", " el)
  1179. and print_call pctx e1 el =
  1180. match e1.eexpr with
  1181. | TField(e1,((FAnon {cf_name = ("toUpperCase" | "toLowerCase" as s)}) | FDynamic ("toUpperCase" | "toLowerCase" as s))) ->
  1182. Printf.sprintf "HxOverrides.%s(%s)" s (print_expr pctx e1)
  1183. | _ ->
  1184. print_call2 pctx e1 el
  1185. and print_exprs pctx sep el =
  1186. String.concat sep (List.map (print_expr pctx) el)
  1187. and print_exprs_named pctx sep fl =
  1188. let args = String.concat sep (List.map (fun (s,e) -> Printf.sprintf "'%s': %s" (handle_keywords s) (print_expr pctx e)) fl) in
  1189. Printf.sprintf "{%s}" args
  1190. and print_params_named pctx sep fl =
  1191. let args = String.concat sep (List.map (fun (s,e) -> Printf.sprintf "%s= %s" (handle_keywords s) (print_expr pctx e)) fl) in
  1192. Printf.sprintf "%s" args
  1193. let handle_keywords s =
  1194. KeywordHandler.handle_keywords s
  1195. end
  1196. module Generator = struct
  1197. type context = {
  1198. com : Common.context;
  1199. buf : Buffer.t;
  1200. packages : (string,int) Hashtbl.t;
  1201. mutable static_inits : (unit -> unit) list;
  1202. mutable class_inits : (unit -> unit) list;
  1203. mutable indent_count : int;
  1204. transform_time : float;
  1205. print_time : float;
  1206. }
  1207. type class_field_infos = {
  1208. cfd_fields : string list;
  1209. cfd_props : string list;
  1210. cfd_methods : string list;
  1211. }
  1212. let mk_context com = {
  1213. com = com;
  1214. buf = Buffer.create 16000;
  1215. packages = Hashtbl.create 0;
  1216. static_inits = [];
  1217. class_inits = [];
  1218. indent_count = 0;
  1219. transform_time = 0.;
  1220. print_time = 0.;
  1221. }
  1222. (* Transformer interface *)
  1223. let transform_expr e =
  1224. let e = Codegen.UnificationCallback.run Transformer.check_unification e in
  1225. Transformer.transform e
  1226. let transform_to_value e =
  1227. let e = Codegen.UnificationCallback.run Transformer.check_unification e in
  1228. Transformer.transform_to_value e
  1229. (* Printer interface *)
  1230. let get_path mt =
  1231. Printer.print_base_type mt
  1232. let tfunc_str f pctx name =
  1233. Printer.print_function pctx f name
  1234. let texpr_str e pctx =
  1235. Printer.print_expr pctx e
  1236. let handle_keywords s =
  1237. Printer.handle_keywords s
  1238. (* Helper *)
  1239. let get_full_name mt =
  1240. (* TODO: haxe source is crazy *)
  1241. s_type_path mt.mt_path
  1242. let collect_class_field_data cfl =
  1243. let fields = DynArray.create () in
  1244. let props = DynArray.create () in
  1245. let methods = DynArray.create () in
  1246. List.iter (fun cf ->
  1247. match cf.cf_kind with
  1248. | Var({v_read = AccResolve}) ->
  1249. ()
  1250. | Var({v_read = AccCall}) ->
  1251. if Meta.has Meta.IsVar cf.cf_meta then
  1252. DynArray.add fields cf.cf_name
  1253. else
  1254. DynArray.add props cf.cf_name
  1255. | Var _ ->
  1256. DynArray.add fields cf.cf_name
  1257. | _ ->
  1258. DynArray.add methods cf.cf_name
  1259. ) cfl;
  1260. {
  1261. cfd_fields = DynArray.to_list fields;
  1262. cfd_props = DynArray.to_list props;
  1263. cfd_methods = DynArray.to_list methods;
  1264. }
  1265. let collect_class_statics_data cfl =
  1266. let fields = DynArray.create () in
  1267. List.iter (fun cf ->
  1268. if not (is_extern_field cf) then
  1269. DynArray.add fields cf.cf_name
  1270. ) cfl;
  1271. DynArray.to_list fields
  1272. let filter_py_metas metas =
  1273. List.filter (fun (n,_,_) -> match n with Meta.Custom ":python" -> true | _ -> false) metas
  1274. let get_members_with_init_expr c =
  1275. List.filter (fun cf -> match cf.cf_kind with
  1276. | Var({v_read = AccResolve | AccCall _}) -> false
  1277. | Var _ when cf.cf_expr = None -> true
  1278. | _ -> false
  1279. ) c.cl_ordered_fields
  1280. (* Printing *)
  1281. let spr ctx s =
  1282. Buffer.add_string ctx.buf s
  1283. let spr_line ctx s =
  1284. Buffer.add_string ctx.buf s;
  1285. Buffer.add_string ctx.buf "\n"
  1286. let print ctx =
  1287. Printf.kprintf (fun s -> begin
  1288. Buffer.add_string ctx.buf s
  1289. end)
  1290. let newline ctx =
  1291. spr ctx "\n"
  1292. (* Generating functions *)
  1293. let gen_pre_code_meta ctx metadata =
  1294. try
  1295. begin match Meta.get (Meta.Custom ":preCode") metadata with
  1296. | _,[(EConst(String s)),_],_ -> spr ctx s
  1297. | _ -> raise Not_found
  1298. end
  1299. with Not_found ->
  1300. ()
  1301. let gen_py_metas ctx metas indent =
  1302. List.iter (fun (n,el,_) ->
  1303. match el with
  1304. | [EConst(String s),_] ->
  1305. print ctx "%s@%s\n" indent s
  1306. | _ ->
  1307. assert false
  1308. ) metas
  1309. let gen_expr ctx e field indent =
  1310. let pctx = Printer.create_context ("\t" ^ indent) in
  1311. let e = match e.eexpr with
  1312. | TFunction(f) ->
  1313. {e with eexpr = TBlock [e]}
  1314. | _ ->
  1315. e
  1316. in
  1317. let expr2 = transform_to_value e in
  1318. let name = "_hx_init_" ^ (String.concat "_" (ExtString.String.nsplit field ".")) in
  1319. let maybe_split_expr expr2 = match expr2.eexpr with
  1320. | TBlock es when es <> [] && field <> "" ->
  1321. begin match List.rev es with
  1322. | e_last :: el ->
  1323. let new_last = {e_last with eexpr = TReturn (Some e_last)} in
  1324. let new_block = {expr2 with eexpr = TBlock (List.rev (new_last :: el))} in
  1325. let v_name = alloc_var name (tfun [] e_last.etype) in
  1326. let f_name = mk (TLocal v_name) v_name.v_type e_last.epos in
  1327. let call_f = mk (TCall(f_name,[])) e_last.etype e_last.epos in
  1328. Some new_block,call_f
  1329. | _ ->
  1330. assert false
  1331. end
  1332. | _ ->
  1333. None,expr2
  1334. in
  1335. let r = maybe_split_expr expr2 in
  1336. match r with
  1337. | Some e1,e2 ->
  1338. let expr_string_1 = texpr_str e1 pctx in
  1339. let expr_string_2 = texpr_str e2 pctx in
  1340. print ctx "%sdef %s():\n\t%s" indent name expr_string_1;
  1341. print ctx "%s%s = %s" indent field expr_string_2;
  1342. | None,e2 ->
  1343. let expr_string_2 = texpr_str e2 pctx in
  1344. if field = "" then
  1345. spr ctx expr_string_2
  1346. else
  1347. print ctx "%s%s = %s" indent field expr_string_2
  1348. let gen_func_expr ctx e c name metas extra_args indent stat =
  1349. let pctx = Printer.create_context indent in
  1350. let e = match e.eexpr with
  1351. | TFunction(f) ->
  1352. let args = List.map (fun s ->
  1353. alloc_var s t_dynamic,None
  1354. ) extra_args in
  1355. {e with eexpr = TFunction {f with tf_args = args @ f.tf_args}}
  1356. | _ ->
  1357. e
  1358. in
  1359. let expr1 = transform_expr e in
  1360. let field_name = if stat then
  1361. Printf.sprintf "%s_statics_%s" (snd c.cl_path) name
  1362. else
  1363. name
  1364. in
  1365. let expr_string = match expr1.eexpr with
  1366. | TFunction f ->
  1367. tfunc_str f pctx (Some field_name)
  1368. | _ ->
  1369. Printf.sprintf "%s = %s" field_name (texpr_str expr1 pctx)
  1370. in
  1371. gen_py_metas ctx metas indent;
  1372. spr ctx indent;
  1373. spr ctx expr_string;
  1374. if stat then begin
  1375. print ctx "%s.%s = %s" (get_path (t_infos (TClassDecl c))) name field_name
  1376. end
  1377. let gen_class_constructor ctx c cf =
  1378. let member_inits = get_members_with_init_expr c in
  1379. newline ctx;
  1380. let py_metas = filter_py_metas cf.cf_meta in
  1381. begin match member_inits,cf.cf_expr with
  1382. | _,Some ({eexpr = TFunction f} as ef) ->
  1383. let ethis = mk (TConst TThis) (TInst(c,List.map snd c.cl_types)) cf.cf_pos in
  1384. let member_data = List.map (fun cf ->
  1385. let ef = mk (TField(ethis,FInstance(c, cf))) cf.cf_type cf.cf_pos in
  1386. mk (TBinop(OpAssign,ef,null ef.etype ef.epos)) ef.etype ef.epos
  1387. ) member_inits in
  1388. let e = {f.tf_expr with eexpr = TBlock (member_data @ [f.tf_expr])} in
  1389. cf.cf_expr <- Some {ef with eexpr = TFunction {f with tf_expr = e}};
  1390. | _ ->
  1391. (* TODO: is this correct? *)
  1392. ()
  1393. end;
  1394. gen_func_expr ctx (match cf.cf_expr with None -> assert false | Some e -> e) c "__init__" py_metas ["self"] "\t" false;
  1395. newline ctx
  1396. let gen_class_field ctx c p cf =
  1397. let field = handle_keywords cf.cf_name in
  1398. begin match cf.cf_expr with
  1399. | None ->
  1400. ()(* print ctx "\t# var %s" field *)
  1401. | Some e ->
  1402. begin match cf.cf_kind with
  1403. | Method _ ->
  1404. let py_metas = filter_py_metas cf.cf_meta in
  1405. gen_func_expr ctx e c field py_metas ["self"] "\t" false;
  1406. | _ ->
  1407. gen_expr ctx e (Printf.sprintf "# var %s" field) "\t";
  1408. newline ctx;
  1409. end
  1410. end
  1411. let gen_static_field ctx c p cf =
  1412. let p = get_path (t_infos (TClassDecl c)) in
  1413. let field = handle_keywords cf.cf_name in
  1414. match cf.cf_expr with
  1415. | None ->
  1416. print ctx "%s.%s = None;\n" p field
  1417. | Some e ->
  1418. match cf.cf_kind with
  1419. | Method _ ->
  1420. let py_metas = filter_py_metas cf.cf_meta in
  1421. gen_func_expr ctx e c field py_metas [] "" true;
  1422. newline ctx
  1423. | _ ->
  1424. (let f = fun () ->
  1425. gen_expr ctx e (Printf.sprintf "%s.%s" p field) "";
  1426. newline ctx
  1427. in
  1428. ctx.static_inits <- f :: ctx.static_inits;)
  1429. let gen_class_data ctx c cfd p_super p_interfaces p p_name =
  1430. let field_str = String.concat "," (List.map (fun s -> "\"" ^ s ^ "\"") cfd.cfd_fields) in
  1431. let props_str = String.concat "," (List.map (fun s -> "\"" ^ s ^ "\"") cfd.cfd_props) in
  1432. let method_str = String.concat "," (List.map (fun s -> "\"" ^ s ^ "\"") cfd.cfd_methods) in
  1433. let statics_str =
  1434. let statics = collect_class_statics_data c.cl_ordered_statics in
  1435. String.concat "," (List.map (fun s -> "\"" ^ s ^ "\"") statics)
  1436. in
  1437. print ctx "%s._hx_class = %s\n" p p;
  1438. print ctx "%s._hx_class_name = \"%s\"\n" p p_name;
  1439. print ctx "_hx_classes[\"%s\"] = %s\n" p_name p;
  1440. print ctx "_hx_c.%s = %s\n" p p;
  1441. print ctx "%s._hx_fields = [%s]\n" p field_str;
  1442. print ctx "%s._hx_props = [%s]\n" p props_str;
  1443. print ctx "%s._hx_methods = [%s]\n" p method_str;
  1444. (* TODO: It seems strange to have a separation for member fields but a plain _hx_statics for static ones *)
  1445. print ctx "%s._hx_statics = [%s]\n" p statics_str;
  1446. print ctx "%s._hx_interfaces = [%s]\n" p (String.concat "," p_interfaces);
  1447. match p_super with
  1448. | None ->
  1449. ()
  1450. | Some ps ->
  1451. print ctx "%s._hx_super = %s\n" p ps
  1452. let gen_class_empty_constructor ctx p cfl =
  1453. let s_name = p ^ "_hx_empty_init" in
  1454. print ctx "def %s (_hx_o):\n" s_name;
  1455. let found_fields = ref false in
  1456. List.iter (fun cf -> match cf.cf_kind with
  1457. | Var ({v_read = AccResolve | AccCall}) ->
  1458. ()
  1459. | Var _ ->
  1460. found_fields := true;
  1461. print ctx "\t_hx_o.%s = None\n" (handle_keywords cf.cf_name)
  1462. | _ ->
  1463. ()
  1464. ) cfl;
  1465. if not !found_fields then
  1466. spr ctx "\tpass\n";
  1467. print ctx "%s._hx_empty_init = %s\n" p s_name
  1468. let gen_class_statics ctx c p =
  1469. List.iter (fun cf -> gen_static_field ctx c p cf) c.cl_ordered_statics
  1470. let gen_class_init ctx c =
  1471. match c.cl_init with
  1472. | None ->
  1473. ()
  1474. | Some e ->
  1475. let f = fun () ->
  1476. let e = transform_expr e in
  1477. spr_line ctx (texpr_str e (Printer.create_context ""));
  1478. in
  1479. ctx.class_inits <- f :: ctx.class_inits
  1480. let gen_class ctx c =
  1481. gen_pre_code_meta ctx c.cl_meta;
  1482. (* print ctx "# print %s.%s\n" (s_type_path c.cl_module.m_path) (snd c.cl_path); *)
  1483. if not c.cl_extern then begin
  1484. let mt = (t_infos (TClassDecl c)) in
  1485. let p = get_path mt in
  1486. let p_name = get_full_name mt in
  1487. newline ctx;
  1488. print ctx "class %s" p;
  1489. let p_super = match c.cl_super with
  1490. | None ->
  1491. None
  1492. | Some (csup,_) ->
  1493. let p = get_path (t_infos (TClassDecl csup)) in
  1494. print ctx "(%s)" p;
  1495. Some p
  1496. in
  1497. let p_interfaces = List.map (fun (c,tl) ->
  1498. get_path (t_infos (TClassDecl c))
  1499. ) c.cl_implements in
  1500. spr ctx ":";
  1501. spr ctx "\n";
  1502. begin match c.cl_constructor with
  1503. | Some cf -> gen_class_constructor ctx c cf;
  1504. | None -> ()
  1505. end;
  1506. List.iter (fun cf -> gen_class_field ctx c p cf) c.cl_ordered_fields;
  1507. let x = collect_class_field_data c.cl_ordered_fields in
  1508. let use_pass = match x.cfd_methods with
  1509. | [] -> c.cl_constructor = None
  1510. | _ -> c.cl_interface
  1511. in
  1512. if use_pass then spr_line ctx "\tpass\n";
  1513. gen_class_data ctx c x p_super p_interfaces p p_name;
  1514. gen_class_empty_constructor ctx p c.cl_ordered_fields;
  1515. gen_class_statics ctx c p;
  1516. end;
  1517. gen_class_init ctx c
  1518. let gen_enum_metadata ctx en p =
  1519. let meta = Codegen.build_metadata ctx.com (TEnumDecl en) in
  1520. match meta with
  1521. | None ->
  1522. ()
  1523. | Some e ->
  1524. print ctx "%s.__meta__ = " p;
  1525. gen_expr ctx e "" "";
  1526. newline ctx
  1527. let gen_enum ctx en =
  1528. let mt = (t_infos (TEnumDecl en)) in
  1529. let p = get_path mt in
  1530. let p_name = get_full_name mt in
  1531. newline ctx;
  1532. print ctx "class %s(_hx_c.Enum):\n" p;
  1533. spr ctx "\tdef __init__(self, t, i, p):\n";
  1534. print ctx "\t\tsuper(%s,self).__init__(t, i, p)\n" p;
  1535. let enum_constructs = PMap.foldi (fun k ef acc ->
  1536. let f = handle_keywords ef.ef_name in
  1537. begin match follow ef.ef_type with
  1538. | TFun(args,_) ->
  1539. let print_args args =
  1540. let had_optional = ref false in
  1541. let sl = List.map (fun (n,o,_) ->
  1542. let name = handle_keywords n in
  1543. let arg_value = if !had_optional then
  1544. "= None"
  1545. else if o then begin
  1546. had_optional := true;
  1547. " = None"
  1548. end else
  1549. ""
  1550. in
  1551. Printf.sprintf "%s%s" name arg_value
  1552. ) args in
  1553. String.concat "," sl
  1554. in
  1555. let param_str = print_args args in
  1556. let args_str = String.concat "," (List.map (fun (n,_,_) -> handle_keywords n) args) in
  1557. print ctx "def _%s_statics_%s (%s):\n" p f param_str;
  1558. print ctx "\treturn %s(\"%s\", %i, [%s])\n" p ef.ef_name ef.ef_index args_str;
  1559. print ctx "%s.%s = _%s_statics_%s\n" p f p f;
  1560. | _ ->
  1561. (* TODO: haxe source has api.quoteString for ef.ef_name *)
  1562. print ctx "%s.%s = %s(\"%s\", %i, list())\n" p f p ef.ef_name ef.ef_index
  1563. end;
  1564. newline ctx;
  1565. ef :: acc
  1566. ) en.e_constrs [] in
  1567. let fix = match enum_constructs with [] -> "" | _ -> "\"" in
  1568. 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
  1569. let enum_constructs_str = fix ^ (String.concat ("\",\"") (List.map (fun ef -> ef.ef_name) enum_constructs)) ^ fix in
  1570. print ctx "%s._hx_constructs = [%s]\n" p enum_constructs_str;
  1571. print ctx "%s._hx_class = %s\n" p p;
  1572. print ctx "%s._hx_class_name = \"%s\"\n" p p_name;
  1573. print ctx "_hx_classes[\"%s\"] = %s\n" p_name p;
  1574. print ctx "_hx_c.%s = %s\n" p p;
  1575. gen_enum_metadata ctx en p
  1576. let gen_abstract ctx a =
  1577. gen_pre_code_meta ctx a.a_meta;
  1578. (* print ctx "# print %s.%s\n" (s_type_path a.a_module.m_path) (snd a.a_path); *)
  1579. newline ctx;
  1580. let mt = (t_infos (TAbstractDecl a)) in
  1581. let p = get_path mt in
  1582. let p_name = get_full_name mt in
  1583. print ctx "class %s" p;
  1584. spr ctx ":";
  1585. begin match a.a_impl with
  1586. | Some c ->
  1587. List.iter (fun cf ->
  1588. if cf.cf_name = "_new" then
  1589. gen_class_constructor ctx c cf
  1590. else
  1591. gen_class_field ctx c p cf
  1592. ) c.cl_ordered_statics;
  1593. | None ->
  1594. spr_line ctx "\n\tpass\n";
  1595. end;
  1596. print ctx "%s._hx_class = %s\n" p p;
  1597. print ctx "%s._hx_class_name = \"%s\"\n" p p_name;
  1598. print ctx "_hx_classes[\"%s\"] = %s\n" p_name p;
  1599. print ctx "_hx_c.%s = %s\n" p p
  1600. let gen_type ctx mt = match mt with
  1601. | TClassDecl c -> gen_class ctx c
  1602. | TEnumDecl en -> gen_enum ctx en
  1603. | TAbstractDecl a when Meta.has Meta.CoreType a.a_meta -> gen_abstract ctx a
  1604. | _ -> ()
  1605. (* Generator parts *)
  1606. let gen_resources ctx =
  1607. if Hashtbl.length ctx.com.resources > 0 then begin
  1608. spr ctx "import os;\ndef _hx_resources__():\n\treturn {";
  1609. let first = ref true in
  1610. Hashtbl.iter (fun k v ->
  1611. let prefix = if !first then begin
  1612. first := false;
  1613. "";
  1614. end else
  1615. ","
  1616. in
  1617. print ctx "%s'%s': open('%%s.%%s'%%(__file__,'%s'),'rb').read()" prefix k k;
  1618. Std.output_file (ctx.com.file ^ "." ^ k) v
  1619. ) ctx.com.resources;
  1620. spr ctx "}\n"
  1621. end
  1622. let gen_types ctx =
  1623. let used_paths = Hashtbl.create 0 in
  1624. let find_type path =
  1625. Hashtbl.add used_paths path true;
  1626. Utils.find_type ctx.com path
  1627. in
  1628. gen_type ctx (find_type (["python"],"Boot"));
  1629. gen_type ctx (find_type ([],"Enum"));
  1630. gen_type ctx (find_type ([],"HxOverrides"));
  1631. List.iter (fun mt ->
  1632. if not (Hashtbl.mem used_paths (t_infos mt).mt_path) then
  1633. gen_type ctx mt
  1634. ) ctx.com.types
  1635. let gen_static_inits ctx =
  1636. List.iter (fun f -> f()) (List.rev ctx.static_inits)
  1637. let gen_class_inits ctx =
  1638. List.iter (fun f -> f()) (List.rev ctx.class_inits)
  1639. let gen_main ctx =
  1640. match ctx.com.main with
  1641. | None ->
  1642. ()
  1643. | Some e ->
  1644. gen_expr ctx e "" ""
  1645. (* Entry point *)
  1646. let run com =
  1647. Transformer.init com;
  1648. let ctx = mk_context com in
  1649. gen_resources ctx;
  1650. gen_types ctx;
  1651. gen_class_inits ctx;
  1652. gen_static_inits ctx;
  1653. gen_main ctx;
  1654. let ch = open_out_bin com.file in
  1655. output_string ch (Buffer.contents ctx.buf);
  1656. close_out ch
  1657. end
  1658. let generate com =
  1659. Generator.run com