genswf9.ml 68 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372
  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 As3
  25. open As3hl
  26. open Common
  27. type read = Read
  28. type write = Unused__ | Write
  29. type tkind =
  30. | KInt
  31. | KUInt
  32. | KFloat
  33. | KBool
  34. | KType of hl_name
  35. | KDynamic
  36. | KNone
  37. type register = {
  38. rid : int;
  39. rtype : tkind;
  40. mutable rused : bool;
  41. mutable rinit : bool;
  42. mutable rcond : bool;
  43. }
  44. type 'a access =
  45. | VReg of register
  46. | VId of hl_name
  47. | VCast of hl_name * tkind
  48. | VGlobal of hl_name
  49. | VArray
  50. | VScope of hl_slot
  51. | VVolatile of hl_name * tkind option
  52. | VSuper of hl_name
  53. type local =
  54. | LReg of register
  55. | LScope of hl_slot
  56. | LGlobal of hl_name
  57. type code_infos = {
  58. mutable iregs : register DynArray.t;
  59. mutable ipos : int;
  60. mutable istack : int;
  61. mutable imax : int;
  62. mutable iscopes : int;
  63. mutable imaxscopes : int;
  64. mutable iloop : int;
  65. mutable icond : bool;
  66. }
  67. type try_infos = {
  68. tr_pos : int;
  69. tr_end : int;
  70. tr_catch_pos : int;
  71. tr_type : t;
  72. }
  73. type context = {
  74. (* globals *)
  75. com : Common.context;
  76. debugger : bool;
  77. swc : bool;
  78. boot : path;
  79. swf_protected : bool;
  80. need_ctor_skip : bool;
  81. mutable cur_class : tclass;
  82. mutable debug : bool;
  83. mutable last_line : int;
  84. mutable last_file : string;
  85. (* per-function *)
  86. mutable locals : (int,tvar * local) PMap.t;
  87. mutable code : hl_opcode DynArray.t;
  88. mutable infos : code_infos;
  89. mutable trys : try_infos list;
  90. mutable breaks : (unit -> unit) list;
  91. mutable continues : (int -> unit) list;
  92. mutable in_static : bool;
  93. mutable block_vars : (hl_slot * string * hl_name option) list;
  94. mutable try_scope_reg : register option;
  95. mutable for_call : bool;
  96. }
  97. let invalid_expr p = error "Invalid expression" p
  98. let stack_error p = error "Stack error" p
  99. let index_int (x : int) : 'a index = Obj.magic (x + 1)
  100. let index_nz_int (x : int) : 'a index_nz = Obj.magic x
  101. let tid (x : 'a index) : int = Obj.magic x
  102. let ethis = mk (TConst TThis) (mk_mono()) null_pos
  103. let dynamic_prop = HMMultiNameLate [HNPublic (Some "")]
  104. let is_special_compare e1 e2 =
  105. match e1.eexpr, e2.eexpr with
  106. | TConst TNull, _ | _ , TConst TNull -> None
  107. | _ ->
  108. match follow e1.etype, follow e2.etype with
  109. | TInst ({ cl_path = [],"Xml" } as c,_) , _ | _ , TInst ({ cl_path = [],"Xml" } as c,_) -> Some c
  110. | _ -> None
  111. let write ctx op =
  112. DynArray.add ctx.code op;
  113. ctx.infos.ipos <- ctx.infos.ipos + 1;
  114. let s = ctx.infos.istack + As3hlparse.stack_delta op in
  115. ctx.infos.istack <- s;
  116. if s > ctx.infos.imax then ctx.infos.imax <- s;
  117. match op with
  118. | HScope ->
  119. let n = ctx.infos.iscopes + 1 in
  120. ctx.infos.iscopes <- n;
  121. if n > ctx.infos.imaxscopes then ctx.infos.imaxscopes <- n
  122. | HPopScope ->
  123. ctx.infos.iscopes <- ctx.infos.iscopes - 1
  124. | _ ->
  125. ()
  126. let jump ctx cond =
  127. let op = DynArray.length ctx.code in
  128. let p = ctx.infos.ipos in
  129. write ctx (HJump (cond,0));
  130. (fun () ->
  131. let delta = ctx.infos.ipos - p in
  132. DynArray.set ctx.code op (HJump (cond,delta))
  133. )
  134. let jump_back ctx =
  135. let p = ctx.infos.ipos in
  136. write ctx HLabel;
  137. (fun cond ->
  138. let delta = p - ctx.infos.ipos in
  139. write ctx (HJump (cond,delta))
  140. )
  141. let real_path = function
  142. | [] , "Int" -> [] , "int"
  143. | [] , "UInt" -> [] , "uint"
  144. | [] , "Float" -> [] , "Number"
  145. | [] , "Bool" -> [] , "Boolean"
  146. | [] , "Enum" -> [] , "Class"
  147. | [] , "EnumValue" -> [] , "Object"
  148. | ["flash";"xml"], "XML" -> [], "XML"
  149. | ["flash";"xml"], "XMLList" -> [], "XMLList"
  150. | ["flash";"utils"], "QName" -> [] , "QName"
  151. | ["flash";"utils"], "Namespace" -> [] , "Namespace"
  152. | ["flash";"utils"], "Object" -> [] , "Object"
  153. | ["flash";"utils"], "Function" -> [] , "Function"
  154. | ["flash"] , "FlashXml__" -> [] , "Xml"
  155. | ["flash";"errors"] , "Error" -> [], "Error"
  156. | ["flash"] , "Vector" -> ["__AS3__";"vec"], "Vector"
  157. | path -> path
  158. let type_path ctx path =
  159. let pack, name = real_path path in
  160. HMPath (pack,name)
  161. let rec follow_basic t =
  162. match t with
  163. | TMono r ->
  164. (match !r with
  165. | Some t -> follow_basic t
  166. | _ -> t)
  167. | TLazy f ->
  168. follow_basic (!f())
  169. | TType ({ t_path = [],"Null" },[tp]) ->
  170. (match follow_basic tp with
  171. | TMono _
  172. | TFun _
  173. | TAbstract ({ a_path = ([],"Int") },[])
  174. | TAbstract ({ a_path = ([],"Float") },[])
  175. | TAbstract ({ a_path = [],"UInt" },[])
  176. | TAbstract ({ a_path = ([],"Bool") },[])
  177. | TInst ({ cl_path = (["haxe"],"Int32") },[])
  178. | TInst ({ cl_path = ([],"Int") },[])
  179. | TInst ({ cl_path = ([],"Float") },[])
  180. | TType ({ t_path = [],"UInt" },[])
  181. | TEnum ({ e_path = ([],"Bool") },[]) -> t
  182. | t -> t)
  183. | TType ({ t_path = ["flash";"utils"],"Object" },[])
  184. | TType ({ t_path = ["flash";"utils"],"Function" },[])
  185. | TType ({ t_path = [],"UInt" },[]) ->
  186. t
  187. | TType (t,tl) ->
  188. follow_basic (apply_params t.t_types tl t.t_type)
  189. | TAbstract (a,pl) when a.a_impl <> None ->
  190. follow_basic (apply_params a.a_types pl a.a_this)
  191. | _ -> t
  192. let rec type_id ctx t =
  193. match follow_basic t with
  194. | TInst ({ cl_path = ["haxe"],"Int32" },_) ->
  195. type_path ctx ([],"Int")
  196. | TInst ({ cl_path = ["flash"],"Vector" } as c,pl) ->
  197. (match pl with
  198. | [TInst({cl_kind = KTypeParameter _},_)] -> type_path ctx ([],"Object")
  199. | _ -> HMParams (type_path ctx c.cl_path,List.map (type_id ctx) pl))
  200. | TInst (c,_) ->
  201. (match c.cl_kind with
  202. | KTypeParameter l ->
  203. (match l with
  204. | [t] -> type_id ctx t
  205. | _ -> type_path ctx ([],"Object"))
  206. | KExtension (c,params) ->
  207. type_id ctx (TInst (c,params))
  208. | _ ->
  209. type_path ctx c.cl_path)
  210. | TAbstract (a,_) ->
  211. type_path ctx a.a_path
  212. | TFun _ | TType ({ t_path = ["flash";"utils"],"Function" },[]) ->
  213. type_path ctx ([],"Function")
  214. | TType ({ t_path = ([],"UInt") as path },_) ->
  215. type_path ctx path
  216. | TEnum ({ e_path = [],"XmlType"; e_extern = true },_) ->
  217. HMPath ([],"String")
  218. | TEnum (e,_) ->
  219. let rec loop = function
  220. | [] -> type_path ctx e.e_path
  221. | (Meta.FakeEnum,[Ast.EConst (Ast.Ident n),_],_) :: _ -> type_path ctx ([],n)
  222. | _ :: l -> loop l
  223. in
  224. loop e.e_meta
  225. | _ ->
  226. HMPath ([],"Object")
  227. let type_opt ctx t =
  228. match follow_basic t with
  229. | TDynamic _ | TMono _ -> None
  230. | _ -> Some (type_id ctx t)
  231. let type_void ctx t =
  232. match follow t with
  233. | TEnum ({ e_path = [],"Void" },_) | TAbstract ({ a_path = [],"Void" },_) -> Some (HMPath ([],"void"))
  234. | _ -> type_opt ctx t
  235. let classify ctx t =
  236. match follow_basic t with
  237. | TAbstract ({ a_path = [],"Int" },_) | TInst ({ cl_path = [],"Int" },_) | TInst ({ cl_path = ["haxe"],"Int32" },_) ->
  238. KInt
  239. | TAbstract ({ a_path = [],"Float" },_) | TInst ({ cl_path = [],"Float" },_) ->
  240. KFloat
  241. | TAbstract ({ a_path = [],"Bool" },_) | TEnum ({ e_path = [],"Bool" },_) ->
  242. KBool
  243. | TAbstract ({ a_path = [],"Void" },_) | TEnum ({ e_path = [],"Void" },_) ->
  244. KDynamic
  245. | TEnum ({ e_path = [],"XmlType"; e_extern = true },_) ->
  246. KType (HMPath ([],"String"))
  247. | TEnum (e,_) ->
  248. let rec loop = function
  249. | [] -> KType (type_id ctx t)
  250. | (Meta.FakeEnum,[Ast.EConst (Ident n),_],_) :: _ ->
  251. (match n with
  252. | "Int" -> KInt
  253. | "UInt" -> KUInt
  254. | "String" -> KType (HMPath ([],"String"))
  255. | _ -> assert false)
  256. | _ :: l -> loop l
  257. in
  258. loop e.e_meta
  259. | TAbstract ({ a_path = [],"UInt" },_) | TType ({ t_path = [],"UInt" },_) ->
  260. KUInt
  261. | TFun _ | TType ({ t_path = ["flash";"utils"],"Function" },[]) ->
  262. KType (HMPath ([],"Function"))
  263. | TAnon a ->
  264. (match !(a.a_status) with
  265. | Statics _ -> KNone
  266. | _ -> KDynamic)
  267. | TType ({ t_path = ["flash";"utils"],"Object" },[]) ->
  268. KType (HMPath ([],"Object"))
  269. | TInst _ | TAbstract _ ->
  270. KType (type_id ctx t)
  271. | TMono _
  272. | TType _
  273. | TDynamic _ ->
  274. KDynamic
  275. | TLazy _ ->
  276. assert false
  277. (* some field identifiers might cause issues with SWC *)
  278. let reserved i =
  279. match i with
  280. | "int" -> "_" ^ i
  281. | _ -> i
  282. let ident i =
  283. HMPath ([],reserved i)
  284. let as3 p =
  285. HMName (p,HNNamespace "http://adobe.com/AS3/2006/builtin")
  286. let property ctx p t =
  287. match follow t with
  288. | TInst ({ cl_path = [],"Array" },_) ->
  289. (match p with
  290. | "length" -> ident p, Some KInt, false (* UInt in the spec *)
  291. | "copy" | "insert" | "remove" | "iterator" | "toString" | "map" | "filter" -> ident p , None, true
  292. | _ -> as3 p, None, false);
  293. | TInst ({ cl_path = ["flash"],"Vector" },_) ->
  294. (match p with
  295. | "length" -> ident p, Some KInt, false (* UInt in the spec *)
  296. | "fixed" | "toString" -> ident p, None, false
  297. | "iterator" -> ident p, None, true
  298. | _ -> as3 p, None, false);
  299. | TInst ({ cl_path = [],"String" },_) ->
  300. (match p with
  301. | "length" (* Int in AS3/Haxe *) -> ident p, None, false
  302. | "charCodeAt" (* use Haxe version *) -> ident p, None, true
  303. | "cca" -> as3 "charCodeAt", None, false
  304. | _ -> as3 p, None, false);
  305. | TAnon a ->
  306. (match !(a.a_status) with
  307. | Statics { cl_path = [], "Math" } ->
  308. (match p with
  309. | "POSITIVE_INFINITY" | "NEGATIVE_INFINITY" | "NaN" -> ident p, Some KFloat, false
  310. | "floor" | "ceil" | "round" when ctx.for_call -> ident p, Some KInt, false
  311. | "ffloor" | "fceil" | "fround" -> ident (String.sub p 1 (String.length p - 1)), None, false
  312. | _ -> ident p, None, false)
  313. | _ -> ident p, None, false)
  314. | TInst ({ cl_kind = KExtension _ } as c,params) ->
  315. (* cast type when accessing an extension field *)
  316. (try
  317. let f = PMap.find p c.cl_fields in
  318. ident p, Some (classify ctx (apply_params c.cl_types params f.cf_type)), false
  319. with Not_found ->
  320. ident p, None, false)
  321. | TInst ({ cl_interface = true } as c,_) ->
  322. (* lookup the interface in which the field was actually declared *)
  323. let rec loop c =
  324. try
  325. (match PMap.find p c.cl_fields with
  326. | { cf_kind = Var _ } -> raise Exit (* no vars in interfaces in swf9 *)
  327. | _ -> c)
  328. with Not_found ->
  329. let rec loop2 = function
  330. | [] -> raise Not_found
  331. | (i,_) :: l ->
  332. try loop i with Not_found -> loop2 l
  333. in
  334. loop2 c.cl_implements
  335. in
  336. (try
  337. let c = loop c in
  338. let ns = HMName (reserved p, HNNamespace (match c.cl_path with [],n -> n | l,n -> String.concat "." l ^ ":" ^ n)) in
  339. ns, None, false
  340. with Not_found | Exit ->
  341. ident p, None, false)
  342. | _ ->
  343. ident p, None, false
  344. let default_infos() =
  345. {
  346. ipos = 0;
  347. istack = 0;
  348. imax = 0;
  349. iregs = DynArray.create();
  350. iscopes = 0;
  351. imaxscopes = 0;
  352. iloop = -1;
  353. icond = false;
  354. }
  355. let alloc_reg ctx k =
  356. let regs = ctx.infos.iregs in
  357. try
  358. let p = DynArray.index_of (fun r -> not r.rused && k = r.rtype) regs in
  359. let r = DynArray.unsafe_get regs p in
  360. r.rused <- true;
  361. r.rinit <- false;
  362. r
  363. with
  364. Not_found ->
  365. let r = {
  366. rid = DynArray.length regs + 1;
  367. rused = true;
  368. rinit = false;
  369. rtype = k;
  370. rcond = false;
  371. } in
  372. DynArray.add regs r;
  373. r
  374. let coerce ctx t =
  375. (* it would be useful to know if we don't already have
  376. this type on the stack (as detected by the bytecode verifier)...
  377. maybe this get removed at JIT, so it's only useful to reduce codesize
  378. *)
  379. if t <> KNone then
  380. write ctx (match t with
  381. | KInt -> HToInt
  382. | KUInt -> HToUInt
  383. | KFloat -> HToNumber
  384. | KBool -> HToBool
  385. | KType t -> HCast t
  386. | KDynamic -> HAsAny
  387. | KNone -> assert false
  388. )
  389. let set_reg ctx r =
  390. if not r.rinit then begin
  391. r.rinit <- true;
  392. if ctx.infos.icond then r.rcond <- true;
  393. end;
  394. coerce ctx r.rtype;
  395. write ctx (HSetReg r.rid)
  396. let set_reg_dup ctx r =
  397. if not r.rinit then begin
  398. r.rinit <- true;
  399. if ctx.infos.icond then r.rcond <- true;
  400. end;
  401. coerce ctx r.rtype;
  402. write ctx HDup;
  403. write ctx (HSetReg r.rid)
  404. let free_reg ctx r =
  405. r.rused <- false
  406. let pop ctx n =
  407. let rec loop n =
  408. if n > 0 then begin
  409. write ctx HPop;
  410. loop (n - 1)
  411. end
  412. in
  413. if n < 0 then assert false;
  414. let old = ctx.infos.istack in
  415. loop n;
  416. ctx.infos.istack <- old
  417. let is_member ctx name =
  418. let rec loop c =
  419. PMap.mem name c.cl_fields || (match c.cl_super with None -> false | Some (c,_) -> loop c)
  420. in
  421. loop ctx.cur_class
  422. let rename_block_var ctx v =
  423. (* we need to rename it since slots are accessed on a by-name basis *)
  424. let rec loop i =
  425. let name = v.v_name ^ string_of_int i in
  426. if List.exists (fun(_,x,_) -> name = x) ctx.block_vars || is_member ctx name then
  427. loop (i + 1)
  428. else
  429. v.v_name <- name
  430. in
  431. loop 1
  432. let define_local ctx ?(init=false) v p =
  433. let name = v.v_name in
  434. let t = v.v_type in
  435. let l = (if v.v_capture then begin
  436. let topt = type_opt ctx t in
  437. if List.exists (fun (_,x,_) -> name = x) ctx.block_vars || is_member ctx name then rename_block_var ctx v;
  438. let pos = List.length ctx.block_vars + 1 in
  439. ctx.block_vars <- (pos,v.v_name,topt) :: ctx.block_vars;
  440. LScope pos
  441. end else
  442. let r = alloc_reg ctx (classify ctx t) in
  443. if ctx.debug then write ctx (HDebugReg (name, r.rid, ctx.last_line));
  444. r.rinit <- init;
  445. LReg r
  446. ) in
  447. ctx.locals <- PMap.add v.v_id (v,l) ctx.locals
  448. let is_set v = (Obj.magic v) = Write
  449. let gen_local_access ctx v p (forset : 'a) : 'a access =
  450. match snd (try PMap.find v.v_id ctx.locals with Not_found -> error ("Unbound variable " ^ v.v_name) p) with
  451. | LReg r ->
  452. VReg r
  453. | LScope n ->
  454. write ctx (HGetScope 1);
  455. VScope n
  456. | LGlobal p ->
  457. if is_set forset then write ctx (HFindProp p);
  458. VGlobal p
  459. let get_local_register ctx v =
  460. match (try snd (PMap.find v.v_id ctx.locals) with Not_found -> LScope 0) with
  461. | LReg r -> Some r
  462. | _ -> None
  463. let rec setvar ctx (acc : write access) kret =
  464. match acc with
  465. | VReg r ->
  466. if kret <> None then
  467. set_reg_dup ctx r
  468. else
  469. set_reg ctx r;
  470. | VGlobal _ | VId _ | VCast _ | VArray | VScope _ when kret <> None ->
  471. let r = alloc_reg ctx (match kret with None -> assert false | Some k -> k) in
  472. set_reg_dup ctx r;
  473. setvar ctx acc None;
  474. write ctx (HReg r.rid);
  475. free_reg ctx r
  476. | VGlobal g ->
  477. write ctx (HSetProp g)
  478. | VId id | VCast (id,_) ->
  479. write ctx (HInitProp id)
  480. | VVolatile (id,_) ->
  481. write ctx (HArray 1);
  482. write ctx (HInitProp id)
  483. | VArray ->
  484. write ctx (HSetProp dynamic_prop);
  485. ctx.infos.istack <- ctx.infos.istack - 1
  486. | VScope n ->
  487. write ctx (HSetSlot n)
  488. | VSuper id ->
  489. write ctx (HSetSuper id)
  490. let getvar ctx (acc : read access) =
  491. match acc with
  492. | VReg r ->
  493. if not r.rinit then begin
  494. r.rinit <- true;
  495. r.rcond <- true;
  496. end;
  497. write ctx (HReg r.rid)
  498. | VId id ->
  499. write ctx (HGetProp id)
  500. | VVolatile (id,t) ->
  501. write ctx (HGetProp id);
  502. write ctx (HSmallInt 0);
  503. write ctx (HGetProp dynamic_prop);
  504. ctx.infos.istack <- ctx.infos.istack - 1;
  505. (match t with
  506. | None -> ()
  507. | Some t -> coerce ctx t)
  508. | VCast (id,t) ->
  509. write ctx (HGetProp id);
  510. coerce ctx t
  511. | VGlobal g ->
  512. write ctx (HGetLex g);
  513. | VArray ->
  514. write ctx (HGetProp dynamic_prop);
  515. ctx.infos.istack <- ctx.infos.istack - 1
  516. | VScope n ->
  517. write ctx (HGetSlot n)
  518. | VSuper id ->
  519. write ctx (HGetSuper id)
  520. let open_block ctx retval =
  521. let old_stack = ctx.infos.istack in
  522. let old_regs = DynArray.map (fun r -> r.rused) ctx.infos.iregs in
  523. let old_locals = ctx.locals in
  524. (fun() ->
  525. if ctx.infos.istack <> old_stack + (if retval then 1 else 0) then assert false;
  526. let rcount = DynArray.length old_regs + 1 in
  527. DynArray.iter (fun r ->
  528. if r.rid < rcount then
  529. r.rused <- DynArray.unsafe_get old_regs (r.rid - 1)
  530. else
  531. r.rused <- false
  532. ) ctx.infos.iregs;
  533. ctx.locals <- old_locals;
  534. )
  535. let begin_branch ctx =
  536. if ctx.infos.icond then
  537. (fun() -> ())
  538. else begin
  539. ctx.infos.icond <- true;
  540. (fun() -> ctx.infos.icond <- false)
  541. end
  542. let begin_switch ctx =
  543. let branch = begin_branch ctx in
  544. let switch_index = DynArray.length ctx.code in
  545. let switch_pos = ctx.infos.ipos in
  546. write ctx (HSwitch (0,[]));
  547. let constructs = ref [] in
  548. let max = ref 0 in
  549. let ftag tag =
  550. if tag > !max then max := tag;
  551. constructs := (tag,ctx.infos.ipos) :: !constructs;
  552. in
  553. let fend() =
  554. let cases = Array.create (!max + 1) 1 in
  555. List.iter (fun (tag,pos) -> Array.set cases tag (pos - switch_pos)) !constructs;
  556. DynArray.set ctx.code switch_index (HSwitch (1,Array.to_list cases));
  557. branch();
  558. in
  559. fend, ftag
  560. let debug_infos ?(is_min=true) ctx p =
  561. if ctx.debug then begin
  562. let line = Lexer.get_error_line (if is_min then p else { p with pmin = p.pmax }) in
  563. if ctx.last_file <> p.pfile then begin
  564. write ctx (HDebugFile (if ctx.debugger then Common.get_full_path p.pfile else p.pfile));
  565. ctx.last_file <- p.pfile;
  566. ctx.last_line <- -1;
  567. end;
  568. if ctx.last_line <> line then begin
  569. write ctx (HDebugLine line);
  570. ctx.last_line <- line;
  571. end
  572. end
  573. let gen_constant ctx c t p =
  574. match c with
  575. | TInt i ->
  576. let unsigned = classify ctx t = KUInt in
  577. if Int32.compare i (-128l) > 0 && Int32.compare i 128l < 0 then begin
  578. write ctx (HSmallInt (Int32.to_int i));
  579. if unsigned then write ctx HToUInt;
  580. end else
  581. write ctx (if unsigned then HUIntRef i else HIntRef i)
  582. | TFloat f ->
  583. let f = float_of_string f in
  584. write ctx (HFloat f);
  585. | TString s ->
  586. write ctx (HString (Genswf8.to_utf8 s));
  587. | TBool b ->
  588. write ctx (if b then HTrue else HFalse);
  589. | TNull ->
  590. write ctx HNull;
  591. coerce ctx (classify ctx t)
  592. | TThis ->
  593. write ctx HThis
  594. | TSuper ->
  595. assert false
  596. let end_fun ctx args dparams tret =
  597. {
  598. hlmt_index = 0;
  599. hlmt_ret = type_void ctx tret;
  600. hlmt_args = List.map (fun (v,_) -> type_opt ctx v.v_type) args;
  601. hlmt_native = false;
  602. hlmt_var_args = false;
  603. hlmt_debug_name = None;
  604. hlmt_dparams = dparams;
  605. hlmt_pnames = if ctx.swc || ctx.debugger then Some (List.map (fun (v,_) -> Some v.v_name) args) else None;
  606. hlmt_new_block = false;
  607. hlmt_unused_flag = false;
  608. hlmt_arguments_defined = false;
  609. hlmt_uses_dxns = false;
  610. hlmt_function = None;
  611. }
  612. let begin_fun ctx args tret el stat p =
  613. let old_locals = ctx.locals in
  614. let old_code = ctx.code in
  615. let old_infos = ctx.infos in
  616. let old_trys = ctx.trys in
  617. let old_bvars = ctx.block_vars in
  618. let old_static = ctx.in_static in
  619. let last_line = ctx.last_line in
  620. let old_treg = ctx.try_scope_reg in
  621. ctx.infos <- default_infos();
  622. ctx.code <- DynArray.create();
  623. ctx.trys <- [];
  624. ctx.block_vars <- [];
  625. ctx.in_static <- stat;
  626. ctx.last_line <- -1;
  627. ctx.last_file <- "";
  628. debug_infos ctx p;
  629. let rec find_this e =
  630. match e.eexpr with
  631. | TFunction _ -> ()
  632. | TConst TThis | TConst TSuper -> raise Exit
  633. | _ -> Type.iter find_this e
  634. in
  635. let this_reg = try List.iter find_this el; false with Exit -> true in
  636. ctx.locals <- PMap.foldi (fun _ (v,l) acc ->
  637. match l with
  638. | LReg _ -> acc
  639. | LScope _ -> PMap.add v.v_id (v,LGlobal (ident v.v_name)) acc
  640. | LGlobal _ -> PMap.add v.v_id (v,l) acc
  641. ) ctx.locals PMap.empty;
  642. let dparams = ref None in
  643. let make_constant_value r c t =
  644. let v = (match classify ctx t, c with
  645. | _, None -> HVNone
  646. | (KInt | KFloat | KUInt | KBool) as kind, Some c ->
  647. (match c with
  648. | TInt i -> if kind = KUInt then HVUInt i else HVInt i
  649. | TFloat s -> HVFloat (float_of_string s)
  650. | TBool b -> HVBool b
  651. | TNull -> error ("In Flash9, null can't be used as basic type " ^ s_type (print_context()) t) p
  652. | _ -> assert false)
  653. | _, Some TNull -> HVNone
  654. | k, Some c ->
  655. write ctx (HReg r.rid);
  656. write ctx HNull;
  657. let j = jump ctx J3Neq in
  658. gen_constant ctx c t p;
  659. coerce ctx k;
  660. write ctx (HSetReg r.rid);
  661. j();
  662. HVNone
  663. ) in
  664. match !dparams with
  665. | None -> if c <> None then dparams := Some [v]
  666. | Some l -> dparams := Some (v :: l)
  667. in
  668. let args, varargs = (match List.rev args with
  669. | (({ v_name = "__arguments__"; v_type = t } as v),_) :: l ->
  670. (match follow t with
  671. | TInst ({ cl_path = ([],"Array") },_) -> List.rev l, Some (v,true)
  672. | _ -> List.rev l, Some(v,false))
  673. | _ ->
  674. args, None
  675. ) in
  676. List.iter (fun (v,c) ->
  677. let t = v.v_type in
  678. define_local ctx v ~init:true p;
  679. match gen_local_access ctx v null_pos Write with
  680. | VReg r ->
  681. make_constant_value r c t
  682. | acc ->
  683. let r = alloc_reg ctx (classify ctx t) in
  684. make_constant_value r c t;
  685. write ctx (HReg r.rid);
  686. setvar ctx acc None
  687. ) args;
  688. (match varargs with
  689. | None -> ()
  690. | Some (v,_) ->
  691. define_local ctx v ~init:true p;
  692. ignore(alloc_reg ctx (classify ctx v.v_type)));
  693. let dparams = (match !dparams with None -> None | Some l -> Some (List.rev l)) in
  694. let rec loop_try e =
  695. match e.eexpr with
  696. | TFunction _ -> ()
  697. | TTry _ -> raise Exit
  698. | _ -> Type.iter loop_try e
  699. in
  700. ctx.try_scope_reg <- (try List.iter loop_try el; None with Exit -> Some (alloc_reg ctx KDynamic));
  701. (fun () ->
  702. let hasblock = ctx.block_vars <> [] || ctx.trys <> [] in
  703. let code = DynArray.to_list ctx.code in
  704. let extra = (
  705. if hasblock then begin
  706. let scope = (match ctx.try_scope_reg with
  707. | None -> [HScope]
  708. | Some r -> [HDup; HSetReg r.rid; HScope]
  709. ) in
  710. HThis :: HScope :: HNewBlock :: scope
  711. end else if this_reg then
  712. [HThis; HScope]
  713. else
  714. []
  715. ) in
  716. (* add dummy registers initialization *)
  717. let extra = extra @ List.concat (List.map (fun r ->
  718. if not r.rcond then
  719. []
  720. else
  721. let s = [HSetReg r.rid] in
  722. match r.rtype with
  723. | KInt -> HSmallInt 0 :: s
  724. | KUInt -> HSmallInt 0 :: HToUInt :: s
  725. | KFloat -> HNaN :: s
  726. | KBool -> HFalse :: s
  727. | KType t -> HNull :: HAsType t :: s
  728. | KDynamic -> HNull :: HAsAny :: s
  729. | KNone -> HNull :: HAsType (HMPath ([],"Class")) :: s
  730. ) (DynArray.to_list ctx.infos.iregs)) in
  731. let delta = List.length extra in
  732. let f = {
  733. hlf_stack_size = (if ctx.infos.imax = 0 && (hasblock || this_reg) then 1 else ctx.infos.imax);
  734. hlf_nregs = DynArray.length ctx.infos.iregs + 1;
  735. hlf_init_scope = 1;
  736. hlf_max_scope = ctx.infos.imaxscopes + 1 + (if hasblock then 2 else if this_reg then 1 else 0);
  737. hlf_code = MultiArray.of_array (Array.of_list (extra @ code));
  738. hlf_trys = Array.of_list (List.map (fun t ->
  739. {
  740. hltc_start = t.tr_pos + delta;
  741. hltc_end = t.tr_end + delta;
  742. hltc_handle = t.tr_catch_pos + delta;
  743. hltc_type = type_opt ctx t.tr_type;
  744. hltc_name = None;
  745. }
  746. ) (List.rev ctx.trys));
  747. hlf_locals = Array.of_list (List.map (fun (id,name,t) -> ident name, t, id, false) ctx.block_vars);
  748. } in
  749. let mt = { (end_fun ctx args dparams tret) with
  750. hlmt_var_args = (match varargs with Some (_,true) -> true | _ -> false);
  751. hlmt_arguments_defined = (match varargs with Some (_,false) -> true | _ -> false);
  752. hlmt_new_block = hasblock;
  753. hlmt_function = Some f;
  754. } in
  755. ctx.locals <- old_locals;
  756. ctx.code <- old_code;
  757. ctx.infos <- old_infos;
  758. ctx.trys <- old_trys;
  759. ctx.block_vars <- old_bvars;
  760. ctx.in_static <- old_static;
  761. ctx.last_line <- last_line;
  762. ctx.try_scope_reg <- old_treg;
  763. mt
  764. )
  765. let empty_method ctx p =
  766. let f = begin_fun ctx [] ctx.com.basic.tvoid [] true p in
  767. write ctx HRetVoid;
  768. f()
  769. let begin_loop ctx =
  770. let old_loop = ctx.infos.iloop in
  771. let old_breaks = ctx.breaks in
  772. let old_conts = ctx.continues in
  773. ctx.infos.iloop <- ctx.infos.istack;
  774. ctx.breaks <- [];
  775. ctx.continues <- [];
  776. (fun cont_pos ->
  777. if ctx.infos.istack <> ctx.infos.iloop then assert false;
  778. List.iter (fun j -> j()) ctx.breaks;
  779. List.iter (fun j -> j cont_pos) ctx.continues;
  780. ctx.infos.iloop <- old_loop;
  781. ctx.breaks <- old_breaks;
  782. ctx.continues <- old_conts;
  783. )
  784. let no_value ctx retval =
  785. (* does not push a null but still increment the stack like if
  786. a real value was pushed *)
  787. if retval then ctx.infos.istack <- ctx.infos.istack + 1
  788. let pop_value ctx retval =
  789. (* if we have multiple branches, make sure to forget about previous
  790. branch value *)
  791. if retval then ctx.infos.istack <- ctx.infos.istack - 1
  792. let gen_expr_ref = ref (fun _ _ _ -> assert false)
  793. let gen_expr ctx e retval = (!gen_expr_ref) ctx e retval
  794. let rec gen_access ctx e (forset : 'a) : 'a access =
  795. match e.eexpr with
  796. | TLocal v ->
  797. gen_local_access ctx v e.epos forset
  798. | TField ({ eexpr = TConst TSuper } as e1,f) ->
  799. let f = field_name f in
  800. let id, _, _ = property ctx f e1.etype in
  801. write ctx HThis;
  802. VSuper id
  803. | TField (e1,f) ->
  804. let f = field_name f in
  805. let id, k, closure = property ctx f e1.etype in
  806. if closure && not ctx.for_call then error "In Flash9, this method cannot be accessed this way : please define a local function" e1.epos;
  807. (match e1.eexpr with
  808. | TConst (TThis|TSuper) when not ctx.in_static ->
  809. write ctx (HFindProp id)
  810. | _ -> gen_expr ctx true e1);
  811. (match k with
  812. | Some t -> VCast (id,t)
  813. | None ->
  814. match follow e1.etype, follow e.etype with
  815. | _ , TFun _ when not ctx.for_call -> VCast(id,classify ctx e.etype)
  816. | TEnum _, _ -> VId id
  817. | TInst (_,tl), et ->
  818. (* if the return type is one of the type-parameters, then we need to cast it *)
  819. if List.exists (fun t -> follow t == et) tl then
  820. VCast (id, classify ctx et)
  821. else if Codegen.is_volatile e.etype then
  822. VVolatile (id,None)
  823. else
  824. VId id
  825. | TAnon a, _ when (match !(a.a_status) with Statics _ | EnumStatics _ -> true | _ -> false) ->
  826. if Codegen.is_volatile e.etype then
  827. VVolatile (id,None)
  828. else
  829. VId id
  830. | _ ->
  831. if Codegen.is_volatile e.etype then
  832. VVolatile (id,Some (classify ctx e.etype))
  833. else
  834. VCast (id,classify ctx e.etype)
  835. )
  836. | TArray ({ eexpr = TLocal { v_name = "__global__" } },{ eexpr = TConst (TString s) }) ->
  837. let path = parse_path s in
  838. let id = type_path ctx path in
  839. if is_set forset then write ctx HGetGlobalScope;
  840. VGlobal id
  841. | TArray (e,eindex) ->
  842. gen_expr ctx true e;
  843. gen_expr ctx true eindex;
  844. VArray
  845. | TTypeExpr t ->
  846. let id = type_path ctx (t_path t) in
  847. if is_set forset then write ctx HGetGlobalScope;
  848. VGlobal id
  849. | _ ->
  850. invalid_expr e.epos
  851. let gen_expr_twice ctx e =
  852. match e.eexpr with
  853. | TLocal v ->
  854. (match get_local_register ctx v with
  855. | Some r ->
  856. write ctx (HReg r.rid);
  857. write ctx (HReg r.rid);
  858. | None ->
  859. gen_expr ctx true e;
  860. write ctx HDup)
  861. | TConst _ ->
  862. gen_expr ctx true e;
  863. gen_expr ctx true e;
  864. | _ ->
  865. gen_expr ctx true e;
  866. write ctx HDup
  867. let gen_access_rw ctx e : (read access * write access) =
  868. match e.eexpr with
  869. | TArray ({ eexpr = TLocal _ }, { eexpr = TConst _ })
  870. | TArray ({ eexpr = TLocal _ }, { eexpr = TLocal _ })
  871. | TField ({ eexpr = TLocal _ },_)
  872. | TField ({ eexpr = TConst _ },_)
  873. ->
  874. let w = gen_access ctx e Write in
  875. let r = gen_access ctx e Read in
  876. r, w
  877. | TArray (e,eindex) ->
  878. let r = (match e.eexpr with TLocal v -> get_local_register ctx v | _ -> None) in
  879. (match r with
  880. | None ->
  881. let r = alloc_reg ctx (classify ctx e.etype) in
  882. gen_expr ctx true e;
  883. set_reg ctx r;
  884. write ctx (HReg r.rid);
  885. gen_expr_twice ctx eindex;
  886. write ctx (HReg r.rid);
  887. write ctx HSwap;
  888. free_reg ctx r;
  889. | Some r ->
  890. write ctx (HReg r.rid);
  891. gen_expr_twice ctx eindex;
  892. write ctx (HReg r.rid);
  893. write ctx HSwap;
  894. );
  895. VArray, VArray
  896. | TField _ ->
  897. let w = gen_access ctx e Write in
  898. write ctx HDup;
  899. Obj.magic w, w
  900. | _ ->
  901. let w = gen_access ctx e Write in
  902. let r = gen_access ctx e Read in
  903. r, w
  904. let rec gen_type ctx t =
  905. match t with
  906. | HMParams (t,tl) ->
  907. write ctx (HGetLex t);
  908. List.iter (gen_type ctx) tl;
  909. write ctx (HApplyType (List.length tl));
  910. | _ ->
  911. write ctx (HGetLex t)
  912. let rec gen_expr_content ctx retval e =
  913. match e.eexpr with
  914. | TConst c ->
  915. gen_constant ctx c e.etype e.epos
  916. | TThrow e ->
  917. ctx.infos.icond <- true;
  918. getvar ctx (VGlobal (type_path ctx (["flash"],"Boot")));
  919. let id = type_path ctx (["flash";"errors"],"Error") in
  920. write ctx (HFindPropStrict id);
  921. write ctx (HConstructProperty (id,0));
  922. setvar ctx (VId (ident "lastError")) None;
  923. gen_expr ctx true e;
  924. write ctx HThrow;
  925. no_value ctx retval;
  926. | TParenthesis e ->
  927. gen_expr ctx retval e
  928. | TObjectDecl fl ->
  929. List.iter (fun (name,e) ->
  930. write ctx (HString name);
  931. gen_expr ctx true e
  932. ) fl;
  933. write ctx (HObject (List.length fl))
  934. | TArrayDecl el ->
  935. List.iter (gen_expr ctx true) el;
  936. write ctx (HArray (List.length el))
  937. | TBlock el ->
  938. let rec loop = function
  939. | [] ->
  940. if retval then write ctx HNull
  941. | [e] ->
  942. gen_expr ctx retval e
  943. | e :: l ->
  944. gen_expr ctx false e;
  945. loop l
  946. in
  947. let b = open_block ctx retval in
  948. loop el;
  949. b();
  950. | TVars vl ->
  951. List.iter (fun (v,ei) ->
  952. define_local ctx v e.epos;
  953. (match ei with
  954. | None -> ()
  955. | Some e ->
  956. let acc = gen_local_access ctx v e.epos Write in
  957. gen_expr ctx true e;
  958. setvar ctx acc None)
  959. ) vl
  960. | TReturn None ->
  961. write ctx HRetVoid;
  962. ctx.infos.icond <- true;
  963. no_value ctx retval
  964. | TReturn (Some e) ->
  965. gen_expr ctx true e;
  966. write ctx HRet;
  967. ctx.infos.icond <- true;
  968. no_value ctx retval
  969. | TField _
  970. | TLocal _
  971. | TTypeExpr _ ->
  972. getvar ctx (gen_access ctx e Read)
  973. | TArray _ ->
  974. getvar ctx (gen_access ctx e Read);
  975. coerce ctx (classify ctx e.etype)
  976. | TBinop (op,e1,e2) ->
  977. gen_binop ctx retval op e1 e2 e.etype e.epos
  978. | TCall (f,el) ->
  979. gen_call ctx retval f el e.etype
  980. | TNew ({ cl_path = [],"Array" },_,[]) ->
  981. (* it seems that [] is 4 time faster than new Array() *)
  982. write ctx (HArray 0)
  983. | TNew (c,tl,pl) ->
  984. let id = type_id ctx (TInst (c,tl)) in
  985. (match id with
  986. | HMParams _ ->
  987. gen_type ctx id;
  988. List.iter (gen_expr ctx true) pl;
  989. write ctx (HConstruct (List.length pl))
  990. | _ ->
  991. write ctx (HFindPropStrict id);
  992. List.iter (gen_expr ctx true) pl;
  993. write ctx (HConstructProperty (id,List.length pl))
  994. );
  995. | TFunction f ->
  996. write ctx (HFunction (generate_function ctx f true))
  997. | TIf (e0,e1,e2) ->
  998. let j = jump_expr ctx e0 false in
  999. let branch = begin_branch ctx in
  1000. gen_expr ctx retval e1;
  1001. let t = classify ctx e.etype in
  1002. if retval && classify ctx e1.etype <> t then coerce ctx t;
  1003. (match e2 with
  1004. | None -> j()
  1005. | Some e ->
  1006. (* two expresssions, but one per branch *)
  1007. pop_value ctx retval;
  1008. let jend = jump ctx J3Always in
  1009. j();
  1010. gen_expr ctx retval e;
  1011. if retval && classify ctx e.etype <> t then coerce ctx t;
  1012. jend());
  1013. branch();
  1014. | TWhile (econd,e,flag) ->
  1015. let jstart = jump ctx J3Always in
  1016. let end_loop = begin_loop ctx in
  1017. let branch = begin_branch ctx in
  1018. let loop = jump_back ctx in
  1019. if flag = DoWhile then jstart();
  1020. gen_expr ctx false e;
  1021. if flag = NormalWhile then jstart();
  1022. let continue_pos = ctx.infos.ipos in
  1023. let _ = jump_expr_gen ctx econd true (fun j -> loop j; (fun() -> ())) in
  1024. branch();
  1025. end_loop continue_pos;
  1026. if retval then write ctx HNull
  1027. | TUnop (op,flag,e) ->
  1028. gen_unop ctx retval op flag e
  1029. | TTry (e2,cases) ->
  1030. if ctx.infos.istack <> 0 then error "Cannot compile try/catch as a right-side expression in Flash9" e.epos;
  1031. let branch = begin_branch ctx in
  1032. let p = ctx.infos.ipos in
  1033. gen_expr ctx retval e2;
  1034. let pend = ctx.infos.ipos in
  1035. let jend = jump ctx J3Always in
  1036. let rec loop ncases = function
  1037. | [] -> []
  1038. | (v,e) :: l ->
  1039. let b = open_block ctx retval in
  1040. let t = v.v_type in
  1041. ctx.trys <- {
  1042. tr_pos = p;
  1043. tr_end = pend;
  1044. tr_catch_pos = ctx.infos.ipos;
  1045. tr_type = t;
  1046. } :: ctx.trys;
  1047. ctx.infos.istack <- ctx.infos.istack + 1;
  1048. if ctx.infos.imax < ctx.infos.istack then ctx.infos.imax <- ctx.infos.istack;
  1049. write ctx HThis;
  1050. write ctx HScope;
  1051. write ctx (HReg (match ctx.try_scope_reg with None -> assert false | Some r -> r.rid));
  1052. write ctx HScope;
  1053. (* store the exception into local var, using a tmp register if needed *)
  1054. define_local ctx v e.epos;
  1055. let r = (match snd (try PMap.find v.v_id ctx.locals with Not_found -> assert false) with
  1056. | LReg _ -> None
  1057. | _ ->
  1058. let r = alloc_reg ctx (classify ctx t) in
  1059. set_reg ctx r;
  1060. Some r
  1061. ) in
  1062. let acc = gen_local_access ctx v e.epos Write in
  1063. (match r with None -> () | Some r -> write ctx (HReg r.rid));
  1064. setvar ctx acc None;
  1065. (* ----- *)
  1066. let rec call_loop e =
  1067. match e.eexpr with
  1068. | TCall _ | TNew _ -> raise Exit
  1069. | TFunction _ -> ()
  1070. | _ -> Type.iter call_loop e
  1071. in
  1072. let has_call = (try call_loop e; false with Exit -> true) in
  1073. if has_call then begin
  1074. getvar ctx (gen_local_access ctx v e.epos Read);
  1075. write ctx (HAsType (type_path ctx (["flash";"errors"],"Error")));
  1076. let j = jump ctx J3False in
  1077. getvar ctx (VGlobal (type_path ctx (["flash"],"Boot")));
  1078. getvar ctx (gen_local_access ctx v e.epos Read);
  1079. setvar ctx (VId (ident "lastError")) None;
  1080. j();
  1081. end;
  1082. gen_expr ctx retval e;
  1083. b();
  1084. if retval then ctx.infos.istack <- ctx.infos.istack - 1;
  1085. match l with
  1086. | [] -> []
  1087. | _ ->
  1088. let j = jump ctx J3Always in
  1089. j :: loop (ncases + 1) l
  1090. in
  1091. let loops = loop (List.length ctx.trys) cases in
  1092. List.iter (fun j -> j()) loops;
  1093. branch();
  1094. jend()
  1095. | TFor (v,it,e) ->
  1096. gen_expr ctx true it;
  1097. let r = alloc_reg ctx KDynamic in
  1098. set_reg ctx r;
  1099. let branch = begin_branch ctx in
  1100. let b = open_block ctx retval in
  1101. define_local ctx v e.epos;
  1102. let end_loop = begin_loop ctx in
  1103. let continue_pos = ctx.infos.ipos in
  1104. let start = jump_back ctx in
  1105. write ctx (HReg r.rid);
  1106. write ctx (HCallProperty (ident "hasNext",0));
  1107. let jend = jump ctx J3False in
  1108. let acc = gen_local_access ctx v e.epos Write in
  1109. write ctx (HReg r.rid);
  1110. write ctx (HCallProperty (ident "next",0));
  1111. setvar ctx acc None;
  1112. gen_expr ctx false e;
  1113. start J3Always;
  1114. end_loop continue_pos;
  1115. jend();
  1116. if retval then getvar ctx (gen_local_access ctx v e.epos Read);
  1117. b();
  1118. branch();
  1119. free_reg ctx r;
  1120. | TBreak ->
  1121. pop ctx (ctx.infos.istack - ctx.infos.iloop);
  1122. ctx.breaks <- jump ctx J3Always :: ctx.breaks;
  1123. no_value ctx retval
  1124. | TContinue ->
  1125. pop ctx (ctx.infos.istack - ctx.infos.iloop);
  1126. let op = DynArray.length ctx.code in
  1127. let p = ctx.infos.ipos in
  1128. write ctx (HJump (J3Always,0));
  1129. ctx.continues <- (fun target -> DynArray.set ctx.code op (HJump (J3Always,target - p))) :: ctx.continues;
  1130. no_value ctx retval
  1131. | TSwitch (e0,el,eo) ->
  1132. let t = classify ctx e.etype in
  1133. (try
  1134. let t0 = classify ctx e0.etype in
  1135. (* generate optimized int switch *)
  1136. if t0 <> KInt && t0 <> KUInt then raise Exit;
  1137. let rec get_int e =
  1138. match e.eexpr with
  1139. | TConst (TInt n) -> if n < 0l || n > 512l then raise Exit; Int32.to_int n
  1140. | TParenthesis e | TBlock [e] -> get_int e
  1141. | _ -> raise Not_found
  1142. in
  1143. List.iter (fun (vl,_) -> List.iter (fun v ->
  1144. try ignore (get_int v) with _ -> raise Exit
  1145. ) vl) el;
  1146. gen_expr ctx true e0;
  1147. if t0 <> KInt then write ctx HToInt;
  1148. let switch, case = begin_switch ctx in
  1149. (match eo with
  1150. | None ->
  1151. if retval then begin
  1152. write ctx HNull;
  1153. coerce ctx t;
  1154. end;
  1155. | Some e ->
  1156. gen_expr ctx retval e;
  1157. if retval && classify ctx e.etype <> t then coerce ctx t);
  1158. let jends = List.map (fun (vl,e) ->
  1159. let j = jump ctx J3Always in
  1160. List.iter (fun v -> case (get_int v)) vl;
  1161. pop_value ctx retval;
  1162. gen_expr ctx retval e;
  1163. if retval && classify ctx e.etype <> t then coerce ctx t;
  1164. j
  1165. ) el in
  1166. List.iter (fun j -> j()) jends;
  1167. switch();
  1168. with Exit ->
  1169. let r = alloc_reg ctx (classify ctx e0.etype) in
  1170. gen_expr ctx true e0;
  1171. set_reg ctx r;
  1172. let branch = begin_branch ctx in
  1173. let prev = ref (fun () -> ()) in
  1174. let jend = List.map (fun (vl,e) ->
  1175. (!prev)();
  1176. let rec loop = function
  1177. | [] ->
  1178. assert false
  1179. | [v] ->
  1180. write ctx (HReg r.rid);
  1181. gen_expr ctx true v;
  1182. prev := jump ctx J3Neq;
  1183. | v :: l ->
  1184. write ctx (HReg r.rid);
  1185. gen_expr ctx true v;
  1186. let j = jump ctx J3Eq in
  1187. loop l;
  1188. j()
  1189. in
  1190. loop vl;
  1191. gen_expr ctx retval e;
  1192. pop_value ctx retval;
  1193. if retval && classify ctx e.etype <> t then coerce ctx t;
  1194. jump ctx J3Always
  1195. ) el in
  1196. (!prev)();
  1197. free_reg ctx r;
  1198. (match eo with
  1199. | None ->
  1200. if retval then begin
  1201. write ctx HNull;
  1202. coerce ctx t;
  1203. end;
  1204. | Some e ->
  1205. gen_expr ctx retval e;
  1206. if retval && classify ctx e.etype <> t then coerce ctx t;
  1207. );
  1208. List.iter (fun j -> j()) jend;
  1209. branch());
  1210. | TMatch (e0,_,cases,def) ->
  1211. let t = classify ctx e.etype in
  1212. let rparams = alloc_reg ctx (KType (type_path ctx ([],"Array"))) in
  1213. let has_params = List.exists (fun (_,p,_) -> p <> None) cases in
  1214. gen_expr ctx true e0;
  1215. if has_params then begin
  1216. write ctx HDup;
  1217. write ctx (HGetProp (ident "params"));
  1218. set_reg ctx rparams;
  1219. end;
  1220. write ctx (HGetProp (ident "index"));
  1221. write ctx HToInt;
  1222. let switch,case = begin_switch ctx in
  1223. (match def with
  1224. | None ->
  1225. if retval then begin
  1226. write ctx HNull;
  1227. coerce ctx t;
  1228. end;
  1229. | Some e ->
  1230. gen_expr ctx retval e;
  1231. if retval && classify ctx e.etype <> t then coerce ctx t);
  1232. let jends = List.map (fun (cl,params,e) ->
  1233. let j = jump ctx J3Always in
  1234. List.iter case cl;
  1235. pop_value ctx retval;
  1236. let b = open_block ctx retval in
  1237. (match params with
  1238. | None -> ()
  1239. | Some l ->
  1240. let p = ref (-1) in
  1241. List.iter (fun v ->
  1242. incr p;
  1243. match v with
  1244. | None -> ()
  1245. | Some v ->
  1246. define_local ctx v e.epos;
  1247. let acc = gen_local_access ctx v e.epos Write in
  1248. write ctx (HReg rparams.rid);
  1249. write ctx (HSmallInt !p);
  1250. getvar ctx VArray;
  1251. setvar ctx acc None
  1252. ) l
  1253. );
  1254. gen_expr ctx retval e;
  1255. b();
  1256. if retval && classify ctx e.etype <> t then coerce ctx t;
  1257. j
  1258. ) cases in
  1259. switch();
  1260. List.iter (fun j -> j()) jends;
  1261. free_reg ctx rparams
  1262. | TCast (e1,t) ->
  1263. gen_expr ctx retval e1;
  1264. if retval then begin
  1265. match t with
  1266. | None ->
  1267. (* no error if cast failure *)
  1268. let t1 = classify ctx e1.etype in
  1269. let t = classify ctx e.etype in
  1270. if t1 <> t then coerce ctx t;
  1271. | Some t ->
  1272. (* manual cast *)
  1273. let tid = (match gen_access ctx (mk (TTypeExpr t) t_dynamic e.epos) Read with
  1274. | VGlobal id -> id
  1275. | _ -> assert false
  1276. ) in
  1277. match classify ctx e.etype with
  1278. | KType n when (match n with HMPath ([],"String") -> false | _ -> true) ->
  1279. (* for normal classes, we can use native cast *)
  1280. write ctx (HCast tid)
  1281. | _ ->
  1282. (* we need to check with "is" first *)
  1283. write ctx HDup;
  1284. write ctx (HIsType tid);
  1285. let j = jump ctx J3True in
  1286. write ctx (HString "Class cast error");
  1287. write ctx HThrow;
  1288. j();
  1289. write ctx (HCast tid)
  1290. end
  1291. and gen_call ctx retval e el r =
  1292. match e.eexpr , el with
  1293. | TLocal { v_name = "__is__" }, [e;t] ->
  1294. gen_expr ctx true e;
  1295. gen_expr ctx true t;
  1296. write ctx (HOp A3OIs)
  1297. | TLocal { v_name = "__as__" }, [e;t] ->
  1298. gen_expr ctx true e;
  1299. gen_expr ctx true t;
  1300. write ctx (HOp A3OAs)
  1301. | TLocal { v_name = "__int__" }, [e] ->
  1302. gen_expr ctx true e;
  1303. write ctx HToInt
  1304. | TLocal { v_name = "__float__" }, [e] ->
  1305. gen_expr ctx true e;
  1306. write ctx HToNumber
  1307. | TLocal { v_name = "__foreach__" }, [obj;counter] ->
  1308. gen_expr ctx true obj;
  1309. gen_expr ctx true counter;
  1310. write ctx HForEach
  1311. | TLocal { v_name = "__forin__" }, [obj;counter] ->
  1312. gen_expr ctx true obj;
  1313. gen_expr ctx true counter;
  1314. write ctx HForIn
  1315. | TLocal { v_name = "__has_next__" }, [obj;counter] ->
  1316. let oreg = match gen_access ctx obj Read with VReg r -> r | _ -> error "Must be a local variable" obj.epos in
  1317. let creg = match gen_access ctx counter Read with VReg r -> r | _ -> error "Must be a local variable" obj.epos in
  1318. write ctx (HNext (oreg.rid,creg.rid))
  1319. | TLocal { v_name = "__hkeys__" }, [e2]
  1320. | TLocal { v_name = "__foreach__" }, [e2]
  1321. | TLocal { v_name = "__keys__" }, [e2] ->
  1322. let racc = alloc_reg ctx (KType (type_path ctx ([],"Array"))) in
  1323. let rcounter = alloc_reg ctx KInt in
  1324. let rtmp = alloc_reg ctx KDynamic in
  1325. write ctx (HSmallInt 0);
  1326. set_reg ctx rcounter;
  1327. write ctx (HArray 0);
  1328. set_reg ctx racc;
  1329. gen_expr ctx true e2;
  1330. set_reg ctx rtmp;
  1331. let start = jump ctx J3Always in
  1332. let loop = jump_back ctx in
  1333. write ctx (HReg racc.rid);
  1334. write ctx (HReg rtmp.rid);
  1335. write ctx (HReg rcounter.rid);
  1336. (match e.eexpr with
  1337. | TLocal { v_name = "__foreach__" } ->
  1338. write ctx HForEach
  1339. | TLocal { v_name = "__hkeys__" } ->
  1340. write ctx HForIn;
  1341. write ctx (HSmallInt 1);
  1342. write ctx (HCallProperty (as3 "substr",1));
  1343. | _ ->
  1344. write ctx HForIn);
  1345. write ctx (HCallPropVoid (as3 "push",1));
  1346. start();
  1347. write ctx (HNext (rtmp.rid,rcounter.rid));
  1348. loop J3True;
  1349. write ctx (HReg racc.rid);
  1350. free_reg ctx rtmp;
  1351. free_reg ctx rcounter;
  1352. free_reg ctx racc;
  1353. | TLocal { v_name = "__new__" }, e :: el ->
  1354. gen_expr ctx true e;
  1355. List.iter (gen_expr ctx true) el;
  1356. write ctx (HConstruct (List.length el))
  1357. | TLocal { v_name = "__delete__" }, [o;f] ->
  1358. gen_expr ctx true o;
  1359. gen_expr ctx true f;
  1360. write ctx (HDeleteProp dynamic_prop);
  1361. | TLocal { v_name = "__unprotect__" }, [e] ->
  1362. write ctx (HGetLex (type_path ctx (["flash"],"Boot")));
  1363. gen_expr ctx true e;
  1364. write ctx (HCallProperty (ident "__unprotect__",1));
  1365. | TLocal { v_name = "__typeof__" }, [e] ->
  1366. gen_expr ctx true e;
  1367. write ctx HTypeof
  1368. | TLocal { v_name = "__in__" }, [e; f] ->
  1369. gen_expr ctx true e;
  1370. gen_expr ctx true f;
  1371. write ctx (HOp A3OIn)
  1372. | TLocal { v_name = "__resources__" }, [] ->
  1373. let count = ref 0 in
  1374. Hashtbl.iter (fun name data ->
  1375. incr count;
  1376. write ctx (HString "name");
  1377. write ctx (HString name);
  1378. write ctx (HObject 1);
  1379. ) ctx.com.resources;
  1380. write ctx (HArray !count)
  1381. | TLocal { v_name = "__vmem_set__" }, [{ eexpr = TConst (TInt code) };e1;e2] ->
  1382. gen_expr ctx true e2;
  1383. gen_expr ctx true e1;
  1384. write ctx (HOp (match code with
  1385. | 0l -> A3OMemSet8
  1386. | 1l -> A3OMemSet16
  1387. | 2l -> A3OMemSet32
  1388. | 3l -> A3OMemSetFloat
  1389. | 4l -> A3OMemSetDouble
  1390. | _ -> assert false
  1391. ))
  1392. | TLocal { v_name = "__vmem_get__" }, [{ eexpr = TConst (TInt code) };e] ->
  1393. gen_expr ctx true e;
  1394. write ctx (HOp (match code with
  1395. | 0l -> A3OMemGet8
  1396. | 1l -> A3OMemGet16
  1397. | 2l -> A3OMemGet32
  1398. | 3l -> A3OMemGetFloat
  1399. | 4l -> A3OMemGetDouble
  1400. | _ -> assert false
  1401. ))
  1402. | TLocal { v_name = "__vmem_sign__" }, [{ eexpr = TConst (TInt code) };e] ->
  1403. gen_expr ctx true e;
  1404. write ctx (HOp (match code with
  1405. | 0l -> A3OSign1
  1406. | 1l -> A3OSign8
  1407. | 2l -> A3OSign16
  1408. | _ -> assert false
  1409. ))
  1410. | TLocal { v_name = "__vector__" }, [ep] ->
  1411. gen_type ctx (type_id ctx r);
  1412. write ctx HGetGlobalScope;
  1413. gen_expr ctx true ep;
  1414. write ctx (HCallStack 1)
  1415. | TArray ({ eexpr = TLocal { v_name = "__global__" } },{ eexpr = TConst (TString s) }), _ ->
  1416. (match gen_access ctx e Read with
  1417. | VGlobal id ->
  1418. write ctx (HFindPropStrict id);
  1419. List.iter (gen_expr ctx true) el;
  1420. write ctx (HCallProperty (id,List.length el));
  1421. | _ -> assert false)
  1422. | TConst TSuper , _ ->
  1423. write ctx HThis;
  1424. List.iter (gen_expr ctx true) el;
  1425. write ctx (HConstructSuper (List.length el));
  1426. | TField ({ eexpr = TConst TSuper },f) , _ ->
  1427. let id = ident (field_name f) in
  1428. write ctx (HFindPropStrict id);
  1429. List.iter (gen_expr ctx true) el;
  1430. write ctx (HCallSuper (id,List.length el));
  1431. coerce ctx (classify ctx r);
  1432. | TField ({ eexpr = TConst TThis },f) , _ when not ctx.in_static ->
  1433. let id = ident (field_name f) in
  1434. write ctx (HFindProp id);
  1435. List.iter (gen_expr ctx true) el;
  1436. if retval then begin
  1437. write ctx (HCallProperty (id,List.length el));
  1438. coerce ctx (classify ctx r);
  1439. end else
  1440. write ctx (HCallPropVoid (id,List.length el))
  1441. | TField (e1,f) , _ ->
  1442. let old = ctx.for_call in
  1443. ctx.for_call <- true;
  1444. gen_expr ctx true e1;
  1445. let id , _, _ = property ctx (field_name f) e1.etype in
  1446. ctx.for_call <- old;
  1447. List.iter (gen_expr ctx true) el;
  1448. if retval then begin
  1449. write ctx (HCallProperty (id,List.length el));
  1450. coerce ctx (classify ctx r);
  1451. end else
  1452. write ctx (HCallPropVoid (id,List.length el))
  1453. | _ ->
  1454. gen_expr ctx true e;
  1455. write ctx HGetGlobalScope;
  1456. List.iter (gen_expr ctx true) el;
  1457. write ctx (HCallStack (List.length el));
  1458. coerce ctx (classify ctx r)
  1459. and gen_unop ctx retval op flag e =
  1460. let k = classify ctx e.etype in
  1461. match op with
  1462. | Not ->
  1463. gen_expr ctx true e;
  1464. write ctx (HOp A3ONot);
  1465. | Neg ->
  1466. gen_expr ctx true e;
  1467. write ctx (HOp (if k = KInt then A3OINeg else A3ONeg));
  1468. | NegBits ->
  1469. gen_expr ctx true e;
  1470. write ctx (HOp A3OBitNot);
  1471. | Increment
  1472. | Decrement ->
  1473. let incr = (op = Increment) in
  1474. let r = (match e.eexpr with TLocal v -> get_local_register ctx v | _ -> None) in
  1475. match r with
  1476. | Some r when r.rtype = KInt ->
  1477. if not r.rinit then r.rcond <- true;
  1478. if retval && flag = Postfix then getvar ctx (VReg r);
  1479. write ctx (if incr then HIncrIReg r.rid else HDecrIReg r.rid);
  1480. if retval && flag = Prefix then getvar ctx (VReg r);
  1481. | _ ->
  1482. let acc_read, acc_write = gen_access_rw ctx e in
  1483. let op = (match k, incr with
  1484. | KInt, true -> A3OIIncr
  1485. | KInt, false -> A3OIDecr
  1486. | _ , true -> A3OIncr
  1487. | _ , false -> A3ODecr
  1488. ) in
  1489. getvar ctx acc_read;
  1490. match flag with
  1491. | Postfix when retval ->
  1492. let r = alloc_reg ctx k in
  1493. write ctx HDup;
  1494. set_reg ctx r;
  1495. write ctx (HOp op);
  1496. setvar ctx acc_write None;
  1497. write ctx (HReg r.rid);
  1498. free_reg ctx r
  1499. | Postfix | Prefix ->
  1500. write ctx (HOp op);
  1501. setvar ctx acc_write (if retval then Some k else None)
  1502. and check_binop ctx e1 e2 =
  1503. let invalid = (match classify ctx e1.etype, classify ctx e2.etype with
  1504. | KInt, KUInt | KUInt, KInt -> (match e1.eexpr, e2.eexpr with TConst (TInt i) , _ | _ , TConst (TInt i) -> i < 0l | _ -> true)
  1505. | _ -> false) in
  1506. if invalid then error "Comparison of Int and UInt might lead to unexpected results" (punion e1.epos e2.epos);
  1507. and gen_binop ctx retval op e1 e2 t p =
  1508. let write_op op =
  1509. let iop = (match op with
  1510. | OpAdd -> Some A3OIAdd
  1511. | OpSub -> Some A3OISub
  1512. | OpMult -> Some A3OIMul
  1513. | _ -> None
  1514. ) in
  1515. let op = (match op with
  1516. | OpAdd -> A3OAdd
  1517. | OpSub -> A3OSub
  1518. | OpMult -> A3OMul
  1519. | OpDiv -> A3ODiv
  1520. | OpAnd -> A3OAnd
  1521. | OpOr -> A3OOr
  1522. | OpXor -> A3OXor
  1523. | OpShl -> A3OShl
  1524. | OpShr -> A3OShr
  1525. | OpUShr -> A3OUShr
  1526. | OpMod -> A3OMod
  1527. | _ -> assert false
  1528. ) in
  1529. match iop with
  1530. | Some iop ->
  1531. let k1 = classify ctx e1.etype in
  1532. let k2 = classify ctx e2.etype in
  1533. (match k1, k2 with
  1534. | KInt, KInt | KUInt, KUInt | KInt, KUInt | KUInt, KInt -> write ctx (HOp iop)
  1535. | _ ->
  1536. write ctx (HOp op);
  1537. (* add is a generic operation, so let's make sure we don't loose our type in the process *)
  1538. if op = A3OAdd then coerce ctx (classify ctx t))
  1539. | _ ->
  1540. write ctx (HOp op);
  1541. if op = A3OMod && classify ctx e1.etype = KInt && classify ctx e2.etype = KInt then coerce ctx (classify ctx t);
  1542. in
  1543. let gen_op o =
  1544. check_binop ctx e1 e2;
  1545. gen_expr ctx true e1;
  1546. gen_expr ctx true e2;
  1547. write ctx (HOp o)
  1548. in
  1549. let gen_eq() =
  1550. match is_special_compare e1 e2 with
  1551. | None ->
  1552. gen_op A3OEq
  1553. | Some c ->
  1554. let f = FStatic (c,try PMap.find "compare" c.cl_statics with Not_found -> assert false) in
  1555. gen_expr ctx true (mk (TCall (mk (TField (mk (TTypeExpr (TClassDecl c)) t_dynamic p,f)) t_dynamic p,[e1;e2])) ctx.com.basic.tbool p);
  1556. in
  1557. match op with
  1558. | OpAssign ->
  1559. let acc = gen_access ctx e1 Write in
  1560. gen_expr ctx true e2;
  1561. setvar ctx acc (if retval then Some (classify ctx e1.etype) else None)
  1562. | OpBoolAnd ->
  1563. write ctx HFalse;
  1564. let j = jump_expr ctx e1 false in
  1565. let b = begin_branch ctx in
  1566. write ctx HPop;
  1567. gen_expr ctx true e2;
  1568. coerce ctx KBool;
  1569. j();
  1570. b();
  1571. | OpBoolOr ->
  1572. write ctx HTrue;
  1573. let j = jump_expr ctx e1 true in
  1574. let b = begin_branch ctx in
  1575. write ctx HPop;
  1576. gen_expr ctx true e2;
  1577. coerce ctx KBool;
  1578. j();
  1579. b();
  1580. | OpAssignOp op ->
  1581. let racc, wacc = gen_access_rw ctx e1 in
  1582. getvar ctx racc;
  1583. gen_expr ctx true e2;
  1584. write_op op;
  1585. setvar ctx wacc (if retval then Some (classify ctx e1.etype) else None)
  1586. | OpAdd | OpMult | OpDiv | OpSub | OpAnd | OpOr | OpXor | OpShl | OpShr | OpUShr | OpMod ->
  1587. gen_expr ctx true e1;
  1588. gen_expr ctx true e2;
  1589. write_op op
  1590. | OpEq ->
  1591. gen_eq()
  1592. | OpNotEq ->
  1593. gen_eq();
  1594. write ctx (HOp A3ONot)
  1595. | OpGt ->
  1596. gen_op A3OGt
  1597. | OpGte ->
  1598. gen_op A3OGte
  1599. | OpLt ->
  1600. gen_op A3OLt
  1601. | OpLte ->
  1602. gen_op A3OLte
  1603. | OpInterval | OpArrow ->
  1604. assert false
  1605. and gen_expr ctx retval e =
  1606. let old = ctx.infos.istack in
  1607. debug_infos ctx e.epos;
  1608. gen_expr_content ctx retval e;
  1609. if old <> ctx.infos.istack then begin
  1610. if old + 1 <> ctx.infos.istack then stack_error e.epos;
  1611. if not retval then write ctx HPop;
  1612. end else if retval then stack_error e.epos
  1613. and generate_function ctx fdata stat =
  1614. let f = begin_fun ctx fdata.tf_args fdata.tf_type [fdata.tf_expr] stat fdata.tf_expr.epos in
  1615. gen_expr ctx false fdata.tf_expr;
  1616. (match follow fdata.tf_type with
  1617. | TEnum ({ e_path = [],"Void" },[]) | TAbstract ({ a_path = [],"Void" },[]) ->
  1618. debug_infos ctx ~is_min:false fdata.tf_expr.epos;
  1619. write ctx HRetVoid
  1620. | _ ->
  1621. (* check that we have a return that can be accepted by Flash9 VM *)
  1622. let rec loop e =
  1623. match e.eexpr with
  1624. | TBlock [] -> false
  1625. | TBlock l -> loop (List.hd (List.rev l))
  1626. | TReturn None -> true
  1627. | TReturn (Some e) ->
  1628. let rec inner_loop e =
  1629. match e.eexpr with
  1630. | TSwitch _ | TMatch _ | TFor _ | TWhile _ | TTry _ -> false
  1631. | TIf _ -> loop e
  1632. | TParenthesis e -> inner_loop e
  1633. | _ -> true
  1634. in
  1635. inner_loop e
  1636. | TIf (_,e1,Some e2) -> loop e1 && loop e2
  1637. | TSwitch (_,_,Some e) -> loop e
  1638. | TParenthesis e -> loop e
  1639. | _ -> false
  1640. in
  1641. if not (loop fdata.tf_expr) then write ctx HRetVoid;
  1642. );
  1643. f()
  1644. and jump_expr_gen ctx e jif jfun =
  1645. match e.eexpr with
  1646. | TParenthesis e -> jump_expr_gen ctx e jif jfun
  1647. | TBinop (op,e1,e2) ->
  1648. let j t f =
  1649. check_binop ctx e1 e2;
  1650. gen_expr ctx true e1;
  1651. gen_expr ctx true e2;
  1652. jfun (if jif then t else f)
  1653. in
  1654. (match op with
  1655. | OpEq when is_special_compare e1 e2 = None -> j J3Eq J3Neq
  1656. | OpNotEq when is_special_compare e1 e2 = None -> j J3Neq J3Eq
  1657. | OpGt -> j J3Gt J3NotGt
  1658. | OpGte -> j J3Gte J3NotGte
  1659. | OpLt -> j J3Lt J3NotLt
  1660. | OpLte -> j J3Lte J3NotLte
  1661. | _ ->
  1662. gen_expr ctx true e;
  1663. jfun (if jif then J3True else J3False))
  1664. | _ ->
  1665. gen_expr ctx true e;
  1666. jfun (if jif then J3True else J3False)
  1667. and jump_expr ctx e jif =
  1668. jump_expr_gen ctx e jif (jump ctx)
  1669. let do_debug ctx meta =
  1670. let old = ctx.debug in
  1671. ctx.debug <- (old || Meta.has Meta.Debug meta) && not (Meta.has Meta.NoDebug meta);
  1672. (fun() -> ctx.debug <- old)
  1673. let generate_method ctx fdata stat fmeta =
  1674. let old = do_debug ctx fmeta in
  1675. let m = generate_function ctx fdata stat in
  1676. old();
  1677. m
  1678. let generate_construct ctx fdata c =
  1679. (* make all args optional to allow no-param constructor *)
  1680. let cargs = if not ctx.need_ctor_skip then fdata.tf_args else List.map (fun (v,c) ->
  1681. let c = (match c with Some _ -> c | None ->
  1682. Some (match classify ctx v.v_type with
  1683. | KInt | KUInt -> TInt 0l
  1684. | KFloat -> TFloat "0"
  1685. | KBool -> TBool false
  1686. | KType _ | KDynamic | KNone -> TNull)
  1687. ) in
  1688. v,c
  1689. ) fdata.tf_args in
  1690. let f = begin_fun ctx cargs fdata.tf_type [ethis;fdata.tf_expr] false fdata.tf_expr.epos in
  1691. (* if skip_constructor, then returns immediatly *)
  1692. if ctx.need_ctor_skip then (match c.cl_kind with
  1693. | KGenericInstance _ -> ()
  1694. | _ when not (Codegen.constructor_side_effects fdata.tf_expr) -> ()
  1695. | _ ->
  1696. let id = ident "skip_constructor" in
  1697. getvar ctx (VGlobal (type_path ctx (["flash"],"Boot")));
  1698. getvar ctx (VId id);
  1699. let j = jump ctx J3False in
  1700. write ctx HRetVoid;
  1701. j());
  1702. (* --- *)
  1703. PMap.iter (fun _ f ->
  1704. match f.cf_expr, f.cf_kind with
  1705. | Some { eexpr = TFunction fdata }, Method MethDynamic ->
  1706. let id = ident f.cf_name in
  1707. write ctx (HFindProp id);
  1708. write ctx (HGetProp id);
  1709. let j = jump ctx J3True in
  1710. write ctx (HFindProp id);
  1711. write ctx (HFunction (generate_method ctx fdata false []));
  1712. write ctx (HInitProp id);
  1713. j();
  1714. | _ -> ()
  1715. ) c.cl_fields;
  1716. gen_expr ctx false fdata.tf_expr;
  1717. debug_infos ctx ~is_min:false fdata.tf_expr.epos;
  1718. write ctx HRetVoid;
  1719. f() , List.length fdata.tf_args
  1720. let rec is_const e =
  1721. match e.eexpr with
  1722. | TConst _ -> true
  1723. | TArrayDecl el | TBlock el -> List.for_all is_const el
  1724. | TObjectDecl fl -> List.for_all (fun (_,e) -> is_const e) fl
  1725. | TParenthesis e -> is_const e
  1726. | TFunction _ -> true
  1727. | _ -> false
  1728. let generate_class_statics ctx c const =
  1729. List.iter (fun f ->
  1730. match f.cf_expr with
  1731. | Some { eexpr = TFunction _ } when (match f.cf_kind with Method (MethNormal | MethInline) -> true | _ -> false) -> ()
  1732. | Some e when is_const e = const ->
  1733. write ctx (HGetLex (type_path ctx c.cl_path));
  1734. gen_expr ctx true e;
  1735. if Codegen.is_volatile f.cf_type then write ctx (HArray 1);
  1736. write ctx (HInitProp (ident f.cf_name));
  1737. | _ -> ()
  1738. ) c.cl_ordered_statics
  1739. let need_init ctx c =
  1740. not ctx.swc && not c.cl_extern && List.exists (fun f -> match f.cf_expr with Some e -> not (is_const e) | _ -> false) c.cl_ordered_statics
  1741. let generate_extern_inits ctx =
  1742. List.iter (fun t ->
  1743. match t with
  1744. | TClassDecl c when c.cl_extern ->
  1745. (match c.cl_init with
  1746. | None -> ()
  1747. | Some e -> gen_expr ctx false e);
  1748. | _ -> ()
  1749. ) ctx.com.types
  1750. let generate_inits ctx =
  1751. let finit = begin_fun ctx [] ctx.com.basic.tvoid [] true null_pos in
  1752. if not ctx.swc then generate_extern_inits ctx;
  1753. List.iter (fun t ->
  1754. match t with
  1755. | TClassDecl c when need_init ctx c ->
  1756. let id = ident "init__" in
  1757. getvar ctx (VGlobal (type_path ctx c.cl_path));
  1758. getvar ctx (VId id);
  1759. let j = jump ctx J3True in
  1760. getvar ctx (VGlobal (type_path ctx c.cl_path));
  1761. write ctx HTrue;
  1762. setvar ctx (VId id) None;
  1763. let branch = begin_branch ctx in
  1764. generate_class_statics ctx c false;
  1765. branch();
  1766. j()
  1767. | _ -> ()
  1768. ) ctx.com.types;
  1769. (match ctx.com.main with
  1770. | None -> ()
  1771. | Some e -> gen_expr ctx false e);
  1772. write ctx HRetVoid;
  1773. finit()
  1774. let generate_class_init ctx c hc =
  1775. write ctx HGetGlobalScope;
  1776. if c.cl_interface then
  1777. write ctx HNull
  1778. else begin
  1779. let path = (match c.cl_super with None -> ([],"Object") | Some (sup,_) -> sup.cl_path) in
  1780. write ctx (HGetLex (type_path ctx path));
  1781. write ctx HScope;
  1782. write ctx (HGetLex (type_path ctx path));
  1783. end;
  1784. write ctx (HClassDef hc);
  1785. List.iter (fun f ->
  1786. match f.cf_expr, f.cf_kind with
  1787. | Some { eexpr = TFunction fdata }, Method MethDynamic ->
  1788. write ctx HDup;
  1789. write ctx (HFunction (generate_method ctx fdata true f.cf_meta));
  1790. write ctx (HInitProp (ident f.cf_name));
  1791. | _ -> ()
  1792. ) c.cl_ordered_statics;
  1793. if not c.cl_interface then write ctx HPopScope;
  1794. write ctx (HInitProp (type_path ctx c.cl_path));
  1795. if ctx.swc && c.cl_path = ctx.boot then generate_extern_inits ctx;
  1796. (match c.cl_init with
  1797. | None -> ()
  1798. | Some e ->
  1799. gen_expr ctx false e;
  1800. if ctx.block_vars <> [] then error "You can't have a local variable referenced from a closure inside __init__ (FP 10.1.53 crash)" e.epos;
  1801. );
  1802. generate_class_statics ctx c true;
  1803. if ctx.swc then begin
  1804. generate_class_statics ctx c false;
  1805. if ctx.block_vars <> [] then error "You can't have a local variable referenced from a closure inside a static (FP 10.1.53 crash)" c.cl_pos;
  1806. end
  1807. let generate_enum_init ctx e hc meta =
  1808. let path = ([],"Object") in
  1809. let name_id = type_path ctx e.e_path in
  1810. write ctx HGetGlobalScope;
  1811. write ctx (HGetLex (type_path ctx path));
  1812. write ctx HScope;
  1813. write ctx (HGetLex (type_path ctx path));
  1814. write ctx (HClassDef hc);
  1815. write ctx HPopScope;
  1816. let r = alloc_reg ctx KDynamic in
  1817. write ctx HDup;
  1818. write ctx (HSetReg r.rid); (* needed for setslot *)
  1819. write ctx (HInitProp name_id);
  1820. let nslot = ref 0 in
  1821. PMap.iter (fun _ f ->
  1822. incr nslot;
  1823. match f.ef_type with
  1824. | TFun _ -> ()
  1825. | _ ->
  1826. write ctx (HReg r.rid);
  1827. write ctx (HFindPropStrict name_id);
  1828. write ctx (HString f.ef_name);
  1829. write ctx (HInt f.ef_index);
  1830. write ctx HNull;
  1831. write ctx (HConstructProperty (name_id,3));
  1832. write ctx (HSetSlot !nslot);
  1833. ) e.e_constrs;
  1834. write ctx (HReg r.rid);
  1835. List.iter (fun n -> write ctx (HString n)) e.e_names;
  1836. write ctx (HArray (List.length e.e_names));
  1837. write ctx (HSetProp (ident "__constructs__"));
  1838. (match meta with
  1839. | None -> ()
  1840. | Some e ->
  1841. write ctx (HReg r.rid);
  1842. gen_expr ctx true e;
  1843. write ctx (HSetProp (ident "__meta__"));
  1844. );
  1845. free_reg ctx r
  1846. let extract_meta meta =
  1847. let rec loop = function
  1848. | [] -> []
  1849. | (Meta.Meta,[ECall ((EConst (Ident n),_),args),_],_) :: l ->
  1850. let mk_arg (a,p) =
  1851. match a with
  1852. | EConst (String s) -> (None, s)
  1853. | EBinop (OpAssign,(EConst (Ident n),_),(EConst (String s),_)) -> (Some n, s)
  1854. | _ -> error "Invalid meta definition" p
  1855. in
  1856. { hlmeta_name = n; hlmeta_data = Array.of_list (List.map mk_arg args) } :: loop l
  1857. | _ :: l -> loop l
  1858. in
  1859. match loop meta with
  1860. | [] -> None
  1861. | l -> Some (Array.of_list l)
  1862. let generate_field_kind ctx f c stat =
  1863. let method_kind() =
  1864. let rec loop = function
  1865. | [] -> f.cf_name, MK3Normal
  1866. | (Meta.Getter,[EConst (Ident f),_],_) :: _ -> f, MK3Getter
  1867. | (Meta.Setter,[EConst (Ident f),_],_) :: _ -> f, MK3Setter
  1868. | _ :: l -> loop l
  1869. in
  1870. loop f.cf_meta
  1871. in
  1872. if is_extern_field f then None else
  1873. match f.cf_expr with
  1874. | Some { eexpr = TFunction fdata } ->
  1875. let rec loop c name =
  1876. match c.cl_super with
  1877. | None -> false
  1878. | Some (c,_) ->
  1879. PMap.exists name c.cl_fields || loop c name
  1880. in
  1881. (match f.cf_kind with
  1882. | Method MethDynamic when List.memq f c.cl_overrides ->
  1883. None
  1884. | Var _ | Method MethDynamic ->
  1885. Some (HFVar {
  1886. hlv_type = Some (type_path ctx ([],"Function"));
  1887. hlv_value = HVNone;
  1888. hlv_const = false;
  1889. })
  1890. | _ ->
  1891. let name, kind = method_kind() in
  1892. let m = generate_method ctx fdata stat f.cf_meta in
  1893. Some (HFMethod {
  1894. hlm_type = m;
  1895. hlm_final = stat || (Meta.has Meta.Final f.cf_meta);
  1896. hlm_override = not stat && loop c name;
  1897. hlm_kind = kind;
  1898. })
  1899. );
  1900. | _ when c.cl_interface && not stat ->
  1901. (match follow f.cf_type, f.cf_kind with
  1902. | TFun (args,tret), Method (MethNormal | MethInline) ->
  1903. let dparams = ref None in
  1904. List.iter (fun (_,o,t) ->
  1905. match !dparams with
  1906. | None -> if o then dparams := Some [HVNone]
  1907. | Some l -> dparams := Some (HVNone :: l)
  1908. ) args;
  1909. let dparams = (match !dparams with None -> None | Some l -> Some (List.rev l)) in
  1910. Some (HFMethod {
  1911. hlm_type = end_fun ctx (List.map (fun (a,opt,t) -> alloc_var a t, (if opt then Some TNull else None)) args) dparams tret;
  1912. hlm_final = false;
  1913. hlm_override = false;
  1914. hlm_kind = snd (method_kind());
  1915. })
  1916. | _ ->
  1917. None)
  1918. | _ ->
  1919. Some (HFVar {
  1920. hlv_type = if Codegen.is_volatile f.cf_type then Some (type_path ctx ([],"Array")) else type_opt ctx f.cf_type;
  1921. hlv_value = HVNone;
  1922. hlv_const = false;
  1923. })
  1924. let generate_class ctx c =
  1925. let name = type_path ctx c.cl_path in
  1926. ctx.cur_class <- c;
  1927. let cid , cnargs = (match c.cl_constructor with
  1928. | None ->
  1929. if c.cl_interface then
  1930. { (empty_method ctx null_pos) with hlmt_function = None }, 0
  1931. else
  1932. generate_construct ctx {
  1933. tf_args = [];
  1934. tf_type = ctx.com.basic.tvoid;
  1935. tf_expr = {
  1936. eexpr = TBlock [];
  1937. etype = ctx.com.basic.tvoid;
  1938. epos = null_pos;
  1939. }
  1940. } c
  1941. | Some f ->
  1942. match f.cf_expr with
  1943. | Some { eexpr = TFunction fdata } ->
  1944. let old = do_debug ctx f.cf_meta in
  1945. let m = generate_construct ctx fdata c in
  1946. old();
  1947. m
  1948. | _ -> assert false
  1949. ) in
  1950. let has_protected = ref None in
  1951. let make_name f stat =
  1952. let rec find_meta c =
  1953. try
  1954. let f = PMap.find f.cf_name (if stat then c.cl_statics else c.cl_fields) in
  1955. if List.memq f c.cl_overrides then raise Not_found;
  1956. f.cf_meta
  1957. with Not_found ->
  1958. match c.cl_super with
  1959. | None -> []
  1960. | Some _ when stat -> []
  1961. | Some (c,_) -> find_meta c
  1962. in
  1963. let protect() =
  1964. let p = (match c.cl_path with [], n -> n | p, n -> String.concat "." p ^ ":" ^ n) in
  1965. has_protected := Some p;
  1966. HMName (f.cf_name,HNProtected p)
  1967. in
  1968. let rec loop_meta = function
  1969. | [] ->
  1970. if not f.cf_public && ctx.swf_protected then
  1971. protect()
  1972. else
  1973. ident f.cf_name
  1974. | x :: l ->
  1975. match x with
  1976. | ((Meta.Getter | Meta.Setter),[EConst (Ident f),_],_) -> ident f
  1977. | (Meta.Ns,[EConst (String ns),_],_) -> HMName (f.cf_name,HNNamespace ns)
  1978. | (Meta.Protected,[],_) -> protect()
  1979. | _ -> loop_meta l
  1980. in
  1981. if c.cl_interface then
  1982. HMName (reserved f.cf_name, HNNamespace (match c.cl_path with [],n -> n | l,n -> String.concat "." l ^ ":" ^ n))
  1983. else
  1984. loop_meta (find_meta c)
  1985. in
  1986. let generate_prop f acc alloc_slot =
  1987. match f.cf_kind with
  1988. | Method _ -> acc
  1989. | Var v ->
  1990. (* let p = f.cf_pos in *)
  1991. (* let ethis = mk (TConst TThis) (TInst (c,[])) p in *)
  1992. acc
  1993. in
  1994. let fields = PMap.fold (fun f acc ->
  1995. let acc = generate_prop f acc (fun() -> 0) in
  1996. match generate_field_kind ctx f c false with
  1997. | None -> acc
  1998. | Some k ->
  1999. {
  2000. hlf_name = make_name f false;
  2001. hlf_slot = 0;
  2002. hlf_kind = k;
  2003. hlf_metas = extract_meta f.cf_meta;
  2004. } :: acc
  2005. ) c.cl_fields [] in
  2006. let fields = if c.cl_path <> ctx.boot then fields else begin
  2007. {
  2008. hlf_name = make_name {
  2009. cf_name = "init";
  2010. cf_public = ctx.swc && ctx.swf_protected;
  2011. cf_meta = [];
  2012. cf_doc = None;
  2013. cf_pos = c.cl_pos;
  2014. cf_type = TFun ([],t_dynamic);
  2015. cf_params = [];
  2016. cf_expr = None;
  2017. cf_kind = Method MethNormal;
  2018. cf_overloads = [];
  2019. } false;
  2020. hlf_slot = 0;
  2021. hlf_kind = (HFMethod {
  2022. hlm_type = generate_inits ctx;
  2023. hlm_final = false;
  2024. hlm_override = true;
  2025. hlm_kind = MK3Normal;
  2026. });
  2027. hlf_metas = None;
  2028. } :: fields
  2029. end in
  2030. let st_field_count = ref 0 in
  2031. let st_meth_count = ref 0 in
  2032. let statics = List.rev (List.fold_left (fun acc f ->
  2033. let acc = generate_prop f acc (fun() -> incr st_meth_count; !st_meth_count) in
  2034. match generate_field_kind ctx f c true with
  2035. | None -> acc
  2036. | Some k ->
  2037. let count = (match k with HFMethod _ -> st_meth_count | HFVar _ -> st_field_count | _ -> assert false) in
  2038. incr count;
  2039. {
  2040. hlf_name = make_name f true;
  2041. hlf_slot = !count;
  2042. hlf_kind = k;
  2043. hlf_metas = extract_meta f.cf_meta;
  2044. } :: acc
  2045. ) [] c.cl_ordered_statics) in
  2046. let statics = if not (need_init ctx c) then statics else
  2047. {
  2048. hlf_name = ident "init__";
  2049. hlf_slot = (incr st_field_count; !st_field_count);
  2050. hlf_kind = HFVar { hlv_type = (Some (type_id ctx ctx.com.basic.tbool)); hlv_value = HVNone; hlv_const = false; };
  2051. hlf_metas = None;
  2052. } :: statics
  2053. in
  2054. let rec is_dynamic c =
  2055. if c.cl_dynamic <> None || c.cl_array_access <> None then true
  2056. else match c.cl_super with
  2057. | None -> false
  2058. | Some (c,_) -> is_dynamic c
  2059. in
  2060. {
  2061. hlc_index = 0;
  2062. hlc_name = name;
  2063. hlc_super = (if c.cl_interface then None else Some (type_path ctx (match c.cl_super with None -> [],"Object" | Some (c,_) -> c.cl_path)));
  2064. hlc_sealed = not (is_dynamic c);
  2065. hlc_final = Meta.has Meta.Final c.cl_meta;
  2066. hlc_interface = c.cl_interface;
  2067. hlc_namespace = (match !has_protected with None -> None | Some p -> Some (HNProtected p));
  2068. hlc_implements = Array.of_list (List.map (fun (c,_) ->
  2069. if not c.cl_interface then error "Can't implement class in Flash9" c.cl_pos;
  2070. let pack, name = real_path c.cl_path in
  2071. HMMultiName (Some name,[HNPublic (Some (String.concat "." pack))])
  2072. ) c.cl_implements);
  2073. hlc_construct = cid;
  2074. hlc_fields = Array.of_list fields;
  2075. hlc_static_construct = empty_method ctx c.cl_pos;
  2076. hlc_static_fields = Array.of_list statics;
  2077. }
  2078. let generate_enum ctx e meta =
  2079. let name_id = type_path ctx e.e_path in
  2080. let api = ctx.com.basic in
  2081. let f = begin_fun ctx [alloc_var "tag" api.tstring, None;alloc_var "index" api.tint, None;alloc_var "params" (mk_mono()), None] api.tvoid [ethis] false e.e_pos in
  2082. let tag_id = ident "tag" in
  2083. let index_id = ident "index" in
  2084. let params_id = ident "params" in
  2085. write ctx (HFindProp tag_id);
  2086. write ctx (HReg 1);
  2087. write ctx (HInitProp tag_id);
  2088. write ctx (HFindProp index_id);
  2089. write ctx (HReg 2);
  2090. write ctx (HInitProp index_id);
  2091. write ctx (HFindProp params_id);
  2092. write ctx (HReg 3);
  2093. write ctx (HInitProp params_id);
  2094. write ctx HRetVoid;
  2095. let construct = f() in
  2096. let f = begin_fun ctx [] api.tstring [] true e.e_pos in
  2097. write ctx (HGetLex (type_path ctx (["flash"],"Boot")));
  2098. write ctx HThis;
  2099. write ctx (HCallProperty (ident "enum_to_string",1));
  2100. write ctx HRet;
  2101. let tostring = f() in
  2102. let st_count = ref 0 in
  2103. let constrs = PMap.fold (fun f acc ->
  2104. incr st_count;
  2105. {
  2106. hlf_name = ident f.ef_name;
  2107. hlf_slot = !st_count;
  2108. hlf_kind = (match f.ef_type with
  2109. | TFun (args,_) ->
  2110. let fdata = begin_fun ctx (List.map (fun (a,opt,t) -> alloc_var a t, (if opt then Some TNull else None)) args) (TEnum (e,[])) [] true f.ef_pos in
  2111. write ctx (HFindPropStrict name_id);
  2112. write ctx (HString f.ef_name);
  2113. write ctx (HInt f.ef_index);
  2114. let n = ref 0 in
  2115. List.iter (fun _ -> incr n; write ctx (HReg !n)) args;
  2116. write ctx (HArray (!n));
  2117. write ctx (HConstructProperty (name_id,3));
  2118. write ctx HRet;
  2119. let fid = fdata() in
  2120. HFMethod {
  2121. hlm_type = fid;
  2122. hlm_final = true;
  2123. hlm_override = false;
  2124. hlm_kind = MK3Normal;
  2125. }
  2126. | _ ->
  2127. HFVar { hlv_type = (Some name_id); hlv_value = HVNone; hlv_const = false; }
  2128. );
  2129. hlf_metas = None;
  2130. } :: acc
  2131. ) e.e_constrs [] in
  2132. let constrs = (match meta with
  2133. | None -> constrs
  2134. | Some _ ->
  2135. incr st_count;
  2136. {
  2137. hlf_name = ident "__meta__";
  2138. hlf_slot = !st_count;
  2139. hlf_kind = HFVar { hlv_type = None; hlv_value = HVNone; hlv_const = false; };
  2140. hlf_metas = None;
  2141. } :: constrs
  2142. ) in
  2143. {
  2144. hlc_index = 0;
  2145. hlc_name = name_id;
  2146. hlc_super = Some (type_path ctx ([],"Object"));
  2147. hlc_sealed = true;
  2148. hlc_final = true;
  2149. hlc_interface = false;
  2150. hlc_namespace = None;
  2151. hlc_implements = [||];
  2152. hlc_construct = construct;
  2153. hlc_fields = [|
  2154. { hlf_name = tag_id; hlf_slot = 0; hlf_kind = HFVar { hlv_type = Some (HMPath ([],"String")); hlv_value = HVNone; hlv_const = false; }; hlf_metas = None };
  2155. { hlf_name = index_id; hlf_slot = 0; hlf_kind = HFVar { hlv_type = Some (HMPath ([],"int")); hlv_value = HVNone; hlv_const = false; }; hlf_metas = None };
  2156. { hlf_name = params_id; hlf_slot = 0; hlf_kind = HFVar { hlv_type = Some (HMPath ([],"Array")); hlv_value = HVNone; hlv_const = false; }; hlf_metas = None };
  2157. { hlf_name = ident "__enum__"; hlf_slot = 0; hlf_kind = HFVar { hlv_type = Some (HMPath ([],"Boolean")); hlv_value = HVBool true; hlv_const = true }; hlf_metas = None };
  2158. {
  2159. hlf_name = ident "toString";
  2160. hlf_slot = 0;
  2161. hlf_kind = HFMethod {
  2162. hlm_type = tostring;
  2163. hlm_final = true;
  2164. hlm_override = false;
  2165. hlm_kind = MK3Normal;
  2166. };
  2167. hlf_metas = None;
  2168. };
  2169. |];
  2170. hlc_static_construct = empty_method ctx e.e_pos;
  2171. hlc_static_fields = Array.of_list ({
  2172. hlf_name = ident "__isenum";
  2173. hlf_slot = !st_count + 2;
  2174. hlf_kind = HFVar { hlv_type = Some (HMPath ([],"Boolean")); hlv_value = HVBool true; hlv_const = true; };
  2175. hlf_metas = None;
  2176. } :: {
  2177. hlf_name = ident "__constructs__";
  2178. hlf_slot = !st_count + 1;
  2179. hlf_kind = HFVar { hlv_type = None; hlv_value = HVNone; hlv_const = false; };
  2180. hlf_metas = None;
  2181. } :: constrs);
  2182. }
  2183. let rec generate_type ctx t =
  2184. match t with
  2185. | TClassDecl c ->
  2186. if c.cl_path = (["flash";"_Boot"],"RealBoot") then c.cl_path <- ctx.boot;
  2187. if c.cl_extern && (c.cl_path <> ([],"Dynamic") || Meta.has Meta.RealPath c.cl_meta) then
  2188. None
  2189. else
  2190. let debug = do_debug ctx c.cl_meta in
  2191. let hlc = generate_class ctx c in
  2192. let init = begin_fun ctx [] ctx.com.basic.tvoid [ethis] false c.cl_pos in
  2193. generate_class_init ctx c hlc;
  2194. write ctx HRetVoid;
  2195. debug();
  2196. Some (init(), {
  2197. hlf_name = type_path ctx c.cl_path;
  2198. hlf_slot = 0;
  2199. hlf_kind = HFClass hlc;
  2200. hlf_metas = extract_meta c.cl_meta;
  2201. })
  2202. | TEnumDecl e ->
  2203. if e.e_extern then
  2204. None
  2205. else
  2206. let meta = Codegen.build_metadata ctx.com t in
  2207. let hlc = generate_enum ctx e meta in
  2208. let init = begin_fun ctx [] ctx.com.basic.tvoid [ethis] false e.e_pos in
  2209. generate_enum_init ctx e hlc meta;
  2210. write ctx HRetVoid;
  2211. Some (init(), {
  2212. hlf_name = type_path ctx e.e_path;
  2213. hlf_slot = 0;
  2214. hlf_kind = HFClass hlc;
  2215. hlf_metas = extract_meta e.e_meta;
  2216. })
  2217. | TAbstractDecl ({ a_path = [],"Dynamic" } as a) ->
  2218. generate_type ctx (TClassDecl (mk_class a.a_module a.a_path a.a_pos))
  2219. | TTypeDecl _ | TAbstractDecl _ ->
  2220. None
  2221. let resource_path name =
  2222. (["_res"],"_" ^ String.concat "_" (ExtString.String.nsplit name "."))
  2223. let generate_resource ctx name =
  2224. let c = mk_class null_module (resource_path name) null_pos in
  2225. c.cl_super <- Some (mk_class null_module (["flash";"utils"],"ByteArray") null_pos,[]);
  2226. let t = TClassDecl c in
  2227. match generate_type ctx t with
  2228. | Some (m,f) -> (t,m,f)
  2229. | None -> assert false
  2230. let generate com boot_name =
  2231. let ctx = {
  2232. com = com;
  2233. need_ctor_skip = Common.has_feature com "Type.createEmptyInstance";
  2234. debug = com.Common.debug;
  2235. cur_class = null_class;
  2236. boot = ([],boot_name);
  2237. debugger = Common.defined com Define.Fdb;
  2238. swc = Common.defined com Define.Swc;
  2239. swf_protected = Common.defined com Define.SwfProtected;
  2240. code = DynArray.create();
  2241. locals = PMap.empty;
  2242. infos = default_infos();
  2243. trys = [];
  2244. breaks = [];
  2245. continues = [];
  2246. block_vars = [];
  2247. in_static = false;
  2248. last_line = -1;
  2249. last_file = "";
  2250. try_scope_reg = None;
  2251. for_call = false;
  2252. } in
  2253. let types = if ctx.swc && com.main_class = None then
  2254. (*
  2255. make sure that both Boot and RealBoot are the first two classes in the SWC
  2256. this way initializing RealBoot will also run externs __init__ blocks before
  2257. another class static is defined
  2258. *)
  2259. let hd = ref [] in
  2260. let types = List.fold_left (fun acc t ->
  2261. match t_path t with
  2262. | ["flash";"_Boot"],"RealBoot" -> hd := !hd @ [t]; acc
  2263. | ["flash"], "Boot" -> hd := t :: !hd; acc
  2264. | _ -> t :: acc
  2265. ) [] com.types in
  2266. !hd @ List.rev types
  2267. else
  2268. com.types
  2269. in
  2270. let res = Hashtbl.fold (fun name _ acc -> generate_resource ctx name :: acc) com.resources [] in
  2271. let classes = List.fold_left (fun acc t ->
  2272. match generate_type ctx t with
  2273. | None -> acc
  2274. | Some (m,f) -> (t,m,f) :: acc
  2275. ) res types in
  2276. List.rev classes
  2277. ;;
  2278. Random.self_init();
  2279. gen_expr_ref := gen_expr