finalization.ml 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. open Globals
  2. open Ast
  3. open Common
  4. open Type
  5. open Error
  6. open TyperBase
  7. open Typecore
  8. (* ---------------------------------------------------------------------- *)
  9. (* FINALIZATION *)
  10. let get_main ctx types =
  11. match ctx.com.main_class with
  12. | None -> None
  13. | Some path ->
  14. let p = null_pos in
  15. let pack,name = path in
  16. let m = Typeload.load_module ctx (pack,name) p in
  17. let c,f =
  18. let p = ref p in
  19. try
  20. match m.m_statics with
  21. | None ->
  22. raise Not_found
  23. | Some c ->
  24. p := c.cl_name_pos;
  25. c, PMap.find "main" c.cl_statics
  26. with Not_found -> try
  27. let t = Typeload.find_type_in_module_raise ctx m name null_pos in
  28. match t with
  29. | TEnumDecl _ | TTypeDecl _ | TAbstractDecl _ ->
  30. raise_typing_error ("Invalid -main : " ^ s_type_path path ^ " is not a class") null_pos
  31. | TClassDecl c ->
  32. p := c.cl_name_pos;
  33. c, PMap.find "main" c.cl_statics
  34. with Not_found ->
  35. raise_typing_error ("Invalid -main : " ^ s_type_path path ^ " does not have static function main") !p
  36. in
  37. let ft = Type.field_type f in
  38. let fmode, r =
  39. match follow ft with
  40. | TFun ([],r) -> FStatic (c,f), r
  41. | _ -> raise_typing_error ("Invalid -main : " ^ s_type_path path ^ " has invalid main function") c.cl_pos
  42. in
  43. if not (ExtType.is_void (follow r)) then raise_typing_error (Printf.sprintf "Return type of main function should be Void (found %s)" (s_type (print_context()) r)) f.cf_name_pos;
  44. f.cf_meta <- (Dce.mk_keep_meta f.cf_pos) :: f.cf_meta;
  45. let emain = type_module_type ctx (TClassDecl c) None null_pos in
  46. let main = mk (TCall (mk (TField (emain,fmode)) ft null_pos,[])) r null_pos in
  47. let call_static path method_name =
  48. let et = List.find (fun t -> t_path t = path) types in
  49. let ec = (match et with TClassDecl c -> c | _ -> die "" __LOC__) in
  50. let ef = PMap.find method_name ec.cl_statics in
  51. let et = mk (TTypeExpr et) (mk_anon (ref (Statics ec))) null_pos in
  52. mk (TCall (mk (TField (et,FStatic (ec,ef))) ef.cf_type null_pos,[])) ctx.t.tvoid null_pos
  53. in
  54. (* add haxe.EntryPoint.run() call *)
  55. let add_entry_point_run main =
  56. try
  57. [main; call_static (["haxe"],"EntryPoint") "run"]
  58. with Not_found ->
  59. [main]
  60. (* add calls for event loop *)
  61. and add_event_loop main =
  62. (try
  63. [main; call_static (["sys";"thread";"_Thread"],"Thread_Impl_") "processEvents"]
  64. with Not_found ->
  65. [main]
  66. )
  67. in
  68. let main =
  69. (* Threaded targets run event loops per thread *)
  70. let exprs =
  71. if ctx.com.config.pf_supports_threads then add_event_loop main
  72. else add_entry_point_run main
  73. in
  74. match exprs with
  75. | [e] -> e
  76. | _ -> mk (TBlock exprs) ctx.t.tvoid p
  77. in
  78. Some main
  79. let finalize ctx =
  80. flush_pass ctx PFinal "final";
  81. match ctx.com.callbacks#get_after_typing with
  82. | [] ->
  83. ()
  84. | fl ->
  85. let rec loop handled_types =
  86. let all_types = ctx.com.module_lut#fold (fun _ m acc -> m.m_types @ acc) [] in
  87. match (List.filter (fun mt -> not (List.memq mt handled_types)) all_types) with
  88. | [] ->
  89. ()
  90. | new_types ->
  91. List.iter (fun f -> f new_types) fl;
  92. flush_pass ctx PFinal "final";
  93. loop all_types
  94. in
  95. loop []
  96. type state =
  97. | Generating
  98. | Done
  99. | NotYet
  100. let sort_types com (modules : (path,module_def) lookup) =
  101. let types = ref [] in
  102. let states = Hashtbl.create 0 in
  103. let state p = try Hashtbl.find states p with Not_found -> NotYet in
  104. let statics = ref PMap.empty in
  105. let rec loop t =
  106. let p = t_path t in
  107. match state p with
  108. | Done -> ()
  109. | Generating ->
  110. com.warning WStaticInitOrder [] ("Warning : maybe loop in static generation of " ^ s_type_path p) (t_infos t).mt_pos;
  111. | NotYet ->
  112. Hashtbl.add states p Generating;
  113. let t = (match t with
  114. | TClassDecl c ->
  115. walk_class p c;
  116. t
  117. | TEnumDecl _ | TTypeDecl _ | TAbstractDecl _ ->
  118. t
  119. ) in
  120. Hashtbl.replace states p Done;
  121. types := t :: !types
  122. and loop_class p c =
  123. if c.cl_path <> p then loop (TClassDecl c)
  124. and loop_enum p e =
  125. if e.e_path <> p then loop (TEnumDecl e)
  126. and loop_abstract p a =
  127. if a.a_path <> p then loop (TAbstractDecl a)
  128. and walk_static_field p c cf =
  129. match cf.cf_expr with
  130. | None -> ()
  131. | Some e ->
  132. if PMap.mem (c.cl_path,cf.cf_name) (!statics) then
  133. ()
  134. else begin
  135. statics := PMap.add (c.cl_path,cf.cf_name) () (!statics);
  136. walk_expr p e;
  137. end
  138. and walk_expr p e =
  139. match e.eexpr with
  140. | TTypeExpr t ->
  141. (match t with
  142. | TClassDecl c -> loop_class p c
  143. | TEnumDecl e -> loop_enum p e
  144. | TAbstractDecl a -> loop_abstract p a
  145. | TTypeDecl _ -> die "" __LOC__)
  146. | TNew (c,_,_) ->
  147. iter (walk_expr p) e;
  148. loop_class p c;
  149. let rec loop c =
  150. if PMap.mem (c.cl_path,"new") (!statics) then
  151. ()
  152. else begin
  153. statics := PMap.add (c.cl_path,"new") () !statics;
  154. (match c.cl_constructor with
  155. | Some { cf_expr = Some e } -> walk_expr p e
  156. | _ -> ());
  157. match c.cl_super with
  158. | None -> ()
  159. | Some (csup,_) -> loop csup
  160. end
  161. in
  162. loop c
  163. | TField(e1,FStatic(c,cf)) ->
  164. walk_expr p e1;
  165. walk_static_field p c cf;
  166. | _ ->
  167. iter (walk_expr p) e
  168. and walk_class p c =
  169. (match c.cl_super with None -> () | Some (c,_) -> loop_class p c);
  170. List.iter (fun (c,_) -> loop_class p c) c.cl_implements;
  171. (match c.cl_init with
  172. | None -> ()
  173. | Some e -> walk_expr p e);
  174. PMap.iter (fun _ f ->
  175. match f.cf_expr with
  176. | None -> ()
  177. | Some e ->
  178. match e.eexpr with
  179. | TFunction _ -> ()
  180. | _ -> walk_expr p e
  181. ) c.cl_statics
  182. in
  183. let sorted_modules = List.sort (fun m1 m2 -> compare m1.m_path m2.m_path) (modules#fold (fun _ m acc -> m :: acc) []) in
  184. List.iter (fun m -> List.iter loop m.m_types) sorted_modules;
  185. List.rev !types, sorted_modules
  186. let generate ctx =
  187. let types,modules = sort_types ctx.com ctx.com.module_lut in
  188. get_main ctx types,types,modules