codegen.ml 71 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155
  1. (*
  2. * Copyright (C)2005-2013 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. open Typecore
  26. (* -------------------------------------------------------------------------- *)
  27. (* TOOLS *)
  28. let field e name t p =
  29. mk (TField (e,try quick_field e.etype name with Not_found -> assert false)) t p
  30. let fcall e name el ret p =
  31. let ft = tfun (List.map (fun e -> e.etype) el) ret in
  32. mk (TCall (field e name ft p,el)) ret p
  33. let mk_parent e =
  34. mk (TParenthesis e) e.etype e.epos
  35. let string com str p =
  36. mk (TConst (TString str)) com.basic.tstring p
  37. let binop op a b t p =
  38. mk (TBinop (op,a,b)) t p
  39. let index com e index t p =
  40. mk (TArray (e,mk (TConst (TInt (Int32.of_int index))) com.basic.tint p)) t p
  41. let concat e1 e2 =
  42. let e = (match e1.eexpr, e2.eexpr with
  43. | TBlock el1, TBlock el2 -> TBlock (el1@el2)
  44. | TBlock el, _ -> TBlock (el @ [e2])
  45. | _, TBlock el -> TBlock (e1 :: el)
  46. | _ , _ -> TBlock [e1;e2]
  47. ) in
  48. mk e e2.etype (punion e1.epos e2.epos)
  49. let type_constant com c p =
  50. let t = com.basic in
  51. match c with
  52. | Int s ->
  53. if String.length s > 10 && String.sub s 0 2 = "0x" then error "Invalid hexadecimal integer" p;
  54. (try mk (TConst (TInt (Int32.of_string s))) t.tint p
  55. with _ -> mk (TConst (TFloat s)) t.tfloat p)
  56. | Float f -> mk (TConst (TFloat f)) t.tfloat p
  57. | String s -> mk (TConst (TString s)) t.tstring p
  58. | Ident "true" -> mk (TConst (TBool true)) t.tbool p
  59. | Ident "false" -> mk (TConst (TBool false)) t.tbool p
  60. | Ident "null" -> mk (TConst TNull) (t.tnull (mk_mono())) p
  61. | Ident t -> error ("Invalid constant : " ^ t) p
  62. | Regexp _ -> error "Invalid constant" p
  63. let rec type_constant_value com (e,p) =
  64. match e with
  65. | EConst c ->
  66. type_constant com c p
  67. | EParenthesis e ->
  68. type_constant_value com e
  69. | EObjectDecl el ->
  70. mk (TObjectDecl (List.map (fun (n,e) -> n, type_constant_value com e) el)) (TAnon { a_fields = PMap.empty; a_status = ref Closed }) p
  71. | EArrayDecl el ->
  72. mk (TArrayDecl (List.map (type_constant_value com) el)) (com.basic.tarray t_dynamic) p
  73. | _ ->
  74. error "Constant value expected" p
  75. let rec has_properties c =
  76. List.exists (fun f ->
  77. match f.cf_kind with
  78. | Var { v_read = AccCall } -> true
  79. | Var { v_write = AccCall } -> true
  80. | _ -> false
  81. ) c.cl_ordered_fields || (match c.cl_super with Some (c,_) -> has_properties c | _ -> false)
  82. let get_properties fields =
  83. List.fold_left (fun acc f ->
  84. let acc = (match f.cf_kind with
  85. | Var { v_read = AccCall } -> ("get_" ^ f.cf_name , "get_" ^ f.cf_name) :: acc
  86. | _ -> acc) in
  87. match f.cf_kind with
  88. | Var { v_write = AccCall } -> ("set_" ^ f.cf_name , "set_" ^ f.cf_name) :: acc
  89. | _ -> acc
  90. ) [] fields
  91. let add_property_field com c =
  92. let p = c.cl_pos in
  93. let props = get_properties (c.cl_ordered_statics @ c.cl_ordered_fields) in
  94. match props with
  95. | [] -> ()
  96. | _ ->
  97. let fields,values = List.fold_left (fun (fields,values) (n,v) ->
  98. let cf = mk_field n com.basic.tstring p in
  99. PMap.add n cf fields,(n, string com v p) :: values
  100. ) (PMap.empty,[]) props in
  101. let t = mk_anon fields in
  102. let e = mk (TObjectDecl values) t p in
  103. let cf = mk_field "__properties__" t p in
  104. cf.cf_expr <- Some e;
  105. c.cl_statics <- PMap.add cf.cf_name cf c.cl_statics;
  106. c.cl_ordered_statics <- cf :: c.cl_ordered_statics
  107. (* -------------------------------------------------------------------------- *)
  108. (* REMOTING PROXYS *)
  109. let extend_remoting ctx c t p async prot =
  110. if c.cl_super <> None then error "Cannot extend several classes" p;
  111. (* remove forbidden packages *)
  112. let rules = ctx.com.package_rules in
  113. ctx.com.package_rules <- PMap.foldi (fun key r acc -> match r with Forbidden -> acc | _ -> PMap.add key r acc) rules PMap.empty;
  114. (* parse module *)
  115. let path = (t.tpackage,t.tname) in
  116. let new_name = (if async then "Async_" else "Remoting_") ^ t.tname in
  117. (* check if the proxy already exists *)
  118. let t = (try
  119. Typeload.load_type_def ctx p { tpackage = fst path; tname = new_name; tparams = []; tsub = None }
  120. with
  121. Error (Module_not_found _,p2) when p == p2 ->
  122. (* build it *)
  123. Common.log ctx.com ("Building proxy for " ^ s_type_path path);
  124. let file, decls = (try
  125. Typeload.parse_module ctx path p
  126. with
  127. | Not_found -> ctx.com.package_rules <- rules; error ("Could not load proxy module " ^ s_type_path path ^ (if fst path = [] then " (try using absolute path)" else "")) p
  128. | e -> ctx.com.package_rules <- rules; raise e) in
  129. ctx.com.package_rules <- rules;
  130. let base_fields = [
  131. { cff_name = "__cnx"; cff_pos = p; cff_doc = None; cff_meta = []; cff_access = []; cff_kind = FVar (Some (CTPath { tpackage = ["haxe";"remoting"]; tname = if async then "AsyncConnection" else "Connection"; tparams = []; tsub = None }),None) };
  132. { cff_name = "new"; cff_pos = p; cff_doc = None; cff_meta = []; cff_access = [APublic]; cff_kind = FFun { f_args = ["c",false,None,None]; f_type = None; f_expr = Some (EBinop (OpAssign,(EConst (Ident "__cnx"),p),(EConst (Ident "c"),p)),p); f_params = [] } };
  133. ] in
  134. let tvoid = CTPath { tpackage = []; tname = "Void"; tparams = []; tsub = None } in
  135. let build_field is_public acc f =
  136. if f.cff_name = "new" then
  137. acc
  138. else match f.cff_kind with
  139. | FFun fd when (is_public || List.mem APublic f.cff_access) && not (List.mem AStatic f.cff_access) ->
  140. if List.exists (fun (_,_,t,_) -> t = None) fd.f_args then error ("Field " ^ f.cff_name ^ " type is not complete and cannot be used by RemotingProxy") p;
  141. let eargs = [EArrayDecl (List.map (fun (a,_,_,_) -> (EConst (Ident a),p)) fd.f_args),p] in
  142. let ftype = (match fd.f_type with Some (CTPath { tpackage = []; tname = "Void" }) -> None | _ -> fd.f_type) in
  143. let fargs, eargs = if async then match ftype with
  144. | Some tret -> fd.f_args @ ["__callb",true,Some (CTFunction ([tret],tvoid)),None], eargs @ [EConst (Ident "__callb"),p]
  145. | _ -> fd.f_args, eargs @ [EConst (Ident "null"),p]
  146. else
  147. fd.f_args, eargs
  148. in
  149. let id = (EConst (String f.cff_name), p) in
  150. let id = if prot then id else ECall ((EConst (Ident "__unprotect__"),p),[id]),p in
  151. let expr = ECall (
  152. (EField (
  153. (ECall ((EField ((EConst (Ident "__cnx"),p),"resolve"),p),[id]),p),
  154. "call")
  155. ,p),eargs),p
  156. in
  157. let expr = if async || ftype = None then expr else (EReturn (Some expr),p) in
  158. let fd = {
  159. f_params = fd.f_params;
  160. f_args = fargs;
  161. f_type = if async then None else ftype;
  162. f_expr = Some (EBlock [expr],p);
  163. } in
  164. { cff_name = f.cff_name; cff_pos = p; cff_doc = None; cff_meta = []; cff_access = [APublic]; cff_kind = FFun fd } :: acc
  165. | _ -> acc
  166. in
  167. let decls = List.map (fun d ->
  168. match d with
  169. | EClass c, p when c.d_name = t.tname ->
  170. let is_public = List.mem HExtern c.d_flags || List.mem HInterface c.d_flags in
  171. let fields = List.rev (List.fold_left (build_field is_public) base_fields c.d_data) in
  172. (EClass { c with d_flags = []; d_name = new_name; d_data = fields },p)
  173. | _ -> d
  174. ) decls in
  175. let m = Typeload.type_module ctx (t.tpackage,new_name) file decls p in
  176. add_dependency ctx.m.curmod m;
  177. try
  178. List.find (fun tdecl -> snd (t_path tdecl) = new_name) m.m_types
  179. with Not_found ->
  180. error ("Module " ^ s_type_path path ^ " does not define type " ^ t.tname) p
  181. ) in
  182. match t with
  183. | TClassDecl c2 when c2.cl_types = [] -> c2.cl_build(); c.cl_super <- Some (c2,[]);
  184. | _ -> error "Remoting proxy must be a class without parameters" p
  185. (* -------------------------------------------------------------------------- *)
  186. (* HAXE.RTTI.GENERIC *)
  187. exception Generic_Exception of string * Ast.pos
  188. type generic_context = {
  189. ctx : typer;
  190. subst : (t * t) list;
  191. name : string;
  192. p : pos;
  193. mutable mg : module_def option;
  194. }
  195. let make_generic ctx ps pt p =
  196. let rec loop l1 l2 =
  197. match l1, l2 with
  198. | [] , [] -> []
  199. | (x,TLazy f) :: l1, _ -> loop ((x,(!f)()) :: l1) l2
  200. | (_,t1) :: l1 , t2 :: l2 -> (t1,t2) :: loop l1 l2
  201. | _ -> assert false
  202. in
  203. let name =
  204. String.concat "_" (List.map2 (fun (s,_) t ->
  205. let path = (match follow t with
  206. | TInst (ct,_) -> ct.cl_path
  207. | TEnum (e,_) -> e.e_path
  208. | TAbstract (a,_) when Meta.has Meta.RuntimeValue a.a_meta -> a.a_path
  209. | TMono _ -> raise (Generic_Exception (("Could not determine type for parameter " ^ s), p))
  210. | t -> raise (Generic_Exception (("Type parameter must be a class or enum instance (found " ^ (s_type (print_context()) t) ^ ")"), p))
  211. ) in
  212. match path with
  213. | [] , name -> name
  214. | l , name -> String.concat "_" l ^ "_" ^ name
  215. ) ps pt)
  216. in
  217. {
  218. ctx = ctx;
  219. subst = loop ps pt;
  220. name = name;
  221. p = p;
  222. mg = None;
  223. }
  224. let rec generic_substitute_type gctx t =
  225. match t with
  226. | TInst ({ cl_kind = KGeneric } as c2,tl2) ->
  227. (* maybe loop, or generate cascading generics *)
  228. let _, _, f = gctx.ctx.g.do_build_instance gctx.ctx (TClassDecl c2) gctx.p in
  229. let t = f (List.map (generic_substitute_type gctx) tl2) in
  230. (match follow t,gctx.mg with TInst(c,_), Some m -> add_dependency m c.cl_module | _ -> ());
  231. t
  232. | _ ->
  233. try List.assq t gctx.subst with Not_found -> Type.map (generic_substitute_type gctx) t
  234. let generic_substitute_expr gctx e =
  235. let vars = Hashtbl.create 0 in
  236. let build_var v =
  237. try
  238. Hashtbl.find vars v.v_id
  239. with Not_found ->
  240. let v2 = alloc_var v.v_name (generic_substitute_type gctx v.v_type) in
  241. Hashtbl.add vars v.v_id v2;
  242. v2
  243. in
  244. let rec build_expr e =
  245. match e.eexpr with
  246. | TField(e1, FInstance({cl_kind = KGeneric},cf)) ->
  247. build_expr {e with eexpr = TField(e1,quick_field_dynamic (generic_substitute_type gctx (e1.etype)) cf.cf_name)}
  248. | _ -> map_expr_type build_expr (generic_substitute_type gctx) build_var e
  249. in
  250. build_expr e
  251. let is_generic_parameter ctx c =
  252. (* first check field parameters, then class parameters *)
  253. try
  254. ignore (List.assoc (snd c.cl_path) ctx.curfield.cf_params);
  255. Meta.has Meta.Generic ctx.curfield.cf_meta
  256. with Not_found -> try
  257. ignore(List.assoc (snd c.cl_path) ctx.type_params);
  258. (match ctx.curclass.cl_kind with | KGeneric -> true | _ -> false);
  259. with Not_found ->
  260. false
  261. let has_ctor_constraint c = match c.cl_kind with
  262. | KTypeParameter tl ->
  263. List.exists (fun t -> match follow t with
  264. | TAnon a when PMap.mem "new" a.a_fields -> true
  265. | _ -> false
  266. ) tl;
  267. | _ -> false
  268. let rec build_generic ctx c p tl =
  269. let pack = fst c.cl_path in
  270. let recurse = ref false in
  271. let rec check_recursive t =
  272. match follow t with
  273. | TInst (c2,tl) ->
  274. (match c2.cl_kind with
  275. | KTypeParameter tl ->
  276. if not (is_generic_parameter ctx c2) && has_ctor_constraint c2 then
  277. error "Type parameters with a constructor cannot be used non-generically" p;
  278. recurse := true
  279. | _ -> ());
  280. List.iter check_recursive tl;
  281. | _ ->
  282. ()
  283. in
  284. List.iter check_recursive tl;
  285. let gctx = try make_generic ctx c.cl_types tl p with Generic_Exception (msg,p) -> error msg p in
  286. let name = (snd c.cl_path) ^ "_" ^ gctx.name in
  287. if !recurse then begin
  288. TInst (c,tl) (* build a normal instance *)
  289. end else try
  290. Typeload.load_instance ctx { tpackage = pack; tname = name; tparams = []; tsub = None } p false
  291. with Error(Module_not_found path,_) when path = (pack,name) ->
  292. let m = (try Hashtbl.find ctx.g.modules (Hashtbl.find ctx.g.types_module c.cl_path) with Not_found -> assert false) in
  293. let ctx = { ctx with m = { ctx.m with module_types = m.m_types @ ctx.m.module_types } } in
  294. c.cl_build(); (* make sure the super class is already setup *)
  295. let mg = {
  296. m_id = alloc_mid();
  297. m_path = (pack,name);
  298. m_types = [];
  299. m_extra = module_extra (s_type_path (pack,name)) m.m_extra.m_sign 0. MFake;
  300. } in
  301. gctx.mg <- Some mg;
  302. let cg = mk_class mg (pack,name) c.cl_pos in
  303. mg.m_types <- [TClassDecl cg];
  304. Hashtbl.add ctx.g.modules mg.m_path mg;
  305. add_dependency mg m;
  306. add_dependency ctx.m.curmod mg;
  307. (* ensure that type parameters are set in dependencies *)
  308. let dep_stack = ref [] in
  309. let rec loop t =
  310. if not (List.memq t !dep_stack) then begin
  311. dep_stack := t :: !dep_stack;
  312. match t with
  313. | TInst (c,tl) -> add_dep c.cl_module tl
  314. | TEnum (e,tl) -> add_dep e.e_module tl
  315. | TType (t,tl) -> add_dep t.t_module tl
  316. | TAbstract (a,tl) -> add_dep a.a_module tl
  317. | TMono r ->
  318. (match !r with
  319. | None -> ()
  320. | Some t -> loop t)
  321. | TLazy f ->
  322. loop ((!f)());
  323. | TDynamic t2 ->
  324. if t == t2 then () else loop t2
  325. | TAnon a ->
  326. PMap.iter (fun _ f -> loop f.cf_type) a.a_fields
  327. | TFun (args,ret) ->
  328. List.iter (fun (_,_,t) -> loop t) args;
  329. loop ret
  330. end
  331. and add_dep m tl =
  332. add_dependency mg m;
  333. List.iter loop tl
  334. in
  335. List.iter loop tl;
  336. let delays = ref [] in
  337. let build_field f =
  338. let t = generic_substitute_type gctx f.cf_type in
  339. let f = { f with cf_type = t} in
  340. (* delay the expression mapping to make sure all cf_type fields are set correctly first *)
  341. (delays := (fun () ->
  342. try (match f.cf_expr with None -> () | Some e -> f.cf_expr <- Some (generic_substitute_expr gctx e))
  343. with Unify_error l -> error (error_msg (Unify l)) f.cf_pos) :: !delays);
  344. f
  345. in
  346. if c.cl_init <> None || c.cl_dynamic <> None then error "This class can't be generic" p;
  347. if c.cl_ordered_statics <> [] then error "A generic class can't have static fields" p;
  348. cg.cl_super <- (match c.cl_super with
  349. | None -> None
  350. | Some (cs,pl) ->
  351. (match apply_params c.cl_types tl (TInst (cs,pl)) with
  352. | TInst (cs,pl) when cs.cl_kind = KGeneric ->
  353. (match build_generic ctx cs p pl with
  354. | TInst (cs,pl) -> Some (cs,pl)
  355. | _ -> assert false)
  356. | TInst (cs,pl) -> Some (cs,pl)
  357. | _ -> assert false)
  358. );
  359. cg.cl_kind <- KGenericInstance (c,tl);
  360. cg.cl_interface <- c.cl_interface;
  361. cg.cl_constructor <- (match c.cl_constructor, c.cl_super with
  362. | None, None -> None
  363. | Some c, _ -> Some (build_field c)
  364. | _ -> error "Please define a constructor for this class in order to use it as generic" c.cl_pos
  365. );
  366. cg.cl_implements <- List.map (fun (i,tl) ->
  367. (match follow (generic_substitute_type gctx (TInst (i, List.map (generic_substitute_type gctx) tl))) with
  368. | TInst (i,tl) -> i, tl
  369. | _ -> assert false)
  370. ) c.cl_implements;
  371. cg.cl_ordered_fields <- List.map (fun f ->
  372. let f = build_field f in
  373. cg.cl_fields <- PMap.add f.cf_name f cg.cl_fields;
  374. f
  375. ) c.cl_ordered_fields;
  376. List.iter (fun f -> f()) !delays;
  377. TInst (cg,[])
  378. (* -------------------------------------------------------------------------- *)
  379. (* HAXE.XML.PROXY *)
  380. let extend_xml_proxy ctx c t file p =
  381. let t = Typeload.load_complex_type ctx p t in
  382. let file = (try Common.find_file ctx.com file with Not_found -> file) in
  383. add_dependency c.cl_module (create_fake_module ctx file);
  384. let used = ref PMap.empty in
  385. let print_results() =
  386. PMap.iter (fun id used ->
  387. if not used then ctx.com.warning (id ^ " is not used") p;
  388. ) (!used)
  389. in
  390. let check_used = Common.defined ctx.com Define.CheckXmlProxy in
  391. if check_used then ctx.g.hook_generate <- print_results :: ctx.g.hook_generate;
  392. try
  393. let rec loop = function
  394. | Xml.Element (_,attrs,childs) ->
  395. (try
  396. let id = List.assoc "id" attrs in
  397. if PMap.mem id c.cl_fields then error ("Duplicate id " ^ id) p;
  398. let t = if not check_used then t else begin
  399. used := PMap.add id false (!used);
  400. let ft() = used := PMap.add id true (!used); t in
  401. TLazy (ref ft)
  402. end in
  403. let f = {
  404. cf_name = id;
  405. cf_type = t;
  406. cf_public = true;
  407. cf_pos = p;
  408. cf_doc = None;
  409. cf_meta = no_meta;
  410. cf_kind = Var { v_read = AccResolve; v_write = AccNo };
  411. cf_params = [];
  412. cf_expr = None;
  413. cf_overloads = [];
  414. } in
  415. c.cl_fields <- PMap.add id f c.cl_fields;
  416. with
  417. Not_found -> ());
  418. List.iter loop childs;
  419. | Xml.PCData _ -> ()
  420. in
  421. loop (Xml.parse_file file)
  422. with
  423. | Xml.Error e -> error ("XML error " ^ Xml.error e) p
  424. | Xml.File_not_found f -> error ("XML File not found : " ^ f) p
  425. (* -------------------------------------------------------------------------- *)
  426. (* BUILD META DATA OBJECT *)
  427. let build_metadata com t =
  428. let api = com.basic in
  429. let p, meta, fields, statics = (match t with
  430. | TClassDecl c ->
  431. let fields = List.map (fun f -> f.cf_name,f.cf_meta) (c.cl_ordered_fields @ (match c.cl_constructor with None -> [] | Some f -> [{ f with cf_name = "_" }])) in
  432. let statics = List.map (fun f -> f.cf_name,f.cf_meta) c.cl_ordered_statics in
  433. (c.cl_pos, ["",c.cl_meta],fields,statics)
  434. | TEnumDecl e ->
  435. (e.e_pos, ["",e.e_meta],List.map (fun n -> n, (PMap.find n e.e_constrs).ef_meta) e.e_names, [])
  436. | TTypeDecl t ->
  437. (t.t_pos, ["",t.t_meta],(match follow t.t_type with TAnon a -> PMap.fold (fun f acc -> (f.cf_name,f.cf_meta) :: acc) a.a_fields [] | _ -> []),[])
  438. | TAbstractDecl a ->
  439. (a.a_pos, ["",a.a_meta],[],[])
  440. ) in
  441. let filter l =
  442. let l = List.map (fun (n,ml) -> n, ExtList.List.filter_map (fun (m,el,p) -> match m with Meta.Custom s when String.length s > 0 && s.[0] <> ':' -> Some (s,el,p) | _ -> None) ml) l in
  443. List.filter (fun (_,ml) -> ml <> []) l
  444. in
  445. let meta, fields, statics = filter meta, filter fields, filter statics in
  446. let make_meta_field ml =
  447. let h = Hashtbl.create 0 in
  448. mk (TObjectDecl (List.map (fun (f,el,p) ->
  449. if Hashtbl.mem h f then error ("Duplicate metadata '" ^ f ^ "'") p;
  450. Hashtbl.add h f ();
  451. f, mk (match el with [] -> TConst TNull | _ -> TArrayDecl (List.map (type_constant_value com) el)) (api.tarray t_dynamic) p
  452. ) ml)) (api.tarray t_dynamic) p
  453. in
  454. let make_meta l =
  455. mk (TObjectDecl (List.map (fun (f,ml) -> f,make_meta_field ml) l)) t_dynamic p
  456. in
  457. if meta = [] && fields = [] && statics = [] then
  458. None
  459. else
  460. let meta_obj = [] in
  461. let meta_obj = (if fields = [] then meta_obj else ("fields",make_meta fields) :: meta_obj) in
  462. let meta_obj = (if statics = [] then meta_obj else ("statics",make_meta statics) :: meta_obj) in
  463. let meta_obj = (try ("obj", make_meta_field (List.assoc "" meta)) :: meta_obj with Not_found -> meta_obj) in
  464. Some (mk (TObjectDecl meta_obj) t_dynamic p)
  465. (* -------------------------------------------------------------------------- *)
  466. (* MACRO TYPE *)
  467. let build_macro_type ctx pl p =
  468. let path, field, args = (match pl with
  469. | [TInst ({ cl_kind = KExpr (ECall (e,args),_) },_)]
  470. | [TInst ({ cl_kind = KExpr (EArrayDecl [ECall (e,args),_],_) },_)] ->
  471. let rec loop e =
  472. match fst e with
  473. | EField (e,f) -> f :: loop e
  474. | EConst (Ident i) -> [i]
  475. | _ -> error "Invalid macro call" p
  476. in
  477. (match loop e with
  478. | meth :: cl :: path -> (List.rev path,cl), meth, args
  479. | _ -> error "Invalid macro call" p)
  480. | _ ->
  481. error "MacroType require a single expression call parameter" p
  482. ) in
  483. let old = ctx.ret in
  484. let t = (match ctx.g.do_macro ctx MMacroType path field args p with
  485. | None -> mk_mono()
  486. | Some _ -> ctx.ret
  487. ) in
  488. ctx.ret <- old;
  489. t
  490. (* -------------------------------------------------------------------------- *)
  491. (* API EVENTS *)
  492. let build_instance ctx mtype p =
  493. match mtype with
  494. | TClassDecl c ->
  495. if ctx.pass > PBuildClass then c.cl_build();
  496. let ft = (fun pl ->
  497. match c.cl_kind with
  498. | KGeneric ->
  499. let r = exc_protect ctx (fun r ->
  500. let t = mk_mono() in
  501. r := (fun() -> t);
  502. unify_raise ctx (build_generic ctx c p pl) t p;
  503. t
  504. ) "build_generic" in
  505. delay ctx PForce (fun() -> ignore ((!r)()));
  506. TLazy r
  507. | KMacroType ->
  508. let r = exc_protect ctx (fun r ->
  509. let t = mk_mono() in
  510. r := (fun() -> t);
  511. unify_raise ctx (build_macro_type ctx pl p) t p;
  512. t
  513. ) "macro_type" in
  514. delay ctx PForce (fun() -> ignore ((!r)()));
  515. TLazy r
  516. | _ ->
  517. TInst (c,pl)
  518. ) in
  519. c.cl_types , c.cl_path , ft
  520. | TEnumDecl e ->
  521. e.e_types , e.e_path , (fun t -> TEnum (e,t))
  522. | TTypeDecl t ->
  523. t.t_types , t.t_path , (fun tl -> TType(t,tl))
  524. | TAbstractDecl a ->
  525. a.a_types, a.a_path, (fun tl -> TAbstract(a,tl))
  526. let on_inherit ctx c p h =
  527. match h with
  528. | HExtends { tpackage = ["haxe";"remoting"]; tname = "Proxy"; tparams = [TPType(CTPath t)] } ->
  529. extend_remoting ctx c t p false true;
  530. false
  531. | HExtends { tpackage = ["haxe";"remoting"]; tname = "AsyncProxy"; tparams = [TPType(CTPath t)] } ->
  532. extend_remoting ctx c t p true true;
  533. false
  534. | HExtends { tpackage = ["mt"]; tname = "AsyncProxy"; tparams = [TPType(CTPath t)] } ->
  535. extend_remoting ctx c t p true false;
  536. false
  537. | HExtends { tpackage = ["haxe";"xml"]; tname = "Proxy"; tparams = [TPExpr(EConst (String file),p);TPType t] } ->
  538. extend_xml_proxy ctx c t file p;
  539. true
  540. | _ ->
  541. true
  542. (* -------------------------------------------------------------------------- *)
  543. (* FINAL GENERATION *)
  544. (* Saves a class state so it can be restored later, e.g. after DCE or native path rewrite *)
  545. let save_class_state ctx t = match t with
  546. | TClassDecl c ->
  547. let meta = c.cl_meta and path = c.cl_path and ext = c.cl_extern in
  548. let fl = c.cl_fields and ofl = c.cl_ordered_fields and st = c.cl_statics and ost = c.cl_ordered_statics in
  549. let cst = c.cl_constructor and over = c.cl_overrides in
  550. let oflk = List.map (fun f -> f.cf_kind,f.cf_expr,f.cf_type) ofl in
  551. let ostk = List.map (fun f -> f.cf_kind,f.cf_expr,f.cf_type) ost in
  552. c.cl_restore <- (fun() ->
  553. c.cl_meta <- meta;
  554. c.cl_extern <- ext;
  555. c.cl_path <- path;
  556. c.cl_fields <- fl;
  557. c.cl_ordered_fields <- ofl;
  558. c.cl_statics <- st;
  559. c.cl_ordered_statics <- ost;
  560. c.cl_constructor <- cst;
  561. c.cl_overrides <- over;
  562. (* DCE might modify the cf_kind, so let's restore it as well *)
  563. List.iter2 (fun f (k,e,t) -> f.cf_kind <- k; f.cf_expr <- e; f.cf_type <- t;) ofl oflk;
  564. List.iter2 (fun f (k,e,t) -> f.cf_kind <- k; f.cf_expr <- e; f.cf_type <- t;) ost ostk;
  565. )
  566. | _ ->
  567. ()
  568. (* Checks if a private class' path clashes with another path *)
  569. let check_private_path ctx t = match t with
  570. | TClassDecl c when c.cl_private ->
  571. let rpath = (fst c.cl_module.m_path,"_" ^ snd c.cl_module.m_path) in
  572. if Hashtbl.mem ctx.g.types_module rpath then error ("This private class name will clash with " ^ s_type_path rpath) c.cl_pos;
  573. | _ ->
  574. ()
  575. (* Removes generic base classes *)
  576. let remove_generic_base ctx t = match t with
  577. | TClassDecl c when c.cl_kind = KGeneric && has_ctor_constraint c ->
  578. c.cl_extern <- true
  579. | _ ->
  580. ()
  581. (* Rewrites class or enum paths if @:native metadata is set *)
  582. let apply_native_paths ctx t =
  583. let get_real_path meta path =
  584. let (_,e,mp) = Meta.get Meta.Native meta in
  585. match e with
  586. | [Ast.EConst (Ast.String name),p] ->
  587. (Meta.RealPath,[Ast.EConst (Ast.String (s_type_path path)),p],mp),parse_path name
  588. | _ ->
  589. error "String expected" mp
  590. in
  591. try
  592. (match t with
  593. | TClassDecl c ->
  594. let meta,path = get_real_path c.cl_meta c.cl_path in
  595. c.cl_meta <- meta :: c.cl_meta;
  596. c.cl_path <- path;
  597. | TEnumDecl e ->
  598. let meta,path = get_real_path e.e_meta e.e_path in
  599. e.e_meta <- meta :: e.e_meta;
  600. e.e_path <- path;
  601. | _ ->
  602. ())
  603. with Not_found ->
  604. ()
  605. (* Adds the __rtti field if required *)
  606. let add_rtti ctx t =
  607. let rec has_rtti c =
  608. Meta.has Meta.Rtti c.cl_meta || match c.cl_super with None -> false | Some (csup,_) -> has_rtti csup
  609. in
  610. match t with
  611. | TClassDecl c when has_rtti c && not (PMap.mem "__rtti" c.cl_statics) ->
  612. let f = mk_field "__rtti" ctx.t.tstring c.cl_pos in
  613. let str = Genxml.gen_type_string ctx.com t in
  614. f.cf_expr <- Some (mk (TConst (TString str)) f.cf_type c.cl_pos);
  615. c.cl_ordered_statics <- f :: c.cl_ordered_statics;
  616. c.cl_statics <- PMap.add f.cf_name f c.cl_statics;
  617. | _ ->
  618. ()
  619. (* Removes extern and macro fields, also checks for Void fields *)
  620. let remove_extern_fields ctx t = match t with
  621. | TClassDecl c ->
  622. let do_remove f =
  623. Meta.has Meta.Extern f.cf_meta || Meta.has Meta.Generic f.cf_meta
  624. || (match f.cf_kind with
  625. | Var {v_read = AccRequire (s,_)} -> true
  626. | Method MethMacro -> not ctx.in_macro
  627. | _ -> false)
  628. in
  629. if not (Common.defined ctx.com Define.DocGen) then begin
  630. c.cl_ordered_fields <- List.filter (fun f ->
  631. let b = do_remove f in
  632. if b then c.cl_fields <- PMap.remove f.cf_name c.cl_fields;
  633. not b
  634. ) c.cl_ordered_fields;
  635. c.cl_ordered_statics <- List.filter (fun f ->
  636. let b = do_remove f in
  637. if b then c.cl_statics <- PMap.remove f.cf_name c.cl_statics;
  638. not b
  639. ) c.cl_ordered_statics;
  640. end
  641. | _ ->
  642. ()
  643. (* Adds member field initializations as assignments to the constructor *)
  644. let add_field_inits ctx t =
  645. let apply c =
  646. let ethis = mk (TConst TThis) (TInst (c,List.map snd c.cl_types)) c.cl_pos in
  647. (* TODO: we have to find a variable name which is not used in any of the functions *)
  648. let v = alloc_var "_g" ethis.etype in
  649. let need_this = ref false in
  650. let inits,fields = List.fold_left (fun (inits,fields) cf ->
  651. match cf.cf_kind,cf.cf_expr with
  652. | Var _, Some _ ->
  653. if ctx.com.config.pf_can_init_member cf then (inits, cf :: fields) else (cf :: inits, cf :: fields)
  654. | Method MethDynamic, Some e when Common.defined ctx.com Define.As3 ->
  655. (* TODO : this would have a better place in genSWF9 I think - NC *)
  656. (* we move the initialization of dynamic functions to the constructor and also solve the
  657. 'this' problem along the way *)
  658. let rec use_this v e = match e.eexpr with
  659. | TConst TThis ->
  660. need_this := true;
  661. mk (TLocal v) v.v_type e.epos
  662. | _ -> Type.map_expr (use_this v) e
  663. in
  664. let e = Type.map_expr (use_this v) e in
  665. let cf2 = {cf with cf_expr = Some e} in
  666. (* if the method is an override, we have to remove the class field to not get invalid overrides *)
  667. let fields = if List.memq cf c.cl_overrides then begin
  668. c.cl_fields <- PMap.remove cf.cf_name c.cl_fields;
  669. fields
  670. end else
  671. cf2 :: fields
  672. in
  673. (cf2 :: inits, fields)
  674. | _ -> (inits, cf :: fields)
  675. ) ([],[]) c.cl_ordered_fields in
  676. c.cl_ordered_fields <- fields;
  677. match inits with
  678. | [] -> ()
  679. | _ ->
  680. let el = List.map (fun cf ->
  681. match cf.cf_expr with
  682. | None -> assert false
  683. | Some e ->
  684. let lhs = mk (TField(ethis,FInstance (c,cf))) cf.cf_type e.epos in
  685. cf.cf_expr <- None;
  686. let eassign = mk (TBinop(OpAssign,lhs,e)) e.etype e.epos in
  687. if Common.defined ctx.com Define.As3 then begin
  688. let echeck = mk (TBinop(OpEq,lhs,(mk (TConst TNull) lhs.etype e.epos))) ctx.com.basic.tbool e.epos in
  689. mk (TIf(echeck,eassign,None)) eassign.etype e.epos
  690. end else
  691. eassign;
  692. ) inits in
  693. let el = if !need_this then (mk (TVars([v, Some ethis])) ethis.etype ethis.epos) :: el else el in
  694. match c.cl_constructor with
  695. | None ->
  696. let ct = TFun([],ctx.com.basic.tvoid) in
  697. let ce = mk (TFunction {
  698. tf_args = [];
  699. tf_type = ctx.com.basic.tvoid;
  700. tf_expr = mk (TBlock el) ctx.com.basic.tvoid c.cl_pos;
  701. }) ct c.cl_pos in
  702. let ctor = mk_field "new" ct c.cl_pos in
  703. ctor.cf_kind <- Method MethNormal;
  704. c.cl_constructor <- Some { ctor with cf_expr = Some ce };
  705. | Some cf ->
  706. match cf.cf_expr with
  707. | Some { eexpr = TFunction f } ->
  708. let bl = match f.tf_expr with {eexpr = TBlock b } -> b | x -> [x] in
  709. let ce = mk (TFunction {f with tf_expr = mk (TBlock (el @ bl)) ctx.com.basic.tvoid c.cl_pos }) cf.cf_type cf.cf_pos in
  710. c.cl_constructor <- Some {cf with cf_expr = Some ce }
  711. | _ ->
  712. assert false
  713. in
  714. match t with
  715. | TClassDecl c ->
  716. apply c
  717. | _ ->
  718. ()
  719. (* Adds the __meta__ field if required *)
  720. let add_meta_field ctx t = match t with
  721. | TClassDecl c ->
  722. (match build_metadata ctx.com t with
  723. | None -> ()
  724. | Some e ->
  725. let f = mk_field "__meta__" t_dynamic c.cl_pos in
  726. f.cf_expr <- Some e;
  727. c.cl_ordered_statics <- f :: c.cl_ordered_statics;
  728. c.cl_statics <- PMap.add f.cf_name f c.cl_statics)
  729. | _ ->
  730. ()
  731. (* Removes interfaces tagged with @:remove metadata *)
  732. let check_remove_metadata ctx t = match t with
  733. | TClassDecl c ->
  734. c.cl_implements <- List.filter (fun (c,_) -> not (Meta.has Meta.Remove c.cl_meta)) c.cl_implements;
  735. | _ ->
  736. ()
  737. (* Checks for Void class fields *)
  738. let check_void_field ctx t = match t with
  739. | TClassDecl c ->
  740. let check f =
  741. match follow f.cf_type with TAbstract({a_path=[],"Void"},_) -> error "Fields of type Void are not allowed" f.cf_pos | _ -> ();
  742. in
  743. List.iter check c.cl_ordered_fields;
  744. List.iter check c.cl_ordered_statics;
  745. | _ ->
  746. ()
  747. (* Promotes type parameters of abstracts to their implementation fields *)
  748. let promote_abstract_parameters ctx t = match t with
  749. | TClassDecl ({cl_kind = KAbstractImpl a} as c) when a.a_types <> [] ->
  750. List.iter (fun f ->
  751. List.iter (fun (n,t) -> match t with
  752. | TInst({cl_kind = KTypeParameter _; cl_path=p,n} as cp,[]) when not (List.mem_assoc n f.cf_params) ->
  753. let path = List.rev ((snd c.cl_path) :: List.rev (fst c.cl_path)),n in
  754. f.cf_params <- (n,TInst({cp with cl_path = path},[])) :: f.cf_params
  755. | _ ->
  756. ()
  757. ) a.a_types;
  758. ) c.cl_ordered_statics;
  759. | _ ->
  760. ()
  761. (* -------------------------------------------------------------------------- *)
  762. (* LOCAL VARIABLES USAGE *)
  763. type usage =
  764. | Block of ((usage -> unit) -> unit)
  765. | Loop of ((usage -> unit) -> unit)
  766. | Function of ((usage -> unit) -> unit)
  767. | Declare of tvar
  768. | Use of tvar
  769. let rec local_usage f e =
  770. match e.eexpr with
  771. | TLocal v ->
  772. f (Use v)
  773. | TVars l ->
  774. List.iter (fun (v,e) ->
  775. (match e with None -> () | Some e -> local_usage f e);
  776. f (Declare v);
  777. ) l
  778. | TFunction tf ->
  779. let cc f =
  780. List.iter (fun (v,_) -> f (Declare v)) tf.tf_args;
  781. local_usage f tf.tf_expr;
  782. in
  783. f (Function cc)
  784. | TBlock l ->
  785. f (Block (fun f -> List.iter (local_usage f) l))
  786. | TFor (v,it,e) ->
  787. local_usage f it;
  788. f (Loop (fun f ->
  789. f (Declare v);
  790. local_usage f e;
  791. ))
  792. | TWhile _ ->
  793. f (Loop (fun f ->
  794. iter (local_usage f) e
  795. ))
  796. | TTry (e,catchs) ->
  797. local_usage f e;
  798. List.iter (fun (v,e) ->
  799. f (Block (fun f ->
  800. f (Declare v);
  801. local_usage f e;
  802. ))
  803. ) catchs;
  804. | TMatch (e,_,cases,def) ->
  805. local_usage f e;
  806. List.iter (fun (_,vars,e) ->
  807. let cc f =
  808. (match vars with
  809. | None -> ()
  810. | Some l -> List.iter (function None -> () | Some v -> f (Declare v)) l);
  811. local_usage f e;
  812. in
  813. f (Block cc)
  814. ) cases;
  815. (match def with None -> () | Some e -> local_usage f e);
  816. | _ ->
  817. iter (local_usage f) e
  818. (* -------------------------------------------------------------------------- *)
  819. (* BLOCK VARIABLES CAPTURE *)
  820. (*
  821. For some platforms, it will simply mark the variables which are used in closures
  822. using the v_capture flag so it can be processed in a more optimized
  823. For Flash/JS platforms, it will ensure that variables used in loop sub-functions
  824. have an unique scope. It transforms the following expression :
  825. for( x in array )
  826. funs.push(function() return x++);
  827. Into the following :
  828. for( _x in array ) {
  829. var x = [_x];
  830. funs.push(function(x) { function() return x[0]++; }(x));
  831. }
  832. *)
  833. let captured_vars com e =
  834. let t = com.basic in
  835. let rec mk_init av v pos =
  836. mk (TVars [av,Some (mk (TArrayDecl [mk (TLocal v) v.v_type pos]) av.v_type pos)]) t.tvoid pos
  837. and mk_var v used =
  838. alloc_var v.v_name (PMap.find v.v_id used)
  839. and wrap used e =
  840. match e.eexpr with
  841. | TVars vl ->
  842. let vl = List.map (fun (v,ve) ->
  843. if PMap.mem v.v_id used then
  844. v, Some (mk (TArrayDecl (match ve with None -> [] | Some e -> [wrap used e])) v.v_type e.epos)
  845. else
  846. v, (match ve with None -> None | Some e -> Some (wrap used e))
  847. ) vl in
  848. { e with eexpr = TVars vl }
  849. | TLocal v when PMap.mem v.v_id used ->
  850. mk (TArray ({ e with etype = v.v_type },mk (TConst (TInt 0l)) t.tint e.epos)) e.etype e.epos
  851. | TFor (v,it,expr) when PMap.mem v.v_id used ->
  852. let vtmp = mk_var v used in
  853. let it = wrap used it in
  854. let expr = wrap used expr in
  855. mk (TFor (vtmp,it,concat (mk_init v vtmp e.epos) expr)) e.etype e.epos
  856. | TTry (expr,catchs) ->
  857. let catchs = List.map (fun (v,e) ->
  858. let e = wrap used e in
  859. try
  860. let vtmp = mk_var v used in
  861. vtmp, concat (mk_init v vtmp e.epos) e
  862. with Not_found ->
  863. v, e
  864. ) catchs in
  865. mk (TTry (wrap used expr,catchs)) e.etype e.epos
  866. | TMatch (expr,enum,cases,def) ->
  867. let cases = List.map (fun (il,vars,e) ->
  868. let pos = e.epos in
  869. let e = ref (wrap used e) in
  870. let vars = match vars with
  871. | None -> None
  872. | Some l ->
  873. Some (List.map (fun v ->
  874. match v with
  875. | Some v when PMap.mem v.v_id used ->
  876. let vtmp = mk_var v used in
  877. e := concat (mk_init v vtmp pos) !e;
  878. Some vtmp
  879. | _ -> v
  880. ) l)
  881. in
  882. il, vars, !e
  883. ) cases in
  884. let def = match def with None -> None | Some e -> Some (wrap used e) in
  885. mk (TMatch (wrap used expr,enum,cases,def)) e.etype e.epos
  886. | TFunction f ->
  887. (*
  888. list variables that are marked as used, but also used in that
  889. function and which are not declared inside it !
  890. *)
  891. let fused = ref PMap.empty in
  892. let tmp_used = ref used in
  893. let rec browse = function
  894. | Block f | Loop f | Function f -> f browse
  895. | Use v ->
  896. if PMap.mem v.v_id !tmp_used then fused := PMap.add v.v_id v !fused;
  897. | Declare v ->
  898. tmp_used := PMap.remove v.v_id !tmp_used
  899. in
  900. local_usage browse e;
  901. let vars = PMap.fold (fun v acc -> v :: acc) !fused [] in
  902. (* in case the variable has been marked as used in a parallel scope... *)
  903. let fexpr = ref (wrap used f.tf_expr) in
  904. let fargs = List.map (fun (v,o) ->
  905. if PMap.mem v.v_id used then
  906. let vtmp = mk_var v used in
  907. fexpr := concat (mk_init v vtmp e.epos) !fexpr;
  908. vtmp, o
  909. else
  910. v, o
  911. ) f.tf_args in
  912. let e = { e with eexpr = TFunction { f with tf_args = fargs; tf_expr = !fexpr } } in
  913. (*
  914. Create a new function scope to make sure that the captured loop variable
  915. will not be overwritten in next loop iteration
  916. *)
  917. if com.config.pf_capture_policy = CPLoopVars then
  918. mk (TCall (
  919. mk_parent (mk (TFunction {
  920. tf_args = List.map (fun v -> v, None) vars;
  921. tf_type = e.etype;
  922. tf_expr = mk_block (mk (TReturn (Some e)) e.etype e.epos);
  923. }) (TFun (List.map (fun v -> v.v_name,false,v.v_type) vars,e.etype)) e.epos),
  924. List.map (fun v -> mk (TLocal v) v.v_type e.epos) vars)
  925. ) e.etype e.epos
  926. else
  927. e
  928. | _ ->
  929. map_expr (wrap used) e
  930. and do_wrap used e =
  931. if PMap.is_empty used then
  932. e
  933. else
  934. let used = PMap.map (fun v ->
  935. let vt = v.v_type in
  936. v.v_type <- t.tarray vt;
  937. v.v_capture <- true;
  938. vt
  939. ) used in
  940. wrap used e
  941. and out_loop e =
  942. match e.eexpr with
  943. | TFor _ | TWhile _ ->
  944. (*
  945. collect variables that are declared in loop but used in subfunctions
  946. *)
  947. let vars = ref PMap.empty in
  948. let used = ref PMap.empty in
  949. let depth = ref 0 in
  950. let rec collect_vars in_loop = function
  951. | Block f ->
  952. let old = !vars in
  953. f (collect_vars in_loop);
  954. vars := old;
  955. | Loop f ->
  956. let old = !vars in
  957. f (collect_vars true);
  958. vars := old;
  959. | Function f ->
  960. incr depth;
  961. f (collect_vars false);
  962. decr depth;
  963. | Declare v ->
  964. if in_loop then vars := PMap.add v.v_id !depth !vars;
  965. | Use v ->
  966. try
  967. let d = PMap.find v.v_id !vars in
  968. if d <> !depth then used := PMap.add v.v_id v !used;
  969. with Not_found ->
  970. ()
  971. in
  972. local_usage (collect_vars false) e;
  973. do_wrap !used e
  974. | _ ->
  975. map_expr out_loop e
  976. and all_vars e =
  977. let vars = ref PMap.empty in
  978. let used = ref PMap.empty in
  979. let depth = ref 0 in
  980. let rec collect_vars = function
  981. | Block f ->
  982. let old = !vars in
  983. f collect_vars;
  984. vars := old;
  985. | Loop f ->
  986. let old = !vars in
  987. f collect_vars;
  988. vars := old;
  989. | Function f ->
  990. incr depth;
  991. f collect_vars;
  992. decr depth;
  993. | Declare v ->
  994. vars := PMap.add v.v_id !depth !vars;
  995. | Use v ->
  996. try
  997. let d = PMap.find v.v_id !vars in
  998. if d <> !depth then used := PMap.add v.v_id v !used;
  999. with Not_found -> ()
  1000. in
  1001. local_usage collect_vars e;
  1002. !used
  1003. in
  1004. (* mark all capture variables - also used in rename_local_vars at later stage *)
  1005. let captured = all_vars e in
  1006. PMap.iter (fun _ v -> v.v_capture <- true) captured;
  1007. match com.config.pf_capture_policy with
  1008. | CPNone -> e
  1009. | CPWrapRef -> do_wrap captured e
  1010. | CPLoopVars -> out_loop e
  1011. (* -------------------------------------------------------------------------- *)
  1012. (* RENAME LOCAL VARS *)
  1013. let rename_local_vars com e =
  1014. let cfg = com.config in
  1015. let all_scope = (not cfg.pf_captured_scope) || (not cfg.pf_locals_scope) in
  1016. let vars = ref PMap.empty in
  1017. let all_vars = ref PMap.empty in
  1018. let vtemp = alloc_var "~" t_dynamic in
  1019. let rebuild_vars = ref false in
  1020. let rebuild m =
  1021. PMap.fold (fun v acc -> PMap.add v.v_name v acc) m PMap.empty
  1022. in
  1023. let save() =
  1024. let old = !vars in
  1025. if cfg.pf_unique_locals then (fun() -> ()) else (fun() -> vars := if !rebuild_vars then rebuild old else old)
  1026. in
  1027. let rename vars v =
  1028. let count = ref 1 in
  1029. while PMap.mem (v.v_name ^ string_of_int !count) vars do
  1030. incr count;
  1031. done;
  1032. v.v_name <- v.v_name ^ string_of_int !count;
  1033. in
  1034. let declare v p =
  1035. (match follow v.v_type with
  1036. | TAbstract ({a_path = [],"Void"},_) -> error "Arguments and variables of type Void are not allowed" p
  1037. | _ -> ());
  1038. (* chop escape char for all local variables generated *)
  1039. if String.unsafe_get v.v_name 0 = String.unsafe_get gen_local_prefix 0 then v.v_name <- "_g" ^ String.sub v.v_name 1 (String.length v.v_name - 1);
  1040. let look_vars = (if not cfg.pf_captured_scope && v.v_capture then !all_vars else !vars) in
  1041. (try
  1042. let v2 = PMap.find v.v_name look_vars in
  1043. (*
  1044. block_vars will create some wrapper-functions that are declaring
  1045. the same variable twice. In that case do not perform a rename since
  1046. we are sure it's actually the same variable
  1047. *)
  1048. if v == v2 then raise Not_found;
  1049. rename look_vars v;
  1050. with Not_found ->
  1051. ());
  1052. vars := PMap.add v.v_name v !vars;
  1053. if all_scope then all_vars := PMap.add v.v_name v !all_vars;
  1054. in
  1055. (*
  1056. This is quite a rare case, when a local variable would otherwise prevent
  1057. accessing a type because it masks the type value or the package name.
  1058. *)
  1059. let check t =
  1060. match (t_infos t).mt_path with
  1061. | [], name | name :: _, _ ->
  1062. let vars = if cfg.pf_locals_scope then vars else all_vars in
  1063. (try
  1064. let v = PMap.find name !vars in
  1065. if v == vtemp then raise Not_found; (* ignore *)
  1066. rename (!vars) v;
  1067. rebuild_vars := true;
  1068. vars := PMap.add v.v_name v !vars
  1069. with Not_found ->
  1070. ());
  1071. vars := PMap.add name vtemp !vars
  1072. in
  1073. let check_type t =
  1074. match follow t with
  1075. | TInst (c,_) -> check (TClassDecl c)
  1076. | TEnum (e,_) -> check (TEnumDecl e)
  1077. | TType (t,_) -> check (TTypeDecl t)
  1078. | TAbstract (a,_) -> check (TAbstractDecl a)
  1079. | TMono _ | TLazy _ | TAnon _ | TDynamic _ | TFun _ -> ()
  1080. in
  1081. let rec loop e =
  1082. match e.eexpr with
  1083. | TVars l ->
  1084. List.iter (fun (v,eo) ->
  1085. if not cfg.pf_locals_scope then declare v e.epos;
  1086. (match eo with None -> () | Some e -> loop e);
  1087. if cfg.pf_locals_scope then declare v e.epos;
  1088. ) l
  1089. | TFunction tf ->
  1090. let old = save() in
  1091. List.iter (fun (v,_) -> declare v e.epos) tf.tf_args;
  1092. loop tf.tf_expr;
  1093. old()
  1094. | TBlock el ->
  1095. let old = save() in
  1096. List.iter loop el;
  1097. old()
  1098. | TFor (v,it,e1) ->
  1099. loop it;
  1100. let old = save() in
  1101. declare v e.epos;
  1102. loop e1;
  1103. old()
  1104. | TTry (e,catchs) ->
  1105. loop e;
  1106. List.iter (fun (v,e) ->
  1107. let old = save() in
  1108. declare v e.epos;
  1109. check_type v.v_type;
  1110. loop e;
  1111. old()
  1112. ) catchs;
  1113. | TMatch (e,_,cases,def) ->
  1114. loop e;
  1115. List.iter (fun (_,vars,e) ->
  1116. let old = save() in
  1117. (match vars with
  1118. | None -> ()
  1119. | Some l -> List.iter (function None -> () | Some v -> declare v e.epos) l);
  1120. loop e;
  1121. old();
  1122. ) cases;
  1123. (match def with None -> () | Some e -> loop e);
  1124. | TTypeExpr t ->
  1125. check t
  1126. | TNew (c,_,_) ->
  1127. Type.iter loop e;
  1128. check (TClassDecl c);
  1129. | TCast (e,Some t) ->
  1130. loop e;
  1131. check t;
  1132. | _ ->
  1133. Type.iter loop e
  1134. in
  1135. declare (alloc_var "this" t_dynamic) Ast.null_pos; (* force renaming of 'this' vars in abstract *)
  1136. loop e;
  1137. e
  1138. (* -------------------------------------------------------------------------- *)
  1139. (* CHECK LOCAL VARS INIT *)
  1140. let check_local_vars_init e =
  1141. let intersect vl1 vl2 =
  1142. PMap.mapi (fun v t -> t && PMap.find v vl2) vl1
  1143. in
  1144. let join vars cvars =
  1145. List.iter (fun v -> vars := intersect !vars v) cvars
  1146. in
  1147. let restore vars old_vars declared =
  1148. (* restore variables declared in this block to their previous state *)
  1149. vars := List.fold_left (fun acc v ->
  1150. try PMap.add v (PMap.find v old_vars) acc with Not_found -> PMap.remove v acc
  1151. ) !vars declared;
  1152. in
  1153. let declared = ref [] in
  1154. let rec loop vars e =
  1155. match e.eexpr with
  1156. | TLocal v ->
  1157. let init = (try PMap.find v.v_id !vars with Not_found -> true) in
  1158. if not init then begin
  1159. if v.v_name = "this" then error "Missing this = value" e.epos
  1160. else error ("Local variable " ^ v.v_name ^ " used without being initialized") e.epos
  1161. end
  1162. | TVars vl ->
  1163. List.iter (fun (v,eo) ->
  1164. match eo with
  1165. | None ->
  1166. declared := v.v_id :: !declared;
  1167. vars := PMap.add v.v_id false !vars
  1168. | Some e ->
  1169. loop vars e
  1170. ) vl
  1171. | TBlock el ->
  1172. let old = !declared in
  1173. let old_vars = !vars in
  1174. declared := [];
  1175. List.iter (loop vars) el;
  1176. restore vars old_vars (List.rev !declared);
  1177. declared := old;
  1178. | TBinop (OpAssign,{ eexpr = TLocal v },e) when PMap.mem v.v_id !vars ->
  1179. loop vars e;
  1180. vars := PMap.add v.v_id true !vars
  1181. | TIf (e1,e2,eo) ->
  1182. loop vars e1;
  1183. let vbase = !vars in
  1184. loop vars e2;
  1185. (match eo with
  1186. | None -> vars := vbase
  1187. | Some e ->
  1188. let v1 = !vars in
  1189. vars := vbase;
  1190. loop vars e;
  1191. vars := intersect !vars v1)
  1192. | TWhile (cond,e,flag) ->
  1193. (match flag with
  1194. | NormalWhile ->
  1195. loop vars cond;
  1196. let old = !vars in
  1197. loop vars e;
  1198. vars := old;
  1199. | DoWhile ->
  1200. loop vars e;
  1201. loop vars cond)
  1202. | TTry (e,catches) ->
  1203. let cvars = List.map (fun (v,e) ->
  1204. let old = !vars in
  1205. loop vars e;
  1206. let v = !vars in
  1207. vars := old;
  1208. v
  1209. ) catches in
  1210. loop vars e;
  1211. join vars cvars;
  1212. | TSwitch (e,cases,def) ->
  1213. loop vars e;
  1214. let cvars = List.map (fun (ec,e) ->
  1215. let old = !vars in
  1216. List.iter (loop vars) ec;
  1217. vars := old;
  1218. loop vars e;
  1219. let v = !vars in
  1220. vars := old;
  1221. v
  1222. ) cases in
  1223. (match def with
  1224. | None -> ()
  1225. | Some e ->
  1226. loop vars e;
  1227. join vars cvars)
  1228. | TMatch (e,_,cases,def) ->
  1229. loop vars e;
  1230. let old = !vars in
  1231. let cvars = List.map (fun (_,vl,e) ->
  1232. vars := old;
  1233. loop vars e;
  1234. restore vars old [];
  1235. !vars
  1236. ) cases in
  1237. (match def with None -> () | Some e -> vars := old; loop vars e);
  1238. join vars cvars
  1239. (* mark all reachable vars as initialized, since we don't exit the block *)
  1240. | TBreak | TContinue | TReturn None ->
  1241. vars := PMap.map (fun _ -> true) !vars
  1242. | TThrow e | TReturn (Some e) ->
  1243. loop vars e;
  1244. vars := PMap.map (fun _ -> true) !vars
  1245. | _ ->
  1246. Type.iter (loop vars) e
  1247. in
  1248. loop (ref PMap.empty) e;
  1249. e
  1250. (* -------------------------------------------------------------------------- *)
  1251. (* ABSTRACT CASTS *)
  1252. module Abstract = struct
  1253. let find_to ab pl b = List.find (Type.unify_to_field ab pl b) ab.a_to
  1254. let find_from ab pl a b = List.find (Type.unify_from_field ab pl a b) ab.a_from
  1255. let cast_stack = ref []
  1256. let get_underlying_type a pl =
  1257. try
  1258. if not (Meta.has Meta.MultiType a.a_meta) then raise Not_found;
  1259. let m = mk_mono() in
  1260. let _ = find_to a pl m in
  1261. follow m
  1262. with Not_found ->
  1263. apply_params a.a_types pl a.a_this
  1264. let rec make_static_call ctx c cf a pl args t p =
  1265. let ta = TAnon { a_fields = c.cl_statics; a_status = ref (Statics c) } in
  1266. let ethis = mk (TTypeExpr (TClassDecl c)) ta p in
  1267. let monos = List.map (fun _ -> mk_mono()) cf.cf_params in
  1268. let map t = apply_params a.a_types pl (apply_params cf.cf_params monos t) in
  1269. let tcf = match follow (map cf.cf_type),args with
  1270. | TFun((_,_,ta) :: args,r) as tf,e :: el when Meta.has Meta.From cf.cf_meta ->
  1271. unify ctx e.etype ta p;
  1272. tf
  1273. | t,_ -> t
  1274. in
  1275. let def () =
  1276. let e = mk (TField (ethis,(FStatic (c,cf)))) tcf p in
  1277. loop ctx (mk (TCall(e,args)) (map t) p)
  1278. in
  1279. match cf.cf_expr with
  1280. | Some { eexpr = TFunction fd } when cf.cf_kind = Method MethInline ->
  1281. let config = if Meta.has Meta.Impl cf.cf_meta then (Some (a.a_types <> [] || cf.cf_params <> [], map)) else None in
  1282. (match Optimizer.type_inline ctx cf fd ethis args t config p true with
  1283. | Some e -> (match e.eexpr with TCast(e,None) -> e | _ -> e)
  1284. | None -> def())
  1285. | _ ->
  1286. def()
  1287. and check_cast ctx tleft eright p =
  1288. let tright = follow eright.etype in
  1289. let tleft = follow tleft in
  1290. if tleft == tright then eright else
  1291. let recurse cf f =
  1292. if cf == ctx.curfield || List.mem cf !cast_stack then error "Recursive implicit cast" p;
  1293. cast_stack := cf :: !cast_stack;
  1294. let r = f() in
  1295. cast_stack := List.tl !cast_stack;
  1296. r
  1297. in
  1298. try (match tright,tleft with
  1299. | (TAbstract({a_impl = Some c1} as a1,pl1) as t1),(TAbstract({a_impl = Some c2} as a2,pl2) as t2) ->
  1300. if a1 == a2 then
  1301. eright
  1302. else begin
  1303. let c,cfo,a,pl = try
  1304. if Meta.has Meta.MultiType a1.a_meta then raise Not_found;
  1305. c1,snd (find_to a1 pl1 t2),a1,pl1
  1306. with Not_found ->
  1307. if Meta.has Meta.MultiType a2.a_meta then raise Not_found;
  1308. c2,snd (find_from a2 pl2 t1 t2),a2,pl2
  1309. in
  1310. match cfo with
  1311. | None -> eright
  1312. | Some cf ->
  1313. recurse cf (fun () -> make_static_call ctx c cf a pl [eright] tleft p)
  1314. end
  1315. | TDynamic _,_ | _,TDynamic _ ->
  1316. eright
  1317. | TAbstract({a_impl = Some c} as a,pl),t2 when not (Meta.has Meta.MultiType a.a_meta) ->
  1318. begin match find_to a pl t2 with
  1319. | tcf,None ->
  1320. let tcf = apply_params a.a_types pl tcf in
  1321. if type_iseq tcf tleft then eright else check_cast ctx tcf eright p
  1322. | _,Some cf ->
  1323. recurse cf (fun () -> make_static_call ctx c cf a pl [eright] tleft p)
  1324. end
  1325. | t1,(TAbstract({a_impl = Some c} as a,pl) as t2) when not (Meta.has Meta.MultiType a.a_meta) ->
  1326. begin match find_from a pl t1 t2 with
  1327. | tcf,None ->
  1328. let tcf = apply_params a.a_types pl tcf in
  1329. if type_iseq tcf tleft then eright else check_cast ctx tcf eright p
  1330. | _,Some cf ->
  1331. recurse cf (fun () -> make_static_call ctx c cf a pl [eright] tleft p)
  1332. end
  1333. | _ ->
  1334. eright)
  1335. with Not_found ->
  1336. eright
  1337. and call_args ctx el tl = match el,tl with
  1338. | [],_ -> []
  1339. | e :: el, [] -> (loop ctx e) :: call_args ctx el []
  1340. | e :: el, (_,_,t) :: tl ->
  1341. (check_cast ctx t (loop ctx e) e.epos) :: call_args ctx el tl
  1342. and loop ctx e = match e.eexpr with
  1343. | TBinop(OpAssign,e1,e2) ->
  1344. let e2 = check_cast ctx e1.etype (loop ctx e2) e.epos in
  1345. { e with eexpr = TBinop(OpAssign,loop ctx e1,e2) }
  1346. | TVars vl ->
  1347. let vl = List.map (fun (v,eo) -> match eo with
  1348. | None -> (v,eo)
  1349. | Some e ->
  1350. let is_generic_abstract = match e.etype with TAbstract ({a_impl = Some _} as a,_) -> Meta.has Meta.MultiType a.a_meta | _ -> false in
  1351. let e = check_cast ctx v.v_type (loop ctx e) e.epos in
  1352. (* we can rewrite this for better field inference *)
  1353. if is_generic_abstract then v.v_type <- e.etype;
  1354. v, Some e
  1355. ) vl in
  1356. { e with eexpr = TVars vl }
  1357. | TNew({cl_kind = KAbstractImpl a} as c,pl,el) ->
  1358. (* a TNew of an abstract implementation is only generated if it is a generic abstract *)
  1359. let at = apply_params a.a_types pl a.a_this in
  1360. let m = mk_mono() in
  1361. let _,cfo =
  1362. try find_to a pl m
  1363. with Not_found ->
  1364. let st = s_type (print_context()) at in
  1365. if has_mono at then
  1366. error ("Type parameters of multi type abstracts must be known (for " ^ st ^ ")") e.epos
  1367. else
  1368. error ("Abstract " ^ (s_type_path a.a_path) ^ " has no @:to function that accepts " ^ st) e.epos;
  1369. in
  1370. begin match cfo with
  1371. | None -> assert false
  1372. | Some cf ->
  1373. let m = follow m in
  1374. let e = make_static_call ctx c cf a pl ((mk (TConst TNull) at e.epos) :: el) m e.epos in
  1375. {e with etype = m}
  1376. end
  1377. | TNew(c,pl,el) ->
  1378. begin try
  1379. let t,_ = (!get_constructor_ref) ctx c pl e.epos in
  1380. begin match follow t with
  1381. | TFun(args,_) ->
  1382. { e with eexpr = TNew(c,pl,call_args ctx el args)}
  1383. | _ ->
  1384. Type.map_expr (loop ctx) e
  1385. end
  1386. with Error _ ->
  1387. (* TODO: when does this happen? *)
  1388. Type.map_expr (loop ctx) e
  1389. end
  1390. | TCall(e1, el) ->
  1391. let e1 = loop ctx e1 in
  1392. begin try
  1393. begin match e1.eexpr with
  1394. | TField(_,FStatic(_,cf)) when Meta.has Meta.To cf.cf_meta ->
  1395. (* do not recurse over @:to functions to avoid infinite recursion *)
  1396. { e with eexpr = TCall(e1,el)}
  1397. | TField(e2,fa) ->
  1398. begin match follow e2.etype with
  1399. | TAbstract(a,pl) when Meta.has Meta.MultiType a.a_meta ->
  1400. let m = get_underlying_type a pl in
  1401. let fname = field_name fa in
  1402. let el = List.map (loop ctx) el in
  1403. begin try
  1404. let ef = mk (TField({e2 with etype = m},quick_field m fname)) e1.etype e2.epos in
  1405. make_call ctx ef el e.etype e.epos
  1406. with Not_found ->
  1407. (* quick_field raises Not_found if m is an abstract, we have to replicate the 'using' call here *)
  1408. match follow m with
  1409. | TAbstract({a_impl = Some c} as a,pl) ->
  1410. let cf = PMap.find fname c.cl_statics in
  1411. make_static_call ctx c cf a pl (e2 :: el) e.etype e.epos
  1412. | _ -> raise Not_found
  1413. end
  1414. | _ -> raise Not_found
  1415. end
  1416. | _ ->
  1417. raise Not_found
  1418. end
  1419. with Not_found ->
  1420. begin match follow e1.etype with
  1421. | TFun(args,_) ->
  1422. { e with eexpr = TCall(loop ctx e1,call_args ctx el args)}
  1423. | _ ->
  1424. Type.map_expr (loop ctx) e
  1425. end
  1426. end
  1427. | TArrayDecl el ->
  1428. begin match e.etype with
  1429. | TInst(_,[t]) ->
  1430. let el = List.map (fun e -> check_cast ctx t (loop ctx e) e.epos) el in
  1431. { e with eexpr = TArrayDecl el}
  1432. | _ ->
  1433. Type.map_expr (loop ctx) e
  1434. end
  1435. | TObjectDecl fl ->
  1436. begin match follow e.etype with
  1437. | TAnon a ->
  1438. let fl = List.map (fun (n,e) ->
  1439. try
  1440. let cf = PMap.find n a.a_fields in
  1441. let e = match e.eexpr with TCast(e1,None) -> e1 | _ -> e in
  1442. (n,check_cast ctx cf.cf_type (loop ctx e) e.epos)
  1443. with Not_found ->
  1444. (n,loop ctx e)
  1445. ) fl in
  1446. { e with eexpr = TObjectDecl fl }
  1447. | _ ->
  1448. Type.map_expr (loop ctx) e
  1449. end
  1450. | _ ->
  1451. Type.map_expr (loop ctx) e
  1452. let handle_abstract_casts ctx e =
  1453. loop ctx e
  1454. end
  1455. (* -------------------------------------------------------------------------- *)
  1456. (* USAGE *)
  1457. let detect_usage com =
  1458. let usage = ref [] in
  1459. List.iter (fun t -> match t with
  1460. | TClassDecl c ->
  1461. let rec expr e = match e.eexpr with
  1462. | TField(_,fa) ->
  1463. (match extract_field fa with
  1464. | Some cf when Meta.has Meta.Usage cf.cf_meta ->
  1465. let p = {e.epos with pmin = e.epos.pmax - (String.length cf.cf_name)} in
  1466. usage := p :: !usage;
  1467. | _ -> ());
  1468. Type.iter expr e
  1469. | _ -> Type.iter expr e
  1470. in
  1471. let field cf = match cf.cf_expr with None -> () | Some e -> expr e in
  1472. (match c.cl_constructor with None -> () | Some cf -> field cf);
  1473. (match c.cl_init with None -> () | Some e -> expr e);
  1474. List.iter field c.cl_ordered_statics;
  1475. List.iter field c.cl_ordered_fields;
  1476. | _ -> ()
  1477. ) com.types;
  1478. let usage = List.sort (fun p1 p2 ->
  1479. let c = compare p1.pfile p2.pfile in
  1480. if c <> 0 then c else compare p1.pmin p2.pmin
  1481. ) !usage in
  1482. raise (Typecore.DisplayPosition usage)
  1483. (* -------------------------------------------------------------------------- *)
  1484. (* POST PROCESS *)
  1485. let pp_counter = ref 1
  1486. let post_process filters t =
  1487. (* ensure that we don't process twice the same (cached) module *)
  1488. let m = (t_infos t).mt_module.m_extra in
  1489. if m.m_processed = 0 then m.m_processed <- !pp_counter;
  1490. if m.m_processed = !pp_counter then
  1491. match t with
  1492. | TClassDecl c ->
  1493. let process_field f =
  1494. match f.cf_expr with
  1495. | None -> ()
  1496. | Some e ->
  1497. Abstract.cast_stack := f :: !Abstract.cast_stack;
  1498. f.cf_expr <- Some (List.fold_left (fun e f -> f e) e filters);
  1499. Abstract.cast_stack := List.tl !Abstract.cast_stack;
  1500. in
  1501. List.iter process_field c.cl_ordered_fields;
  1502. List.iter process_field c.cl_ordered_statics;
  1503. (match c.cl_constructor with
  1504. | None -> ()
  1505. | Some f -> process_field f);
  1506. (match c.cl_init with
  1507. | None -> ()
  1508. | Some e ->
  1509. c.cl_init <- Some (List.fold_left (fun e f -> f e) e filters));
  1510. | TEnumDecl _ -> ()
  1511. | TTypeDecl _ -> ()
  1512. | TAbstractDecl _ -> ()
  1513. let post_process_end() =
  1514. incr pp_counter
  1515. (* -------------------------------------------------------------------------- *)
  1516. (* STACK MANAGEMENT EMULATION *)
  1517. type stack_context = {
  1518. stack_var : string;
  1519. stack_exc_var : string;
  1520. stack_pos_var : string;
  1521. stack_pos : pos;
  1522. stack_expr : texpr;
  1523. stack_pop : texpr;
  1524. stack_save_pos : texpr;
  1525. stack_restore : texpr list;
  1526. stack_push : tclass -> string -> texpr;
  1527. stack_return : texpr -> texpr;
  1528. }
  1529. let stack_context_init com stack_var exc_var pos_var tmp_var use_add p =
  1530. let t = com.basic in
  1531. let st = t.tarray t.tstring in
  1532. let stack_var = alloc_var stack_var st in
  1533. let exc_var = alloc_var exc_var st in
  1534. let pos_var = alloc_var pos_var t.tint in
  1535. let stack_e = mk (TLocal stack_var) st p in
  1536. let exc_e = mk (TLocal exc_var) st p in
  1537. let stack_pop = fcall stack_e "pop" [] t.tstring p in
  1538. let stack_push c m =
  1539. fcall stack_e "push" [
  1540. if use_add then
  1541. binop OpAdd (string com (s_type_path c.cl_path ^ "::") p) (string com m p) t.tstring p
  1542. else
  1543. string com (s_type_path c.cl_path ^ "::" ^ m) p
  1544. ] t.tvoid p
  1545. in
  1546. let stack_return e =
  1547. let tmp = alloc_var tmp_var e.etype in
  1548. mk (TBlock [
  1549. mk (TVars [tmp, Some e]) t.tvoid e.epos;
  1550. stack_pop;
  1551. mk (TReturn (Some (mk (TLocal tmp) e.etype e.epos))) e.etype e.epos
  1552. ]) e.etype e.epos
  1553. in
  1554. {
  1555. stack_var = stack_var.v_name;
  1556. stack_exc_var = exc_var.v_name;
  1557. stack_pos_var = pos_var.v_name;
  1558. stack_pos = p;
  1559. stack_expr = stack_e;
  1560. stack_pop = stack_pop;
  1561. stack_save_pos = mk (TVars [pos_var, Some (field stack_e "length" t.tint p)]) t.tvoid p;
  1562. stack_push = stack_push;
  1563. stack_return = stack_return;
  1564. stack_restore = [
  1565. binop OpAssign exc_e (mk (TArrayDecl []) st p) st p;
  1566. mk (TWhile (
  1567. mk_parent (binop OpGte (field stack_e "length" t.tint p) (mk (TLocal pos_var) t.tint p) t.tbool p),
  1568. fcall exc_e "unshift" [fcall stack_e "pop" [] t.tstring p] t.tvoid p,
  1569. NormalWhile
  1570. )) t.tvoid p;
  1571. fcall stack_e "push" [index com exc_e 0 t.tstring p] t.tvoid p
  1572. ];
  1573. }
  1574. let stack_init com use_add =
  1575. stack_context_init com "$s" "$e" "$spos" "$tmp" use_add null_pos
  1576. let rec stack_block_loop ctx e =
  1577. match e.eexpr with
  1578. | TFunction _ ->
  1579. e
  1580. | TReturn None | TReturn (Some { eexpr = TConst _ }) | TReturn (Some { eexpr = TLocal _ }) ->
  1581. mk (TBlock [
  1582. ctx.stack_pop;
  1583. e;
  1584. ]) e.etype e.epos
  1585. | TReturn (Some e) ->
  1586. ctx.stack_return (stack_block_loop ctx e)
  1587. | TTry (v,cases) ->
  1588. let v = stack_block_loop ctx v in
  1589. let cases = List.map (fun (v,e) ->
  1590. let e = stack_block_loop ctx e in
  1591. let e = (match (mk_block e).eexpr with
  1592. | TBlock l -> mk (TBlock (ctx.stack_restore @ l)) e.etype e.epos
  1593. | _ -> assert false
  1594. ) in
  1595. v , e
  1596. ) cases in
  1597. mk (TTry (v,cases)) e.etype e.epos
  1598. | _ ->
  1599. map_expr (stack_block_loop ctx) e
  1600. let stack_block ctx c m e =
  1601. match (mk_block e).eexpr with
  1602. | TBlock l ->
  1603. mk (TBlock (
  1604. ctx.stack_push c m ::
  1605. ctx.stack_save_pos ::
  1606. List.map (stack_block_loop ctx) l
  1607. @ [ctx.stack_pop]
  1608. )) e.etype e.epos
  1609. | _ ->
  1610. assert false
  1611. (* -------------------------------------------------------------------------- *)
  1612. (* FIX OVERRIDES *)
  1613. (*
  1614. on some platforms which doesn't support type parameters, we must have the
  1615. exact same type for overriden/implemented function as the original one
  1616. *)
  1617. let rec find_field c f =
  1618. try
  1619. (match c.cl_super with
  1620. | None ->
  1621. raise Not_found
  1622. | Some ( {cl_path = (["cpp"],"FastIterator")}, _ ) ->
  1623. raise Not_found (* This is a strongly typed 'extern' and the usual rules don't apply *)
  1624. | Some (c,_) ->
  1625. find_field c f)
  1626. with Not_found -> try
  1627. let rec loop = function
  1628. | [] ->
  1629. raise Not_found
  1630. | (c,_) :: l ->
  1631. try
  1632. find_field c f
  1633. with
  1634. Not_found -> loop l
  1635. in
  1636. loop c.cl_implements
  1637. with Not_found ->
  1638. let f = PMap.find f.cf_name c.cl_fields in
  1639. (match f.cf_kind with Var { v_read = AccRequire _ } -> raise Not_found | _ -> ());
  1640. f
  1641. let fix_override com c f fd =
  1642. let f2 = (try Some (find_field c f) with Not_found -> None) in
  1643. match f2,fd with
  1644. | Some (f2), Some(fd) ->
  1645. let targs, tret = (match follow f2.cf_type with TFun (args,ret) -> args, ret | _ -> assert false) in
  1646. let changed_args = ref [] in
  1647. let prefix = "_tmp_" in
  1648. let nargs = List.map2 (fun ((v,c) as cur) (_,_,t2) ->
  1649. try
  1650. type_eq EqStrict v.v_type t2;
  1651. cur
  1652. with Unify_error _ ->
  1653. let v2 = alloc_var (prefix ^ v.v_name) t2 in
  1654. changed_args := (v,v2) :: !changed_args;
  1655. v2,c
  1656. ) fd.tf_args targs in
  1657. let fd2 = {
  1658. tf_args = nargs;
  1659. tf_type = tret;
  1660. tf_expr = (match List.rev !changed_args with
  1661. | [] -> fd.tf_expr
  1662. | args ->
  1663. let e = fd.tf_expr in
  1664. let el = (match e.eexpr with TBlock el -> el | _ -> [e]) in
  1665. let p = (match el with [] -> e.epos | e :: _ -> e.epos) in
  1666. let v = mk (TVars (List.map (fun (v,v2) ->
  1667. (v,Some (mk (TCast (mk (TLocal v2) v2.v_type p,None)) v.v_type p))
  1668. ) args)) com.basic.tvoid p in
  1669. { e with eexpr = TBlock (v :: el) }
  1670. );
  1671. } in
  1672. (* as3 does not allow wider visibility, so the base method has to be made public *)
  1673. if Common.defined com Define.As3 && f.cf_public then f2.cf_public <- true;
  1674. let targs = List.map (fun(v,c) -> (v.v_name, Option.is_some c, v.v_type)) nargs in
  1675. let fde = (match f.cf_expr with None -> assert false | Some e -> e) in
  1676. f.cf_expr <- Some { fde with eexpr = TFunction fd2 };
  1677. f.cf_type <- TFun(targs,tret);
  1678. | Some(f2), None when c.cl_interface ->
  1679. let targs, tret = (match follow f2.cf_type with TFun (args,ret) -> args, ret | _ -> assert false) in
  1680. f.cf_type <- TFun(targs,tret)
  1681. | _ ->
  1682. ()
  1683. let fix_overrides com t =
  1684. match t with
  1685. | TClassDecl c ->
  1686. (* overrides can be removed from interfaces *)
  1687. if c.cl_interface then
  1688. c.cl_ordered_fields <- List.filter (fun f ->
  1689. try
  1690. if find_field c f == f then raise Not_found;
  1691. c.cl_fields <- PMap.remove f.cf_name c.cl_fields;
  1692. false;
  1693. with Not_found ->
  1694. true
  1695. ) c.cl_ordered_fields;
  1696. List.iter (fun f ->
  1697. match f.cf_expr, f.cf_kind with
  1698. | Some { eexpr = TFunction fd }, Method (MethNormal | MethInline) ->
  1699. fix_override com c f (Some fd)
  1700. | None, Method (MethNormal | MethInline) when c.cl_interface ->
  1701. fix_override com c f None
  1702. | _ ->
  1703. ()
  1704. ) c.cl_ordered_fields
  1705. | _ ->
  1706. ()
  1707. (*
  1708. PHP does not allow abstract classes extending other abstract classes to override any fields, so these duplicates
  1709. must be removed from the child interface
  1710. *)
  1711. let fix_abstract_inheritance com t =
  1712. match t with
  1713. | TClassDecl c when c.cl_interface ->
  1714. c.cl_ordered_fields <- List.filter (fun f ->
  1715. let b = try (find_field c f) == f
  1716. with Not_found -> false in
  1717. if not b then c.cl_fields <- PMap.remove f.cf_name c.cl_fields;
  1718. b;
  1719. ) c.cl_ordered_fields
  1720. | _ -> ()
  1721. (* -------------------------------------------------------------------------- *)
  1722. (* MISC FEATURES *)
  1723. let rec is_volatile t =
  1724. match t with
  1725. | TMono r ->
  1726. (match !r with
  1727. | Some t -> is_volatile t
  1728. | _ -> false)
  1729. | TLazy f ->
  1730. is_volatile (!f())
  1731. | TType (t,tl) ->
  1732. (match t.t_path with
  1733. | ["mt";"flash"],"Volatile" -> true
  1734. | _ -> is_volatile (apply_params t.t_types tl t.t_type))
  1735. | _ ->
  1736. false
  1737. let set_default ctx a c p =
  1738. let t = a.v_type in
  1739. let ve = mk (TLocal a) t p in
  1740. let cond = TBinop (OpEq,ve,mk (TConst TNull) t p) in
  1741. mk (TIf (mk_parent (mk cond ctx.basic.tbool p), mk (TBinop (OpAssign,ve,mk (TConst c) t p)) t p,None)) ctx.basic.tvoid p
  1742. let bytes_serialize data =
  1743. let b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789%:" in
  1744. let tbl = Array.init (String.length b64) (fun i -> String.get b64 i) in
  1745. let str = Base64.str_encode ~tbl data in
  1746. "s" ^ string_of_int (String.length str) ^ ":" ^ str
  1747. (*
  1748. Tells if the constructor might be called without any issue whatever its parameters
  1749. *)
  1750. let rec constructor_side_effects e =
  1751. match e.eexpr with
  1752. | TBinop (op,_,_) when op <> OpAssign ->
  1753. true
  1754. | TField (_,FEnum _) ->
  1755. false
  1756. | TUnop _ | TArray _ | TField _ | TCall _ | TNew _ | TFor _ | TWhile _ | TSwitch _ | TMatch _ | TReturn _ | TThrow _ ->
  1757. true
  1758. | TBinop _ | TTry _ | TIf _ | TBlock _ | TVars _
  1759. | TFunction _ | TArrayDecl _ | TObjectDecl _
  1760. | TParenthesis _ | TTypeExpr _ | TLocal _
  1761. | TConst _ | TContinue | TBreak | TCast _ ->
  1762. try
  1763. Type.iter (fun e -> if constructor_side_effects e then raise Exit) e;
  1764. false;
  1765. with Exit ->
  1766. true
  1767. (*
  1768. Make a dump of the full typed AST of all types
  1769. *)
  1770. let rec create_dumpfile acc = function
  1771. | [] -> assert false
  1772. | d :: [] ->
  1773. let ch = open_out (String.concat "/" (List.rev (d :: acc)) ^ ".dump") in
  1774. let buf = Buffer.create 0 in
  1775. buf, (fun () ->
  1776. output_string ch (Buffer.contents buf);
  1777. close_out ch)
  1778. | d :: l ->
  1779. let dir = String.concat "/" (List.rev (d :: acc)) in
  1780. if not (Sys.file_exists dir) then Unix.mkdir dir 0o755;
  1781. create_dumpfile (d :: acc) l
  1782. let dump_types com =
  1783. let s_type = s_type (Type.print_context()) in
  1784. let params = function [] -> "" | l -> Printf.sprintf "<%s>" (String.concat "," (List.map (fun (n,t) -> n ^ " : " ^ s_type t) l)) in
  1785. let s_expr = try if Common.defined_value com Define.Dump = "pretty" then Type.s_expr_pretty "\t" else Type.s_expr with Not_found -> Type.s_expr in
  1786. List.iter (fun mt ->
  1787. let path = Type.t_path mt in
  1788. let buf,close = create_dumpfile [] ("dump" :: (Common.platform_name com.platform) :: fst path @ [snd path]) in
  1789. let print fmt = Printf.kprintf (fun s -> Buffer.add_string buf s) fmt in
  1790. (match mt with
  1791. | Type.TClassDecl c ->
  1792. let rec print_field stat f =
  1793. print "\t%s%s%s%s" (if stat then "static " else "") (if f.cf_public then "public " else "") f.cf_name (params f.cf_params);
  1794. print "(%s) : %s" (s_kind f.cf_kind) (s_type f.cf_type);
  1795. (match f.cf_expr with
  1796. | None -> ()
  1797. | Some e -> print "\n\n\t = %s" (s_expr s_type e));
  1798. print ";\n\n";
  1799. List.iter (fun f -> print_field stat f) f.cf_overloads
  1800. in
  1801. print "%s%s%s %s%s" (if c.cl_private then "private " else "") (if c.cl_extern then "extern " else "") (if c.cl_interface then "interface" else "class") (s_type_path path) (params c.cl_types);
  1802. (match c.cl_super with None -> () | Some (c,pl) -> print " extends %s" (s_type (TInst (c,pl))));
  1803. List.iter (fun (c,pl) -> print " implements %s" (s_type (TInst (c,pl)))) c.cl_implements;
  1804. (match c.cl_dynamic with None -> () | Some t -> print " implements Dynamic<%s>" (s_type t));
  1805. (match c.cl_array_access with None -> () | Some t -> print " implements ArrayAccess<%s>" (s_type t));
  1806. print "{\n";
  1807. (match c.cl_constructor with
  1808. | None -> ()
  1809. | Some f -> print_field false f);
  1810. List.iter (print_field false) c.cl_ordered_fields;
  1811. List.iter (print_field true) c.cl_ordered_statics;
  1812. print "}";
  1813. | Type.TEnumDecl e ->
  1814. print "%s%senum %s%s {\n" (if e.e_private then "private " else "") (if e.e_extern then "extern " else "") (s_type_path path) (params e.e_types);
  1815. List.iter (fun n ->
  1816. let f = PMap.find n e.e_constrs in
  1817. print "\t%s : %s;\n" f.ef_name (s_type f.ef_type);
  1818. ) e.e_names;
  1819. print "}"
  1820. | Type.TTypeDecl t ->
  1821. print "%stype %s%s = %s" (if t.t_private then "private " else "") (s_type_path path) (params t.t_types) (s_type t.t_type);
  1822. | Type.TAbstractDecl a ->
  1823. print "%sabstract %s%s {}" (if a.a_private then "private " else "") (s_type_path path) (params a.a_types);
  1824. );
  1825. close();
  1826. ) com.types
  1827. let dump_dependencies com =
  1828. let buf,close = create_dumpfile [] ["dump";Common.platform_name com.platform;".dependencies"] in
  1829. let print fmt = Printf.kprintf (fun s -> Buffer.add_string buf s) fmt in
  1830. let dep = Hashtbl.create 0 in
  1831. List.iter (fun m ->
  1832. print "%s:\n" m.m_extra.m_file;
  1833. PMap.iter (fun _ m2 ->
  1834. print "\t%s\n" (m2.m_extra.m_file);
  1835. let l = try Hashtbl.find dep m2.m_extra.m_file with Not_found -> [] in
  1836. Hashtbl.replace dep m2.m_extra.m_file (m :: l)
  1837. ) m.m_extra.m_deps;
  1838. ) com.Common.modules;
  1839. close();
  1840. let buf,close = create_dumpfile [] ["dump";Common.platform_name com.platform;".dependants"] in
  1841. let print fmt = Printf.kprintf (fun s -> Buffer.add_string buf s) fmt in
  1842. Hashtbl.iter (fun n ml ->
  1843. print "%s:\n" n;
  1844. List.iter (fun m ->
  1845. print "\t%s\n" (m.m_extra.m_file);
  1846. ) ml;
  1847. ) dep;
  1848. close()
  1849. (*
  1850. Build a default safe-cast expression :
  1851. { var $t = <e>; if( Std.is($t,<t>) ) $t else throw "Class cast error"; }
  1852. *)
  1853. let default_cast ?(vtmp="$t") com e texpr t p =
  1854. let api = com.basic in
  1855. let mk_texpr = function
  1856. | TClassDecl c -> TAnon { a_fields = PMap.empty; a_status = ref (Statics c) }
  1857. | TEnumDecl e -> TAnon { a_fields = PMap.empty; a_status = ref (EnumStatics e) }
  1858. | TAbstractDecl a -> TAnon { a_fields = PMap.empty; a_status = ref (AbstractStatics a) }
  1859. | TTypeDecl _ -> assert false
  1860. in
  1861. let vtmp = alloc_var vtmp e.etype in
  1862. let var = mk (TVars [vtmp,Some e]) api.tvoid p in
  1863. let vexpr = mk (TLocal vtmp) e.etype p in
  1864. let texpr = mk (TTypeExpr texpr) (mk_texpr texpr) p in
  1865. let std = (try List.find (fun t -> t_path t = ([],"Std")) com.types with Not_found -> assert false) in
  1866. let fis = (try
  1867. let c = (match std with TClassDecl c -> c | _ -> assert false) in
  1868. FStatic (c, PMap.find "is" c.cl_statics)
  1869. with Not_found ->
  1870. assert false
  1871. ) in
  1872. let std = mk (TTypeExpr std) (mk_texpr std) p in
  1873. let is = mk (TField (std,fis)) (tfun [t_dynamic;t_dynamic] api.tbool) p in
  1874. let is = mk (TCall (is,[vexpr;texpr])) api.tbool p in
  1875. let exc = mk (TThrow (mk (TConst (TString "Class cast error")) api.tstring p)) t p in
  1876. let check = mk (TIf (mk_parent is,mk (TCast (vexpr,None)) t p,Some exc)) t p in
  1877. mk (TBlock [var;check;vexpr]) t p
  1878. (** Overload resolution **)
  1879. module Overloads =
  1880. struct
  1881. let rec simplify_t t = match t with
  1882. | TInst _ | TEnum _ | TAbstract({ a_impl = None }, _) ->
  1883. t
  1884. | TAbstract(a,tl) -> simplify_t (Abstract.get_underlying_type a tl)
  1885. | TType(({ t_path = [],"Null" } as t), [t2]) -> (match simplify_t t2 with
  1886. | (TAbstract({ a_impl = None }, _) | TEnum _ as t2) -> TType(t, [simplify_t t2])
  1887. | t2 -> t2)
  1888. | TType(t, tl) ->
  1889. simplify_t (apply_params t.t_types tl t.t_type)
  1890. | TMono r -> (match !r with
  1891. | Some t -> simplify_t t
  1892. | None -> t_dynamic)
  1893. | TAnon _ -> t_dynamic
  1894. | TDynamic _ -> t
  1895. | TLazy f -> simplify_t (!f())
  1896. | TFun _ -> t
  1897. (* rate type parameters *)
  1898. let rate_tp tlfun tlarg =
  1899. let acc = ref 0 in
  1900. List.iter2 (fun f a -> if not (type_iseq f a) then incr acc) tlfun tlarg;
  1901. !acc
  1902. let rec rate_conv cacc tfun targ =
  1903. match simplify_t tfun, simplify_t targ with
  1904. | TInst({ cl_interface = true } as cf, tlf), TInst(ca, tla) ->
  1905. (* breadth-first *)
  1906. let stack = ref [0,ca,tla] in
  1907. let cur = ref (0, ca,tla) in
  1908. let rec loop () =
  1909. match !stack with
  1910. | [] -> (let acc, ca, tla = !cur in match ca.cl_super with
  1911. | None -> raise Not_found
  1912. | Some (sup,tls) ->
  1913. cur := (acc+1,sup,List.map (apply_params ca.cl_types tla) tls);
  1914. stack := [!cur];
  1915. loop())
  1916. | (acc,ca,tla) :: _ when ca == cf ->
  1917. acc,tla
  1918. | (acc,ca,tla) :: s ->
  1919. stack := s @ List.map (fun (c,tl) -> (acc+1,c,List.map (apply_params ca.cl_types tla) tl)) ca.cl_implements;
  1920. loop()
  1921. in
  1922. let acc, tla = loop() in
  1923. (cacc + acc, rate_tp tlf tla)
  1924. | TInst(cf,tlf), TInst(ca,tla) ->
  1925. let rec loop acc ca tla =
  1926. if cf == ca then
  1927. acc, tla
  1928. else match ca.cl_super with
  1929. | None -> raise Not_found
  1930. | Some(sup,stl) ->
  1931. loop (acc+1) sup (List.map (apply_params ca.cl_types tla) stl)
  1932. in
  1933. let acc, tla = loop 0 ca tla in
  1934. (cacc + acc, rate_tp tlf tla)
  1935. | TEnum(ef,tlf), TEnum(ea, tla) ->
  1936. if ef != ea then raise Not_found;
  1937. (cacc, rate_tp tlf tla)
  1938. | TDynamic _, TDynamic _ ->
  1939. (cacc, 0)
  1940. | TDynamic _, _ ->
  1941. (max_int, 0) (* a function with dynamic will always be worst of all *)
  1942. | TAbstract({ a_impl = None }, _), TDynamic _ ->
  1943. (cacc + 2, 0) (* a dynamic to a basic type will have an "unboxing" penalty *)
  1944. | _, TDynamic _ ->
  1945. (cacc + 1, 0)
  1946. | TAbstract(af,tlf), TAbstract(aa,tla) ->
  1947. (if af == aa then
  1948. (cacc, rate_tp tlf tla)
  1949. else
  1950. let ret = ref None in
  1951. if List.exists (fun (t,_) -> try
  1952. ret := Some (rate_conv (cacc+1) (apply_params af.a_types tlf t) targ);
  1953. true
  1954. with | Not_found ->
  1955. false
  1956. ) af.a_from then
  1957. Option.get !ret
  1958. else
  1959. if List.exists (fun (t,_) -> try
  1960. ret := Some (rate_conv (cacc+1) tfun (apply_params aa.a_types tla t));
  1961. true
  1962. with | Not_found ->
  1963. false
  1964. ) aa.a_to then
  1965. Option.get !ret
  1966. else
  1967. raise Not_found)
  1968. | TType({ t_path = [], "Null" }, [tf]), TType({ t_path = [], "Null" }, [ta]) ->
  1969. rate_conv (cacc+0) tf ta
  1970. | TType({ t_path = [], "Null" }, [tf]), ta ->
  1971. rate_conv (cacc+1) tf ta
  1972. | tf, TType({ t_path = [], "Null" }, [ta]) ->
  1973. rate_conv (cacc+1) tf ta
  1974. | TFun _, TFun _ -> (* unify will make sure they are compatible *)
  1975. cacc,0
  1976. | tfun,targ ->
  1977. raise Not_found
  1978. let is_best arg1 arg2 =
  1979. (List.for_all2 (fun v1 v2 ->
  1980. v1 <= v2)
  1981. arg1 arg2) && (List.exists2 (fun v1 v2 ->
  1982. v1 < v2)
  1983. arg1 arg2)
  1984. let rec rm_duplicates acc ret = match ret with
  1985. | [] -> acc
  1986. | ( el, t ) :: ret when List.exists (fun (_,t2) -> type_iseq t t2) acc ->
  1987. rm_duplicates acc ret
  1988. | r :: ret ->
  1989. rm_duplicates (r :: acc) ret
  1990. let s_options rated =
  1991. String.concat ",\n" (List.map (fun ((_,t),rate) ->
  1992. "( " ^ (String.concat "," (List.map (fun (i,i2) -> string_of_int i ^ ":" ^ string_of_int i2) rate)) ^ " ) => " ^ (s_type (print_context()) t)
  1993. ) rated)
  1994. let count_optionals elist =
  1995. List.fold_left (fun acc (_,is_optional) -> if is_optional then acc + 1 else acc) 0 elist
  1996. let rec fewer_optionals acc compatible = match acc, compatible with
  1997. | _, [] -> acc
  1998. | [], c :: comp -> fewer_optionals [c] comp
  1999. | (elist_acc, _) :: _, ((elist, _) as cur) :: comp ->
  2000. let acc_opt = count_optionals elist_acc in
  2001. let comp_opt = count_optionals elist in
  2002. if acc_opt = comp_opt then
  2003. fewer_optionals (cur :: acc) comp
  2004. else if acc_opt < comp_opt then
  2005. fewer_optionals acc comp
  2006. else
  2007. fewer_optionals [cur] comp
  2008. let reduce_compatible compatible = match fewer_optionals [] (rm_duplicates [] compatible) with
  2009. | [] -> [] | [v] -> [v]
  2010. | compatible ->
  2011. (* convert compatible into ( rate * compatible_type ) list *)
  2012. let rec mk_rate acc elist args = match elist, args with
  2013. | [], [] -> acc
  2014. | (_,true) :: elist, _ :: args -> mk_rate acc elist args
  2015. | (e,false) :: elist, (n,o,t) :: args ->
  2016. mk_rate (rate_conv 0 t e.etype :: acc) elist args
  2017. | _ -> assert false
  2018. in
  2019. let rated = ref [] in
  2020. List.iter (function
  2021. | (elist,TFun(args,ret)) -> (try
  2022. rated := ( (elist,TFun(args,ret)), mk_rate [] elist args ) :: !rated
  2023. with | Not_found -> ())
  2024. | _ -> assert false
  2025. ) compatible;
  2026. let rec loop best rem = match best, rem with
  2027. | _, [] -> best
  2028. | [], r1 :: rem -> loop [r1] rem
  2029. | (bover, bargs) :: b1, (rover, rargs) :: rem ->
  2030. if is_best bargs rargs then
  2031. loop best rem
  2032. else if is_best rargs bargs then
  2033. loop (loop b1 [rover,rargs]) rem
  2034. else (* equally specific *)
  2035. loop ( (rover,rargs) :: best ) rem
  2036. in
  2037. List.map fst (loop [] !rated)
  2038. end;;