genas3.ml 35 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244
  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 Type
  23. open Common
  24. type context_infos = {
  25. com : Common.context;
  26. }
  27. type context = {
  28. inf : context_infos;
  29. ch : out_channel;
  30. buf : Buffer.t;
  31. path : path;
  32. mutable get_sets : (string * bool,string) Hashtbl.t;
  33. mutable curclass : tclass;
  34. mutable tabs : string;
  35. mutable in_value : tvar option;
  36. mutable in_static : bool;
  37. mutable handle_break : bool;
  38. mutable imports : (string,string list list) Hashtbl.t;
  39. mutable gen_uid : int;
  40. mutable local_types : t list;
  41. mutable constructor_block : bool;
  42. mutable block_inits : (unit -> unit) option;
  43. }
  44. let is_var_field f =
  45. match f with
  46. | FStatic (_,f) | FInstance (_,f) ->
  47. (match f.cf_kind with Var _ -> true | _ -> false)
  48. | _ ->
  49. false
  50. let is_special_compare e1 e2 =
  51. match e1.eexpr, e2.eexpr with
  52. | TConst TNull, _ | _ , TConst TNull -> None
  53. | _ ->
  54. match follow e1.etype, follow e2.etype with
  55. | TInst ({ cl_path = [],"Xml" } as c,_) , _ | _ , TInst ({ cl_path = [],"Xml" } as c,_) -> Some c
  56. | _ -> None
  57. let protect name =
  58. match name with
  59. | "Error" | "Namespace" -> "_" ^ name
  60. | _ -> name
  61. let s_path ctx stat path p =
  62. match path with
  63. | ([],name) ->
  64. (match name with
  65. | "Int" -> "int"
  66. | "Float" -> "Number"
  67. | "Dynamic" -> "Object"
  68. | "Bool" -> "Boolean"
  69. | "Enum" -> "Class"
  70. | "EnumValue" -> "enum"
  71. | _ -> name)
  72. | (["flash"],"FlashXml__") ->
  73. "Xml"
  74. | (["flash";"errors"],"Error") ->
  75. "Error"
  76. | (["flash"],"Vector") ->
  77. "Vector"
  78. | (["flash";"xml"],"XML") ->
  79. "XML"
  80. | (["flash";"xml"],"XMLList") ->
  81. "XMLList"
  82. | ["flash";"utils"],"QName" ->
  83. "QName"
  84. | ["flash";"utils"],"Namespace" ->
  85. "Namespace"
  86. | (["haxe"],"Int32") when not stat ->
  87. "int"
  88. | (pack,name) ->
  89. let name = protect name in
  90. let packs = (try Hashtbl.find ctx.imports name with Not_found -> []) in
  91. if not (List.mem pack packs) then Hashtbl.replace ctx.imports name (pack :: packs);
  92. Ast.s_type_path (pack,name)
  93. let reserved =
  94. let h = Hashtbl.create 0 in
  95. List.iter (fun l -> Hashtbl.add h l ())
  96. (* these ones are defined in order to prevent recursion in some Std functions *)
  97. ["is";"as";"int";"uint";"const";"getTimer";"typeof";"parseInt";"parseFloat";
  98. (* AS3 keywords which are not Haxe ones *)
  99. "finally";"with";"final";"internal";"native";"namespace";"include";"delete";
  100. (* some globals give some errors with Flex SDK as well *)
  101. "print";"trace";
  102. (* we don't include get+set since they are not 'real' keywords, but they can't be used as method names *)
  103. "function";"class";"var";"if";"else";"while";"do";"for";"break";"continue";"return";"extends";"implements";
  104. "import";"switch";"case";"default";"static";"public";"private";"try";"catch";"new";"this";"throw";"interface";
  105. "override";"package";"null";"true";"false";"void"
  106. ];
  107. h
  108. (* "each", "label" : removed (actually allowed in locals and fields accesses) *)
  109. let s_ident n =
  110. if Hashtbl.mem reserved n then "_" ^ n else n
  111. let rec create_dir acc = function
  112. | [] -> ()
  113. | d :: l ->
  114. let dir = String.concat "/" (List.rev (d :: acc)) in
  115. if not (Sys.file_exists dir) then Unix.mkdir dir 0o755;
  116. create_dir (d :: acc) l
  117. let init infos path =
  118. let dir = infos.com.file :: fst path in
  119. create_dir [] dir;
  120. let ch = open_out (String.concat "/" dir ^ "/" ^ snd path ^ ".as") in
  121. let imports = Hashtbl.create 0 in
  122. Hashtbl.add imports (snd path) [fst path];
  123. {
  124. inf = infos;
  125. tabs = "";
  126. ch = ch;
  127. path = path;
  128. buf = Buffer.create (1 lsl 14);
  129. in_value = None;
  130. in_static = false;
  131. handle_break = false;
  132. imports = imports;
  133. curclass = null_class;
  134. gen_uid = 0;
  135. local_types = [];
  136. get_sets = Hashtbl.create 0;
  137. constructor_block = false;
  138. block_inits = None;
  139. }
  140. let close ctx =
  141. output_string ctx.ch (Printf.sprintf "package %s {\n" (String.concat "." (fst ctx.path)));
  142. Hashtbl.iter (fun name paths ->
  143. List.iter (fun pack ->
  144. let path = pack, name in
  145. if path <> ctx.path then output_string ctx.ch ("\timport " ^ Ast.s_type_path path ^ ";\n");
  146. ) paths
  147. ) ctx.imports;
  148. output_string ctx.ch (Buffer.contents ctx.buf);
  149. close_out ctx.ch
  150. let gen_local ctx l =
  151. ctx.gen_uid <- ctx.gen_uid + 1;
  152. if ctx.gen_uid = 1 then l else l ^ string_of_int ctx.gen_uid
  153. let spr ctx s = Buffer.add_string ctx.buf s
  154. let print ctx = Printf.kprintf (fun s -> Buffer.add_string ctx.buf s)
  155. let unsupported p = error "This expression cannot be generated to AS3" p
  156. let newline ctx =
  157. let rec loop p =
  158. match Buffer.nth ctx.buf p with
  159. | '}' | '{' | ':' | ';' -> print ctx "\n%s" ctx.tabs
  160. | '\n' | '\t' -> loop (p - 1)
  161. | _ -> print ctx ";\n%s" ctx.tabs
  162. in
  163. loop (Buffer.length ctx.buf - 1)
  164. let block_newline ctx = match Buffer.nth ctx.buf (Buffer.length ctx.buf - 1) with
  165. | '}' -> print ctx ";\n%s" ctx.tabs
  166. | _ -> newline ctx
  167. let rec concat ctx s f = function
  168. | [] -> ()
  169. | [x] -> f x
  170. | x :: l ->
  171. f x;
  172. spr ctx s;
  173. concat ctx s f l
  174. let open_block ctx =
  175. let oldt = ctx.tabs in
  176. ctx.tabs <- "\t" ^ ctx.tabs;
  177. (fun() -> ctx.tabs <- oldt)
  178. let parent e =
  179. match e.eexpr with
  180. | TParenthesis _ -> e
  181. | _ -> mk (TParenthesis e) e.etype e.epos
  182. let default_value tstr =
  183. match tstr with
  184. | "int" | "uint" -> "0"
  185. | "Number" -> "NaN"
  186. | "Boolean" -> "false"
  187. | _ -> "null"
  188. let rec type_str ctx t p =
  189. match t with
  190. | TEnum _ | TInst _ when List.memq t ctx.local_types ->
  191. "*"
  192. | TAbstract ({ a_impl = Some _ } as a,pl) ->
  193. type_str ctx (apply_params a.a_types pl a.a_this) p
  194. | TAbstract (a,_) ->
  195. (match a.a_path with
  196. | [], "Void" -> "void"
  197. | [], "UInt" -> "uint"
  198. | [], "Int" -> "int"
  199. | [], "Float" -> "Number"
  200. | [], "Bool" -> "Boolean"
  201. | _ -> s_path ctx true a.a_path p)
  202. | TEnum (e,_) ->
  203. if e.e_extern then (match e.e_path with
  204. | [], "Void" -> "void"
  205. | [], "Bool" -> "Boolean"
  206. | _ ->
  207. let rec loop = function
  208. | [] -> "Object"
  209. | (Ast.Meta.FakeEnum,[Ast.EConst (Ast.Ident n),_],_) :: _ ->
  210. (match n with
  211. | "Int" -> "int"
  212. | "UInt" -> "uint"
  213. | _ -> n)
  214. | _ :: l -> loop l
  215. in
  216. loop e.e_meta
  217. ) else
  218. s_path ctx true e.e_path p
  219. | TInst ({ cl_path = ["flash"],"Vector" },[pt]) ->
  220. (match pt with
  221. | TInst({cl_kind = KTypeParameter _},_) -> "*"
  222. | _ -> "Vector.<" ^ type_str ctx pt p ^ ">")
  223. | TInst (c,_) ->
  224. (match c.cl_kind with
  225. | KNormal | KGeneric | KGenericInstance _ | KAbstractImpl _ -> s_path ctx false c.cl_path p
  226. | KTypeParameter _ | KExtension _ | KExpr _ | KMacroType -> "*")
  227. | TFun _ ->
  228. "Function"
  229. | TMono r ->
  230. (match !r with None -> "*" | Some t -> type_str ctx t p)
  231. | TAnon _ | TDynamic _ ->
  232. "*"
  233. | TType (t,args) ->
  234. (match t.t_path with
  235. | [], "UInt" -> "uint"
  236. | [] , "Null" ->
  237. (match args with
  238. | [t] ->
  239. (match follow t with
  240. | TAbstract ({ a_path = [],"UInt" },_)
  241. | TAbstract ({ a_path = [],"Int" },_)
  242. | TAbstract ({ a_path = [],"Float" },_)
  243. | TAbstract ({ a_path = [],"Bool" },_)
  244. | TInst ({ cl_path = [],"Int" },_)
  245. | TInst ({ cl_path = [],"Float" },_)
  246. | TEnum ({ e_path = [],"Bool" },_) -> "*"
  247. | _ -> type_str ctx t p)
  248. | _ -> assert false);
  249. | _ -> type_str ctx (apply_params t.t_types args t.t_type) p)
  250. | TLazy f ->
  251. type_str ctx ((!f)()) p
  252. let rec iter_switch_break in_switch e =
  253. match e.eexpr with
  254. | TFunction _ | TWhile _ | TFor _ -> ()
  255. | TSwitch _ | TMatch _ when not in_switch -> iter_switch_break true e
  256. | TBreak when in_switch -> raise Exit
  257. | _ -> iter (iter_switch_break in_switch) e
  258. let handle_break ctx e =
  259. let old_handle = ctx.handle_break in
  260. try
  261. iter_switch_break false e;
  262. ctx.handle_break <- false;
  263. (fun() -> ctx.handle_break <- old_handle)
  264. with
  265. Exit ->
  266. spr ctx "try {";
  267. let b = open_block ctx in
  268. newline ctx;
  269. ctx.handle_break <- true;
  270. (fun() ->
  271. b();
  272. ctx.handle_break <- old_handle;
  273. newline ctx;
  274. spr ctx "} catch( e : * ) { if( e != \"__break__\" ) throw e; }";
  275. )
  276. let this ctx = if ctx.in_value <> None then "$this" else "this"
  277. let escape_bin s =
  278. let b = Buffer.create 0 in
  279. for i = 0 to String.length s - 1 do
  280. match Char.code (String.unsafe_get s i) with
  281. | c when c < 32 -> Buffer.add_string b (Printf.sprintf "\\x%.2X" c)
  282. | c -> Buffer.add_char b (Char.chr c)
  283. done;
  284. Buffer.contents b
  285. let generate_resources infos =
  286. if Hashtbl.length infos.com.resources <> 0 then begin
  287. let dir = (infos.com.file :: ["__res"]) in
  288. create_dir [] dir;
  289. let add_resource name data =
  290. let ch = open_out_bin (String.concat "/" (dir @ [name])) in
  291. output_string ch data;
  292. close_out ch
  293. in
  294. Hashtbl.iter (fun name data -> add_resource name data) infos.com.resources;
  295. let ctx = init infos ([],"__resources__") in
  296. spr ctx "\timport flash.utils.Dictionary;\n";
  297. spr ctx "\tpublic class __resources__ {\n";
  298. spr ctx "\t\tpublic static var list:Dictionary;\n";
  299. let inits = ref [] in
  300. let k = ref 0 in
  301. Hashtbl.iter (fun name _ ->
  302. let varname = ("v" ^ (string_of_int !k)) in
  303. k := !k + 1;
  304. print ctx "\t\t[Embed(source = \"__res/%s\", mimeType = \"application/octet-stream\")]\n" name;
  305. print ctx "\t\tpublic static var %s:Class;\n" varname;
  306. inits := ("list[\"" ^name^ "\"] = " ^ varname ^ ";") :: !inits;
  307. ) infos.com.resources;
  308. spr ctx "\t\tstatic public function __init__():void {\n";
  309. spr ctx "\t\t\tlist = new Dictionary();\n";
  310. List.iter (fun init ->
  311. print ctx "\t\t\t%s\n" init
  312. ) !inits;
  313. spr ctx "\t\t}\n";
  314. spr ctx "\t}\n";
  315. spr ctx "}";
  316. close ctx;
  317. end
  318. let gen_constant ctx p = function
  319. | TInt i -> print ctx "%ld" i
  320. | TFloat s -> spr ctx s
  321. | TString s -> print ctx "\"%s\"" (escape_bin (Ast.s_escape s))
  322. | TBool b -> spr ctx (if b then "true" else "false")
  323. | TNull -> spr ctx "null"
  324. | TThis -> spr ctx (this ctx)
  325. | TSuper -> spr ctx "super"
  326. let gen_function_header ctx name f params p =
  327. let old = ctx.in_value in
  328. let old_t = ctx.local_types in
  329. let old_bi = ctx.block_inits in
  330. ctx.in_value <- None;
  331. ctx.local_types <- List.map snd params @ ctx.local_types;
  332. let init () =
  333. List.iter (fun (v,o) -> match o with
  334. | Some c when is_nullable v.v_type && c <> TNull ->
  335. newline ctx;
  336. print ctx "if(%s==null) %s=" v.v_name v.v_name;
  337. gen_constant ctx p c;
  338. | _ -> ()
  339. ) f.tf_args;
  340. ctx.block_inits <- None;
  341. in
  342. ctx.block_inits <- Some init;
  343. print ctx "function%s(" (match name with None -> "" | Some (n,meta) ->
  344. let rec loop = function
  345. | [] -> n
  346. | (Ast.Meta.Getter,[Ast.EConst (Ast.Ident i),_],_) :: _ -> "get " ^ i
  347. | (Ast.Meta.Setter,[Ast.EConst (Ast.Ident i),_],_) :: _ -> "set " ^ i
  348. | _ :: l -> loop l
  349. in
  350. " " ^ loop meta
  351. );
  352. concat ctx "," (fun (v,c) ->
  353. let tstr = type_str ctx v.v_type p in
  354. print ctx "%s : %s" (s_ident v.v_name) tstr;
  355. match c with
  356. | None ->
  357. if ctx.constructor_block then print ctx " = %s" (default_value tstr);
  358. | Some c ->
  359. spr ctx " = ";
  360. gen_constant ctx p c
  361. ) f.tf_args;
  362. print ctx ") : %s " (type_str ctx f.tf_type p);
  363. (fun () ->
  364. ctx.in_value <- old;
  365. ctx.local_types <- old_t;
  366. ctx.block_inits <- old_bi;
  367. )
  368. let rec gen_call ctx e el r =
  369. match e.eexpr , el with
  370. | TCall (x,_) , el ->
  371. spr ctx "(";
  372. gen_value ctx e;
  373. spr ctx ")";
  374. spr ctx "(";
  375. concat ctx "," (gen_value ctx) el;
  376. spr ctx ")";
  377. | TLocal { v_name = "__is__" } , [e1;e2] ->
  378. gen_value ctx e1;
  379. spr ctx " is ";
  380. gen_value ctx e2;
  381. | TLocal { v_name = "__as__" }, [e1;e2] ->
  382. gen_value ctx e1;
  383. spr ctx " as ";
  384. gen_value ctx e2;
  385. | TLocal { v_name = "__int__" }, [e] ->
  386. spr ctx "int(";
  387. gen_value ctx e;
  388. spr ctx ")";
  389. | TLocal { v_name = "__float__" }, [e] ->
  390. spr ctx "Number(";
  391. gen_value ctx e;
  392. spr ctx ")";
  393. | TLocal { v_name = "__typeof__" }, [e] ->
  394. spr ctx "typeof ";
  395. gen_value ctx e;
  396. | TLocal { v_name = "__keys__" }, [e] ->
  397. let ret = (match ctx.in_value with None -> assert false | Some r -> r) in
  398. print ctx "%s = new Array()" ret.v_name;
  399. newline ctx;
  400. let tmp = gen_local ctx "$k" in
  401. print ctx "for(var %s : String in " tmp;
  402. gen_value ctx e;
  403. print ctx ") %s.push(%s)" ret.v_name tmp;
  404. | TLocal { v_name = "__hkeys__" }, [e] ->
  405. let ret = (match ctx.in_value with None -> assert false | Some r -> r) in
  406. print ctx "%s = new Array()" ret.v_name;
  407. newline ctx;
  408. let tmp = gen_local ctx "$k" in
  409. print ctx "for(var %s : String in " tmp;
  410. gen_value ctx e;
  411. print ctx ") %s.push(%s.substr(1))" ret.v_name tmp;
  412. | TLocal { v_name = "__foreach__" }, [e] ->
  413. let ret = (match ctx.in_value with None -> assert false | Some r -> r) in
  414. print ctx "%s = new Array()" ret.v_name;
  415. newline ctx;
  416. let tmp = gen_local ctx "$k" in
  417. print ctx "for each(var %s : * in " tmp;
  418. gen_value ctx e;
  419. print ctx ") %s.push(%s)" ret.v_name tmp;
  420. | TLocal { v_name = "__new__" }, e :: args ->
  421. spr ctx "new ";
  422. gen_value ctx e;
  423. spr ctx "(";
  424. concat ctx "," (gen_value ctx) args;
  425. spr ctx ")";
  426. | TLocal { v_name = "__delete__" }, [e;f] ->
  427. spr ctx "delete(";
  428. gen_value ctx e;
  429. spr ctx "[";
  430. gen_value ctx f;
  431. spr ctx "]";
  432. spr ctx ")";
  433. | TLocal { v_name = "__unprotect__" }, [e] ->
  434. gen_value ctx e
  435. | TLocal { v_name = "__vector__" }, [e] ->
  436. spr ctx (type_str ctx r e.epos);
  437. spr ctx "(";
  438. gen_value ctx e;
  439. spr ctx ")"
  440. | TField (_, FStatic( { cl_path = (["flash"],"Lib") }, { cf_name = "as" })), [e1;e2] ->
  441. gen_value ctx e1;
  442. spr ctx " as ";
  443. gen_value ctx e2
  444. | TField (_, FStatic ({ cl_path = (["flash"],"Vector") }, cf)), args ->
  445. (match cf.cf_name, args with
  446. | "ofArray", [e] | "convert", [e] ->
  447. (match follow r with
  448. | TInst ({ cl_path = (["flash"],"Vector") },[t]) ->
  449. print ctx "Vector.<%s>(" (type_str ctx t e.epos);
  450. gen_value ctx e;
  451. print ctx ")";
  452. | _ -> assert false)
  453. | _ -> assert false)
  454. | TField (ee,f), args when is_var_field f ->
  455. spr ctx "(";
  456. gen_value ctx e;
  457. spr ctx ")";
  458. spr ctx "(";
  459. concat ctx "," (gen_value ctx) el;
  460. spr ctx ")"
  461. | _ ->
  462. gen_value ctx e;
  463. spr ctx "(";
  464. concat ctx "," (gen_value ctx) el;
  465. spr ctx ")"
  466. and gen_value_op ctx e =
  467. match e.eexpr with
  468. | TBinop (op,_,_) when op = Ast.OpAnd || op = Ast.OpOr || op = Ast.OpXor ->
  469. spr ctx "(";
  470. gen_value ctx e;
  471. spr ctx ")";
  472. | _ ->
  473. gen_value ctx e
  474. and gen_field_access ctx t s =
  475. let field c =
  476. match fst c.cl_path, snd c.cl_path, s with
  477. | [], "Math", "NaN"
  478. | [], "Math", "NEGATIVE_INFINITY"
  479. | [], "Math", "POSITIVE_INFINITY"
  480. | [], "Math", "isFinite"
  481. | [], "Math", "isNaN"
  482. | [], "Date", "now"
  483. | [], "Date", "fromTime"
  484. | [], "Date", "fromString"
  485. ->
  486. print ctx "[\"%s\"]" s
  487. | [], "String", "charCodeAt" ->
  488. spr ctx "[\"charCodeAtHX\"]"
  489. | [], "Array", "map" ->
  490. spr ctx "[\"mapHX\"]"
  491. | [], "Array", "filter" ->
  492. spr ctx "[\"filterHX\"]"
  493. | [], "Date", "toString" ->
  494. print ctx "[\"toStringHX\"]"
  495. | [], "String", "cca" ->
  496. print ctx ".charCodeAt"
  497. | ["flash";"xml"], "XML", "namespace" ->
  498. print ctx ".namespace"
  499. | _ ->
  500. print ctx ".%s" (s_ident s)
  501. in
  502. match follow t with
  503. | TInst (c,_) -> field c
  504. | TAnon a ->
  505. (match !(a.a_status) with
  506. | Statics c -> field c
  507. | _ -> print ctx ".%s" (s_ident s))
  508. | _ ->
  509. print ctx ".%s" (s_ident s)
  510. and gen_expr ctx e =
  511. match e.eexpr with
  512. | TConst c ->
  513. gen_constant ctx e.epos c
  514. | TLocal v ->
  515. spr ctx (s_ident v.v_name)
  516. | TArray ({ eexpr = TLocal { v_name = "__global__" } },{ eexpr = TConst (TString s) }) ->
  517. let path = Ast.parse_path s in
  518. spr ctx (s_path ctx false path e.epos)
  519. | TArray (e1,e2) ->
  520. gen_value ctx e1;
  521. spr ctx "[";
  522. gen_value ctx e2;
  523. spr ctx "]";
  524. | TBinop (Ast.OpEq,e1,e2) when (match is_special_compare e1 e2 with Some c -> true | None -> false) ->
  525. let c = match is_special_compare e1 e2 with Some c -> c | None -> assert false in
  526. gen_expr ctx (mk (TCall (mk (TField (mk (TTypeExpr (TClassDecl c)) t_dynamic e.epos,FDynamic "compare")) t_dynamic e.epos,[e1;e2])) ctx.inf.com.basic.tbool e.epos);
  527. (* what is this used for? *)
  528. (* | TBinop (op,{ eexpr = TField (e1,s) },e2) ->
  529. gen_value_op ctx e1;
  530. gen_field_access ctx e1.etype s;
  531. print ctx " %s " (Ast.s_binop op);
  532. gen_value_op ctx e2; *)
  533. | TBinop (op,e1,e2) ->
  534. gen_value_op ctx e1;
  535. print ctx " %s " (Ast.s_binop op);
  536. gen_value_op ctx e2;
  537. (* variable fields on interfaces are generated as (class["field"] as class) *)
  538. | TField ({etype = TInst({cl_interface = true} as c,_)} as e,FInstance (_,{ cf_name = s }))
  539. when (try (match (PMap.find s c.cl_fields).cf_kind with Var _ -> true | _ -> false) with Not_found -> false) ->
  540. spr ctx "(";
  541. gen_value ctx e;
  542. print ctx "[\"%s\"]" s;
  543. print ctx " as %s)" (type_str ctx e.etype e.epos);
  544. | TField({eexpr = TArrayDecl _} as e1,s) ->
  545. spr ctx "(";
  546. gen_expr ctx e1;
  547. spr ctx ")";
  548. gen_field_access ctx e1.etype (field_name s)
  549. | TField (e,s) ->
  550. gen_value ctx e;
  551. gen_field_access ctx e.etype (field_name s)
  552. | TTypeExpr t ->
  553. spr ctx (s_path ctx true (t_path t) e.epos)
  554. | TParenthesis e ->
  555. spr ctx "(";
  556. gen_value ctx e;
  557. spr ctx ")";
  558. | TReturn eo ->
  559. if ctx.in_value <> None then unsupported e.epos;
  560. (match eo with
  561. | None ->
  562. spr ctx "return"
  563. | Some e when (match follow e.etype with TEnum({ e_path = [],"Void" },[]) | TAbstract ({ a_path = [],"Void" },[]) -> true | _ -> false) ->
  564. print ctx "{";
  565. let bend = open_block ctx in
  566. newline ctx;
  567. gen_value ctx e;
  568. newline ctx;
  569. spr ctx "return";
  570. bend();
  571. newline ctx;
  572. print ctx "}";
  573. | Some e ->
  574. spr ctx "return ";
  575. gen_value ctx e);
  576. | TBreak ->
  577. if ctx.in_value <> None then unsupported e.epos;
  578. if ctx.handle_break then spr ctx "throw \"__break__\"" else spr ctx "break"
  579. | TContinue ->
  580. if ctx.in_value <> None then unsupported e.epos;
  581. spr ctx "continue"
  582. | TBlock el ->
  583. print ctx "{";
  584. let bend = open_block ctx in
  585. let cb = (if not ctx.constructor_block then
  586. (fun () -> ())
  587. else if not (Codegen.constructor_side_effects e) then begin
  588. ctx.constructor_block <- false;
  589. (fun () -> ())
  590. end else begin
  591. ctx.constructor_block <- false;
  592. print ctx " if( !%s.skip_constructor ) {" (s_path ctx true (["flash"],"Boot") e.epos);
  593. (fun() -> print ctx "}")
  594. end) in
  595. (match ctx.block_inits with None -> () | Some i -> i());
  596. List.iter (fun e -> block_newline ctx; gen_expr ctx e) el;
  597. bend();
  598. newline ctx;
  599. cb();
  600. print ctx "}";
  601. | TFunction f ->
  602. let h = gen_function_header ctx None f [] e.epos in
  603. let old = ctx.in_static in
  604. ctx.in_static <- true;
  605. gen_expr ctx f.tf_expr;
  606. ctx.in_static <- old;
  607. h();
  608. | TCall (v,el) ->
  609. gen_call ctx v el e.etype
  610. | TArrayDecl el ->
  611. spr ctx "[";
  612. concat ctx "," (gen_value ctx) el;
  613. spr ctx "]"
  614. | TThrow e ->
  615. spr ctx "throw ";
  616. gen_value ctx e;
  617. | TVars [] ->
  618. ()
  619. | TVars vl ->
  620. spr ctx "var ";
  621. concat ctx ", " (fun (v,eo) ->
  622. print ctx "%s : %s" (s_ident v.v_name) (type_str ctx v.v_type e.epos);
  623. match eo with
  624. | None -> ()
  625. | Some e ->
  626. spr ctx " = ";
  627. gen_value ctx e
  628. ) vl;
  629. | TNew (c,params,el) ->
  630. (match c.cl_path, params with
  631. | (["flash"],"Vector"), [pt] -> print ctx "new Vector.<%s>(" (type_str ctx pt e.epos)
  632. | _ -> print ctx "new %s(" (s_path ctx true c.cl_path e.epos));
  633. concat ctx "," (gen_value ctx) el;
  634. spr ctx ")"
  635. | TIf (cond,e,eelse) ->
  636. spr ctx "if";
  637. gen_value ctx (parent cond);
  638. spr ctx " ";
  639. gen_expr ctx e;
  640. (match eelse with
  641. | None -> ()
  642. | Some e ->
  643. newline ctx;
  644. spr ctx "else ";
  645. gen_expr ctx e);
  646. | TUnop (op,Ast.Prefix,e) ->
  647. spr ctx (Ast.s_unop op);
  648. gen_value ctx e
  649. | TUnop (op,Ast.Postfix,e) ->
  650. gen_value ctx e;
  651. spr ctx (Ast.s_unop op)
  652. | TWhile (cond,e,Ast.NormalWhile) ->
  653. let handle_break = handle_break ctx e in
  654. spr ctx "while";
  655. gen_value ctx (parent cond);
  656. spr ctx " ";
  657. gen_expr ctx e;
  658. handle_break();
  659. | TWhile (cond,e,Ast.DoWhile) ->
  660. let handle_break = handle_break ctx e in
  661. spr ctx "do ";
  662. gen_expr ctx e;
  663. spr ctx " while";
  664. gen_value ctx (parent cond);
  665. handle_break();
  666. | TObjectDecl fields ->
  667. spr ctx "{ ";
  668. concat ctx ", " (fun (f,e) -> print ctx "%s : " (s_ident f); gen_value ctx e) fields;
  669. spr ctx "}"
  670. | TFor (v,it,e) ->
  671. let handle_break = handle_break ctx e in
  672. let tmp = gen_local ctx "$it" in
  673. print ctx "{ var %s : * = " tmp;
  674. gen_value ctx it;
  675. newline ctx;
  676. print ctx "while( %s.hasNext() ) { var %s : %s = %s.next()" tmp (s_ident v.v_name) (type_str ctx v.v_type e.epos) tmp;
  677. newline ctx;
  678. gen_expr ctx e;
  679. newline ctx;
  680. spr ctx "}}";
  681. handle_break();
  682. | TTry (e,catchs) ->
  683. spr ctx "try ";
  684. gen_expr ctx e;
  685. List.iter (fun (v,e) ->
  686. newline ctx;
  687. print ctx "catch( %s : %s )" (s_ident v.v_name) (type_str ctx v.v_type e.epos);
  688. gen_expr ctx e;
  689. ) catchs;
  690. | TMatch (e,_,cases,def) ->
  691. print ctx "{";
  692. let bend = open_block ctx in
  693. newline ctx;
  694. let tmp = gen_local ctx "$e" in
  695. print ctx "var %s : enum = " tmp;
  696. gen_value ctx e;
  697. newline ctx;
  698. print ctx "switch( %s.index ) {" tmp;
  699. List.iter (fun (cl,params,e) ->
  700. List.iter (fun c ->
  701. newline ctx;
  702. print ctx "case %d:" c;
  703. ) cl;
  704. (match params with
  705. | None | Some [] -> ()
  706. | Some l ->
  707. let n = ref (-1) in
  708. let l = List.fold_left (fun acc v -> incr n; match v with None -> acc | Some v -> (v,!n) :: acc) [] l in
  709. match l with
  710. | [] -> ()
  711. | l ->
  712. newline ctx;
  713. spr ctx "var ";
  714. concat ctx ", " (fun (v,n) ->
  715. print ctx "%s : %s = %s.params[%d]" (s_ident v.v_name) (type_str ctx v.v_type e.epos) tmp n;
  716. ) l);
  717. gen_block ctx e;
  718. print ctx "break";
  719. ) cases;
  720. (match def with
  721. | None -> ()
  722. | Some e ->
  723. newline ctx;
  724. spr ctx "default:";
  725. gen_block ctx e;
  726. print ctx "break";
  727. );
  728. newline ctx;
  729. spr ctx "}";
  730. bend();
  731. newline ctx;
  732. spr ctx "}";
  733. | TSwitch (e,cases,def) ->
  734. spr ctx "switch";
  735. gen_value ctx (parent e);
  736. spr ctx " {";
  737. newline ctx;
  738. List.iter (fun (el,e2) ->
  739. List.iter (fun e ->
  740. spr ctx "case ";
  741. gen_value ctx e;
  742. spr ctx ":";
  743. ) el;
  744. gen_block ctx e2;
  745. print ctx "break";
  746. newline ctx;
  747. ) cases;
  748. (match def with
  749. | None -> ()
  750. | Some e ->
  751. spr ctx "default:";
  752. gen_block ctx e;
  753. print ctx "break";
  754. newline ctx;
  755. );
  756. spr ctx "}"
  757. | TCast (e1,None) ->
  758. spr ctx "((";
  759. gen_expr ctx e1;
  760. print ctx ") as %s)" (type_str ctx e.etype e.epos);
  761. | TCast (e1,Some t) ->
  762. gen_expr ctx (Codegen.default_cast ctx.inf.com e1 t e.etype e.epos)
  763. and gen_block ctx e =
  764. newline ctx;
  765. match e.eexpr with
  766. | TBlock [] -> ()
  767. | _ ->
  768. gen_expr ctx e;
  769. newline ctx
  770. and gen_value ctx e =
  771. let assign e =
  772. mk (TBinop (Ast.OpAssign,
  773. mk (TLocal (match ctx.in_value with None -> assert false | Some r -> r)) t_dynamic e.epos,
  774. e
  775. )) e.etype e.epos
  776. in
  777. let block e =
  778. mk (TBlock [e]) e.etype e.epos
  779. in
  780. let value block =
  781. let old = ctx.in_value in
  782. let t = type_str ctx e.etype e.epos in
  783. let r = alloc_var (gen_local ctx "$r") e.etype in
  784. ctx.in_value <- Some r;
  785. if ctx.in_static then
  786. print ctx "function() : %s " t
  787. else
  788. print ctx "(function($this:%s) : %s " (snd ctx.path) t;
  789. let b = if block then begin
  790. spr ctx "{";
  791. let b = open_block ctx in
  792. newline ctx;
  793. print ctx "var %s : %s" r.v_name t;
  794. newline ctx;
  795. b
  796. end else
  797. (fun() -> ())
  798. in
  799. (fun() ->
  800. if block then begin
  801. newline ctx;
  802. print ctx "return %s" r.v_name;
  803. b();
  804. newline ctx;
  805. spr ctx "}";
  806. end;
  807. ctx.in_value <- old;
  808. if ctx.in_static then
  809. print ctx "()"
  810. else
  811. print ctx "(%s))" (this ctx)
  812. )
  813. in
  814. match e.eexpr with
  815. | TCall ({ eexpr = TLocal { v_name = "__keys__" } },_) | TCall ({ eexpr = TLocal { v_name = "__hkeys__" } },_) ->
  816. let v = value true in
  817. gen_expr ctx e;
  818. v()
  819. | TConst _
  820. | TLocal _
  821. | TArray _
  822. | TBinop _
  823. | TField _
  824. | TTypeExpr _
  825. | TParenthesis _
  826. | TObjectDecl _
  827. | TArrayDecl _
  828. | TCall _
  829. | TNew _
  830. | TUnop _
  831. | TFunction _ ->
  832. gen_expr ctx e
  833. | TCast (e1,None) ->
  834. let s = type_str ctx e.etype e1.epos in
  835. if s = "*" then
  836. gen_value ctx e1
  837. else begin
  838. print ctx "%s(" s;
  839. gen_value ctx e1;
  840. spr ctx ")";
  841. end
  842. | TCast (e1,Some t) ->
  843. gen_value ctx (Codegen.default_cast ctx.inf.com e1 t e.etype e.epos)
  844. | TReturn _
  845. | TBreak
  846. | TContinue ->
  847. unsupported e.epos
  848. | TVars _
  849. | TFor _
  850. | TWhile _
  851. | TThrow _ ->
  852. (* value is discarded anyway *)
  853. let v = value true in
  854. gen_expr ctx e;
  855. v()
  856. | TBlock [] ->
  857. spr ctx "null"
  858. | TBlock [e] ->
  859. gen_value ctx e
  860. | TBlock el ->
  861. let v = value true in
  862. let rec loop = function
  863. | [] ->
  864. spr ctx "return null";
  865. | [e] ->
  866. gen_expr ctx (assign e);
  867. | e :: l ->
  868. gen_expr ctx e;
  869. newline ctx;
  870. loop l
  871. in
  872. loop el;
  873. v();
  874. | TIf (cond,e,eo) ->
  875. spr ctx "(";
  876. gen_value ctx cond;
  877. spr ctx "?";
  878. gen_value ctx e;
  879. spr ctx ":";
  880. (match eo with
  881. | None -> spr ctx "null"
  882. | Some e -> gen_value ctx e);
  883. spr ctx ")"
  884. | TSwitch (cond,cases,def) ->
  885. let v = value true in
  886. gen_expr ctx (mk (TSwitch (cond,
  887. List.map (fun (e1,e2) -> (e1,assign e2)) cases,
  888. match def with None -> None | Some e -> Some (assign e)
  889. )) e.etype e.epos);
  890. v()
  891. | TMatch (cond,enum,cases,def) ->
  892. let v = value true in
  893. gen_expr ctx (mk (TMatch (cond,enum,
  894. List.map (fun (constr,params,e) -> (constr,params,assign e)) cases,
  895. match def with None -> None | Some e -> Some (assign e)
  896. )) e.etype e.epos);
  897. v()
  898. | TTry (b,catchs) ->
  899. let v = value true in
  900. gen_expr ctx (mk (TTry (block (assign b),
  901. List.map (fun (v,e) -> v, block (assign e)) catchs
  902. )) e.etype e.epos);
  903. v()
  904. let final m =
  905. if Ast.Meta.has Ast.Meta.Final m then "final " else ""
  906. let generate_field ctx static f =
  907. newline ctx;
  908. ctx.in_static <- static;
  909. ctx.gen_uid <- 0;
  910. List.iter (fun(m,pl,_) ->
  911. match m,pl with
  912. | Ast.Meta.Meta, [Ast.ECall ((Ast.EConst (Ast.Ident n),_),args),_] ->
  913. let mk_arg (a,p) =
  914. match a with
  915. | Ast.EConst (Ast.String s) -> (None, s)
  916. | Ast.EBinop (Ast.OpAssign,(Ast.EConst (Ast.Ident n),_),(Ast.EConst (Ast.String s),_)) -> (Some n, s)
  917. | _ -> error "Invalid meta definition" p
  918. in
  919. print ctx "[%s" n;
  920. (match args with
  921. | [] -> ()
  922. | _ ->
  923. print ctx "(";
  924. concat ctx "," (fun a ->
  925. match mk_arg a with
  926. | None, s -> gen_constant ctx (snd a) (TString s)
  927. | Some s, e -> print ctx "%s=" s; gen_constant ctx (snd a) (TString e)
  928. ) args;
  929. print ctx ")");
  930. print ctx "]";
  931. | _ -> ()
  932. ) f.cf_meta;
  933. let public = f.cf_public || Hashtbl.mem ctx.get_sets (f.cf_name,static) || (f.cf_name = "main" && static) || f.cf_name = "resolve" || Ast.Meta.has Ast.Meta.Public f.cf_meta in
  934. let rights = (if static then "static " else "") ^ (if public then "public" else "protected") in
  935. let p = ctx.curclass.cl_pos in
  936. match f.cf_expr, f.cf_kind with
  937. | Some { eexpr = TFunction fd }, Method (MethNormal | MethInline) ->
  938. print ctx "%s%s " rights (if static then "" else final f.cf_meta);
  939. let rec loop c =
  940. match c.cl_super with
  941. | None -> ()
  942. | Some (c,_) ->
  943. if PMap.mem f.cf_name c.cl_fields then
  944. spr ctx "override "
  945. else
  946. loop c
  947. in
  948. if not static then loop ctx.curclass;
  949. let h = gen_function_header ctx (Some (s_ident f.cf_name, f.cf_meta)) fd f.cf_params p in
  950. gen_expr ctx fd.tf_expr;
  951. h();
  952. newline ctx
  953. | _ ->
  954. let is_getset = (match f.cf_kind with Var { v_read = AccCall } | Var { v_write = AccCall } -> true | _ -> false) in
  955. if ctx.curclass.cl_interface then
  956. match follow f.cf_type with
  957. | TFun (args,r) ->
  958. let rec loop = function
  959. | [] -> f.cf_name
  960. | (Ast.Meta.Getter,[Ast.EConst (Ast.String name),_],_) :: _ -> "get " ^ name
  961. | (Ast.Meta.Setter,[Ast.EConst (Ast.String name),_],_) :: _ -> "set " ^ name
  962. | _ :: l -> loop l
  963. in
  964. print ctx "function %s(" (loop f.cf_meta);
  965. concat ctx "," (fun (arg,o,t) ->
  966. let tstr = type_str ctx t p in
  967. print ctx "%s : %s" arg tstr;
  968. if o then print ctx " = %s" (default_value tstr);
  969. ) args;
  970. print ctx ") : %s " (type_str ctx r p);
  971. | _ when is_getset ->
  972. let t = type_str ctx f.cf_type p in
  973. let id = s_ident f.cf_name in
  974. (match f.cf_kind with
  975. | Var v ->
  976. (match v.v_read with
  977. | AccNormal -> print ctx "function get %s() : %s;" id t;
  978. | AccCall -> print ctx "function %s() : %s;" ("get_" ^ f.cf_name) t;
  979. | _ -> ());
  980. (match v.v_write with
  981. | AccNormal -> print ctx "function set %s( __v : %s ) : void;" id t;
  982. | AccCall -> print ctx "function %s( __v : %s ) : %s;" ("set_" ^ f.cf_name) t t;
  983. | _ -> ());
  984. | _ -> assert false)
  985. | _ -> ()
  986. else
  987. let gen_init () = match f.cf_expr with
  988. | None -> ()
  989. | Some e ->
  990. print ctx " = ";
  991. gen_value ctx e
  992. in
  993. if is_getset then begin
  994. let t = type_str ctx f.cf_type p in
  995. let id = s_ident f.cf_name in
  996. let v = (match f.cf_kind with Var v -> v | _ -> assert false) in
  997. (match v.v_read with
  998. | AccNormal | AccNo | AccNever ->
  999. print ctx "%s function get %s() : %s { return $%s; }" rights id t id;
  1000. newline ctx
  1001. | AccCall ->
  1002. print ctx "%s function get %s() : %s { return %s(); }" rights id t ("get_" ^ f.cf_name);
  1003. newline ctx
  1004. | _ -> ());
  1005. (match v.v_write with
  1006. | AccNormal | AccNo | AccNever ->
  1007. print ctx "%s function set %s( __v : %s ) : void { $%s = __v; }" rights id t id;
  1008. newline ctx
  1009. | AccCall ->
  1010. print ctx "%s function set %s( __v : %s ) : void { %s(__v); }" rights id t ("set_" ^ f.cf_name);
  1011. newline ctx
  1012. | _ -> ());
  1013. print ctx "%sprotected var $%s : %s" (if static then "static " else "") (s_ident f.cf_name) (type_str ctx f.cf_type p);
  1014. gen_init()
  1015. end else begin
  1016. print ctx "%s var %s : %s" rights (s_ident f.cf_name) (type_str ctx f.cf_type p);
  1017. gen_init()
  1018. end
  1019. let rec define_getset ctx stat c =
  1020. let def f name =
  1021. Hashtbl.add ctx.get_sets (name,stat) f.cf_name
  1022. in
  1023. let field f =
  1024. match f.cf_kind with
  1025. | Method _ -> ()
  1026. | Var v ->
  1027. (match v.v_read with AccCall -> def f ("get_" ^ f.cf_name) | _ -> ());
  1028. (match v.v_write with AccCall -> def f ("set_" ^ f.cf_name) | _ -> ())
  1029. in
  1030. List.iter field (if stat then c.cl_ordered_statics else c.cl_ordered_fields);
  1031. match c.cl_super with
  1032. | Some (c,_) when not stat -> define_getset ctx stat c
  1033. | _ -> ()
  1034. let generate_class ctx c =
  1035. ctx.curclass <- c;
  1036. define_getset ctx true c;
  1037. define_getset ctx false c;
  1038. ctx.local_types <- List.map snd c.cl_types;
  1039. let pack = open_block ctx in
  1040. print ctx "\tpublic %s%s%s %s " (final c.cl_meta) (match c.cl_dynamic with None -> "" | Some _ -> if c.cl_interface then "" else "dynamic ") (if c.cl_interface then "interface" else "class") (snd c.cl_path);
  1041. (match c.cl_super with
  1042. | None -> ()
  1043. | Some (csup,_) -> print ctx "extends %s " (s_path ctx true csup.cl_path c.cl_pos));
  1044. (match c.cl_implements with
  1045. | [] -> ()
  1046. | l ->
  1047. spr ctx (if c.cl_interface then "extends " else "implements ");
  1048. concat ctx ", " (fun (i,_) -> print ctx "%s" (s_path ctx true i.cl_path c.cl_pos)) l);
  1049. spr ctx "{";
  1050. let cl = open_block ctx in
  1051. (match c.cl_constructor with
  1052. | None -> ()
  1053. | Some f ->
  1054. let f = { f with
  1055. cf_name = snd c.cl_path;
  1056. cf_public = true;
  1057. cf_kind = Method MethNormal;
  1058. } in
  1059. ctx.constructor_block <- true;
  1060. generate_field ctx false f;
  1061. );
  1062. List.iter (generate_field ctx false) c.cl_ordered_fields;
  1063. List.iter (generate_field ctx true) c.cl_ordered_statics;
  1064. cl();
  1065. newline ctx;
  1066. print ctx "}";
  1067. pack();
  1068. newline ctx;
  1069. print ctx "}";
  1070. newline ctx
  1071. let generate_main ctx inits =
  1072. ctx.curclass <- { null_class with cl_path = [],"__main__" };
  1073. let pack = open_block ctx in
  1074. print ctx "\timport flash.Lib";
  1075. newline ctx;
  1076. print ctx "public class __main__ extends %s {" (s_path ctx true (["flash"],"Boot") Ast.null_pos);
  1077. let cl = open_block ctx in
  1078. newline ctx;
  1079. spr ctx "public function __main__() {";
  1080. let fl = open_block ctx in
  1081. newline ctx;
  1082. spr ctx "super()";
  1083. newline ctx;
  1084. spr ctx "flash.Lib.current = this";
  1085. List.iter (fun e -> newline ctx; gen_expr ctx e) inits;
  1086. fl();
  1087. newline ctx;
  1088. print ctx "}";
  1089. cl();
  1090. newline ctx;
  1091. print ctx "}";
  1092. pack();
  1093. newline ctx;
  1094. print ctx "}";
  1095. newline ctx
  1096. let generate_enum ctx e =
  1097. ctx.local_types <- List.map snd e.e_types;
  1098. let pack = open_block ctx in
  1099. let ename = snd e.e_path in
  1100. print ctx "\tpublic final class %s extends enum {" ename;
  1101. let cl = open_block ctx in
  1102. newline ctx;
  1103. print ctx "public static const __isenum : Boolean = true";
  1104. newline ctx;
  1105. print ctx "public function %s( t : String, index : int, p : Array = null ) : void { this.tag = t; this.index = index; this.params = p; }" ename;
  1106. PMap.iter (fun _ c ->
  1107. newline ctx;
  1108. match c.ef_type with
  1109. | TFun (args,_) ->
  1110. print ctx "public static function %s(" c.ef_name;
  1111. concat ctx ", " (fun (a,o,t) ->
  1112. print ctx "%s : %s" (s_ident a) (type_str ctx t c.ef_pos);
  1113. if o then spr ctx " = null";
  1114. ) args;
  1115. print ctx ") : %s {" ename;
  1116. print ctx " return new %s(\"%s\",%d,[" ename c.ef_name c.ef_index;
  1117. concat ctx "," (fun (a,_,_) -> spr ctx (s_ident a)) args;
  1118. print ctx "]); }";
  1119. | _ ->
  1120. print ctx "public static var %s : %s = new %s(\"%s\",%d)" c.ef_name ename ename c.ef_name c.ef_index;
  1121. ) e.e_constrs;
  1122. newline ctx;
  1123. (match Codegen.build_metadata ctx.inf.com (TEnumDecl e) with
  1124. | None -> ()
  1125. | Some e ->
  1126. print ctx "public static var __meta__ : * = ";
  1127. gen_expr ctx e;
  1128. newline ctx);
  1129. print ctx "public static var __constructs__ : Array = [%s];" (String.concat "," (List.map (fun s -> "\"" ^ Ast.s_escape s ^ "\"") e.e_names));
  1130. cl();
  1131. newline ctx;
  1132. print ctx "}";
  1133. pack();
  1134. newline ctx;
  1135. print ctx "}";
  1136. newline ctx
  1137. let generate_base_enum ctx =
  1138. let pack = open_block ctx in
  1139. spr ctx "\timport flash.Boot";
  1140. newline ctx;
  1141. spr ctx "public class enum {";
  1142. let cl = open_block ctx in
  1143. newline ctx;
  1144. spr ctx "public var tag : String";
  1145. newline ctx;
  1146. spr ctx "public var index : int";
  1147. newline ctx;
  1148. spr ctx "public var params : Array";
  1149. newline ctx;
  1150. spr ctx "public function toString() : String { return flash.Boot.enum_to_string(this); }";
  1151. cl();
  1152. newline ctx;
  1153. print ctx "}";
  1154. pack();
  1155. newline ctx;
  1156. print ctx "}";
  1157. newline ctx
  1158. let generate com =
  1159. let infos = {
  1160. com = com;
  1161. } in
  1162. generate_resources infos;
  1163. let ctx = init infos ([],"enum") in
  1164. generate_base_enum ctx;
  1165. close ctx;
  1166. let inits = ref [] in
  1167. List.iter (fun t ->
  1168. match t with
  1169. | TClassDecl c ->
  1170. let c = (match c.cl_path with
  1171. | ["flash"],"FlashXml__" -> { c with cl_path = [],"Xml" }
  1172. | (pack,name) -> { c with cl_path = (pack,protect name) }
  1173. ) in
  1174. (match c.cl_init with
  1175. | None -> ()
  1176. | Some e -> inits := e :: !inits);
  1177. if c.cl_extern then
  1178. ()
  1179. else
  1180. let ctx = init infos c.cl_path in
  1181. generate_class ctx c;
  1182. close ctx
  1183. | TEnumDecl e ->
  1184. let pack,name = e.e_path in
  1185. let e = { e with e_path = (pack,protect name) } in
  1186. if e.e_extern then
  1187. ()
  1188. else
  1189. let ctx = init infos e.e_path in
  1190. generate_enum ctx e;
  1191. close ctx
  1192. | TTypeDecl _ | TAbstractDecl _ ->
  1193. ()
  1194. ) com.types;
  1195. (match com.main with
  1196. | None -> ()
  1197. | Some e -> inits := e :: !inits);
  1198. let ctx = init infos ([],"__main__") in
  1199. generate_main ctx (List.rev !inits);
  1200. close ctx