codegen.ml 57 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704
  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 type_constant com c p =
  42. let t = com.basic in
  43. match c with
  44. | Int s ->
  45. if String.length s > 10 && String.sub s 0 2 = "0x" then error "Invalid hexadecimal integer" p;
  46. (try mk (TConst (TInt (Int32.of_string s))) t.tint p
  47. with _ -> mk (TConst (TFloat s)) t.tfloat p)
  48. | Float f -> mk (TConst (TFloat f)) t.tfloat p
  49. | String s -> mk (TConst (TString s)) t.tstring p
  50. | Ident "true" -> mk (TConst (TBool true)) t.tbool p
  51. | Ident "false" -> mk (TConst (TBool false)) t.tbool p
  52. | Ident "null" -> mk (TConst TNull) (t.tnull (mk_mono())) p
  53. | Ident t -> error ("Invalid constant : " ^ t) p
  54. | Regexp _ -> error "Invalid constant" p
  55. let rec type_constant_value com (e,p) =
  56. match e with
  57. | EConst c ->
  58. type_constant com c p
  59. | EParenthesis e ->
  60. type_constant_value com e
  61. | EObjectDecl el ->
  62. mk (TObjectDecl (List.map (fun (n,e) -> n, type_constant_value com e) el)) (TAnon { a_fields = PMap.empty; a_status = ref Closed }) p
  63. | EArrayDecl el ->
  64. mk (TArrayDecl (List.map (type_constant_value com) el)) (com.basic.tarray t_dynamic) p
  65. | _ ->
  66. error "Constant value expected" p
  67. let rec has_properties c =
  68. List.exists (fun f ->
  69. match f.cf_kind with
  70. | Var { v_read = AccCall } -> true
  71. | Var { v_write = AccCall } -> true
  72. | _ when Meta.has Meta.Accessor f.cf_meta -> true
  73. | _ -> false
  74. ) c.cl_ordered_fields || (match c.cl_super with Some (c,_) -> has_properties c | _ -> false)
  75. let get_properties fields =
  76. List.fold_left (fun acc f ->
  77. if Meta.has Meta.Accessor f.cf_meta then
  78. (f.cf_name, f.cf_name) :: acc
  79. else
  80. let acc = (match f.cf_kind with
  81. | Var { v_read = AccCall } -> ("get_" ^ f.cf_name , "get_" ^ f.cf_name) :: acc
  82. | _ -> acc) in
  83. match f.cf_kind with
  84. | Var { v_write = AccCall } -> ("set_" ^ f.cf_name , "set_" ^ f.cf_name) :: acc
  85. | _ -> acc
  86. ) [] fields
  87. let add_property_field com c =
  88. let p = c.cl_pos in
  89. let props = get_properties (c.cl_ordered_statics @ c.cl_ordered_fields) in
  90. match props with
  91. | [] -> ()
  92. | _ ->
  93. let fields,values = List.fold_left (fun (fields,values) (n,v) ->
  94. let cf = mk_field n com.basic.tstring p in
  95. PMap.add n cf fields,(n, string com v p) :: values
  96. ) (PMap.empty,[]) props in
  97. let t = mk_anon fields in
  98. let e = mk (TObjectDecl values) t p in
  99. let cf = mk_field "__properties__" t p in
  100. cf.cf_expr <- Some e;
  101. c.cl_statics <- PMap.add cf.cf_name cf c.cl_statics;
  102. c.cl_ordered_statics <- cf :: c.cl_ordered_statics
  103. (* -------------------------------------------------------------------------- *)
  104. (* REMOTING PROXYS *)
  105. let extend_remoting ctx c t p async prot =
  106. if c.cl_super <> None then error "Cannot extend several classes" p;
  107. (* remove forbidden packages *)
  108. let rules = ctx.com.package_rules in
  109. ctx.com.package_rules <- PMap.foldi (fun key r acc -> match r with Forbidden -> acc | _ -> PMap.add key r acc) rules PMap.empty;
  110. (* parse module *)
  111. let path = (t.tpackage,t.tname) in
  112. let new_name = (if async then "Async_" else "Remoting_") ^ t.tname in
  113. (* check if the proxy already exists *)
  114. let t = (try
  115. Typeload.load_type_def ctx p { tpackage = fst path; tname = new_name; tparams = []; tsub = None }
  116. with
  117. Error (Module_not_found _,p2) when p == p2 ->
  118. (* build it *)
  119. Common.log ctx.com ("Building proxy for " ^ s_type_path path);
  120. let file, decls = (try
  121. Typeload.parse_module ctx path p
  122. with
  123. | 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
  124. | e -> ctx.com.package_rules <- rules; raise e) in
  125. ctx.com.package_rules <- rules;
  126. let base_fields = [
  127. { 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) };
  128. { 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 = [] } };
  129. ] in
  130. let tvoid = CTPath { tpackage = []; tname = "Void"; tparams = []; tsub = None } in
  131. let build_field is_public acc f =
  132. if f.cff_name = "new" then
  133. acc
  134. else match f.cff_kind with
  135. | FFun fd when (is_public || List.mem APublic f.cff_access) && not (List.mem AStatic f.cff_access) ->
  136. 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;
  137. let eargs = [EArrayDecl (List.map (fun (a,_,_,_) -> (EConst (Ident a),p)) fd.f_args),p] in
  138. let ftype = (match fd.f_type with Some (CTPath { tpackage = []; tname = "Void" }) -> None | _ -> fd.f_type) in
  139. let fargs, eargs = if async then match ftype with
  140. | Some tret -> fd.f_args @ ["__callb",true,Some (CTFunction ([tret],tvoid)),None], eargs @ [EConst (Ident "__callb"),p]
  141. | _ -> fd.f_args, eargs @ [EConst (Ident "null"),p]
  142. else
  143. fd.f_args, eargs
  144. in
  145. let id = (EConst (String f.cff_name), p) in
  146. let id = if prot then id else ECall ((EConst (Ident "__unprotect__"),p),[id]),p in
  147. let expr = ECall (
  148. (EField (
  149. (ECall ((EField ((EConst (Ident "__cnx"),p),"resolve"),p),[id]),p),
  150. "call")
  151. ,p),eargs),p
  152. in
  153. let expr = if async || ftype = None then expr else (EReturn (Some expr),p) in
  154. let fd = {
  155. f_params = fd.f_params;
  156. f_args = fargs;
  157. f_type = if async then None else ftype;
  158. f_expr = Some (EBlock [expr],p);
  159. } in
  160. { cff_name = f.cff_name; cff_pos = p; cff_doc = None; cff_meta = []; cff_access = [APublic]; cff_kind = FFun fd } :: acc
  161. | _ -> acc
  162. in
  163. let decls = List.map (fun d ->
  164. match d with
  165. | EClass c, p when c.d_name = t.tname ->
  166. let is_public = List.mem HExtern c.d_flags || List.mem HInterface c.d_flags in
  167. let fields = List.rev (List.fold_left (build_field is_public) base_fields c.d_data) in
  168. (EClass { c with d_flags = []; d_name = new_name; d_data = fields },p)
  169. | _ -> d
  170. ) decls in
  171. let m = Typeload.type_module ctx (t.tpackage,new_name) file decls p in
  172. add_dependency ctx.m.curmod m;
  173. try
  174. List.find (fun tdecl -> snd (t_path tdecl) = new_name) m.m_types
  175. with Not_found ->
  176. error ("Module " ^ s_type_path path ^ " does not define type " ^ t.tname) p
  177. ) in
  178. match t with
  179. | TClassDecl c2 when c2.cl_types = [] -> c2.cl_build(); c.cl_super <- Some (c2,[]);
  180. | _ -> error "Remoting proxy must be a class without parameters" p
  181. (* -------------------------------------------------------------------------- *)
  182. (* HAXE.RTTI.GENERIC *)
  183. exception Generic_Exception of string * Ast.pos
  184. type generic_context = {
  185. ctx : typer;
  186. subst : (t * t) list;
  187. name : string;
  188. p : pos;
  189. mutable mg : module_def option;
  190. }
  191. let make_generic ctx ps pt p =
  192. let rec loop l1 l2 =
  193. match l1, l2 with
  194. | [] , [] -> []
  195. | (x,TLazy f) :: l1, _ -> loop ((x,(!f)()) :: l1) l2
  196. | (_,t1) :: l1 , t2 :: l2 -> (t1,t2) :: loop l1 l2
  197. | _ -> assert false
  198. in
  199. let name =
  200. String.concat "_" (List.map2 (fun (s,_) t ->
  201. let s_type_path_underscore (p,s) = match p with [] -> s | _ -> String.concat "_" p ^ "_" ^ s in
  202. let rec loop top t = match follow t with
  203. | TInst(c,tl) -> (s_type_path_underscore c.cl_path) ^ (loop_tl tl)
  204. | TEnum(en,tl) -> (s_type_path_underscore en.e_path) ^ (loop_tl tl)
  205. | TAbstract(a,tl) -> (s_type_path_underscore a.a_path) ^ (loop_tl tl)
  206. | _ when not top -> "_" (* allow unknown/incompatible types as type parameters to retain old behavior *)
  207. | TMono _ -> raise (Generic_Exception (("Could not determine type for parameter " ^ s), p))
  208. | t -> raise (Generic_Exception (("Type parameter must be a class or enum instance (found " ^ (s_type (print_context()) t) ^ ")"), p))
  209. and loop_tl tl = match tl with
  210. | [] -> ""
  211. | tl -> "_" ^ String.concat "_" (List.map (loop false) tl)
  212. in
  213. loop true t
  214. ) ps pt)
  215. in
  216. {
  217. ctx = ctx;
  218. subst = loop ps pt;
  219. name = name;
  220. p = p;
  221. mg = None;
  222. }
  223. let rec generic_substitute_type gctx t =
  224. match t with
  225. | TInst ({ cl_kind = KGeneric } as c2,tl2) ->
  226. (* maybe loop, or generate cascading generics *)
  227. let _, _, f = gctx.ctx.g.do_build_instance gctx.ctx (TClassDecl c2) gctx.p in
  228. let t = f (List.map (generic_substitute_type gctx) tl2) in
  229. (match follow t,gctx.mg with TInst(c,_), Some m -> add_dependency m c.cl_module | _ -> ());
  230. t
  231. | _ ->
  232. try List.assq t gctx.subst with Not_found -> Type.map (generic_substitute_type gctx) t
  233. let generic_substitute_expr gctx e =
  234. let vars = Hashtbl.create 0 in
  235. let build_var v =
  236. try
  237. Hashtbl.find vars v.v_id
  238. with Not_found ->
  239. let v2 = alloc_var v.v_name (generic_substitute_type gctx v.v_type) in
  240. v2.v_meta <- v.v_meta;
  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 has_ctor_constraint c = match c.cl_kind with
  252. | KTypeParameter tl ->
  253. List.exists (fun t -> match follow t with
  254. | TAnon a when PMap.mem "new" a.a_fields -> true
  255. | _ -> false
  256. ) tl;
  257. | _ -> false
  258. let rec build_generic ctx c p tl =
  259. let pack = fst c.cl_path in
  260. let recurse = ref false in
  261. let rec check_recursive t =
  262. match follow t with
  263. | TInst (c2,tl) ->
  264. (match c2.cl_kind with
  265. | KTypeParameter tl ->
  266. if not (Typeload.is_generic_parameter ctx c2) && has_ctor_constraint c2 then
  267. error "Type parameters with a constructor cannot be used non-generically" p;
  268. recurse := true
  269. | _ -> ());
  270. List.iter check_recursive tl;
  271. | _ ->
  272. ()
  273. in
  274. List.iter check_recursive tl;
  275. let gctx = try make_generic ctx c.cl_types tl p with Generic_Exception (msg,p) -> error msg p in
  276. let name = (snd c.cl_path) ^ "_" ^ gctx.name in
  277. if !recurse then begin
  278. TInst (c,tl) (* build a normal instance *)
  279. end else try
  280. Typeload.load_instance ctx { tpackage = pack; tname = name; tparams = []; tsub = None } p false
  281. with Error(Module_not_found path,_) when path = (pack,name) ->
  282. let m = (try Hashtbl.find ctx.g.modules (Hashtbl.find ctx.g.types_module c.cl_path) with Not_found -> assert false) in
  283. let ctx = { ctx with m = { ctx.m with module_types = m.m_types @ ctx.m.module_types } } in
  284. c.cl_build(); (* make sure the super class is already setup *)
  285. let mg = {
  286. m_id = alloc_mid();
  287. m_path = (pack,name);
  288. m_types = [];
  289. m_extra = module_extra (s_type_path (pack,name)) m.m_extra.m_sign 0. MFake;
  290. } in
  291. gctx.mg <- Some mg;
  292. let cg = mk_class mg (pack,name) c.cl_pos in
  293. mg.m_types <- [TClassDecl cg];
  294. Hashtbl.add ctx.g.modules mg.m_path mg;
  295. add_dependency mg m;
  296. add_dependency ctx.m.curmod mg;
  297. (* ensure that type parameters are set in dependencies *)
  298. let dep_stack = ref [] in
  299. let rec loop t =
  300. if not (List.memq t !dep_stack) then begin
  301. dep_stack := t :: !dep_stack;
  302. match t with
  303. | TInst (c,tl) -> add_dep c.cl_module tl
  304. | TEnum (e,tl) -> add_dep e.e_module tl
  305. | TType (t,tl) -> add_dep t.t_module tl
  306. | TAbstract (a,tl) -> add_dep a.a_module tl
  307. | TMono r ->
  308. (match !r with
  309. | None -> ()
  310. | Some t -> loop t)
  311. | TLazy f ->
  312. loop ((!f)());
  313. | TDynamic t2 ->
  314. if t == t2 then () else loop t2
  315. | TAnon a ->
  316. PMap.iter (fun _ f -> loop f.cf_type) a.a_fields
  317. | TFun (args,ret) ->
  318. List.iter (fun (_,_,t) -> loop t) args;
  319. loop ret
  320. end
  321. and add_dep m tl =
  322. add_dependency mg m;
  323. List.iter loop tl
  324. in
  325. List.iter loop tl;
  326. let delays = ref [] in
  327. let build_field f =
  328. let t = generic_substitute_type gctx f.cf_type in
  329. let f = { f with cf_type = t} in
  330. (* delay the expression mapping to make sure all cf_type fields are set correctly first *)
  331. (delays := (fun () ->
  332. try (match f.cf_expr with None -> () | Some e -> f.cf_expr <- Some (generic_substitute_expr gctx e))
  333. with Unify_error l -> error (error_msg (Unify l)) f.cf_pos) :: !delays);
  334. f
  335. in
  336. if c.cl_init <> None || c.cl_dynamic <> None then error "This class can't be generic" p;
  337. if c.cl_ordered_statics <> [] then error "A generic class can't have static fields" p;
  338. cg.cl_super <- (match c.cl_super with
  339. | None -> None
  340. | Some (cs,pl) ->
  341. let find_class subst =
  342. let rec loop subst = match subst with
  343. | (TInst(c,[]),t) :: subst when c == cs -> t
  344. | _ :: subst -> loop subst
  345. | [] -> raise Not_found
  346. in
  347. try
  348. if pl <> [] then raise Not_found;
  349. let t = loop subst in
  350. (* extended type parameter: concrete type must have a constructor, but generic base class must not have one *)
  351. begin match follow t,c.cl_constructor with
  352. | TInst({cl_constructor = None} as cs,_),None -> error ("Cannot use " ^ (s_type_path cs.cl_path) ^ " as type parameter because it is extended and has no constructor") p
  353. | _,Some cf -> error "Generics extending type parameters cannot have constructors" cf.cf_pos
  354. | _ -> ()
  355. end;
  356. t
  357. with Not_found ->
  358. apply_params c.cl_types tl (TInst(cs,pl))
  359. in
  360. let ts = follow (find_class gctx.subst) in
  361. let cs,pl = Typeload.check_extends ctx c ts p in
  362. match cs.cl_kind with
  363. | KGeneric ->
  364. (match build_generic ctx cs p pl with
  365. | TInst (cs,pl) -> Some (cs,pl)
  366. | _ -> assert false)
  367. | _ -> Some(cs,pl)
  368. );
  369. Typeload.add_constructor ctx cg false p;
  370. cg.cl_kind <- KGenericInstance (c,tl);
  371. cg.cl_interface <- c.cl_interface;
  372. cg.cl_constructor <- (match cg.cl_constructor, c.cl_constructor, c.cl_super with
  373. | _, Some c, _ -> Some (build_field c)
  374. | Some ctor, _, _ -> Some ctor
  375. | None, None, None -> None
  376. | _ -> error "Please define a constructor for this class in order to use it as generic" c.cl_pos
  377. );
  378. cg.cl_implements <- List.map (fun (i,tl) ->
  379. (match follow (generic_substitute_type gctx (TInst (i, List.map (generic_substitute_type gctx) tl))) with
  380. | TInst (i,tl) -> i, tl
  381. | _ -> assert false)
  382. ) c.cl_implements;
  383. cg.cl_ordered_fields <- List.map (fun f ->
  384. let f = build_field f in
  385. cg.cl_fields <- PMap.add f.cf_name f cg.cl_fields;
  386. f
  387. ) c.cl_ordered_fields;
  388. List.iter (fun f -> f()) !delays;
  389. TInst (cg,[])
  390. (* -------------------------------------------------------------------------- *)
  391. (* HAXE.XML.PROXY *)
  392. let extend_xml_proxy ctx c t file p =
  393. let t = Typeload.load_complex_type ctx p t in
  394. let file = (try Common.find_file ctx.com file with Not_found -> file) in
  395. add_dependency c.cl_module (create_fake_module ctx file);
  396. let used = ref PMap.empty in
  397. let print_results() =
  398. PMap.iter (fun id used ->
  399. if not used then ctx.com.warning (id ^ " is not used") p;
  400. ) (!used)
  401. in
  402. let check_used = Common.defined ctx.com Define.CheckXmlProxy in
  403. if check_used then ctx.g.hook_generate <- print_results :: ctx.g.hook_generate;
  404. try
  405. let rec loop = function
  406. | Xml.Element (_,attrs,childs) ->
  407. (try
  408. let id = List.assoc "id" attrs in
  409. if PMap.mem id c.cl_fields then error ("Duplicate id " ^ id) p;
  410. let t = if not check_used then t else begin
  411. used := PMap.add id false (!used);
  412. let ft() = used := PMap.add id true (!used); t in
  413. TLazy (ref ft)
  414. end in
  415. let f = {
  416. cf_name = id;
  417. cf_type = t;
  418. cf_public = true;
  419. cf_pos = p;
  420. cf_doc = None;
  421. cf_meta = no_meta;
  422. cf_kind = Var { v_read = AccResolve; v_write = AccNo };
  423. cf_params = [];
  424. cf_expr = None;
  425. cf_overloads = [];
  426. } in
  427. c.cl_fields <- PMap.add id f c.cl_fields;
  428. with
  429. Not_found -> ());
  430. List.iter loop childs;
  431. | Xml.PCData _ -> ()
  432. in
  433. loop (Xml.parse_file file)
  434. with
  435. | Xml.Error e -> error ("XML error " ^ Xml.error e) p
  436. | Xml.File_not_found f -> error ("XML File not found : " ^ f) p
  437. (* -------------------------------------------------------------------------- *)
  438. (* BUILD META DATA OBJECT *)
  439. let build_metadata com t =
  440. let api = com.basic in
  441. let p, meta, fields, statics = (match t with
  442. | TClassDecl c ->
  443. 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
  444. let statics = List.map (fun f -> f.cf_name,f.cf_meta) c.cl_ordered_statics in
  445. (c.cl_pos, ["",c.cl_meta],fields,statics)
  446. | TEnumDecl e ->
  447. (e.e_pos, ["",e.e_meta],List.map (fun n -> n, (PMap.find n e.e_constrs).ef_meta) e.e_names, [])
  448. | TTypeDecl t ->
  449. (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 [] | _ -> []),[])
  450. | TAbstractDecl a ->
  451. (a.a_pos, ["",a.a_meta],[],[])
  452. ) in
  453. let filter l =
  454. 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
  455. List.filter (fun (_,ml) -> ml <> []) l
  456. in
  457. let meta, fields, statics = filter meta, filter fields, filter statics in
  458. let make_meta_field ml =
  459. let h = Hashtbl.create 0 in
  460. mk (TObjectDecl (List.map (fun (f,el,p) ->
  461. if Hashtbl.mem h f then error ("Duplicate metadata '" ^ f ^ "'") p;
  462. Hashtbl.add h f ();
  463. f, mk (match el with [] -> TConst TNull | _ -> TArrayDecl (List.map (type_constant_value com) el)) (api.tarray t_dynamic) p
  464. ) ml)) (api.tarray t_dynamic) p
  465. in
  466. let make_meta l =
  467. mk (TObjectDecl (List.map (fun (f,ml) -> f,make_meta_field ml) l)) t_dynamic p
  468. in
  469. if meta = [] && fields = [] && statics = [] then
  470. None
  471. else
  472. let meta_obj = [] in
  473. let meta_obj = (if fields = [] then meta_obj else ("fields",make_meta fields) :: meta_obj) in
  474. let meta_obj = (if statics = [] then meta_obj else ("statics",make_meta statics) :: meta_obj) in
  475. let meta_obj = (try ("obj", make_meta_field (List.assoc "" meta)) :: meta_obj with Not_found -> meta_obj) in
  476. Some (mk (TObjectDecl meta_obj) t_dynamic p)
  477. (* -------------------------------------------------------------------------- *)
  478. (* MACRO TYPE *)
  479. let get_macro_path ctx e args p =
  480. let rec loop e =
  481. match fst e with
  482. | EField (e,f) -> f :: loop e
  483. | EConst (Ident i) -> [i]
  484. | _ -> error "Invalid macro call" p
  485. in
  486. let path = match e with
  487. | (EConst(Ident i)),_ ->
  488. let path = try
  489. if not (PMap.mem i ctx.curclass.cl_statics) then raise Not_found;
  490. ctx.curclass.cl_path
  491. with Not_found -> try
  492. (t_infos (fst (PMap.find i ctx.m.module_globals))).mt_path
  493. with Not_found ->
  494. error "Invalid macro call" p
  495. in
  496. i :: (snd path) :: (fst path)
  497. | _ ->
  498. loop e
  499. in
  500. (match path with
  501. | meth :: cl :: path -> (List.rev path,cl), meth, args
  502. | _ -> error "Invalid macro call" p)
  503. let build_macro_type ctx pl p =
  504. let path, field, args = (match pl with
  505. | [TInst ({ cl_kind = KExpr (ECall (e,args),_) },_)]
  506. | [TInst ({ cl_kind = KExpr (EArrayDecl [ECall (e,args),_],_) },_)] ->
  507. get_macro_path ctx e args p
  508. | _ ->
  509. error "MacroType requires a single expression call parameter" p
  510. ) in
  511. let old = ctx.ret in
  512. let t = (match ctx.g.do_macro ctx MMacroType path field args p with
  513. | None -> mk_mono()
  514. | Some _ -> ctx.ret
  515. ) in
  516. ctx.ret <- old;
  517. t
  518. let build_macro_build ctx c pl cfl p =
  519. let path, field, args = match Meta.get Meta.GenericBuild c.cl_meta with
  520. | _,[ECall(e,args),_],_ -> get_macro_path ctx e args p
  521. | _ -> error "genericBuild requires a single expression call parameter" p
  522. in
  523. let old = ctx.ret,ctx.g.get_build_infos in
  524. ctx.g.get_build_infos <- (fun() -> Some (TClassDecl c, pl, cfl));
  525. let t = (match ctx.g.do_macro ctx MMacroType path field args p with
  526. | None -> mk_mono()
  527. | Some _ -> ctx.ret
  528. ) in
  529. ctx.ret <- fst old;
  530. ctx.g.get_build_infos <- snd old;
  531. t
  532. (* -------------------------------------------------------------------------- *)
  533. (* API EVENTS *)
  534. let build_instance ctx mtype p =
  535. match mtype with
  536. | TClassDecl c ->
  537. if ctx.pass > PBuildClass then c.cl_build();
  538. let build f s =
  539. let r = exc_protect ctx (fun r ->
  540. let t = mk_mono() in
  541. r := (fun() -> t);
  542. unify_raise ctx (f()) t p;
  543. t
  544. ) s in
  545. delay ctx PForce (fun() -> ignore ((!r)()));
  546. TLazy r
  547. in
  548. let ft = (fun pl ->
  549. match c.cl_kind with
  550. | KGeneric ->
  551. build (fun () -> build_generic ctx c p pl) "build_generic"
  552. | KMacroType ->
  553. build (fun () -> build_macro_type ctx pl p) "macro_type"
  554. | KGenericBuild cfl ->
  555. build (fun () -> build_macro_build ctx c pl cfl p) "generic_build"
  556. | _ ->
  557. TInst (c,pl)
  558. ) in
  559. c.cl_types , c.cl_path , ft
  560. | TEnumDecl e ->
  561. e.e_types , e.e_path , (fun t -> TEnum (e,t))
  562. | TTypeDecl t ->
  563. t.t_types , t.t_path , (fun tl -> TType(t,tl))
  564. | TAbstractDecl a ->
  565. a.a_types, a.a_path, (fun tl -> TAbstract(a,tl))
  566. let on_inherit ctx c p h =
  567. match h with
  568. | HExtends { tpackage = ["haxe";"remoting"]; tname = "Proxy"; tparams = [TPType(CTPath t)] } ->
  569. extend_remoting ctx c t p false true;
  570. false
  571. | HExtends { tpackage = ["haxe";"remoting"]; tname = "AsyncProxy"; tparams = [TPType(CTPath t)] } ->
  572. extend_remoting ctx c t p true true;
  573. false
  574. | HExtends { tpackage = ["mt"]; tname = "AsyncProxy"; tparams = [TPType(CTPath t)] } ->
  575. extend_remoting ctx c t p true false;
  576. false
  577. | HExtends { tpackage = ["haxe";"xml"]; tname = "Proxy"; tparams = [TPExpr(EConst (String file),p);TPType t] } ->
  578. extend_xml_proxy ctx c t file p;
  579. true
  580. | _ ->
  581. true
  582. (* Promotes type parameters of abstracts to their implementation fields *)
  583. let promote_abstract_parameters ctx t = match t with
  584. | TClassDecl ({cl_kind = KAbstractImpl a} as c) when a.a_types <> [] ->
  585. List.iter (fun f ->
  586. List.iter (fun (n,t) -> match t with
  587. | TInst({cl_kind = KTypeParameter _; cl_path=p,n} as cp,[]) when not (List.mem_assoc n f.cf_params) ->
  588. let path = List.rev ((snd c.cl_path) :: List.rev (fst c.cl_path)),n in
  589. f.cf_params <- (n,TInst({cp with cl_path = path},[])) :: f.cf_params
  590. | _ ->
  591. ()
  592. ) a.a_types;
  593. ) c.cl_ordered_statics;
  594. | _ ->
  595. ()
  596. (* -------------------------------------------------------------------------- *)
  597. (* ABSTRACT CASTS *)
  598. module Abstract = struct
  599. let find_to ab pl b =
  600. if follow b == t_dynamic then
  601. List.find (fun (t,_) -> t == t_dynamic) ab.a_to
  602. else
  603. List.find (Type.unify_to_field ab pl b) ab.a_to
  604. let find_from ab pl a b =
  605. if follow a == t_dynamic then
  606. List.find (fun (t,_) -> t == t_dynamic) ab.a_from
  607. else
  608. List.find (Type.unify_from_field ab pl a b) ab.a_from
  609. let cast_stack = ref []
  610. let underlying_type_stack = ref []
  611. let rec get_underlying_type a pl =
  612. let maybe_recurse t =
  613. underlying_type_stack := a :: !underlying_type_stack;
  614. let t = match follow t with
  615. | TAbstract(a,tl) when not (Meta.has Meta.CoreType a.a_meta) ->
  616. if List.mem a !underlying_type_stack then begin
  617. let s = String.concat " -> " (List.map (fun a -> s_type_path a.a_path) (List.rev (a :: !underlying_type_stack))) in
  618. (* technically this should be done at type declaration level *)
  619. error ("Abstract chain detected: " ^ s) a.a_pos
  620. end;
  621. get_underlying_type a tl
  622. | _ ->
  623. t
  624. in
  625. underlying_type_stack := List.tl !underlying_type_stack;
  626. t
  627. in
  628. try
  629. if not (Meta.has Meta.MultiType a.a_meta) then raise Not_found;
  630. let m = mk_mono() in
  631. let _ = find_to a pl m in
  632. maybe_recurse (follow m)
  633. with Not_found ->
  634. if Meta.has Meta.CoreType a.a_meta then
  635. t_dynamic
  636. else
  637. maybe_recurse (apply_params a.a_types pl a.a_this)
  638. let make_static_call ctx c cf a pl args t p =
  639. make_static_call ctx c cf (apply_params a.a_types pl) args t p
  640. let rec do_check_cast ctx tleft eright p =
  641. let tright = follow eright.etype in
  642. let tleft = follow tleft in
  643. if tleft == tright then eright else
  644. let recurse cf f =
  645. if cf == ctx.curfield || List.mem cf !cast_stack then error "Recursive implicit cast" p;
  646. cast_stack := cf :: !cast_stack;
  647. let r = f() in
  648. cast_stack := List.tl !cast_stack;
  649. r
  650. in
  651. try (match tright,tleft with
  652. | (TAbstract({a_impl = Some c1} as a1,pl1) as t1),(TAbstract({a_impl = Some c2} as a2,pl2) as t2) ->
  653. if a1 == a2 then
  654. eright
  655. else begin
  656. let c,cfo,a,pl = try
  657. if Meta.has Meta.MultiType a1.a_meta then raise Not_found;
  658. c1,snd (find_to a1 pl1 t2),a1,pl1
  659. with Not_found ->
  660. if Meta.has Meta.MultiType a2.a_meta then raise Not_found;
  661. c2,snd (find_from a2 pl2 t1 t2),a2,pl2
  662. in
  663. match cfo with
  664. | None -> eright
  665. | Some cf ->
  666. recurse cf (fun () -> make_static_call ctx c cf a pl [eright] tleft p)
  667. end
  668. | _, TMono _ | TMono _, _ ->
  669. eright
  670. | TAbstract({a_impl = Some c} as a,pl),t2 when not (Meta.has Meta.MultiType a.a_meta) ->
  671. begin match find_to a pl t2 with
  672. | tcf,None ->
  673. let tcf = apply_params a.a_types pl tcf in
  674. if type_iseq tcf tleft then eright else do_check_cast ctx tcf eright p
  675. | _,Some cf ->
  676. recurse cf (fun () -> make_static_call ctx c cf a pl [eright] tleft p)
  677. end
  678. | t1,(TAbstract({a_impl = Some c} as a,pl) as t2) when not (Meta.has Meta.MultiType a.a_meta) ->
  679. begin match find_from a pl t1 t2 with
  680. | tcf,None ->
  681. let tcf = apply_params a.a_types pl tcf in
  682. if type_iseq tcf tleft then eright else do_check_cast ctx tcf eright p
  683. | _,Some cf ->
  684. recurse cf (fun () -> make_static_call ctx c cf a pl [eright] tleft p)
  685. end
  686. | _ ->
  687. eright)
  688. with Not_found ->
  689. eright
  690. let check_cast ctx tleft eright p =
  691. if ctx.com.display <> DMNone then eright else do_check_cast ctx tleft eright p
  692. let find_multitype_specialization a pl p =
  693. let m = mk_mono() in
  694. let tl = match Meta.get Meta.MultiType a.a_meta with
  695. | _,[],_ -> pl
  696. | _,el,_ ->
  697. let relevant = Hashtbl.create 0 in
  698. List.iter (fun e -> match fst e with
  699. | EConst(Ident s) -> Hashtbl.replace relevant s true
  700. | _ -> error "Type parameter expected" (pos e)
  701. ) el;
  702. let tl = List.map2 (fun (n,_) t -> if Hashtbl.mem relevant n || not (has_mono t) then t else t_dynamic) a.a_types pl in
  703. tl
  704. in
  705. let _,cfo =
  706. try find_to a tl m
  707. with Not_found ->
  708. let at = apply_params a.a_types pl a.a_this in
  709. let st = s_type (print_context()) at in
  710. if has_mono at then
  711. error ("Type parameters of multi type abstracts must be known (for " ^ st ^ ")") p
  712. else
  713. error ("Abstract " ^ (s_type_path a.a_path) ^ " has no @:to function that accepts " ^ st) p;
  714. in
  715. match cfo with
  716. | None -> assert false
  717. | Some cf -> cf, follow m
  718. let handle_abstract_casts ctx e =
  719. let rec loop ctx e = match e.eexpr with
  720. | TNew({cl_kind = KAbstractImpl a} as c,pl,el) ->
  721. (* a TNew of an abstract implementation is only generated if it is a multi type abstract *)
  722. let cf,m = find_multitype_specialization a pl e.epos in
  723. let e = make_static_call ctx c cf a pl ((mk (TConst TNull) (TAbstract(a,pl)) e.epos) :: el) m e.epos in
  724. {e with etype = m}
  725. | TCall({eexpr = TField(_,FStatic({cl_path=[],"Std"},{cf_name = "string"}))},[e1]) when (match follow e1.etype with TAbstract({a_impl = Some _},_) -> true | _ -> false) ->
  726. begin match follow e1.etype with
  727. | TAbstract({a_impl = Some c} as a,tl) ->
  728. begin try
  729. let cf = PMap.find "toString" c.cl_statics in
  730. make_static_call ctx c cf a tl [e1] ctx.t.tstring e.epos
  731. with Not_found ->
  732. e
  733. end
  734. | _ ->
  735. assert false
  736. end
  737. | TCall(e1, el) ->
  738. begin try
  739. begin match e1.eexpr with
  740. | TField(e2,fa) ->
  741. begin match follow e2.etype with
  742. | TAbstract(a,pl) when Meta.has Meta.MultiType a.a_meta ->
  743. let m = get_underlying_type a pl in
  744. let fname = field_name fa in
  745. let el = List.map (loop ctx) el in
  746. begin try
  747. let ef = mk (TField({e2 with etype = m},quick_field m fname)) e1.etype e2.epos in
  748. make_call ctx ef el e.etype e.epos
  749. with Not_found ->
  750. (* quick_field raises Not_found if m is an abstract, we have to replicate the 'using' call here *)
  751. match follow m with
  752. | TAbstract({a_impl = Some c} as a,pl) ->
  753. let cf = PMap.find fname c.cl_statics in
  754. make_static_call ctx c cf a pl (e2 :: el) e.etype e.epos
  755. | _ -> raise Not_found
  756. end
  757. | _ -> raise Not_found
  758. end
  759. | _ ->
  760. raise Not_found
  761. end
  762. with Not_found ->
  763. Type.map_expr (loop ctx) e
  764. end
  765. | _ ->
  766. Type.map_expr (loop ctx) e
  767. in
  768. loop ctx e
  769. end
  770. module PatternMatchConversion = struct
  771. type cctx = {
  772. ctx : typer;
  773. mutable eval_stack : ((tvar * pos) * texpr) list list;
  774. dt_lookup : dt array;
  775. }
  776. let is_declared cctx v =
  777. let rec loop sl = match sl with
  778. | stack :: sl ->
  779. List.exists (fun ((v2,_),_) -> v == v2) stack || loop sl
  780. | [] ->
  781. false
  782. in
  783. loop cctx.eval_stack
  784. let group_cases cases =
  785. let dt_eq dt1 dt2 = match dt1,dt2 with
  786. | DTGoto i1, DTGoto i2 when i1 = i2 -> true
  787. (* TODO equal bindings *)
  788. | _ -> false
  789. in
  790. match List.rev cases with
  791. | [] -> []
  792. | [con,dt] -> [[con],dt]
  793. | (con,dt) :: cases ->
  794. let tmp,ldt,cases = List.fold_left (fun (tmp,ldt,acc) (con,dt) ->
  795. if dt_eq dt ldt then
  796. (con :: tmp,dt,acc)
  797. else
  798. ([con],dt,(tmp,ldt) :: acc)
  799. ) ([con],dt,[]) cases in
  800. match tmp with
  801. | [] -> cases
  802. | tmp -> ((tmp,ldt) :: cases)
  803. let rec convert_dt cctx dt =
  804. match dt with
  805. | DTBind (bl,dt) ->
  806. cctx.eval_stack <- bl :: cctx.eval_stack;
  807. let e = convert_dt cctx dt in
  808. cctx.eval_stack <- List.tl cctx.eval_stack;
  809. let vl,el = List.fold_left (fun (vl,el) ((v,p),e) ->
  810. if is_declared cctx v then
  811. vl, (mk (TBinop(OpAssign,mk (TLocal v) v.v_type p,e)) e.etype e.epos) :: el
  812. else
  813. ((v,Some e) :: vl), el
  814. ) ([],[e]) bl in
  815. let el_v = List.map (fun (v,eo) -> mk (TVar (v,eo)) cctx.ctx.t.tvoid e.epos) vl in
  816. mk (TBlock (el_v @ el)) e.etype e.epos
  817. | DTGoto i ->
  818. convert_dt cctx (cctx.dt_lookup.(i))
  819. | DTExpr e ->
  820. e
  821. | DTGuard(e,dt1,dt2) ->
  822. let ethen = convert_dt cctx dt1 in
  823. mk (TIf(e,ethen,match dt2 with None -> None | Some dt -> Some (convert_dt cctx dt))) ethen.etype (punion e.epos ethen.epos)
  824. | DTSwitch({eexpr = TMeta((Meta.Exhaustive,_,_),_)},[_,dt],None) ->
  825. convert_dt cctx dt
  826. | DTSwitch(e_st,cl,dto) ->
  827. let def = match dto with None -> None | Some dt -> Some (convert_dt cctx dt) in
  828. let cases = group_cases cl in
  829. let cases = List.map (fun (cl,dt) -> cl,convert_dt cctx dt) cases in
  830. mk (TSwitch(e_st,cases,def)) (mk_mono()) e_st.epos
  831. let to_typed_ast ctx dt p =
  832. let first = dt.dt_dt_lookup.(dt.dt_first) in
  833. let cctx = {
  834. ctx = ctx;
  835. dt_lookup = dt.dt_dt_lookup;
  836. eval_stack = [];
  837. } in
  838. let e = convert_dt cctx first in
  839. let e = { e with epos = p; etype = dt.dt_type} in
  840. if dt.dt_var_init = [] then
  841. e
  842. else begin
  843. let el_v = List.map (fun (v,eo) -> mk (TVar (v,eo)) cctx.ctx.t.tvoid p) dt.dt_var_init in
  844. mk (TBlock (el_v @ [e])) dt.dt_type e.epos
  845. end
  846. end
  847. (* -------------------------------------------------------------------------- *)
  848. (* USAGE *)
  849. let detect_usage com =
  850. let usage = ref [] in
  851. List.iter (fun t -> match t with
  852. | TClassDecl c ->
  853. let rec expr e = match e.eexpr with
  854. | TField(_,fa) ->
  855. begin match extract_field fa with
  856. | Some cf when Meta.has Meta.Usage cf.cf_meta ->
  857. let p = {e.epos with pmin = e.epos.pmax - (String.length cf.cf_name)} in
  858. usage := p :: !usage;
  859. | _ ->
  860. ()
  861. end;
  862. Type.iter expr e
  863. | TLocal v when Meta.has Meta.Usage v.v_meta ->
  864. usage := e.epos :: !usage
  865. | _ -> Type.iter expr e
  866. in
  867. let field cf = match cf.cf_expr with None -> () | Some e -> expr e in
  868. (match c.cl_constructor with None -> () | Some cf -> field cf);
  869. (match c.cl_init with None -> () | Some e -> expr e);
  870. List.iter field c.cl_ordered_statics;
  871. List.iter field c.cl_ordered_fields;
  872. | _ -> ()
  873. ) com.types;
  874. let usage = List.sort (fun p1 p2 ->
  875. let c = compare p1.pfile p2.pfile in
  876. if c <> 0 then c else compare p1.pmin p2.pmin
  877. ) !usage in
  878. raise (Typecore.DisplayPosition usage)
  879. let update_cache_dependencies com =
  880. let rec check_t m t = match t with
  881. | TInst(c,tl) ->
  882. add_dependency m c.cl_module;
  883. List.iter (check_t m) tl;
  884. | TEnum(en,tl) ->
  885. add_dependency m en.e_module;
  886. List.iter (check_t m) tl;
  887. | TType(t,tl) ->
  888. add_dependency m t.t_module;
  889. List.iter (check_t m) tl;
  890. | TAbstract(a,tl) ->
  891. add_dependency m a.a_module;
  892. List.iter (check_t m) tl;
  893. | TFun(targs,tret) ->
  894. List.iter (fun (_,_,t) -> check_t m t) targs;
  895. check_t m tret;
  896. | TAnon an ->
  897. PMap.iter (fun _ cf -> check_field m cf) an.a_fields
  898. | TMono r ->
  899. (match !r with
  900. | Some t -> check_t m t
  901. | _ -> ())
  902. | TLazy f ->
  903. check_t m (!f())
  904. | TDynamic t ->
  905. if t == t_dynamic then
  906. ()
  907. else
  908. check_t m t
  909. and check_field m cf =
  910. check_t m cf.cf_type
  911. in
  912. List.iter (fun t -> match t with
  913. | TClassDecl c ->
  914. List.iter (check_field c.cl_module) c.cl_ordered_statics;
  915. List.iter (check_field c.cl_module) c.cl_ordered_fields;
  916. (match c.cl_constructor with None -> () | Some cf -> check_field c.cl_module cf);
  917. | _ ->
  918. ()
  919. ) com.types
  920. (* -------------------------------------------------------------------------- *)
  921. (* STACK MANAGEMENT EMULATION *)
  922. type stack_context = {
  923. stack_var : string;
  924. stack_exc_var : string;
  925. stack_pos_var : string;
  926. stack_pos : pos;
  927. stack_expr : texpr;
  928. stack_pop : texpr;
  929. stack_save_pos : texpr;
  930. stack_restore : texpr list;
  931. stack_push : tclass -> string -> texpr;
  932. stack_return : texpr -> texpr;
  933. }
  934. let stack_context_init com stack_var exc_var pos_var tmp_var use_add p =
  935. let t = com.basic in
  936. let st = t.tarray t.tstring in
  937. let stack_var = alloc_var stack_var st in
  938. let exc_var = alloc_var exc_var st in
  939. let pos_var = alloc_var pos_var t.tint in
  940. let stack_e = mk (TLocal stack_var) st p in
  941. let exc_e = mk (TLocal exc_var) st p in
  942. let stack_pop = fcall stack_e "pop" [] t.tstring p in
  943. let stack_push c m =
  944. fcall stack_e "push" [
  945. if use_add then
  946. binop OpAdd (string com (s_type_path c.cl_path ^ "::") p) (string com m p) t.tstring p
  947. else
  948. string com (s_type_path c.cl_path ^ "::" ^ m) p
  949. ] t.tvoid p
  950. in
  951. let stack_return e =
  952. let tmp = alloc_var tmp_var e.etype in
  953. mk (TBlock [
  954. mk (TVar (tmp, Some e)) t.tvoid e.epos;
  955. stack_pop;
  956. mk (TReturn (Some (mk (TLocal tmp) e.etype e.epos))) e.etype e.epos
  957. ]) e.etype e.epos
  958. in
  959. {
  960. stack_var = stack_var.v_name;
  961. stack_exc_var = exc_var.v_name;
  962. stack_pos_var = pos_var.v_name;
  963. stack_pos = p;
  964. stack_expr = stack_e;
  965. stack_pop = stack_pop;
  966. stack_save_pos = mk (TVar (pos_var, Some (field stack_e "length" t.tint p))) t.tvoid p;
  967. stack_push = stack_push;
  968. stack_return = stack_return;
  969. stack_restore = [
  970. binop OpAssign exc_e (mk (TArrayDecl []) st p) st p;
  971. mk (TWhile (
  972. mk_parent (binop OpGte (field stack_e "length" t.tint p) (mk (TLocal pos_var) t.tint p) t.tbool p),
  973. fcall exc_e "unshift" [fcall stack_e "pop" [] t.tstring p] t.tvoid p,
  974. NormalWhile
  975. )) t.tvoid p;
  976. fcall stack_e "push" [index com exc_e 0 t.tstring p] t.tvoid p
  977. ];
  978. }
  979. let stack_init com use_add =
  980. stack_context_init com "$s" "$e" "$spos" "$tmp" use_add null_pos
  981. let rec stack_block_loop ctx e =
  982. match e.eexpr with
  983. | TFunction _ ->
  984. e
  985. | TReturn None | TReturn (Some { eexpr = TConst _ }) | TReturn (Some { eexpr = TLocal _ }) ->
  986. mk (TBlock [
  987. ctx.stack_pop;
  988. e;
  989. ]) e.etype e.epos
  990. | TReturn (Some e) ->
  991. ctx.stack_return (stack_block_loop ctx e)
  992. | TTry (v,cases) ->
  993. let v = stack_block_loop ctx v in
  994. let cases = List.map (fun (v,e) ->
  995. let e = stack_block_loop ctx e in
  996. let e = (match (mk_block e).eexpr with
  997. | TBlock l -> mk (TBlock (ctx.stack_restore @ l)) e.etype e.epos
  998. | _ -> assert false
  999. ) in
  1000. v , e
  1001. ) cases in
  1002. mk (TTry (v,cases)) e.etype e.epos
  1003. | _ ->
  1004. map_expr (stack_block_loop ctx) e
  1005. let stack_block ctx c m e =
  1006. match (mk_block e).eexpr with
  1007. | TBlock l ->
  1008. mk (TBlock (
  1009. ctx.stack_push c m ::
  1010. ctx.stack_save_pos ::
  1011. List.map (stack_block_loop ctx) l
  1012. @ [ctx.stack_pop]
  1013. )) e.etype e.epos
  1014. | _ ->
  1015. assert false
  1016. (* -------------------------------------------------------------------------- *)
  1017. (* FIX OVERRIDES *)
  1018. (*
  1019. on some platforms which doesn't support type parameters, we must have the
  1020. exact same type for overriden/implemented function as the original one
  1021. *)
  1022. let rec find_field c f =
  1023. try
  1024. (match c.cl_super with
  1025. | None ->
  1026. raise Not_found
  1027. | Some ( {cl_path = (["cpp"],"FastIterator")}, _ ) ->
  1028. raise Not_found (* This is a strongly typed 'extern' and the usual rules don't apply *)
  1029. | Some (c,_) ->
  1030. find_field c f)
  1031. with Not_found -> try
  1032. let rec loop = function
  1033. | [] ->
  1034. raise Not_found
  1035. | (c,_) :: l ->
  1036. try
  1037. find_field c f
  1038. with
  1039. Not_found -> loop l
  1040. in
  1041. loop c.cl_implements
  1042. with Not_found ->
  1043. let f = PMap.find f.cf_name c.cl_fields in
  1044. (match f.cf_kind with Var { v_read = AccRequire _ } -> raise Not_found | _ -> ());
  1045. f
  1046. let fix_override com c f fd =
  1047. let f2 = (try Some (find_field c f) with Not_found -> None) in
  1048. match f2,fd with
  1049. | Some (f2), Some(fd) ->
  1050. let targs, tret = (match follow f2.cf_type with TFun (args,ret) -> args, ret | _ -> assert false) in
  1051. let changed_args = ref [] in
  1052. let prefix = "_tmp_" in
  1053. let nargs = List.map2 (fun ((v,ct) as cur) (_,_,t2) ->
  1054. try
  1055. type_eq EqStrict (monomorphs c.cl_types (monomorphs f.cf_params v.v_type)) t2;
  1056. (* Flash generates type parameters with a single constraint as that constraint type, so we
  1057. have to detect this case and change the variable (issue #2712). *)
  1058. begin match follow v.v_type with
  1059. | TInst({cl_kind = KTypeParameter [tc]} as cp,_) when com.platform = Flash ->
  1060. if List.mem_assoc (snd cp.cl_path) c.cl_types then raise (Unify_error [])
  1061. | _ ->
  1062. ()
  1063. end;
  1064. cur
  1065. with Unify_error _ ->
  1066. let v2 = alloc_var (prefix ^ v.v_name) t2 in
  1067. changed_args := (v,v2) :: !changed_args;
  1068. v2,ct
  1069. ) fd.tf_args targs in
  1070. let fd2 = {
  1071. tf_args = nargs;
  1072. tf_type = tret;
  1073. tf_expr = (match List.rev !changed_args with
  1074. | [] -> fd.tf_expr
  1075. | args ->
  1076. let e = fd.tf_expr in
  1077. let el = (match e.eexpr with TBlock el -> el | _ -> [e]) in
  1078. let p = (match el with [] -> e.epos | e :: _ -> e.epos) in
  1079. let el_v = List.map (fun (v,v2) ->
  1080. mk (TVar (v,Some (mk (TCast (mk (TLocal v2) v2.v_type p,None)) v.v_type p))) com.basic.tvoid p
  1081. ) args in
  1082. { e with eexpr = TBlock (el_v @ el) }
  1083. );
  1084. } in
  1085. (* as3 does not allow wider visibility, so the base method has to be made public *)
  1086. if Common.defined com Define.As3 && f.cf_public then f2.cf_public <- true;
  1087. let targs = List.map (fun(v,c) -> (v.v_name, Option.is_some c, v.v_type)) nargs in
  1088. let fde = (match f.cf_expr with None -> assert false | Some e -> e) in
  1089. f.cf_expr <- Some { fde with eexpr = TFunction fd2 };
  1090. f.cf_type <- TFun(targs,tret);
  1091. | Some(f2), None when c.cl_interface ->
  1092. let targs, tret = (match follow f2.cf_type with TFun (args,ret) -> args, ret | _ -> assert false) in
  1093. f.cf_type <- TFun(targs,tret)
  1094. | _ ->
  1095. ()
  1096. let fix_overrides com t =
  1097. match t with
  1098. | TClassDecl c ->
  1099. (* overrides can be removed from interfaces *)
  1100. if c.cl_interface then
  1101. c.cl_ordered_fields <- List.filter (fun f ->
  1102. try
  1103. if find_field c f == f then raise Not_found;
  1104. c.cl_fields <- PMap.remove f.cf_name c.cl_fields;
  1105. false;
  1106. with Not_found ->
  1107. true
  1108. ) c.cl_ordered_fields;
  1109. List.iter (fun f ->
  1110. match f.cf_expr, f.cf_kind with
  1111. | Some { eexpr = TFunction fd }, Method (MethNormal | MethInline) ->
  1112. fix_override com c f (Some fd)
  1113. | None, Method (MethNormal | MethInline) when c.cl_interface ->
  1114. fix_override com c f None
  1115. | _ ->
  1116. ()
  1117. ) c.cl_ordered_fields
  1118. | _ ->
  1119. ()
  1120. (*
  1121. PHP does not allow abstract classes extending other abstract classes to override any fields, so these duplicates
  1122. must be removed from the child interface
  1123. *)
  1124. let fix_abstract_inheritance com t =
  1125. match t with
  1126. | TClassDecl c when c.cl_interface ->
  1127. c.cl_ordered_fields <- List.filter (fun f ->
  1128. let b = try (find_field c f) == f
  1129. with Not_found -> false in
  1130. if not b then c.cl_fields <- PMap.remove f.cf_name c.cl_fields;
  1131. b;
  1132. ) c.cl_ordered_fields
  1133. | _ -> ()
  1134. (* -------------------------------------------------------------------------- *)
  1135. (* MISC FEATURES *)
  1136. let rec is_volatile t =
  1137. match t with
  1138. | TMono r ->
  1139. (match !r with
  1140. | Some t -> is_volatile t
  1141. | _ -> false)
  1142. | TLazy f ->
  1143. is_volatile (!f())
  1144. | TType (t,tl) ->
  1145. (match t.t_path with
  1146. | ["mt";"flash"],"Volatile" -> true
  1147. | _ -> is_volatile (apply_params t.t_types tl t.t_type))
  1148. | _ ->
  1149. false
  1150. let set_default ctx a c p =
  1151. let t = a.v_type in
  1152. let ve = mk (TLocal a) t p in
  1153. let cond = TBinop (OpEq,ve,mk (TConst TNull) t p) in
  1154. 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
  1155. let bytes_serialize data =
  1156. let b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" in
  1157. let tbl = Array.init (String.length b64) (fun i -> String.get b64 i) in
  1158. Base64.str_encode ~tbl data
  1159. (*
  1160. Tells if the constructor might be called without any issue whatever its parameters
  1161. *)
  1162. let rec constructor_side_effects e =
  1163. match e.eexpr with
  1164. | TBinop (op,_,_) when op <> OpAssign ->
  1165. true
  1166. | TField (_,FEnum _) ->
  1167. false
  1168. | TUnop _ | TArray _ | TField _ | TEnumParameter _ | TCall _ | TNew _ | TFor _ | TWhile _ | TSwitch _ | TPatMatch _ | TReturn _ | TThrow _ ->
  1169. true
  1170. | TBinop _ | TTry _ | TIf _ | TBlock _ | TVar _
  1171. | TFunction _ | TArrayDecl _ | TObjectDecl _
  1172. | TParenthesis _ | TTypeExpr _ | TLocal _ | TMeta _
  1173. | TConst _ | TContinue | TBreak | TCast _ ->
  1174. try
  1175. Type.iter (fun e -> if constructor_side_effects e then raise Exit) e;
  1176. false;
  1177. with Exit ->
  1178. true
  1179. (*
  1180. Make a dump of the full typed AST of all types
  1181. *)
  1182. let rec create_dumpfile acc = function
  1183. | [] -> assert false
  1184. | d :: [] ->
  1185. let ch = open_out (String.concat "/" (List.rev (d :: acc)) ^ ".dump") in
  1186. let buf = Buffer.create 0 in
  1187. buf, (fun () ->
  1188. output_string ch (Buffer.contents buf);
  1189. close_out ch)
  1190. | d :: l ->
  1191. let dir = String.concat "/" (List.rev (d :: acc)) in
  1192. if not (Sys.file_exists dir) then Unix.mkdir dir 0o755;
  1193. create_dumpfile (d :: acc) l
  1194. let dump_types com =
  1195. let s_type = s_type (Type.print_context()) in
  1196. let params = function [] -> "" | l -> Printf.sprintf "<%s>" (String.concat "," (List.map (fun (n,t) -> n ^ " : " ^ s_type t) l)) in
  1197. 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
  1198. List.iter (fun mt ->
  1199. let path = Type.t_path mt in
  1200. let buf,close = create_dumpfile [] ("dump" :: (Common.platform_name com.platform) :: fst path @ [snd path]) in
  1201. let print fmt = Printf.kprintf (fun s -> Buffer.add_string buf s) fmt in
  1202. (match mt with
  1203. | Type.TClassDecl c ->
  1204. let rec print_field stat f =
  1205. 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);
  1206. print "(%s) : %s" (s_kind f.cf_kind) (s_type f.cf_type);
  1207. (match f.cf_expr with
  1208. | None -> ()
  1209. | Some e -> print "\n\n\t = %s" (s_expr s_type e));
  1210. print ";\n\n";
  1211. List.iter (fun f -> print_field stat f) f.cf_overloads
  1212. in
  1213. 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);
  1214. (match c.cl_super with None -> () | Some (c,pl) -> print " extends %s" (s_type (TInst (c,pl))));
  1215. List.iter (fun (c,pl) -> print " implements %s" (s_type (TInst (c,pl)))) c.cl_implements;
  1216. (match c.cl_dynamic with None -> () | Some t -> print " implements Dynamic<%s>" (s_type t));
  1217. (match c.cl_array_access with None -> () | Some t -> print " implements ArrayAccess<%s>" (s_type t));
  1218. print "{\n";
  1219. (match c.cl_constructor with
  1220. | None -> ()
  1221. | Some f -> print_field false f);
  1222. List.iter (print_field false) c.cl_ordered_fields;
  1223. List.iter (print_field true) c.cl_ordered_statics;
  1224. print "}";
  1225. | Type.TEnumDecl e ->
  1226. 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);
  1227. List.iter (fun n ->
  1228. let f = PMap.find n e.e_constrs in
  1229. print "\t%s : %s;\n" f.ef_name (s_type f.ef_type);
  1230. ) e.e_names;
  1231. print "}"
  1232. | Type.TTypeDecl t ->
  1233. 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);
  1234. | Type.TAbstractDecl a ->
  1235. print "%sabstract %s%s {}" (if a.a_private then "private " else "") (s_type_path path) (params a.a_types);
  1236. );
  1237. close();
  1238. ) com.types
  1239. let dump_dependencies com =
  1240. let buf,close = create_dumpfile [] ["dump";Common.platform_name com.platform;".dependencies"] in
  1241. let print fmt = Printf.kprintf (fun s -> Buffer.add_string buf s) fmt in
  1242. let dep = Hashtbl.create 0 in
  1243. List.iter (fun m ->
  1244. print "%s:\n" m.m_extra.m_file;
  1245. PMap.iter (fun _ m2 ->
  1246. print "\t%s\n" (m2.m_extra.m_file);
  1247. let l = try Hashtbl.find dep m2.m_extra.m_file with Not_found -> [] in
  1248. Hashtbl.replace dep m2.m_extra.m_file (m :: l)
  1249. ) m.m_extra.m_deps;
  1250. ) com.Common.modules;
  1251. close();
  1252. let buf,close = create_dumpfile [] ["dump";Common.platform_name com.platform;".dependants"] in
  1253. let print fmt = Printf.kprintf (fun s -> Buffer.add_string buf s) fmt in
  1254. Hashtbl.iter (fun n ml ->
  1255. print "%s:\n" n;
  1256. List.iter (fun m ->
  1257. print "\t%s\n" (m.m_extra.m_file);
  1258. ) ml;
  1259. ) dep;
  1260. close()
  1261. (*
  1262. Build a default safe-cast expression :
  1263. { var $t = <e>; if( Std.is($t,<t>) ) $t else throw "Class cast error"; }
  1264. *)
  1265. let default_cast ?(vtmp="$t") com e texpr t p =
  1266. let api = com.basic in
  1267. let mk_texpr = function
  1268. | TClassDecl c -> TAnon { a_fields = PMap.empty; a_status = ref (Statics c) }
  1269. | TEnumDecl e -> TAnon { a_fields = PMap.empty; a_status = ref (EnumStatics e) }
  1270. | TAbstractDecl a -> TAnon { a_fields = PMap.empty; a_status = ref (AbstractStatics a) }
  1271. | TTypeDecl _ -> assert false
  1272. in
  1273. let vtmp = alloc_var vtmp e.etype in
  1274. let var = mk (TVar (vtmp,Some e)) api.tvoid p in
  1275. let vexpr = mk (TLocal vtmp) e.etype p in
  1276. let texpr = mk (TTypeExpr texpr) (mk_texpr texpr) p in
  1277. let std = (try List.find (fun t -> t_path t = ([],"Std")) com.types with Not_found -> assert false) in
  1278. let fis = (try
  1279. let c = (match std with TClassDecl c -> c | _ -> assert false) in
  1280. FStatic (c, PMap.find "is" c.cl_statics)
  1281. with Not_found ->
  1282. assert false
  1283. ) in
  1284. let std = mk (TTypeExpr std) (mk_texpr std) p in
  1285. let is = mk (TField (std,fis)) (tfun [t_dynamic;t_dynamic] api.tbool) p in
  1286. let is = mk (TCall (is,[vexpr;texpr])) api.tbool p in
  1287. let exc = mk (TThrow (mk (TConst (TString "Class cast error")) api.tstring p)) t p in
  1288. let check = mk (TIf (mk_parent is,mk (TCast (vexpr,None)) t p,Some exc)) t p in
  1289. mk (TBlock [var;check;vexpr]) t p
  1290. (** Overload resolution **)
  1291. module Overloads =
  1292. struct
  1293. let rec simplify_t t = match t with
  1294. | TInst _ | TEnum _ | TAbstract({ a_impl = None }, _) ->
  1295. t
  1296. | TAbstract(a,tl) -> simplify_t (Abstract.get_underlying_type a tl)
  1297. | TType(({ t_path = [],"Null" } as t), [t2]) -> (match simplify_t t2 with
  1298. | (TAbstract({ a_impl = None }, _) | TEnum _ as t2) -> TType(t, [simplify_t t2])
  1299. | t2 -> t2)
  1300. | TType(t, tl) ->
  1301. simplify_t (apply_params t.t_types tl t.t_type)
  1302. | TMono r -> (match !r with
  1303. | Some t -> simplify_t t
  1304. | None -> t_dynamic)
  1305. | TAnon _ -> t_dynamic
  1306. | TDynamic _ -> t
  1307. | TLazy f -> simplify_t (!f())
  1308. | TFun _ -> t
  1309. (* rate type parameters *)
  1310. let rate_tp tlfun tlarg =
  1311. let acc = ref 0 in
  1312. List.iter2 (fun f a -> if not (type_iseq f a) then incr acc) tlfun tlarg;
  1313. !acc
  1314. let rec rate_conv cacc tfun targ =
  1315. match simplify_t tfun, simplify_t targ with
  1316. | TInst({ cl_interface = true } as cf, tlf), TInst(ca, tla) ->
  1317. (* breadth-first *)
  1318. let stack = ref [0,ca,tla] in
  1319. let cur = ref (0, ca,tla) in
  1320. let rec loop () =
  1321. match !stack with
  1322. | [] -> (let acc, ca, tla = !cur in match ca.cl_super with
  1323. | None -> raise Not_found
  1324. | Some (sup,tls) ->
  1325. cur := (acc+1,sup,List.map (apply_params ca.cl_types tla) tls);
  1326. stack := [!cur];
  1327. loop())
  1328. | (acc,ca,tla) :: _ when ca == cf ->
  1329. acc,tla
  1330. | (acc,ca,tla) :: s ->
  1331. stack := s @ List.map (fun (c,tl) -> (acc+1,c,List.map (apply_params ca.cl_types tla) tl)) ca.cl_implements;
  1332. loop()
  1333. in
  1334. let acc, tla = loop() in
  1335. (cacc + acc, rate_tp tlf tla)
  1336. | TInst(cf,tlf), TInst(ca,tla) ->
  1337. let rec loop acc ca tla =
  1338. if cf == ca then
  1339. acc, tla
  1340. else match ca.cl_super with
  1341. | None -> raise Not_found
  1342. | Some(sup,stl) ->
  1343. loop (acc+1) sup (List.map (apply_params ca.cl_types tla) stl)
  1344. in
  1345. let acc, tla = loop 0 ca tla in
  1346. (cacc + acc, rate_tp tlf tla)
  1347. | TEnum(ef,tlf), TEnum(ea, tla) ->
  1348. if ef != ea then raise Not_found;
  1349. (cacc, rate_tp tlf tla)
  1350. | TDynamic _, TDynamic _ ->
  1351. (cacc, 0)
  1352. | TDynamic _, _ ->
  1353. (max_int, 0) (* a function with dynamic will always be worst of all *)
  1354. | TAbstract({ a_impl = None }, _), TDynamic _ ->
  1355. (cacc + 2, 0) (* a dynamic to a basic type will have an "unboxing" penalty *)
  1356. | _, TDynamic _ ->
  1357. (cacc + 1, 0)
  1358. | TAbstract(af,tlf), TAbstract(aa,tla) ->
  1359. (if af == aa then
  1360. (cacc, rate_tp tlf tla)
  1361. else
  1362. let ret = ref None in
  1363. if List.exists (fun (t,_) -> try
  1364. ret := Some (rate_conv (cacc+1) (apply_params af.a_types tlf t) targ);
  1365. true
  1366. with | Not_found ->
  1367. false
  1368. ) af.a_from then
  1369. Option.get !ret
  1370. else
  1371. if List.exists (fun (t,_) -> try
  1372. ret := Some (rate_conv (cacc+1) tfun (apply_params aa.a_types tla t));
  1373. true
  1374. with | Not_found ->
  1375. false
  1376. ) aa.a_to then
  1377. Option.get !ret
  1378. else
  1379. raise Not_found)
  1380. | TType({ t_path = [], "Null" }, [tf]), TType({ t_path = [], "Null" }, [ta]) ->
  1381. rate_conv (cacc+0) tf ta
  1382. | TType({ t_path = [], "Null" }, [tf]), ta ->
  1383. rate_conv (cacc+1) tf ta
  1384. | tf, TType({ t_path = [], "Null" }, [ta]) ->
  1385. rate_conv (cacc+1) tf ta
  1386. | TFun _, TFun _ -> (* unify will make sure they are compatible *)
  1387. cacc,0
  1388. | tfun,targ ->
  1389. raise Not_found
  1390. let is_best arg1 arg2 =
  1391. (List.for_all2 (fun v1 v2 ->
  1392. v1 <= v2)
  1393. arg1 arg2) && (List.exists2 (fun v1 v2 ->
  1394. v1 < v2)
  1395. arg1 arg2)
  1396. let rec rm_duplicates acc ret = match ret with
  1397. | [] -> acc
  1398. | ( el, t ) :: ret when List.exists (fun (_,t2) -> type_iseq t t2) acc ->
  1399. rm_duplicates acc ret
  1400. | r :: ret ->
  1401. rm_duplicates (r :: acc) ret
  1402. let s_options rated =
  1403. String.concat ",\n" (List.map (fun ((_,t),rate) ->
  1404. "( " ^ (String.concat "," (List.map (fun (i,i2) -> string_of_int i ^ ":" ^ string_of_int i2) rate)) ^ " ) => " ^ (s_type (print_context()) t)
  1405. ) rated)
  1406. let count_optionals elist =
  1407. List.fold_left (fun acc (_,is_optional) -> if is_optional then acc + 1 else acc) 0 elist
  1408. let rec fewer_optionals acc compatible = match acc, compatible with
  1409. | _, [] -> acc
  1410. | [], c :: comp -> fewer_optionals [c] comp
  1411. | (elist_acc, _) :: _, ((elist, _) as cur) :: comp ->
  1412. let acc_opt = count_optionals elist_acc in
  1413. let comp_opt = count_optionals elist in
  1414. if acc_opt = comp_opt then
  1415. fewer_optionals (cur :: acc) comp
  1416. else if acc_opt < comp_opt then
  1417. fewer_optionals acc comp
  1418. else
  1419. fewer_optionals [cur] comp
  1420. let reduce_compatible compatible = match fewer_optionals [] (rm_duplicates [] compatible) with
  1421. | [] -> [] | [v] -> [v]
  1422. | compatible ->
  1423. (* convert compatible into ( rate * compatible_type ) list *)
  1424. let rec mk_rate acc elist args = match elist, args with
  1425. | [], [] -> acc
  1426. | (_,true) :: elist, _ :: args -> mk_rate acc elist args
  1427. | (e,false) :: elist, (n,o,t) :: args ->
  1428. mk_rate (rate_conv 0 t e.etype :: acc) elist args
  1429. | _ -> assert false
  1430. in
  1431. let rated = ref [] in
  1432. List.iter (function
  1433. | (elist,TFun(args,ret)) -> (try
  1434. rated := ( (elist,TFun(args,ret)), mk_rate [] elist args ) :: !rated
  1435. with | Not_found -> ())
  1436. | _ -> assert false
  1437. ) compatible;
  1438. let rec loop best rem = match best, rem with
  1439. | _, [] -> best
  1440. | [], r1 :: rem -> loop [r1] rem
  1441. | (bover, bargs) :: b1, (rover, rargs) :: rem ->
  1442. if is_best bargs rargs then
  1443. loop best rem
  1444. else if is_best rargs bargs then
  1445. loop (loop b1 [rover,rargs]) rem
  1446. else (* equally specific *)
  1447. loop ( (rover,rargs) :: best ) rem
  1448. in
  1449. List.map fst (loop [] !rated)
  1450. end;;
  1451. module UnificationCallback = struct
  1452. let tf_stack = ref []
  1453. let check_call_params f el tl =
  1454. let rec loop acc el tl = match el,tl with
  1455. | e :: el, (n,_,t) :: tl ->
  1456. loop ((f e t) :: acc) el tl
  1457. | [], [] ->
  1458. acc
  1459. | [],_ ->
  1460. acc
  1461. | e :: el, [] ->
  1462. loop (e :: acc) el []
  1463. in
  1464. List.rev (loop [] el tl)
  1465. let check_call f el t = match follow t with
  1466. | TFun(args,_) ->
  1467. check_call_params f el args
  1468. | _ ->
  1469. el
  1470. let rec run f e =
  1471. let f e t =
  1472. (* TODO: I don't think this should cause errors on Flash target *)
  1473. (* if not (type_iseq e.etype t) then f e t else e *)
  1474. f e t
  1475. in
  1476. let check e = match e.eexpr with
  1477. | TBinop((OpAssign | OpAssignOp _ as op),e1,e2) ->
  1478. let e2 = f e2 e1.etype in
  1479. {e with eexpr = TBinop(op,e1,e2)}
  1480. | TVar(v,Some e) ->
  1481. let eo = Some (f e v.v_type) in
  1482. { e with eexpr = TVar(v,eo) }
  1483. | TCall(e1,el) ->
  1484. let el = check_call f el e1.etype in
  1485. {e with eexpr = TCall(e1,el)}
  1486. | TNew(c,tl,el) ->
  1487. begin try
  1488. let tcf,_ = get_constructor (fun cf -> apply_params c.cl_types tl cf.cf_type) c in
  1489. let el = check_call f el tcf in
  1490. {e with eexpr = TNew(c,tl,el)}
  1491. with Not_found ->
  1492. e
  1493. end
  1494. | TArrayDecl el ->
  1495. begin match follow e.etype with
  1496. | TInst({cl_path=[],"Array"},[t]) -> {e with eexpr = TArrayDecl(List.map (fun e -> f e t) el)}
  1497. | _ -> e
  1498. end
  1499. | TObjectDecl fl ->
  1500. begin match follow e.etype with
  1501. | TAnon an ->
  1502. let fl = List.map (fun (n,e) ->
  1503. let e = try
  1504. let t = (PMap.find n an.a_fields).cf_type in
  1505. f e t
  1506. with Not_found ->
  1507. e
  1508. in
  1509. n,e
  1510. ) fl in
  1511. { e with eexpr = TObjectDecl fl }
  1512. | _ -> e
  1513. end
  1514. | TReturn (Some e1) ->
  1515. begin match !tf_stack with
  1516. | tf :: _ -> { e with eexpr = TReturn (Some (f e1 tf.tf_type))}
  1517. | _ -> e
  1518. end
  1519. | _ ->
  1520. e
  1521. in
  1522. match e.eexpr with
  1523. | TFunction tf ->
  1524. tf_stack := tf :: !tf_stack;
  1525. let etf = {e with eexpr = TFunction({tf with tf_expr = run f tf.tf_expr})} in
  1526. tf_stack := List.tl !tf_stack;
  1527. etf
  1528. | _ ->
  1529. check (Type.map_expr (run f) e)
  1530. end;;
  1531. module DeprecationCheck = struct
  1532. let curclass = ref null_class
  1533. let warned_positions = Hashtbl.create 0
  1534. let print_deprecation_message com meta s p_usage =
  1535. let s = match meta with
  1536. | _,[EConst(String s),_],_ -> s
  1537. | _ -> Printf.sprintf "Usage of this %s is deprecated" s
  1538. in
  1539. if not (Hashtbl.mem warned_positions p_usage) then begin
  1540. Hashtbl.replace warned_positions p_usage true;
  1541. com.warning s p_usage;
  1542. end
  1543. let check_meta com meta s p_usage =
  1544. try
  1545. print_deprecation_message com (Meta.get Meta.Deprecated meta) s p_usage;
  1546. with Not_found ->
  1547. ()
  1548. let check_cf com cf p = check_meta com cf.cf_meta "field" p
  1549. let check_class com c p = if c != !curclass then check_meta com c.cl_meta "class" p
  1550. let check_enum com en p = check_meta com en.e_meta "enum" p
  1551. let check_ef com ef p = check_meta com ef.ef_meta "enum field" p
  1552. let check_typedef com t p = check_meta com t.t_meta "typedef" p
  1553. let check_module_type com mt p = match mt with
  1554. | TClassDecl c -> check_class com c p
  1555. | TEnumDecl en -> check_enum com en p
  1556. | _ -> ()
  1557. let run com =
  1558. let rec expr e = match e.eexpr with
  1559. | TField(e1,fa) ->
  1560. expr e1;
  1561. begin match fa with
  1562. | FStatic(c,cf) | FInstance(c,cf) ->
  1563. check_class com c e.epos;
  1564. check_cf com cf e.epos
  1565. | FAnon cf ->
  1566. check_cf com cf e.epos
  1567. | FClosure(co,cf) ->
  1568. (match co with None -> () | Some c -> check_class com c e.epos);
  1569. check_cf com cf e.epos
  1570. | FEnum(en,ef) ->
  1571. check_enum com en e.epos;
  1572. check_ef com ef e.epos;
  1573. | _ ->
  1574. ()
  1575. end
  1576. | TNew(c,_,el) ->
  1577. List.iter expr el;
  1578. check_class com c e.epos;
  1579. (match c.cl_constructor with None -> () | Some cf -> check_cf com cf e.epos)
  1580. | TTypeExpr(mt) | TCast(_,Some mt) ->
  1581. check_module_type com mt e.epos
  1582. | TMeta((Meta.Deprecated,_,_) as meta,e1) ->
  1583. print_deprecation_message com meta "field" e1.epos;
  1584. expr e1;
  1585. | _ ->
  1586. Type.iter expr e
  1587. in
  1588. List.iter (fun t -> match t with
  1589. | TClassDecl c ->
  1590. curclass := c;
  1591. let field cf = match cf.cf_expr with None -> () | Some e -> expr e in
  1592. (match c.cl_constructor with None -> () | Some cf -> field cf);
  1593. (match c.cl_init with None -> () | Some e -> expr e);
  1594. List.iter field c.cl_ordered_statics;
  1595. List.iter field c.cl_ordered_fields;
  1596. | _ ->
  1597. ()
  1598. ) com.types
  1599. end