codegen.ml 69 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078
  1. (*
  2. The Haxe Compiler
  3. Copyright (C) 2005-2016 Haxe Foundation
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  15. *)
  16. open Ast
  17. open Type
  18. open Common
  19. open Typecore
  20. (* -------------------------------------------------------------------------- *)
  21. (* TOOLS *)
  22. let field e name t p =
  23. mk (TField (e,try quick_field e.etype name with Not_found -> assert false)) t p
  24. let fcall e name el ret p =
  25. let ft = tfun (List.map (fun e -> e.etype) el) ret in
  26. mk (TCall (field e name ft p,el)) ret p
  27. let mk_parent e =
  28. mk (TParenthesis e) e.etype e.epos
  29. let string com str p =
  30. mk (TConst (TString str)) com.basic.tstring p
  31. let binop op a b t p =
  32. mk (TBinop (op,a,b)) t p
  33. let index com e index t p =
  34. mk (TArray (e,mk (TConst (TInt (Int32.of_int index))) com.basic.tint p)) t p
  35. let maybe_cast e t =
  36. try
  37. type_eq EqDoNotFollowNull e.etype t;
  38. e
  39. with
  40. Unify_error _ -> mk (TCast(e,None)) t e.epos
  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. let is_removable_field ctx f =
  104. Meta.has Meta.Extern f.cf_meta || Meta.has Meta.Generic f.cf_meta
  105. || (match f.cf_kind with
  106. | Var {v_read = AccRequire (s,_)} -> true
  107. | Method MethMacro -> not ctx.in_macro
  108. | _ -> false)
  109. let escape_res_name name allow_dirs =
  110. ExtString.String.replace_chars (fun chr ->
  111. if (chr >= 'a' && chr <= 'z') || (chr >= 'A' && chr <= 'Z') || (chr >= '0' && chr <= '9') || chr = '_' || chr = '.' then
  112. Char.escaped chr
  113. else if chr = '/' && allow_dirs then
  114. "/"
  115. else
  116. "-x" ^ (string_of_int (Char.code chr))) name
  117. (* -------------------------------------------------------------------------- *)
  118. (* REMOTING PROXYS *)
  119. let extend_remoting ctx c t p async prot =
  120. if c.cl_super <> None then error "Cannot extend several classes" p;
  121. (* remove forbidden packages *)
  122. let rules = ctx.com.package_rules in
  123. ctx.com.package_rules <- PMap.foldi (fun key r acc -> match r with Forbidden -> acc | _ -> PMap.add key r acc) rules PMap.empty;
  124. (* parse module *)
  125. let path = (t.tpackage,t.tname) in
  126. let new_name = (if async then "Async_" else "Remoting_") ^ t.tname in
  127. (* check if the proxy already exists *)
  128. let t = (try
  129. Typeload.load_type_def ctx p { tpackage = fst path; tname = new_name; tparams = []; tsub = None }
  130. with
  131. Error (Module_not_found _,p2) when p == p2 ->
  132. (* build it *)
  133. Common.log ctx.com ("Building proxy for " ^ s_type_path path);
  134. let file, decls = (try
  135. Typeload.parse_module ctx path p
  136. with
  137. | 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
  138. | e -> ctx.com.package_rules <- rules; raise e) in
  139. ctx.com.package_rules <- rules;
  140. let base_fields = [
  141. { 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) };
  142. { 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 = [] } };
  143. ] in
  144. let tvoid = CTPath { tpackage = []; tname = "Void"; tparams = []; tsub = None } in
  145. let build_field is_public acc f =
  146. if f.cff_name = "new" then
  147. acc
  148. else match f.cff_kind with
  149. | FFun fd when (is_public || List.mem APublic f.cff_access) && not (List.mem AStatic f.cff_access) ->
  150. 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;
  151. let eargs = [EArrayDecl (List.map (fun (a,_,_,_) -> (EConst (Ident a),p)) fd.f_args),p] in
  152. let ftype = (match fd.f_type with Some (CTPath { tpackage = []; tname = "Void" }) -> None | _ -> fd.f_type) in
  153. let fargs, eargs = if async then match ftype with
  154. | Some tret -> fd.f_args @ ["__callb",true,Some (CTFunction ([tret],tvoid)),None], eargs @ [EConst (Ident "__callb"),p]
  155. | _ -> fd.f_args, eargs @ [EConst (Ident "null"),p]
  156. else
  157. fd.f_args, eargs
  158. in
  159. let id = (EConst (String f.cff_name), p) in
  160. let id = if prot then id else ECall ((EConst (Ident "__unprotect__"),p),[id]),p in
  161. let expr = ECall (
  162. (EField (
  163. (ECall ((EField ((EConst (Ident "__cnx"),p),"resolve"),p),[id]),p),
  164. "call")
  165. ,p),eargs),p
  166. in
  167. let expr = if async || ftype = None then expr else (EReturn (Some expr),p) in
  168. let fd = {
  169. f_params = fd.f_params;
  170. f_args = fargs;
  171. f_type = if async then None else ftype;
  172. f_expr = Some (EBlock [expr],p);
  173. } in
  174. { cff_name = f.cff_name; cff_pos = f.cff_pos; cff_doc = None; cff_meta = []; cff_access = [APublic]; cff_kind = FFun fd } :: acc
  175. | _ -> acc
  176. in
  177. let decls = List.map (fun d ->
  178. match d with
  179. | EClass c, p when c.d_name = t.tname ->
  180. let is_public = List.mem HExtern c.d_flags || List.mem HInterface c.d_flags in
  181. let fields = List.rev (List.fold_left (build_field is_public) base_fields c.d_data) in
  182. (EClass { c with d_flags = []; d_name = new_name; d_data = fields },p)
  183. | _ -> d
  184. ) decls in
  185. let m = Typeload.type_module ctx (t.tpackage,new_name) file decls p in
  186. add_dependency ctx.m.curmod m;
  187. try
  188. List.find (fun tdecl -> snd (t_path tdecl) = new_name) m.m_types
  189. with Not_found ->
  190. error ("Module " ^ s_type_path path ^ " does not define type " ^ t.tname) p
  191. ) in
  192. match t with
  193. | TClassDecl c2 when c2.cl_params = [] -> ignore(c2.cl_build()); c.cl_super <- Some (c2,[]);
  194. | _ -> error "Remoting proxy must be a class without parameters" p
  195. (* -------------------------------------------------------------------------- *)
  196. (* HAXE.RTTI.GENERIC *)
  197. exception Generic_Exception of string * Ast.pos
  198. type generic_context = {
  199. ctx : typer;
  200. subst : (t * t) list;
  201. name : string;
  202. p : pos;
  203. mutable mg : module_def option;
  204. }
  205. let make_generic ctx ps pt p =
  206. let rec loop l1 l2 =
  207. match l1, l2 with
  208. | [] , [] -> []
  209. | (x,TLazy f) :: l1, _ -> loop ((x,(!f)()) :: l1) l2
  210. | (_,t1) :: l1 , t2 :: l2 -> (t1,t2) :: loop l1 l2
  211. | _ -> assert false
  212. in
  213. let name =
  214. String.concat "_" (List.map2 (fun (s,_) t ->
  215. let s_type_path_underscore (p,s) = match p with [] -> s | _ -> String.concat "_" p ^ "_" ^ s in
  216. let rec loop top t = match follow t with
  217. | TInst(c,tl) -> (s_type_path_underscore c.cl_path) ^ (loop_tl tl)
  218. | TEnum(en,tl) -> (s_type_path_underscore en.e_path) ^ (loop_tl tl)
  219. | TAbstract(a,tl) -> (s_type_path_underscore a.a_path) ^ (loop_tl tl)
  220. | _ when not top -> "_" (* allow unknown/incompatible types as type parameters to retain old behavior *)
  221. | TMono _ -> raise (Generic_Exception (("Could not determine type for parameter " ^ s), p))
  222. | TDynamic _ -> "Dynamic"
  223. | t -> raise (Generic_Exception (("Type parameter must be a class or enum instance (found " ^ (s_type (print_context()) t) ^ ")"), p))
  224. and loop_tl tl = match tl with
  225. | [] -> ""
  226. | tl -> "_" ^ String.concat "_" (List.map (loop false) tl)
  227. in
  228. loop true t
  229. ) ps pt)
  230. in
  231. {
  232. ctx = ctx;
  233. subst = loop ps pt;
  234. name = name;
  235. p = p;
  236. mg = None;
  237. }
  238. let rec generic_substitute_type gctx t =
  239. match t with
  240. | TInst ({ cl_kind = KGeneric } as c2,tl2) ->
  241. (* maybe loop, or generate cascading generics *)
  242. let _, _, f = gctx.ctx.g.do_build_instance gctx.ctx (TClassDecl c2) gctx.p in
  243. let t = f (List.map (generic_substitute_type gctx) tl2) in
  244. (match follow t,gctx.mg with TInst(c,_), Some m -> add_dependency m c.cl_module | _ -> ());
  245. t
  246. | _ ->
  247. try
  248. generic_substitute_type gctx (List.assq t gctx.subst)
  249. with Not_found ->
  250. Type.map (generic_substitute_type gctx) t
  251. let generic_substitute_expr gctx e =
  252. let vars = Hashtbl.create 0 in
  253. let build_var v =
  254. try
  255. Hashtbl.find vars v.v_id
  256. with Not_found ->
  257. let v2 = alloc_var v.v_name (generic_substitute_type gctx v.v_type) in
  258. v2.v_meta <- v.v_meta;
  259. Hashtbl.add vars v.v_id v2;
  260. v2
  261. in
  262. let rec build_expr e =
  263. match e.eexpr with
  264. | TField(e1, FInstance({cl_kind = KGeneric} as c,tl,cf)) ->
  265. let _, _, f = gctx.ctx.g.do_build_instance gctx.ctx (TClassDecl c) gctx.p in
  266. let t = f (List.map (generic_substitute_type gctx) tl) in
  267. build_expr {e with eexpr = TField(e1,quick_field t cf.cf_name)}
  268. | TTypeExpr (TClassDecl ({cl_kind = KTypeParameter _;} as c)) when Meta.has Meta.Const c.cl_meta ->
  269. let rec loop subst = match subst with
  270. | (t1,t2) :: subst ->
  271. begin match follow t1 with
  272. | TInst(c2,_) when c == c2 -> t2
  273. | _ -> loop subst
  274. end
  275. | [] -> raise Not_found
  276. in
  277. begin try
  278. let t = loop gctx.subst in
  279. begin match follow t with
  280. | TInst({cl_kind = KExpr e},_) -> type_expr gctx.ctx e Value
  281. | _ -> error "Only Const type parameters can be used as value" e.epos
  282. end
  283. with Not_found ->
  284. e
  285. end
  286. | _ ->
  287. map_expr_type build_expr (generic_substitute_type gctx) build_var e
  288. in
  289. build_expr e
  290. let has_ctor_constraint c = match c.cl_kind with
  291. | KTypeParameter tl ->
  292. List.exists (fun t -> match follow t with
  293. | TAnon a when PMap.mem "new" a.a_fields -> true
  294. | TAbstract({a_path=["haxe"],"Constructible"},_) -> true
  295. | _ -> false
  296. ) tl;
  297. | _ -> false
  298. let get_short_name =
  299. let i = ref (-1) in
  300. (fun () ->
  301. incr i;
  302. Printf.sprintf "Hx___short___hx_type_%i" !i
  303. )
  304. let rec build_generic ctx c p tl =
  305. let pack = fst c.cl_path in
  306. let recurse = ref false in
  307. let rec check_recursive t =
  308. match follow t with
  309. | TInst (c2,tl) ->
  310. (match c2.cl_kind with
  311. | KTypeParameter tl ->
  312. if not (Typeload.is_generic_parameter ctx c2) && has_ctor_constraint c2 then
  313. error "Type parameters with a constructor cannot be used non-generically" p;
  314. recurse := true
  315. | _ -> ());
  316. List.iter check_recursive tl;
  317. | _ ->
  318. ()
  319. in
  320. List.iter check_recursive tl;
  321. if !recurse then begin
  322. TInst (c,tl) (* build a normal instance *)
  323. end else begin
  324. let gctx = make_generic ctx c.cl_params tl p in
  325. let name = (snd c.cl_path) ^ "_" ^ gctx.name in
  326. try
  327. Typeload.load_instance ctx { tpackage = pack; tname = name; tparams = []; tsub = None } p false
  328. with Error(Module_not_found path,_) when path = (pack,name) ->
  329. let m = (try Hashtbl.find ctx.g.modules (Hashtbl.find ctx.g.types_module c.cl_path) with Not_found -> assert false) in
  330. let ctx = { ctx with m = { ctx.m with module_types = m.m_types @ ctx.m.module_types } } in
  331. ignore(c.cl_build()); (* make sure the super class is already setup *)
  332. let mg = {
  333. m_id = alloc_mid();
  334. m_path = (pack,name);
  335. m_types = [];
  336. m_extra = module_extra (s_type_path (pack,name)) m.m_extra.m_sign 0. MFake;
  337. } in
  338. gctx.mg <- Some mg;
  339. let cg = mk_class mg (pack,name) c.cl_pos in
  340. mg.m_types <- [TClassDecl cg];
  341. Hashtbl.add ctx.g.modules mg.m_path mg;
  342. add_dependency mg m;
  343. add_dependency ctx.m.curmod mg;
  344. (* ensure that type parameters are set in dependencies *)
  345. let dep_stack = ref [] in
  346. let rec loop t =
  347. if not (List.memq t !dep_stack) then begin
  348. dep_stack := t :: !dep_stack;
  349. match t with
  350. | TInst (c,tl) -> add_dep c.cl_module tl
  351. | TEnum (e,tl) -> add_dep e.e_module tl
  352. | TType (t,tl) -> add_dep t.t_module tl
  353. | TAbstract (a,tl) -> add_dep a.a_module tl
  354. | TMono r ->
  355. (match !r with
  356. | None -> ()
  357. | Some t -> loop t)
  358. | TLazy f ->
  359. loop ((!f)());
  360. | TDynamic t2 ->
  361. if t == t2 then () else loop t2
  362. | TAnon a ->
  363. PMap.iter (fun _ f -> loop f.cf_type) a.a_fields
  364. | TFun (args,ret) ->
  365. List.iter (fun (_,_,t) -> loop t) args;
  366. loop ret
  367. end
  368. and add_dep m tl =
  369. add_dependency mg m;
  370. List.iter loop tl
  371. in
  372. List.iter loop tl;
  373. let build_field cf_old =
  374. (* We have to clone the type parameters (issue #4672). We cannot substitute the constraints immediately because
  375. we need the full substitution list first. *)
  376. let param_subst,params = List.fold_left (fun (subst,params) (s,t) -> match follow t with
  377. | TInst(c,tl) as t ->
  378. let t2 = TInst({c with cl_pos = c.cl_pos;},tl) in
  379. (t,t2) :: subst,(s,t2) :: params
  380. | _ -> assert false
  381. ) ([],[]) cf_old.cf_params in
  382. let gctx = {gctx with subst = param_subst @ gctx.subst} in
  383. let cf_new = {cf_old with cf_pos = cf_old.cf_pos} in (* copy *)
  384. (* Type parameter constraints are substituted here. *)
  385. cf_new.cf_params <- List.rev_map (fun (s,t) -> match follow t with
  386. | TInst({cl_kind = KTypeParameter tl1} as c,_) ->
  387. let tl1 = List.map (generic_substitute_type gctx) tl1 in
  388. c.cl_kind <- KTypeParameter tl1;
  389. s,t
  390. | _ -> assert false
  391. ) params;
  392. let f () =
  393. let t = generic_substitute_type gctx cf_old.cf_type in
  394. ignore (follow t);
  395. begin try (match cf_old.cf_expr with
  396. | None ->
  397. begin match cf_old.cf_kind with
  398. | Method _ when not c.cl_interface && not c.cl_extern ->
  399. display_error ctx (Printf.sprintf "Field %s has no expression (possible typing order issue)" cf_new.cf_name) cf_new.cf_pos;
  400. display_error ctx (Printf.sprintf "While building %s" (s_type_path cg.cl_path)) p;
  401. | _ ->
  402. ()
  403. end
  404. | Some e ->
  405. cf_new.cf_expr <- Some (generic_substitute_expr gctx e)
  406. ) with Unify_error l ->
  407. error (error_msg (Unify l)) cf_new.cf_pos
  408. end;
  409. t
  410. in
  411. let r = exc_protect ctx (fun r ->
  412. let t = mk_mono() in
  413. r := (fun() -> t);
  414. unify_raise ctx (f()) t p;
  415. t
  416. ) "build_generic" in
  417. delay ctx PForce (fun() -> ignore ((!r)()));
  418. cf_new.cf_type <- TLazy r;
  419. cf_new
  420. in
  421. if c.cl_init <> None || c.cl_dynamic <> None then error "This class can't be generic" p;
  422. List.iter (fun cf -> match cf.cf_kind with
  423. | Method MethMacro when not ctx.in_macro -> ()
  424. | _ -> error "A generic class can't have static fields" cf.cf_pos
  425. ) c.cl_ordered_statics;
  426. cg.cl_super <- (match c.cl_super with
  427. | None -> None
  428. | Some (cs,pl) ->
  429. let find_class subst =
  430. let rec loop subst = match subst with
  431. | (TInst(c,[]),t) :: subst when c == cs -> t
  432. | _ :: subst -> loop subst
  433. | [] -> raise Not_found
  434. in
  435. try
  436. if pl <> [] then raise Not_found;
  437. let t = loop subst in
  438. (* extended type parameter: concrete type must have a constructor, but generic base class must not have one *)
  439. begin match follow t,c.cl_constructor with
  440. | TInst(cs,_),None ->
  441. ignore(cs.cl_build());
  442. begin match cs.cl_constructor with
  443. | None -> error ("Cannot use " ^ (s_type_path cs.cl_path) ^ " as type parameter because it is extended and has no constructor") p
  444. | _ -> ()
  445. end;
  446. | _,Some cf -> error "Generics extending type parameters cannot have constructors" cf.cf_pos
  447. | _ -> ()
  448. end;
  449. t
  450. with Not_found ->
  451. apply_params c.cl_params tl (TInst(cs,pl))
  452. in
  453. let ts = follow (find_class gctx.subst) in
  454. let cs,pl = Typeload.check_extends ctx c ts p in
  455. match cs.cl_kind with
  456. | KGeneric ->
  457. (match build_generic ctx cs p pl with
  458. | TInst (cs,pl) -> Some (cs,pl)
  459. | _ -> assert false)
  460. | _ -> Some(cs,pl)
  461. );
  462. Typeload.add_constructor ctx cg false p;
  463. cg.cl_kind <- KGenericInstance (c,tl);
  464. cg.cl_meta <- (Meta.NoDoc,[],p) :: cg.cl_meta;
  465. cg.cl_interface <- c.cl_interface;
  466. cg.cl_constructor <- (match cg.cl_constructor, c.cl_constructor, c.cl_super with
  467. | _, Some cf, _ -> Some (build_field cf)
  468. | Some ctor, _, _ -> Some ctor
  469. | None, None, None -> None
  470. | _ -> error "Please define a constructor for this class in order to use it as generic" c.cl_pos
  471. );
  472. cg.cl_implements <- List.map (fun (i,tl) ->
  473. (match follow (generic_substitute_type gctx (TInst (i, List.map (generic_substitute_type gctx) tl))) with
  474. | TInst (i,tl) -> i, tl
  475. | _ -> assert false)
  476. ) c.cl_implements;
  477. cg.cl_ordered_fields <- List.map (fun f ->
  478. let f = build_field f in
  479. cg.cl_fields <- PMap.add f.cf_name f cg.cl_fields;
  480. f
  481. ) c.cl_ordered_fields;
  482. (* In rare cases the class name can become too long, so let's shorten it (issue #3090). *)
  483. if String.length (snd cg.cl_path) > 254 then begin
  484. let n = get_short_name () in
  485. cg.cl_meta <- (Meta.Native,[EConst(String (n)),p],p) :: cg.cl_meta;
  486. end;
  487. TInst (cg,[])
  488. end
  489. (* -------------------------------------------------------------------------- *)
  490. (* HAXE.XML.PROXY *)
  491. let extend_xml_proxy ctx c t file p =
  492. let t = Typeload.load_complex_type ctx p t in
  493. let file = (try Common.find_file ctx.com file with Not_found -> file) in
  494. add_dependency c.cl_module (create_fake_module ctx file);
  495. let used = ref PMap.empty in
  496. let print_results() =
  497. PMap.iter (fun id used ->
  498. if not used then ctx.com.warning (id ^ " is not used") p;
  499. ) (!used)
  500. in
  501. let check_used = Common.defined ctx.com Define.CheckXmlProxy in
  502. if check_used then ctx.g.hook_generate <- print_results :: ctx.g.hook_generate;
  503. try
  504. let rec loop = function
  505. | Xml.Element (_,attrs,childs) ->
  506. (try
  507. let id = List.assoc "id" attrs in
  508. if PMap.mem id c.cl_fields then error ("Duplicate id " ^ id) p;
  509. let t = if not check_used then t else begin
  510. used := PMap.add id false (!used);
  511. let ft() = used := PMap.add id true (!used); t in
  512. TLazy (ref ft)
  513. end in
  514. let f = {
  515. cf_name = id;
  516. cf_type = t;
  517. cf_public = true;
  518. cf_pos = p;
  519. cf_doc = None;
  520. cf_meta = no_meta;
  521. cf_kind = Var { v_read = AccResolve; v_write = AccNo };
  522. cf_params = [];
  523. cf_expr = None;
  524. cf_overloads = [];
  525. } in
  526. c.cl_fields <- PMap.add id f c.cl_fields;
  527. with
  528. Not_found -> ());
  529. List.iter loop childs;
  530. | Xml.PCData _ -> ()
  531. in
  532. loop (Xml.parse_file file)
  533. with
  534. | Xml.Error e -> error ("XML error " ^ Xml.error e) p
  535. | Xml.File_not_found f -> error ("XML File not found : " ^ f) p
  536. (* -------------------------------------------------------------------------- *)
  537. (* BUILD META DATA OBJECT *)
  538. let build_metadata com t =
  539. let api = com.basic in
  540. let p, meta, fields, statics = (match t with
  541. | TClassDecl c ->
  542. 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
  543. let statics = List.map (fun f -> f.cf_name,f.cf_meta) c.cl_ordered_statics in
  544. (c.cl_pos, ["",c.cl_meta],fields,statics)
  545. | TEnumDecl e ->
  546. (e.e_pos, ["",e.e_meta],List.map (fun n -> n, (PMap.find n e.e_constrs).ef_meta) e.e_names, [])
  547. | TTypeDecl t ->
  548. (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 [] | _ -> []),[])
  549. | TAbstractDecl a ->
  550. (a.a_pos, ["",a.a_meta],[],[])
  551. ) in
  552. let filter l =
  553. 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
  554. List.filter (fun (_,ml) -> ml <> []) l
  555. in
  556. let meta, fields, statics = filter meta, filter fields, filter statics in
  557. let make_meta_field ml =
  558. let h = Hashtbl.create 0 in
  559. mk (TObjectDecl (List.map (fun (f,el,p) ->
  560. if Hashtbl.mem h f then error ("Duplicate metadata '" ^ f ^ "'") p;
  561. Hashtbl.add h f ();
  562. f, mk (match el with [] -> TConst TNull | _ -> TArrayDecl (List.map (type_constant_value com) el)) (api.tarray t_dynamic) p
  563. ) ml)) t_dynamic p
  564. in
  565. let make_meta l =
  566. mk (TObjectDecl (List.map (fun (f,ml) -> f,make_meta_field ml) l)) t_dynamic p
  567. in
  568. if meta = [] && fields = [] && statics = [] then
  569. None
  570. else
  571. let meta_obj = [] in
  572. let meta_obj = (if fields = [] then meta_obj else ("fields",make_meta fields) :: meta_obj) in
  573. let meta_obj = (if statics = [] then meta_obj else ("statics",make_meta statics) :: meta_obj) in
  574. let meta_obj = (try ("obj", make_meta_field (List.assoc "" meta)) :: meta_obj with Not_found -> meta_obj) in
  575. Some (mk (TObjectDecl meta_obj) t_dynamic p)
  576. (* -------------------------------------------------------------------------- *)
  577. (* MACRO TYPE *)
  578. let get_macro_path ctx e args p =
  579. let rec loop e =
  580. match fst e with
  581. | EField (e,f) -> f :: loop e
  582. | EConst (Ident i) -> [i]
  583. | _ -> error "Invalid macro call" p
  584. in
  585. let path = match e with
  586. | (EConst(Ident i)),_ ->
  587. let path = try
  588. if not (PMap.mem i ctx.curclass.cl_statics) then raise Not_found;
  589. ctx.curclass.cl_path
  590. with Not_found -> try
  591. (t_infos (fst (PMap.find i ctx.m.module_globals))).mt_path
  592. with Not_found ->
  593. error "Invalid macro call" p
  594. in
  595. i :: (snd path) :: (fst path)
  596. | _ ->
  597. loop e
  598. in
  599. (match path with
  600. | meth :: cl :: path -> (List.rev path,cl), meth, args
  601. | _ -> error "Invalid macro call" p)
  602. let build_macro_type ctx pl p =
  603. let path, field, args = (match pl with
  604. | [TInst ({ cl_kind = KExpr (ECall (e,args),_) },_)]
  605. | [TInst ({ cl_kind = KExpr (EArrayDecl [ECall (e,args),_],_) },_)] ->
  606. get_macro_path ctx e args p
  607. | _ ->
  608. error "MacroType requires a single expression call parameter" p
  609. ) in
  610. let old = ctx.ret in
  611. let t = (match ctx.g.do_macro ctx MMacroType path field args p with
  612. | None -> mk_mono()
  613. | Some _ -> ctx.ret
  614. ) in
  615. ctx.ret <- old;
  616. t
  617. let build_macro_build ctx c pl cfl p =
  618. let path, field, args = match Meta.get Meta.GenericBuild c.cl_meta with
  619. | _,[ECall(e,args),_],_ -> get_macro_path ctx e args p
  620. | _ -> error "genericBuild requires a single expression call parameter" p
  621. in
  622. let old = ctx.ret,ctx.g.get_build_infos in
  623. ctx.g.get_build_infos <- (fun() -> Some (TClassDecl c, pl, cfl));
  624. let t = (match ctx.g.do_macro ctx MMacroType path field args p with
  625. | None -> mk_mono()
  626. | Some _ -> ctx.ret
  627. ) in
  628. ctx.ret <- fst old;
  629. ctx.g.get_build_infos <- snd old;
  630. t
  631. (* -------------------------------------------------------------------------- *)
  632. (* API EVENTS *)
  633. let build_instance ctx mtype p =
  634. match mtype with
  635. | TClassDecl c ->
  636. if ctx.pass > PBuildClass then ignore(c.cl_build());
  637. let build f s =
  638. let r = exc_protect ctx (fun r ->
  639. let t = mk_mono() in
  640. r := (fun() -> t);
  641. let tf = (f()) in
  642. unify_raise ctx tf t p;
  643. link_dynamic t tf;
  644. t
  645. ) s in
  646. delay ctx PForce (fun() -> ignore ((!r)()));
  647. TLazy r
  648. in
  649. let ft = (fun pl ->
  650. match c.cl_kind with
  651. | KGeneric ->
  652. build (fun () -> build_generic ctx c p pl) "build_generic"
  653. | KMacroType ->
  654. build (fun () -> build_macro_type ctx pl p) "macro_type"
  655. | KGenericBuild cfl ->
  656. build (fun () -> build_macro_build ctx c pl cfl p) "generic_build"
  657. | _ ->
  658. TInst (c,pl)
  659. ) in
  660. c.cl_params , c.cl_path , ft
  661. | TEnumDecl e ->
  662. e.e_params , e.e_path , (fun t -> TEnum (e,t))
  663. | TTypeDecl t ->
  664. t.t_params , t.t_path , (fun tl -> TType(t,tl))
  665. | TAbstractDecl a ->
  666. a.a_params, a.a_path, (fun tl -> TAbstract(a,tl))
  667. let on_inherit ctx c p h =
  668. match h with
  669. | HExtends { tpackage = ["haxe";"remoting"]; tname = "Proxy"; tparams = [TPType(CTPath t)] } ->
  670. extend_remoting ctx c t p false true;
  671. false
  672. | HExtends { tpackage = ["haxe";"remoting"]; tname = "AsyncProxy"; tparams = [TPType(CTPath t)] } ->
  673. extend_remoting ctx c t p true true;
  674. false
  675. | HExtends { tpackage = ["haxe";"xml"]; tname = "Proxy"; tparams = [TPExpr(EConst (String file),p);TPType t] } ->
  676. extend_xml_proxy ctx c t file p;
  677. true
  678. | _ ->
  679. true
  680. let push_this ctx e = match e.eexpr with
  681. | TConst ((TInt _ | TFloat _ | TString _ | TBool _) as ct) ->
  682. (EConst (tconst_to_const ct),e.epos),fun () -> ()
  683. | _ ->
  684. ctx.this_stack <- e :: ctx.this_stack;
  685. let er = EMeta((Meta.This,[],e.epos), (EConst(Ident "this"),e.epos)),e.epos in
  686. er,fun () -> ctx.this_stack <- List.tl ctx.this_stack
  687. (* -------------------------------------------------------------------------- *)
  688. (* ABSTRACT CASTS *)
  689. module AbstractCast = struct
  690. let cast_stack = ref []
  691. let make_static_call ctx c cf a pl args t p =
  692. if cf.cf_kind = Method MethMacro then begin
  693. match args with
  694. | [e] ->
  695. let e,f = push_this ctx e in
  696. ctx.with_type_stack <- (WithType t) :: ctx.with_type_stack;
  697. let e = match ctx.g.do_macro ctx MExpr c.cl_path cf.cf_name [e] p with
  698. | Some e -> type_expr ctx e Value
  699. | None -> type_expr ctx (EConst (Ident "null"),p) Value
  700. in
  701. ctx.with_type_stack <- List.tl ctx.with_type_stack;
  702. f();
  703. e
  704. | _ -> assert false
  705. end else
  706. make_static_call ctx c cf (apply_params a.a_params pl) args t p
  707. let do_check_cast ctx tleft eright p =
  708. let recurse cf f =
  709. if cf == ctx.curfield || List.mem cf !cast_stack then error "Recursive implicit cast" p;
  710. cast_stack := cf :: !cast_stack;
  711. let r = f() in
  712. cast_stack := List.tl !cast_stack;
  713. r
  714. in
  715. let find a tl f =
  716. let tcf,cf = f() in
  717. if (Meta.has Meta.MultiType a.a_meta) then
  718. mk_cast eright tleft p
  719. else match a.a_impl with
  720. | Some c -> recurse cf (fun () ->
  721. let ret = make_static_call ctx c cf a tl [eright] tleft p in
  722. { ret with eexpr = TMeta( (Meta.ImplicitCast,[],ret.epos), ret) }
  723. )
  724. | None -> assert false
  725. in
  726. if type_iseq tleft eright.etype then
  727. eright
  728. else begin
  729. let rec loop tleft tright = match follow tleft,follow tright with
  730. | TAbstract(a1,tl1),TAbstract(a2,tl2) ->
  731. begin try find a2 tl2 (fun () -> Abstract.find_to a2 tl2 tleft)
  732. with Not_found -> try find a1 tl1 (fun () -> Abstract.find_from a1 tl1 eright.etype tleft)
  733. with Not_found -> raise Not_found
  734. end
  735. | TAbstract(a,tl),_ ->
  736. begin try find a tl (fun () -> Abstract.find_from a tl eright.etype tleft)
  737. with Not_found ->
  738. let rec loop2 tcl = match tcl with
  739. | tc :: tcl ->
  740. if not (type_iseq tc tleft) then loop (apply_params a.a_params tl tc) tright
  741. else loop2 tcl
  742. | [] -> raise Not_found
  743. in
  744. loop2 a.a_from
  745. end
  746. | _,TAbstract(a,tl) ->
  747. begin try find a tl (fun () -> Abstract.find_to a tl tleft)
  748. with Not_found ->
  749. let rec loop2 tcl = match tcl with
  750. | tc :: tcl ->
  751. if not (type_iseq tc tright) then loop tleft (apply_params a.a_params tl tc)
  752. else loop2 tcl
  753. | [] -> raise Not_found
  754. in
  755. loop2 a.a_to
  756. end
  757. | _ ->
  758. raise Not_found
  759. in
  760. loop tleft eright.etype
  761. end
  762. let cast_or_unify_raise ctx tleft eright p =
  763. try
  764. (* can't do that anymore because this might miss macro calls (#4315) *)
  765. (* if ctx.com.display <> DMNone then raise Not_found; *)
  766. do_check_cast ctx tleft eright p
  767. with Not_found ->
  768. unify_raise ctx eright.etype tleft p;
  769. eright
  770. let cast_or_unify ctx tleft eright p =
  771. try
  772. cast_or_unify_raise ctx tleft eright p
  773. with Error (Unify l,p) ->
  774. raise_or_display ctx l p;
  775. eright
  776. let find_array_access_raise ctx a pl e1 e2o p =
  777. let is_set = e2o <> None in
  778. let ta = apply_params a.a_params pl a.a_this in
  779. let rec loop cfl = match cfl with
  780. | [] -> raise Not_found
  781. | cf :: cfl ->
  782. let monos = List.map (fun _ -> mk_mono()) cf.cf_params in
  783. let map t = apply_params a.a_params pl (apply_params cf.cf_params monos t) in
  784. let check_constraints () =
  785. List.iter2 (fun m (name,t) -> match follow t with
  786. | TInst ({ cl_kind = KTypeParameter constr },_) when constr <> [] ->
  787. List.iter (fun tc -> match follow m with TMono _ -> raise (Unify_error []) | _ -> Type.unify m (map tc) ) constr
  788. | _ -> ()
  789. ) monos cf.cf_params;
  790. in
  791. match follow (map cf.cf_type) with
  792. | TFun([(_,_,tab);(_,_,ta1);(_,_,ta2)],r) as tf when is_set ->
  793. begin try
  794. Type.unify tab ta;
  795. let e1 = cast_or_unify_raise ctx ta1 e1 p in
  796. let e2o = match e2o with None -> None | Some e2 -> Some (cast_or_unify_raise ctx ta2 e2 p) in
  797. check_constraints();
  798. cf,tf,r,e1,e2o
  799. with Unify_error _ | Error (Unify _,_) ->
  800. loop cfl
  801. end
  802. | TFun([(_,_,tab);(_,_,ta1)],r) as tf when not is_set ->
  803. begin try
  804. Type.unify tab ta;
  805. let e1 = cast_or_unify_raise ctx ta1 e1 p in
  806. check_constraints();
  807. cf,tf,r,e1,None
  808. with Unify_error _ | Error (Unify _,_) ->
  809. loop cfl
  810. end
  811. | _ -> loop cfl
  812. in
  813. loop a.a_array
  814. let find_array_access ctx a tl e1 e2o p =
  815. try find_array_access_raise ctx a tl e1 e2o p
  816. with Not_found -> match e2o with
  817. | None ->
  818. error (Printf.sprintf "No @:arrayAccess function accepts argument of %s" (s_type (print_context()) e1.etype)) p
  819. | Some e2 ->
  820. error (Printf.sprintf "No @:arrayAccess function accepts arguments of %s and %s" (s_type (print_context()) e1.etype) (s_type (print_context()) e2.etype)) p
  821. let find_multitype_specialization com a pl p =
  822. let m = mk_mono() in
  823. let tl = match Meta.get Meta.MultiType a.a_meta with
  824. | _,[],_ -> pl
  825. | _,el,_ ->
  826. let relevant = Hashtbl.create 0 in
  827. List.iter (fun e -> match fst e with
  828. | EConst(Ident s) -> Hashtbl.replace relevant s true
  829. | _ -> error "Type parameter expected" (pos e)
  830. ) el;
  831. let tl = List.map2 (fun (n,_) t -> if Hashtbl.mem relevant n || not (has_mono t) then t else t_dynamic) a.a_params pl in
  832. if com.platform = Js && a.a_path = ([],"Map") then begin match tl with
  833. | t1 :: _ ->
  834. let rec loop stack t =
  835. if List.exists (fun t2 -> fast_eq t t2) stack then
  836. t
  837. else begin
  838. let stack = t :: stack in
  839. match follow t with
  840. | TAbstract ({ a_path = [],"Class" },_) ->
  841. error (Printf.sprintf "Cannot use %s as key type to Map because Class<T> is not comparable" (s_type (print_context()) t1)) p;
  842. | TEnum(en,tl) ->
  843. PMap.iter (fun _ ef -> ignore(loop stack ef.ef_type)) en.e_constrs;
  844. Type.map (loop stack) t
  845. | t ->
  846. Type.map (loop stack) t
  847. end
  848. in
  849. ignore(loop [] t1)
  850. | _ -> assert false
  851. end;
  852. tl
  853. in
  854. let _,cf =
  855. try
  856. Abstract.find_to a tl m
  857. with Not_found ->
  858. let at = apply_params a.a_params pl a.a_this in
  859. let st = s_type (print_context()) at in
  860. if has_mono at then
  861. error ("Type parameters of multi type abstracts must be known (for " ^ st ^ ")") p
  862. else
  863. error ("Abstract " ^ (s_type_path a.a_path) ^ " has no @:to function that accepts " ^ st) p;
  864. in
  865. cf, follow m
  866. let handle_abstract_casts ctx e =
  867. let rec loop ctx e = match e.eexpr with
  868. | TNew({cl_kind = KAbstractImpl a} as c,pl,el) ->
  869. if not (Meta.has Meta.MultiType a.a_meta) then begin
  870. (* This must have been a @:generic expansion with a { new } constraint (issue #4364). In this case
  871. let's construct the underlying type. *)
  872. match Abstract.get_underlying_type a pl with
  873. | TInst(c,tl) as t -> {e with eexpr = TNew(c,tl,el); etype = t}
  874. | _ -> error ("Cannot construct " ^ (s_type (print_context()) (TAbstract(a,pl)))) e.epos
  875. end else begin
  876. (* a TNew of an abstract implementation is only generated if it is a multi type abstract *)
  877. let cf,m = find_multitype_specialization ctx.com a pl e.epos in
  878. let e = make_static_call ctx c cf a pl ((mk (TConst TNull) (TAbstract(a,pl)) e.epos) :: el) m e.epos in
  879. {e with etype = m}
  880. end
  881. | TCall({eexpr = TField(_,FStatic({cl_path=[],"Std"},{cf_name = "string"}))},[e1]) when (match follow e1.etype with TAbstract({a_impl = Some _},_) -> true | _ -> false) ->
  882. begin match follow e1.etype with
  883. | TAbstract({a_impl = Some c} as a,tl) ->
  884. begin try
  885. let cf = PMap.find "toString" c.cl_statics in
  886. make_static_call ctx c cf a tl [e1] ctx.t.tstring e.epos
  887. with Not_found ->
  888. e
  889. end
  890. | _ ->
  891. assert false
  892. end
  893. | TCall(e1, el) ->
  894. begin try
  895. let rec find_abstract e = match follow e.etype,e.eexpr with
  896. | TAbstract(a,pl),_ when Meta.has Meta.MultiType a.a_meta -> a,pl,e
  897. | _,TCast(e1,None) -> find_abstract e1
  898. | _ -> raise Not_found
  899. in
  900. let rec find_field e1 =
  901. match e1.eexpr with
  902. | TCast(e2,None) ->
  903. {e1 with eexpr = TCast(find_field e2,None)}
  904. | TField(e2,fa) ->
  905. let a,pl,e2 = find_abstract e2 in
  906. let m = Abstract.get_underlying_type a pl in
  907. let fname = field_name fa in
  908. let el = List.map (loop ctx) el in
  909. begin try
  910. let fa = quick_field m fname in
  911. let get_fun_type t = match follow t with
  912. | TFun(_,tr) as tf -> tf,tr
  913. | _ -> raise Not_found
  914. in
  915. let tf,tr = match fa with
  916. | FStatic(_,cf) -> get_fun_type cf.cf_type
  917. | FInstance(c,tl,cf) -> get_fun_type (apply_params c.cl_params tl cf.cf_type)
  918. | FAnon cf -> get_fun_type cf.cf_type
  919. | _ -> raise Not_found
  920. in
  921. let ef = mk (TField({e2 with etype = m},fa)) tf e2.epos in
  922. let ecall = make_call ctx ef el tr e.epos in
  923. if not (type_iseq ecall.etype e.etype) then
  924. mk (TCast(ecall,None)) e.etype e.epos
  925. else
  926. ecall
  927. with Not_found ->
  928. (* quick_field raises Not_found if m is an abstract, we have to replicate the 'using' call here *)
  929. match follow m with
  930. | TAbstract({a_impl = Some c} as a,pl) ->
  931. let cf = PMap.find fname c.cl_statics in
  932. make_static_call ctx c cf a pl (e2 :: el) e.etype e.epos
  933. | _ -> raise Not_found
  934. end
  935. | _ ->
  936. raise Not_found
  937. in
  938. find_field e1
  939. with Not_found ->
  940. Type.map_expr (loop ctx) e
  941. end
  942. | _ ->
  943. Type.map_expr (loop ctx) e
  944. in
  945. loop ctx e
  946. end
  947. module PatternMatchConversion = struct
  948. type cctx = {
  949. ctx : typer;
  950. mutable eval_stack : ((tvar * pos) * texpr) list list;
  951. dt_lookup : dt array;
  952. }
  953. let is_declared cctx v =
  954. let rec loop sl = match sl with
  955. | stack :: sl ->
  956. List.exists (fun ((v2,_),_) -> v == v2) stack || loop sl
  957. | [] ->
  958. false
  959. in
  960. loop cctx.eval_stack
  961. let group_cases cases =
  962. let dt_eq dt1 dt2 = match dt1,dt2 with
  963. | DTGoto i1, DTGoto i2 when i1 = i2 -> true
  964. (* TODO equal bindings *)
  965. | _ -> false
  966. in
  967. match List.rev cases with
  968. | [] -> []
  969. | [con,dt] -> [[con],dt]
  970. | (con,dt) :: cases ->
  971. let tmp,ldt,cases = List.fold_left (fun (tmp,ldt,acc) (con,dt) ->
  972. if dt_eq dt ldt then
  973. (con :: tmp,dt,acc)
  974. else
  975. ([con],dt,(tmp,ldt) :: acc)
  976. ) ([con],dt,[]) cases in
  977. match tmp with
  978. | [] -> cases
  979. | tmp -> ((tmp,ldt) :: cases)
  980. let replace_locals e =
  981. let v_known = ref IntMap.empty in
  982. let copy v =
  983. let v' = alloc_var v.v_name v.v_type in
  984. v'.v_meta <- v.v_meta;
  985. v_known := IntMap.add v.v_id v' !v_known;
  986. v'
  987. in
  988. let rec loop e = match e.eexpr with
  989. | TVar(v,e1) ->
  990. let v' = copy v in
  991. let e1 = match e1 with None -> None | Some e -> Some (loop e) in
  992. {e with eexpr = TVar(v',e1)}
  993. | TFor(v,e1,e2) ->
  994. let v' = copy v in
  995. let e1 = loop e1 in
  996. let e2 = loop e2 in
  997. {e with eexpr = TFor(v',e1,e2)}
  998. | TTry(e1,catches) ->
  999. let e1 = loop e1 in
  1000. let catches = List.map (fun (v,e) ->
  1001. let v' = copy v in
  1002. let e = loop e in
  1003. v',e
  1004. ) catches in
  1005. {e with eexpr = TTry(e1,catches)}
  1006. | TLocal v ->
  1007. let v' = try IntMap.find v.v_id !v_known with Not_found -> v in
  1008. {e with eexpr = TLocal v'}
  1009. | _ ->
  1010. Type.map_expr loop e
  1011. in
  1012. loop e
  1013. let rec convert_dt cctx dt =
  1014. match dt with
  1015. | DTBind (bl,dt) ->
  1016. cctx.eval_stack <- bl :: cctx.eval_stack;
  1017. let e = convert_dt cctx dt in
  1018. cctx.eval_stack <- List.tl cctx.eval_stack;
  1019. let vl,el = List.fold_left (fun (vl,el) ((v,p),e) ->
  1020. if is_declared cctx v then
  1021. vl, (mk (TBinop(OpAssign,mk (TLocal v) v.v_type p,e)) e.etype e.epos) :: el
  1022. else
  1023. ((v,p,Some e) :: vl), el
  1024. ) ([],[e]) bl in
  1025. let el_v = List.map (fun (v,p,eo) -> mk (TVar (v,eo)) cctx.ctx.t.tvoid p) vl in
  1026. mk (TBlock (el_v @ el)) e.etype e.epos
  1027. | DTGoto i ->
  1028. convert_dt cctx (cctx.dt_lookup.(i))
  1029. | DTExpr e ->
  1030. e
  1031. | DTGuard(e,dt1,dt2) ->
  1032. let ethen = convert_dt cctx dt1 in
  1033. mk (TIf(e,ethen,match dt2 with None -> None | Some dt -> Some (convert_dt cctx dt))) ethen.etype (punion e.epos ethen.epos)
  1034. | DTSwitch({eexpr = TMeta((Meta.Exhaustive,_,_),_)},[_,dt],None) ->
  1035. convert_dt cctx dt
  1036. | DTSwitch(e_st,cl,dto) ->
  1037. let def = match dto with None -> None | Some dt -> Some (convert_dt cctx dt) in
  1038. let cases = group_cases cl in
  1039. let cases = List.map (fun (cl,dt) ->
  1040. let e = convert_dt cctx dt in
  1041. (* The macro interpreter does not care about unique locals and
  1042. we don't run the analyzer on the output, so let's save some
  1043. time here (issue #3937) *)
  1044. let e = if cctx.ctx.in_macro then e else replace_locals e in
  1045. cl,e
  1046. ) cases in
  1047. mk (TSwitch(e_st,cases,def)) (mk_mono()) e_st.epos
  1048. let to_typed_ast ctx dt p =
  1049. let first = dt.dt_dt_lookup.(dt.dt_first) in
  1050. let cctx = {
  1051. ctx = ctx;
  1052. dt_lookup = dt.dt_dt_lookup;
  1053. eval_stack = [];
  1054. } in
  1055. let e = convert_dt cctx first in
  1056. let e = { e with epos = p; etype = dt.dt_type} in
  1057. if dt.dt_var_init = [] then
  1058. e
  1059. else begin
  1060. let el_v = List.map (fun (v,eo) -> mk (TVar (v,eo)) cctx.ctx.t.tvoid p) dt.dt_var_init in
  1061. mk (TBlock (el_v @ [e])) dt.dt_type e.epos
  1062. end
  1063. end
  1064. (* -------------------------------------------------------------------------- *)
  1065. (* USAGE *)
  1066. let detect_usage com =
  1067. let usage = ref [] in
  1068. List.iter (fun t -> match t with
  1069. | TClassDecl c ->
  1070. let check_constructor c p =
  1071. try
  1072. let _,cf = get_constructor (fun cf -> cf.cf_type) c in
  1073. if Meta.has Meta.Usage cf.cf_meta then
  1074. usage := p :: !usage;
  1075. with Not_found ->
  1076. ()
  1077. in
  1078. let rec expr e = match e.eexpr with
  1079. | TField(_,FEnum(_,ef)) when Meta.has Meta.Usage ef.ef_meta ->
  1080. let p = {e.epos with pmin = e.epos.pmax - (String.length ef.ef_name)} in
  1081. usage := p :: !usage;
  1082. Type.iter expr e
  1083. | TField(_,(FAnon cf | FInstance (_,_,cf) | FStatic (_,cf) | FClosure (_,cf))) when Meta.has Meta.Usage cf.cf_meta ->
  1084. let p = {e.epos with pmin = e.epos.pmax - (String.length cf.cf_name)} in
  1085. usage := p :: !usage;
  1086. Type.iter expr e
  1087. | TLocal v when Meta.has Meta.Usage v.v_meta ->
  1088. usage := e.epos :: !usage
  1089. | TVar (v,_) when com.display = DMPosition && Meta.has Meta.Usage v.v_meta ->
  1090. raise (Typecore.DisplayPosition [e.epos])
  1091. | TFunction tf when com.display = DMPosition && List.exists (fun (v,_) -> Meta.has Meta.Usage v.v_meta) tf.tf_args ->
  1092. raise (Typecore.DisplayPosition [e.epos])
  1093. | TTypeExpr mt when (Meta.has Meta.Usage (t_infos mt).mt_meta) ->
  1094. usage := e.epos :: !usage
  1095. | TNew (c,_,_) ->
  1096. check_constructor c e.epos;
  1097. Type.iter expr e;
  1098. | TCall({eexpr = TConst TSuper},_) ->
  1099. begin match c.cl_super with
  1100. | Some (c,_) ->
  1101. check_constructor c e.epos
  1102. | _ ->
  1103. ()
  1104. end
  1105. | _ -> Type.iter expr e
  1106. in
  1107. let field cf = ignore(follow cf.cf_type); match cf.cf_expr with None -> () | Some e -> expr e in
  1108. (match c.cl_constructor with None -> () | Some cf -> field cf);
  1109. (match c.cl_init with None -> () | Some e -> expr e);
  1110. List.iter field c.cl_ordered_statics;
  1111. List.iter field c.cl_ordered_fields;
  1112. | _ -> ()
  1113. ) com.types;
  1114. let usage = List.sort (fun p1 p2 ->
  1115. let c = compare p1.pfile p2.pfile in
  1116. if c <> 0 then c else compare p1.pmin p2.pmin
  1117. ) !usage in
  1118. raise (Typecore.DisplayPosition usage)
  1119. let update_cache_dependencies t =
  1120. let rec check_t m t = match t with
  1121. | TInst(c,tl) ->
  1122. add_dependency m c.cl_module;
  1123. List.iter (check_t m) tl;
  1124. | TEnum(en,tl) ->
  1125. add_dependency m en.e_module;
  1126. List.iter (check_t m) tl;
  1127. | TType(t,tl) ->
  1128. add_dependency m t.t_module;
  1129. List.iter (check_t m) tl;
  1130. | TAbstract(a,tl) ->
  1131. add_dependency m a.a_module;
  1132. List.iter (check_t m) tl;
  1133. | TFun(targs,tret) ->
  1134. List.iter (fun (_,_,t) -> check_t m t) targs;
  1135. check_t m tret;
  1136. | TAnon an ->
  1137. PMap.iter (fun _ cf -> check_field m cf) an.a_fields
  1138. | TMono r ->
  1139. (match !r with
  1140. | Some t -> check_t m t
  1141. | _ -> ())
  1142. | TLazy f ->
  1143. check_t m (!f())
  1144. | TDynamic t ->
  1145. if t == t_dynamic then
  1146. ()
  1147. else
  1148. check_t m t
  1149. and check_field m cf =
  1150. check_t m cf.cf_type
  1151. in
  1152. match t with
  1153. | TClassDecl c ->
  1154. List.iter (check_field c.cl_module) c.cl_ordered_statics;
  1155. List.iter (check_field c.cl_module) c.cl_ordered_fields;
  1156. (match c.cl_constructor with None -> () | Some cf -> check_field c.cl_module cf);
  1157. | _ ->
  1158. ()
  1159. (* -------------------------------------------------------------------------- *)
  1160. (* STACK MANAGEMENT EMULATION *)
  1161. type stack_context = {
  1162. stack_var : string;
  1163. stack_exc_var : string;
  1164. stack_pos_var : string;
  1165. stack_pos : pos;
  1166. stack_expr : texpr;
  1167. stack_pop : texpr;
  1168. stack_save_pos : texpr;
  1169. stack_restore : texpr list;
  1170. stack_push : tclass -> string -> texpr;
  1171. stack_return : texpr -> texpr;
  1172. }
  1173. let stack_context_init com stack_var exc_var pos_var tmp_var use_add p =
  1174. let t = com.basic in
  1175. let st = t.tarray t.tstring in
  1176. let stack_var = alloc_var stack_var st in
  1177. let exc_var = alloc_var exc_var st in
  1178. let pos_var = alloc_var pos_var t.tint in
  1179. let stack_e = mk (TLocal stack_var) st p in
  1180. let exc_e = mk (TLocal exc_var) st p in
  1181. let stack_pop = fcall stack_e "pop" [] t.tstring p in
  1182. let stack_push c m =
  1183. fcall stack_e "push" [
  1184. if use_add then
  1185. binop OpAdd (string com (s_type_path c.cl_path ^ "::") p) (string com m p) t.tstring p
  1186. else
  1187. string com (s_type_path c.cl_path ^ "::" ^ m) p
  1188. ] t.tvoid p
  1189. in
  1190. let stack_return e =
  1191. let tmp = alloc_var tmp_var e.etype in
  1192. mk (TBlock [
  1193. mk (TVar (tmp, Some e)) t.tvoid e.epos;
  1194. stack_pop;
  1195. mk (TReturn (Some (mk (TLocal tmp) e.etype e.epos))) e.etype e.epos
  1196. ]) e.etype e.epos
  1197. in
  1198. {
  1199. stack_var = stack_var.v_name;
  1200. stack_exc_var = exc_var.v_name;
  1201. stack_pos_var = pos_var.v_name;
  1202. stack_pos = p;
  1203. stack_expr = stack_e;
  1204. stack_pop = stack_pop;
  1205. stack_save_pos = mk (TVar (pos_var, Some (field stack_e "length" t.tint p))) t.tvoid p;
  1206. stack_push = stack_push;
  1207. stack_return = stack_return;
  1208. stack_restore = [
  1209. binop OpAssign exc_e (mk (TArrayDecl []) st p) st p;
  1210. mk (TWhile (
  1211. mk_parent (binop OpGte (field stack_e "length" t.tint p) (mk (TLocal pos_var) t.tint p) t.tbool p),
  1212. fcall exc_e "unshift" [fcall stack_e "pop" [] t.tstring p] t.tvoid p,
  1213. NormalWhile
  1214. )) t.tvoid p;
  1215. fcall stack_e "push" [index com exc_e 0 t.tstring p] t.tvoid p
  1216. ];
  1217. }
  1218. let stack_init com use_add =
  1219. stack_context_init com "$s" "$e" "$spos" "$tmp" use_add null_pos
  1220. let rec stack_block_loop ctx e =
  1221. match e.eexpr with
  1222. | TFunction _ ->
  1223. e
  1224. | TReturn None | TReturn (Some { eexpr = TConst _ }) | TReturn (Some { eexpr = TLocal _ }) ->
  1225. mk (TBlock [
  1226. ctx.stack_pop;
  1227. e;
  1228. ]) e.etype e.epos
  1229. | TReturn (Some e) ->
  1230. ctx.stack_return (stack_block_loop ctx e)
  1231. | TTry (v,cases) ->
  1232. let v = stack_block_loop ctx v in
  1233. let cases = List.map (fun (v,e) ->
  1234. let e = stack_block_loop ctx e in
  1235. let e = (match (mk_block e).eexpr with
  1236. | TBlock l -> mk (TBlock (ctx.stack_restore @ l)) e.etype e.epos
  1237. | _ -> assert false
  1238. ) in
  1239. v , e
  1240. ) cases in
  1241. mk (TTry (v,cases)) e.etype e.epos
  1242. | _ ->
  1243. map_expr (stack_block_loop ctx) e
  1244. let stack_block ctx c m e =
  1245. match (mk_block e).eexpr with
  1246. | TBlock l ->
  1247. mk (TBlock (
  1248. ctx.stack_push c m ::
  1249. ctx.stack_save_pos ::
  1250. List.map (stack_block_loop ctx) l
  1251. @ [ctx.stack_pop]
  1252. )) e.etype e.epos
  1253. | _ ->
  1254. assert false
  1255. (* -------------------------------------------------------------------------- *)
  1256. (* FIX OVERRIDES *)
  1257. (*
  1258. on some platforms which doesn't support type parameters, we must have the
  1259. exact same type for overriden/implemented function as the original one
  1260. *)
  1261. let rec find_field com c f =
  1262. try
  1263. (match c.cl_super with
  1264. | None ->
  1265. raise Not_found
  1266. | Some ( {cl_path = (["cpp"],"FastIterator")}, _ ) ->
  1267. raise Not_found (* This is a strongly typed 'extern' and the usual rules don't apply *)
  1268. | Some (c,_) ->
  1269. find_field com c f)
  1270. with Not_found -> try
  1271. if com.platform = Cpp then (* Cpp uses delegation for interfaces *)
  1272. raise Not_found;
  1273. let rec loop = function
  1274. | [] ->
  1275. raise Not_found
  1276. | (c,_) :: l ->
  1277. try
  1278. find_field com c f
  1279. with
  1280. Not_found -> loop l
  1281. in
  1282. loop c.cl_implements
  1283. with Not_found ->
  1284. let f = PMap.find f.cf_name c.cl_fields in
  1285. (match f.cf_kind with Var { v_read = AccRequire _ } -> raise Not_found | _ -> ());
  1286. f
  1287. let fix_override com c f fd =
  1288. let f2 = (try Some (find_field com c f) with Not_found -> None) in
  1289. match f2,fd with
  1290. | Some (f2), Some(fd) ->
  1291. let targs, tret = (match follow f2.cf_type with TFun (args,ret) -> args, ret | _ -> assert false) in
  1292. let changed_args = ref [] in
  1293. let prefix = "_tmp_" in
  1294. let nargs = List.map2 (fun ((v,ct) as cur) (_,_,t2) ->
  1295. try
  1296. type_eq EqStrict (monomorphs c.cl_params (monomorphs f.cf_params v.v_type)) t2;
  1297. (* Flash generates type parameters with a single constraint as that constraint type, so we
  1298. have to detect this case and change the variable (issue #2712). *)
  1299. begin match follow v.v_type with
  1300. | TInst({cl_kind = KTypeParameter [tc]} as cp,_) when com.platform = Flash ->
  1301. if List.mem_assoc (snd cp.cl_path) c.cl_params then raise (Unify_error [])
  1302. | _ ->
  1303. ()
  1304. end;
  1305. cur
  1306. with Unify_error _ ->
  1307. let v2 = alloc_var (prefix ^ v.v_name) t2 in
  1308. changed_args := (v,v2) :: !changed_args;
  1309. v2,ct
  1310. ) fd.tf_args targs in
  1311. let fd2 = {
  1312. tf_args = nargs;
  1313. tf_type = tret;
  1314. tf_expr = (match List.rev !changed_args with
  1315. | [] -> fd.tf_expr
  1316. | args ->
  1317. let e = fd.tf_expr in
  1318. let el = (match e.eexpr with TBlock el -> el | _ -> [e]) in
  1319. let p = (match el with [] -> e.epos | e :: _ -> e.epos) in
  1320. let el_v = List.map (fun (v,v2) ->
  1321. mk (TVar (v,Some (mk (TCast (mk (TLocal v2) v2.v_type p,None)) v.v_type p))) com.basic.tvoid p
  1322. ) args in
  1323. { e with eexpr = TBlock (el_v @ el) }
  1324. );
  1325. } in
  1326. (* as3 does not allow wider visibility, so the base method has to be made public *)
  1327. if Common.defined com Define.As3 && f.cf_public then f2.cf_public <- true;
  1328. let targs = List.map (fun(v,c) -> (v.v_name, Option.is_some c, v.v_type)) nargs in
  1329. let fde = (match f.cf_expr with None -> assert false | Some e -> e) in
  1330. f.cf_expr <- Some { fde with eexpr = TFunction fd2 };
  1331. f.cf_type <- TFun(targs,tret);
  1332. | Some(f2), None when c.cl_interface ->
  1333. let targs, tret = (match follow f2.cf_type with TFun (args,ret) -> args, ret | _ -> assert false) in
  1334. f.cf_type <- TFun(targs,tret)
  1335. | _ ->
  1336. ()
  1337. let fix_overrides com t =
  1338. match t with
  1339. | TClassDecl c ->
  1340. (* overrides can be removed from interfaces *)
  1341. if c.cl_interface then
  1342. c.cl_ordered_fields <- List.filter (fun f ->
  1343. try
  1344. if find_field com c f == f then raise Not_found;
  1345. c.cl_fields <- PMap.remove f.cf_name c.cl_fields;
  1346. false;
  1347. with Not_found ->
  1348. true
  1349. ) c.cl_ordered_fields;
  1350. List.iter (fun f ->
  1351. match f.cf_expr, f.cf_kind with
  1352. | Some { eexpr = TFunction fd }, Method (MethNormal | MethInline) ->
  1353. fix_override com c f (Some fd)
  1354. | None, Method (MethNormal | MethInline) when c.cl_interface ->
  1355. fix_override com c f None
  1356. | _ ->
  1357. ()
  1358. ) c.cl_ordered_fields
  1359. | _ ->
  1360. ()
  1361. (*
  1362. PHP does not allow abstract classes extending other abstract classes to override any fields, so these duplicates
  1363. must be removed from the child interface
  1364. *)
  1365. let fix_abstract_inheritance com t =
  1366. match t with
  1367. | TClassDecl c when c.cl_interface ->
  1368. c.cl_ordered_fields <- List.filter (fun f ->
  1369. let b = try (find_field com c f) == f
  1370. with Not_found -> false in
  1371. if not b then c.cl_fields <- PMap.remove f.cf_name c.cl_fields;
  1372. b;
  1373. ) c.cl_ordered_fields
  1374. | _ -> ()
  1375. (* -------------------------------------------------------------------------- *)
  1376. (* MISC FEATURES *)
  1377. let rec is_volatile t =
  1378. match t with
  1379. | TMono r ->
  1380. (match !r with
  1381. | Some t -> is_volatile t
  1382. | _ -> false)
  1383. | TLazy f ->
  1384. is_volatile (!f())
  1385. | TType (t,tl) ->
  1386. (match t.t_path with
  1387. | _ -> is_volatile (apply_params t.t_params tl t.t_type))
  1388. | _ ->
  1389. false
  1390. let set_default ctx a c p =
  1391. let t = a.v_type in
  1392. let ve = mk (TLocal a) t p in
  1393. let cond = TBinop (OpEq,ve,mk (TConst TNull) t p) in
  1394. 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
  1395. let bytes_serialize data =
  1396. let b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" in
  1397. let tbl = Array.init (String.length b64) (fun i -> String.get b64 i) in
  1398. Base64.str_encode ~tbl data
  1399. (*
  1400. Tells if the constructor might be called without any issue whatever its parameters
  1401. *)
  1402. let rec constructor_side_effects e =
  1403. match e.eexpr with
  1404. | TBinop (op,_,_) when op <> OpAssign ->
  1405. true
  1406. | TField (_,FEnum _) ->
  1407. false
  1408. | TUnop _ | TArray _ | TField _ | TEnumParameter _ | TCall _ | TNew _ | TFor _ | TWhile _ | TSwitch _ | TReturn _ | TThrow _ ->
  1409. true
  1410. | TBinop _ | TTry _ | TIf _ | TBlock _ | TVar _
  1411. | TFunction _ | TArrayDecl _ | TObjectDecl _
  1412. | TParenthesis _ | TTypeExpr _ | TLocal _ | TMeta _
  1413. | TConst _ | TContinue | TBreak | TCast _ ->
  1414. try
  1415. Type.iter (fun e -> if constructor_side_effects e then raise Exit) e;
  1416. false;
  1417. with Exit ->
  1418. true
  1419. let make_valid_filename s =
  1420. let r = Str.regexp "[^A-Za-z0-9_\\-\\.,]" in
  1421. Str.global_substitute r (fun s -> "_") s
  1422. let rec create_file ext acc = function
  1423. | [] -> assert false
  1424. | d :: [] ->
  1425. let d = make_valid_filename d in
  1426. let ch = open_out (String.concat "/" (List.rev (d :: acc)) ^ ext) in
  1427. ch
  1428. | d :: l ->
  1429. let dir = String.concat "/" (List.rev (d :: acc)) in
  1430. if not (Sys.file_exists dir) then Unix.mkdir dir 0o755;
  1431. create_file ext (d :: acc) l
  1432. (*
  1433. Make a dump of the full typed AST of all types
  1434. *)
  1435. let create_dumpfile acc l =
  1436. let ch = create_file ".dump" acc l in
  1437. let buf = Buffer.create 0 in
  1438. buf, (fun () ->
  1439. output_string ch (Buffer.contents buf);
  1440. close_out ch)
  1441. let dump_types com =
  1442. let s_type = s_type (Type.print_context()) in
  1443. let params = function [] -> "" | l -> Printf.sprintf "<%s>" (String.concat "," (List.map (fun (n,t) -> n ^ " : " ^ s_type t) l)) in
  1444. let s_expr = match Common.defined_value_safe com Define.Dump with
  1445. | "pretty" -> Type.s_expr_pretty "\t"
  1446. | "legacy" -> Type.s_expr
  1447. | _ -> Type.s_expr_ast (not (Common.defined com Define.DumpIgnoreVarIds)) "\t"
  1448. in
  1449. List.iter (fun mt ->
  1450. let path = Type.t_path mt in
  1451. let buf,close = create_dumpfile [] ("dump" :: (Common.platform_name com.platform) :: fst path @ [snd path]) in
  1452. let print fmt = Printf.kprintf (fun s -> Buffer.add_string buf s) fmt in
  1453. (match mt with
  1454. | Type.TClassDecl c ->
  1455. let rec print_field stat f =
  1456. 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);
  1457. print "(%s) : %s" (s_kind f.cf_kind) (s_type f.cf_type);
  1458. (match f.cf_expr with
  1459. | None -> ()
  1460. | Some e -> print "\n\n\t = %s" (s_expr s_type e));
  1461. print "\n\n";
  1462. List.iter (fun f -> print_field stat f) f.cf_overloads
  1463. in
  1464. 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_params);
  1465. (match c.cl_super with None -> () | Some (c,pl) -> print " extends %s" (s_type (TInst (c,pl))));
  1466. List.iter (fun (c,pl) -> print " implements %s" (s_type (TInst (c,pl)))) c.cl_implements;
  1467. (match c.cl_dynamic with None -> () | Some t -> print " implements Dynamic<%s>" (s_type t));
  1468. (match c.cl_array_access with None -> () | Some t -> print " implements ArrayAccess<%s>" (s_type t));
  1469. print "{\n";
  1470. (match c.cl_constructor with
  1471. | None -> ()
  1472. | Some f -> print_field false f);
  1473. List.iter (print_field false) c.cl_ordered_fields;
  1474. List.iter (print_field true) c.cl_ordered_statics;
  1475. (match c.cl_init with
  1476. | None -> ()
  1477. | Some e ->
  1478. print "\n\n\t__init__ = ";
  1479. print "%s" (s_expr s_type e);
  1480. print "}\n");
  1481. print "}";
  1482. | Type.TEnumDecl e ->
  1483. 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_params);
  1484. List.iter (fun n ->
  1485. let f = PMap.find n e.e_constrs in
  1486. print "\t%s : %s;\n" f.ef_name (s_type f.ef_type);
  1487. ) e.e_names;
  1488. print "}"
  1489. | Type.TTypeDecl t ->
  1490. print "%stype %s%s = %s" (if t.t_private then "private " else "") (s_type_path path) (params t.t_params) (s_type t.t_type);
  1491. | Type.TAbstractDecl a ->
  1492. print "%sabstract %s%s {}" (if a.a_private then "private " else "") (s_type_path path) (params a.a_params);
  1493. );
  1494. close();
  1495. ) com.types
  1496. let dump_dependencies com =
  1497. let buf,close = create_dumpfile [] ["dump";Common.platform_name com.platform;".dependencies"] in
  1498. let print fmt = Printf.kprintf (fun s -> Buffer.add_string buf s) fmt in
  1499. let dep = Hashtbl.create 0 in
  1500. List.iter (fun m ->
  1501. print "%s:\n" m.m_extra.m_file;
  1502. PMap.iter (fun _ m2 ->
  1503. print "\t%s\n" (m2.m_extra.m_file);
  1504. let l = try Hashtbl.find dep m2.m_extra.m_file with Not_found -> [] in
  1505. Hashtbl.replace dep m2.m_extra.m_file (m :: l)
  1506. ) m.m_extra.m_deps;
  1507. ) com.Common.modules;
  1508. close();
  1509. let buf,close = create_dumpfile [] ["dump";Common.platform_name com.platform;".dependants"] in
  1510. let print fmt = Printf.kprintf (fun s -> Buffer.add_string buf s) fmt in
  1511. Hashtbl.iter (fun n ml ->
  1512. print "%s:\n" n;
  1513. List.iter (fun m ->
  1514. print "\t%s\n" (m.m_extra.m_file);
  1515. ) ml;
  1516. ) dep;
  1517. close()
  1518. (*
  1519. Build a default safe-cast expression :
  1520. { var $t = <e>; if( Std.is($t,<t>) ) $t else throw "Class cast error"; }
  1521. *)
  1522. let default_cast ?(vtmp="$t") com e texpr t p =
  1523. let api = com.basic in
  1524. let mk_texpr = function
  1525. | TClassDecl c -> TAnon { a_fields = PMap.empty; a_status = ref (Statics c) }
  1526. | TEnumDecl e -> TAnon { a_fields = PMap.empty; a_status = ref (EnumStatics e) }
  1527. | TAbstractDecl a -> TAnon { a_fields = PMap.empty; a_status = ref (AbstractStatics a) }
  1528. | TTypeDecl _ -> assert false
  1529. in
  1530. let vtmp = alloc_var vtmp e.etype in
  1531. let var = mk (TVar (vtmp,Some e)) api.tvoid p in
  1532. let vexpr = mk (TLocal vtmp) e.etype p in
  1533. let texpr = mk (TTypeExpr texpr) (mk_texpr texpr) p in
  1534. let std = (try List.find (fun t -> t_path t = ([],"Std")) com.types with Not_found -> assert false) in
  1535. let fis = (try
  1536. let c = (match std with TClassDecl c -> c | _ -> assert false) in
  1537. FStatic (c, PMap.find "is" c.cl_statics)
  1538. with Not_found ->
  1539. assert false
  1540. ) in
  1541. let std = mk (TTypeExpr std) (mk_texpr std) p in
  1542. let is = mk (TField (std,fis)) (tfun [t_dynamic;t_dynamic] api.tbool) p in
  1543. let is = mk (TCall (is,[vexpr;texpr])) api.tbool p in
  1544. let exc = mk (TThrow (mk (TConst (TString "Class cast error")) api.tstring p)) t p in
  1545. let check = mk (TIf (mk_parent is,mk (TCast (vexpr,None)) t p,Some exc)) t p in
  1546. mk (TBlock [var;check;vexpr]) t p
  1547. (** Overload resolution **)
  1548. module Overloads =
  1549. struct
  1550. let rec simplify_t t = match t with
  1551. | TAbstract(a,_) when Meta.has Meta.CoreType a.a_meta ->
  1552. t
  1553. | TInst _ | TEnum _ ->
  1554. t
  1555. | TAbstract(a,tl) -> simplify_t (Abstract.get_underlying_type a tl)
  1556. | TType(({ t_path = [],"Null" } as t), [t2]) -> (match simplify_t t2 with
  1557. | (TAbstract(a,_) as t2) when Meta.has Meta.CoreType a.a_meta ->
  1558. TType(t, [simplify_t t2])
  1559. | (TEnum _ as t2) ->
  1560. TType(t, [simplify_t t2])
  1561. | t2 -> t2)
  1562. | TType(t, tl) ->
  1563. simplify_t (apply_params t.t_params tl t.t_type)
  1564. | TMono r -> (match !r with
  1565. | Some t -> simplify_t t
  1566. | None -> t_dynamic)
  1567. | TAnon _ -> t_dynamic
  1568. | TDynamic _ -> t
  1569. | TLazy f -> simplify_t (!f())
  1570. | TFun _ -> t
  1571. (* rate type parameters *)
  1572. let rate_tp tlfun tlarg =
  1573. let acc = ref 0 in
  1574. List.iter2 (fun f a -> if not (type_iseq f a) then incr acc) tlfun tlarg;
  1575. !acc
  1576. (**
  1577. The rate function returns an ( int * int ) type.
  1578. The smaller the int, the best rated the caller argument is in comparison with the callee.
  1579. The first int refers to how many "conversions" would be necessary to convert from the callee to the caller type, and
  1580. the second refers to the type parameters.
  1581. **)
  1582. let rec rate_conv cacc tfun targ =
  1583. match simplify_t tfun, simplify_t targ with
  1584. | TInst({ cl_interface = true } as cf, tlf), TInst(ca, tla) ->
  1585. (* breadth-first *)
  1586. let stack = ref [0,ca,tla] in
  1587. let cur = ref (0, ca,tla) in
  1588. let rec loop () =
  1589. match !stack with
  1590. | [] -> (let acc, ca, tla = !cur in match ca.cl_super with
  1591. | None -> raise Not_found
  1592. | Some (sup,tls) ->
  1593. cur := (acc+1,sup,List.map (apply_params ca.cl_params tla) tls);
  1594. stack := [!cur];
  1595. loop())
  1596. | (acc,ca,tla) :: _ when ca == cf ->
  1597. acc,tla
  1598. | (acc,ca,tla) :: s ->
  1599. stack := s @ List.map (fun (c,tl) -> (acc+1,c,List.map (apply_params ca.cl_params tla) tl)) ca.cl_implements;
  1600. loop()
  1601. in
  1602. let acc, tla = loop() in
  1603. (cacc + acc, rate_tp tlf tla)
  1604. | TInst(cf,tlf), TInst(ca,tla) ->
  1605. let rec loop acc ca tla =
  1606. if cf == ca then
  1607. acc, tla
  1608. else match ca.cl_super with
  1609. | None -> raise Not_found
  1610. | Some(sup,stl) ->
  1611. loop (acc+1) sup (List.map (apply_params ca.cl_params tla) stl)
  1612. in
  1613. let acc, tla = loop 0 ca tla in
  1614. (cacc + acc, rate_tp tlf tla)
  1615. | TEnum(ef,tlf), TEnum(ea, tla) ->
  1616. if ef != ea then raise Not_found;
  1617. (cacc, rate_tp tlf tla)
  1618. | TDynamic _, TDynamic _ ->
  1619. (cacc, 0)
  1620. | TDynamic _, _ ->
  1621. (max_int, 0) (* a function with dynamic will always be worst of all *)
  1622. | TAbstract(a, _), TDynamic _ when Meta.has Meta.CoreType a.a_meta ->
  1623. (cacc + 2, 0) (* a dynamic to a basic type will have an "unboxing" penalty *)
  1624. | _, TDynamic _ ->
  1625. (cacc + 1, 0)
  1626. | TAbstract(af,tlf), TAbstract(aa,tla) ->
  1627. (if af == aa then
  1628. (cacc, rate_tp tlf tla)
  1629. else
  1630. let ret = ref None in
  1631. if List.exists (fun t -> try
  1632. ret := Some (rate_conv (cacc+1) (apply_params af.a_params tlf t) targ);
  1633. true
  1634. with | Not_found ->
  1635. false
  1636. ) af.a_from then
  1637. Option.get !ret
  1638. else
  1639. if List.exists (fun t -> try
  1640. ret := Some (rate_conv (cacc+1) tfun (apply_params aa.a_params tla t));
  1641. true
  1642. with | Not_found ->
  1643. false
  1644. ) aa.a_to then
  1645. Option.get !ret
  1646. else
  1647. raise Not_found)
  1648. | TType({ t_path = [], "Null" }, [tf]), TType({ t_path = [], "Null" }, [ta]) ->
  1649. rate_conv (cacc+0) tf ta
  1650. | TType({ t_path = [], "Null" }, [tf]), ta ->
  1651. rate_conv (cacc+1) tf ta
  1652. | tf, TType({ t_path = [], "Null" }, [ta]) ->
  1653. rate_conv (cacc+1) tf ta
  1654. | TFun _, TFun _ -> (* unify will make sure they are compatible *)
  1655. cacc,0
  1656. | tfun,targ ->
  1657. raise Not_found
  1658. let is_best arg1 arg2 =
  1659. (List.for_all2 (fun v1 v2 ->
  1660. v1 <= v2)
  1661. arg1 arg2) && (List.exists2 (fun v1 v2 ->
  1662. v1 < v2)
  1663. arg1 arg2)
  1664. let rec rm_duplicates acc ret = match ret with
  1665. | [] -> acc
  1666. | ( el, t, _ ) :: ret when List.exists (fun (_,t2,_) -> type_iseq t t2) acc ->
  1667. rm_duplicates acc ret
  1668. | r :: ret ->
  1669. rm_duplicates (r :: acc) ret
  1670. let s_options rated =
  1671. String.concat ",\n" (List.map (fun ((elist,t,_),rate) ->
  1672. "( " ^ (String.concat "," (List.map (fun(e,_) -> s_expr (s_type (print_context())) e) elist)) ^ " ) => " ^
  1673. "( " ^ (String.concat "," (List.map (fun (i,i2) -> string_of_int i ^ ":" ^ string_of_int i2) rate)) ^ " ) => " ^ (s_type (print_context()) t)
  1674. ) rated)
  1675. let count_optionals elist =
  1676. List.fold_left (fun acc (_,is_optional) -> if is_optional then acc + 1 else acc) 0 elist
  1677. let rec fewer_optionals acc compatible = match acc, compatible with
  1678. | _, [] -> acc
  1679. | [], c :: comp -> fewer_optionals [c] comp
  1680. | (elist_acc, _, _) :: _, ((elist, _, _) as cur) :: comp ->
  1681. let acc_opt = count_optionals elist_acc in
  1682. let comp_opt = count_optionals elist in
  1683. if acc_opt = comp_opt then
  1684. fewer_optionals (cur :: acc) comp
  1685. else if acc_opt < comp_opt then
  1686. fewer_optionals acc comp
  1687. else
  1688. fewer_optionals [cur] comp
  1689. let reduce_compatible compatible = match fewer_optionals [] (rm_duplicates [] compatible) with
  1690. | [] -> []
  1691. | [v] -> [v]
  1692. | compatible ->
  1693. (* convert compatible into ( rate * compatible_type ) list *)
  1694. let rec mk_rate acc elist args = match elist, args with
  1695. | [], [] -> acc
  1696. | (_,true) :: elist, _ :: args -> mk_rate acc elist args
  1697. | (e,false) :: elist, (n,o,t) :: args ->
  1698. (* if the argument is an implicit cast, we need to start with a penalty *)
  1699. (* The penalty should be higher than any other implicit cast - other than Dynamic *)
  1700. (* since Dynamic has a penalty of max_int, we'll impose max_int - 1 to it *)
  1701. (match e.eexpr with
  1702. | TMeta( (Meta.ImplicitCast,_,_), _) ->
  1703. mk_rate ((max_int - 1, 0) :: acc) elist args
  1704. | _ ->
  1705. mk_rate (rate_conv 0 t e.etype :: acc) elist args)
  1706. | _ -> assert false
  1707. in
  1708. let rated = ref [] in
  1709. List.iter (function
  1710. | (elist,TFun(args,ret),d) -> (try
  1711. rated := ( (elist,TFun(args,ret),d), mk_rate [] elist args ) :: !rated
  1712. with | Not_found -> ())
  1713. | _ -> assert false
  1714. ) compatible;
  1715. let rec loop best rem = match best, rem with
  1716. | _, [] -> best
  1717. | [], r1 :: rem -> loop [r1] rem
  1718. | (bover, bargs) :: b1, (rover, rargs) :: rem ->
  1719. if is_best bargs rargs then
  1720. loop best rem
  1721. else if is_best rargs bargs then
  1722. loop (loop b1 [rover,rargs]) rem
  1723. else (* equally specific *)
  1724. loop ( (rover,rargs) :: best ) rem
  1725. in
  1726. let r = loop [] !rated in
  1727. List.map fst r
  1728. end;;
  1729. module UnificationCallback = struct
  1730. let tf_stack = ref []
  1731. let check_call_params f el tl =
  1732. let rec loop acc el tl = match el,tl with
  1733. | e :: el, (n,_,t) :: tl ->
  1734. loop ((f e t) :: acc) el tl
  1735. | [], [] ->
  1736. acc
  1737. | [],_ ->
  1738. acc
  1739. | e :: el, [] ->
  1740. loop (e :: acc) el []
  1741. in
  1742. List.rev (loop [] el tl)
  1743. let check_call f el t = match follow t with
  1744. | TFun(args,_) ->
  1745. check_call_params f el args
  1746. | _ ->
  1747. List.map (fun e -> f e t_dynamic) el
  1748. let rec run ff e =
  1749. let f e t =
  1750. if not (type_iseq e.etype t) then
  1751. ff e t
  1752. else
  1753. e
  1754. in
  1755. let check e = match e.eexpr with
  1756. | TBinop((OpAssign | OpAssignOp _),e1,e2) ->
  1757. assert false; (* this trigger #4347, to be fixed before enabling
  1758. let e2 = f e2 e1.etype in
  1759. {e with eexpr = TBinop(op,e1,e2)} *)
  1760. | TVar(v,Some ev) ->
  1761. let eo = Some (f ev v.v_type) in
  1762. { e with eexpr = TVar(v,eo) }
  1763. | TCall(e1,el) ->
  1764. let el = check_call f el e1.etype in
  1765. {e with eexpr = TCall(e1,el)}
  1766. | TNew(c,tl,el) ->
  1767. begin try
  1768. let tcf,_ = get_constructor (fun cf -> apply_params c.cl_params tl cf.cf_type) c in
  1769. let el = check_call f el tcf in
  1770. {e with eexpr = TNew(c,tl,el)}
  1771. with Not_found ->
  1772. e
  1773. end
  1774. | TArrayDecl el ->
  1775. begin match follow e.etype with
  1776. | TInst({cl_path=[],"Array"},[t]) -> {e with eexpr = TArrayDecl(List.map (fun e -> f e t) el)}
  1777. | _ -> e
  1778. end
  1779. | TObjectDecl fl ->
  1780. begin match follow e.etype with
  1781. | TAnon an ->
  1782. let fl = List.map (fun (n,e) ->
  1783. let e = try
  1784. let t = (PMap.find n an.a_fields).cf_type in
  1785. f e t
  1786. with Not_found ->
  1787. e
  1788. in
  1789. n,e
  1790. ) fl in
  1791. { e with eexpr = TObjectDecl fl }
  1792. | _ -> e
  1793. end
  1794. | TReturn (Some e1) ->
  1795. begin match !tf_stack with
  1796. | tf :: _ -> { e with eexpr = TReturn (Some (f e1 tf.tf_type))}
  1797. | _ -> e
  1798. end
  1799. | _ ->
  1800. e
  1801. in
  1802. match e.eexpr with
  1803. | TFunction tf ->
  1804. tf_stack := tf :: !tf_stack;
  1805. let etf = {e with eexpr = TFunction({tf with tf_expr = run f tf.tf_expr})} in
  1806. tf_stack := List.tl !tf_stack;
  1807. etf
  1808. | _ ->
  1809. check (Type.map_expr (run ff) e)
  1810. end;;
  1811. module DeprecationCheck = struct
  1812. let curclass = ref null_class
  1813. let warned_positions = Hashtbl.create 0
  1814. let print_deprecation_message com meta s p_usage =
  1815. let s = match meta with
  1816. | _,[EConst(String s),_],_ -> s
  1817. | _ -> Printf.sprintf "Usage of this %s is deprecated" s
  1818. in
  1819. if not (Hashtbl.mem warned_positions p_usage) then begin
  1820. Hashtbl.replace warned_positions p_usage true;
  1821. com.warning s p_usage;
  1822. end
  1823. let check_meta com meta s p_usage =
  1824. try
  1825. print_deprecation_message com (Meta.get Meta.Deprecated meta) s p_usage;
  1826. with Not_found ->
  1827. ()
  1828. let check_cf com cf p = check_meta com cf.cf_meta "field" p
  1829. let check_class com c p = if c != !curclass then check_meta com c.cl_meta "class" p
  1830. let check_enum com en p = check_meta com en.e_meta "enum" p
  1831. let check_ef com ef p = check_meta com ef.ef_meta "enum field" p
  1832. let check_typedef com t p = check_meta com t.t_meta "typedef" p
  1833. let check_module_type com mt p = match mt with
  1834. | TClassDecl c -> check_class com c p
  1835. | TEnumDecl en -> check_enum com en p
  1836. | _ -> ()
  1837. let run com =
  1838. let rec expr e = match e.eexpr with
  1839. | TField(e1,fa) ->
  1840. expr e1;
  1841. begin match fa with
  1842. | FStatic(c,cf) | FInstance(c,_,cf) ->
  1843. check_class com c e.epos;
  1844. check_cf com cf e.epos
  1845. | FAnon cf ->
  1846. check_cf com cf e.epos
  1847. | FClosure(co,cf) ->
  1848. (match co with None -> () | Some (c,_) -> check_class com c e.epos);
  1849. check_cf com cf e.epos
  1850. | FEnum(en,ef) ->
  1851. check_enum com en e.epos;
  1852. check_ef com ef e.epos;
  1853. | _ ->
  1854. ()
  1855. end
  1856. | TNew(c,_,el) ->
  1857. List.iter expr el;
  1858. check_class com c e.epos;
  1859. (match c.cl_constructor with None -> () | Some cf -> check_cf com cf e.epos)
  1860. | TTypeExpr(mt) | TCast(_,Some mt) ->
  1861. check_module_type com mt e.epos
  1862. | TMeta((Meta.Deprecated,_,_) as meta,e1) ->
  1863. print_deprecation_message com meta "field" e1.epos;
  1864. expr e1;
  1865. | _ ->
  1866. Type.iter expr e
  1867. in
  1868. List.iter (fun t -> match t with
  1869. | TClassDecl c ->
  1870. curclass := c;
  1871. let field cf = match cf.cf_expr with None -> () | Some e -> expr e in
  1872. (match c.cl_constructor with None -> () | Some cf -> field cf);
  1873. (match c.cl_init with None -> () | Some e -> expr e);
  1874. List.iter field c.cl_ordered_statics;
  1875. List.iter field c.cl_ordered_fields;
  1876. | _ ->
  1877. ()
  1878. ) com.types
  1879. end
  1880. let interpolate_code com code tl f_string f_expr p =
  1881. let exprs = Array.of_list tl in
  1882. let i = ref 0 in
  1883. let err msg =
  1884. let pos = { p with pmin = p.pmin + !i } in
  1885. com.error msg pos
  1886. in
  1887. let regex = Str.regexp "[{}]" in
  1888. let rec loop m = match m with
  1889. | [] ->
  1890. ()
  1891. | Str.Text txt :: tl ->
  1892. i := !i + String.length txt;
  1893. f_string txt;
  1894. loop tl
  1895. | Str.Delim a :: Str.Delim b :: tl when a = b ->
  1896. i := !i + 2;
  1897. f_string a;
  1898. loop tl
  1899. | Str.Delim "{" :: Str.Text n :: Str.Delim "}" :: tl ->
  1900. begin try
  1901. let expr = Array.get exprs (int_of_string n) in
  1902. f_expr expr;
  1903. with
  1904. | Failure "int_of_string" ->
  1905. f_string ("{" ^ n ^ "}");
  1906. | Invalid_argument _ ->
  1907. err ("Out-of-bounds special parameter: " ^ n)
  1908. end;
  1909. i := !i + 2 + String.length n;
  1910. loop tl
  1911. | Str.Delim x :: tl ->
  1912. f_string x;
  1913. incr i;
  1914. loop tl
  1915. in
  1916. loop (Str.full_split regex code)
  1917. let map_source_header com f =
  1918. match Common.defined_value_safe com Define.SourceHeader with
  1919. | "" -> ()
  1920. | s -> f s
  1921. (* Collection of functions that return expressions *)
  1922. module ExprBuilder = struct
  1923. let make_static_this c p =
  1924. let ta = TAnon { a_fields = c.cl_statics; a_status = ref (Statics c) } in
  1925. mk (TTypeExpr (TClassDecl c)) ta p
  1926. let make_int com i p =
  1927. mk (TConst (TInt (Int32.of_int i))) com.basic.tint p
  1928. let make_float com f p =
  1929. mk (TConst (TFloat f)) com.basic.tfloat p
  1930. let make_null t p =
  1931. mk (TConst TNull) t p
  1932. let make_local v p =
  1933. mk (TLocal v) v.v_type p
  1934. let make_const_texpr com ct p = match ct with
  1935. | TString s -> mk (TConst (TString s)) com.basic.tstring p
  1936. | TInt i -> mk (TConst (TInt i)) com.basic.tint p
  1937. | TFloat f -> mk (TConst (TFloat f)) com.basic.tfloat p
  1938. | TBool b -> mk (TConst (TBool b)) com.basic.tbool p
  1939. | TNull -> mk (TConst TNull) (com.basic.tnull (mk_mono())) p
  1940. | _ -> error "Unsupported constant" p
  1941. end
  1942. (* Static extensions for classes *)
  1943. module ExtClass = struct
  1944. let add_cl_init c e = match c.cl_init with
  1945. | None -> c.cl_init <- Some e
  1946. | Some e' -> c.cl_init <- Some (concat e' e)
  1947. let add_static_init c cf e p =
  1948. let ethis = ExprBuilder.make_static_this c p in
  1949. let ef1 = mk (TField(ethis,FStatic(c,cf))) cf.cf_type p in
  1950. let e_assign = mk (TBinop(OpAssign,ef1,e)) e.etype p in
  1951. add_cl_init c e_assign
  1952. end