genas3.ml 35 KB

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