瀏覽代碼

remove --gen-hx-classes (#8237)

* separate genhx from genxml

* remove --gen-hx-classes, but leave the functionality for now, hidden behind undocumented -D gen_hx_classes
Dan Korostelev 6 年之前
父節點
當前提交
a3f7606826
共有 5 個文件被更改,包括 325 次插入304 次删除
  1. 1 1
      extra/extract.hxml
  2. 0 283
      src/codegen/genxml.ml
  3. 1 1
      src/codegen/swfLoader.ml
  4. 21 19
      src/compiler/main.ml
  5. 302 0
      src/generators/genhxold.ml

+ 1 - 1
extra/extract.hxml

@@ -9,4 +9,4 @@
 -swf test.swf
 --swf-version 15
 --macro patchTypes("../extra/extract.patch")
---gen-hx-classes
+-D gen-hx-classes

+ 0 - 283
src/codegen/genxml.ml

@@ -299,286 +299,3 @@ let gen_type_string ctx t =
 	let ch = IO.output_string() in
 	write_xml ch "" x;
 	IO.close_out ch
-
-
-(* -------------------------------------------------------------------------- *)
-(* PRINT HX FROM TYPE *)
-
-let rec create_dir acc = function
-	| [] -> ()
-	| d :: l ->
-		let path = acc ^ "/" ^ d in
-		(try Unix.mkdir path 0o777 with _ -> ());
-		create_dir path l
-
-let conv_path p =
-	match List.rev (fst p) with
-	| x :: l when starts_with x '_' -> List.rev (("priv" ^ x) :: l), snd p
-	| _ -> p
-
-let get_real_path meta path =
-	try
-		let real_path = match Meta.get Meta.RealPath meta with
-			| (_,[(EConst(String s),_)],_) ->
-				s
-			| _ -> raise Not_found
-		in
-		match List.rev (String.nsplit real_path ".") with
-			| name :: pack ->
-				(List.rev pack), name
-			| _ -> raise Not_found
-	with | Not_found ->
-		path
-
-
-let generate_type com t =
-	let base_path = "hxclasses" in
-	match t with TClassDecl { cl_kind = KAbstractImpl _ } -> () | _ ->
-	let pack, name =
-		let info = t_infos t in
-		get_real_path info.mt_meta info.mt_path
-	in
-	create_dir "." (base_path :: pack);
-	match pack, name with
-	| ["flash";"net"], "NetStreamPlayTransitions"
-	| ["flash";"filters"], "BitmapFilterQuality"
-	| ["flash";"display"], ("BitmapDataChannel" | "GraphicsPathCommand")  -> ()
-	| _ ->
-	let f = open_out_bin (base_path ^ "/" ^ (match pack with [] -> "" | l -> String.concat "/" l ^ "/") ^ name ^ ".hx") in
-	let ch = IO.output_channel f in
-	let p fmt = IO.printf ch fmt in
-	if pack <> [] then IO.printf ch "package %s;\n\n" (String.concat "." pack);
-	let rec notnull t =
-		match t with
-		| TMono r ->
-			(match !r with
-			| None -> t
-			| Some t -> notnull t)
-		| TLazy f ->
-			notnull (lazy_type f)
-		| TAbstract ({ a_path = [],"Null" },[t]) ->
-			t
-		| _ ->
-			t
-	in
-	let rec path meta p tl =
-		let p = conv_path (get_real_path meta p) in
-		(if fst p = pack then snd p else s_type_path p) ^ (match tl with [] -> "" | _ -> "<" ^ String.concat "," (List.map stype tl) ^ ">")
-	and stype t =
-		match t with
-		| TMono r ->
-			(match !r with
-			| None -> "Unknown"
-			| Some t -> stype t)
-		| TInst ({ cl_kind = KTypeParameter _ } as c,tl) ->
-			path [] ([],snd c.cl_path) tl
-		| TInst (c,tl) ->
-			path c.cl_meta c.cl_path tl
-		| TEnum (e,tl) ->
-			path e.e_meta e.e_path tl
-		| TType (t,tl) ->
-			path t.t_meta t.t_path tl
-		| TAbstract (a,tl) ->
-			path a.a_meta a.a_path tl
-		| TAnon a ->
-			let fields = PMap.fold (fun f acc -> (f.cf_name ^ " : " ^ stype f.cf_type) :: acc) a.a_fields [] in
-			"{" ^ String.concat ", " fields ^ "}"
-		| TLazy f ->
-			stype (lazy_type f)
-		| TDynamic t2 ->
-			if t == t2 then "Dynamic" else "Dynamic<" ^ stype t2 ^ ">"
-		| TFun ([],ret) ->
-			"Void -> " ^ ftype ret
-		| TFun (args,ret) ->
-			String.concat " -> " (List.map (fun (_,_,t) -> ftype t) args) ^ " -> " ^ ftype ret
-	and ftype t =
-		match t with
-		| TMono r ->
-			(match !r with
-			| None -> stype t
-			| Some t -> ftype t)
-		| TLazy f ->
-			ftype (lazy_type f)
-		| TFun _ ->
-			"(" ^ stype t ^ ")"
-		| _ ->
-			stype t
-	in
-	let sparam (n,v,t) =
-		match v with
-		| None ->
-			n ^ " : " ^ stype t
-		| Some (Ident "null") ->
-			if is_nullable (notnull t) then
-				"?" ^ n ^ " : " ^ stype (notnull t)
-			else
-				(* we have not found a default value stored in metadata, let's generate it *)
-				n ^ " : " ^ stype t ^ " = " ^ (match follow t with
-					| TAbstract ({ a_path = [],("Int"|"Float"|"UInt") },_) -> "0"
-					| TAbstract ({ a_path = [],"Bool" },_) -> "false"
-					| _ -> "null")
-		| Some v ->
-			n ^ " : " ^ stype t ^ " = " ^ (match s_constant v with "nan" -> "0./*NaN*/" | v -> v)
-	in
-	let print_meta ml =
-		List.iter (fun (m,pl,_) ->
-			match m with
-			| Meta.DefParam | Meta.CoreApi | Meta.Used | Meta.MaybeUsed | Meta.FlatEnum | Meta.Value | Meta.DirectlyUsed | Meta.Enum | Meta.Impl -> ()
-			| _ ->
-			match pl with
-			| [] -> p "@%s " (Meta.to_string m)
-			| l -> p "@%s(%s) " (Meta.to_string m) (String.concat "," (List.map Ast.s_expr pl))
-		) ml
-	in
-	let access is_read a = s_access is_read a in
-	let rec print_field stat f =
-		p "\t";
-		print_meta f.cf_meta;
-		if stat then p "static ";
-		let name = try (match Meta.get Meta.RealPath f.cf_meta with
-				| (Meta.RealPath, [EConst( String s ), _], _) ->
-					s
-				| _ ->
-					raise Not_found)
-			with Not_found ->
-				f.cf_name
-		in
-		(match f.cf_kind with
-		| Var v ->
-			if has_class_field_flag f CfFinal then
-				p "final %s" name
-			else begin
-				p "var %s" name;
-				if v.v_read <> AccNormal || v.v_write <> AccNormal then p "(%s,%s)" (access true v.v_read) (access false v.v_write);
-			end;
-			p " : %s" (stype f.cf_type);
-		| Method m ->
-			let params, ret = (match follow f.cf_type with
-				| TFun (args,ret) ->
-					List.map (fun (a,o,t) ->
-						let rec loop = function
-							| [] -> Ident "null"
-							| (Meta.DefParam,[(EConst (String p),_);(EConst v,_)],_) :: _ when p = a ->
-								(match v with
-								| Float "1.#QNAN" -> Float "0./*NaN*/"
-								| Float "4294967295." -> Int "0xFFFFFFFF"
-								| Int "16777215" -> Int "0xFFFFFF"
-								| Float x ->
-									(try
-										let f = float_of_string x in
-										let s = string_of_int (int_of_float f) in
-										if s ^ "." = x then Int s else v
-									with _ ->
-										v)
-								| _ -> v)
-							| _ :: l -> loop l
-						in
-						a,(if o then Some (loop f.cf_meta) else None ),t
-					) args, ret
-				| _ ->
-					assert false
-			) in
-			let tparams = (match f.cf_params with [] -> "" | l -> "<" ^ String.concat "," (List.map fst l) ^ ">") in
-			p "function %s%s(%s) : %s" name tparams (String.concat ", " (List.map sparam params)) (stype ret);
-		);
-		p ";\n";
-		if Meta.has Meta.Overload f.cf_meta then List.iter (fun f -> print_field stat f) f.cf_overloads
-	in
-	(match t with
-	| TClassDecl c ->
-		print_meta c.cl_meta;
-		let finalmod = if c.cl_final then "final " else "" in
-		p "extern %s%s %s" finalmod (if c.cl_interface then "interface" else "class") (stype (TInst (c,List.map snd c.cl_params)));
-		let ext = (match c.cl_super with
-		| None -> []
-		| Some (c,pl) -> [" extends " ^ stype (TInst (c,pl))]
-		) in
-		let ext = List.fold_left (fun acc (i,pl) -> ((if c.cl_interface then " extends " else " implements ") ^ stype (TInst (i,pl))) :: acc) ext c.cl_implements in
-		let ext = (match c.cl_dynamic with
-			| None -> ext
-			| Some t ->
-				(match c.cl_path with
-				| ["flash";"errors"], _ -> ext
-				| _ when t == t_dynamic -> " implements Dynamic" :: ext
-				| _ -> (" implements Dynamic<" ^ stype t ^ ">") :: ext)
-		) in
-		let ext = (match c.cl_path with
-			| ["flash";"utils"], "ByteArray" -> " implements ArrayAccess<Int>" :: ext
-			| ["flash";"utils"], "Dictionary" -> [" implements ArrayAccess<Dynamic>"]
-			| ["flash";"xml"], "XML" -> [" implements Dynamic<XMLList>"]
-			| ["flash";"xml"], "XMLList" -> [" implements ArrayAccess<XML>"]
-			| ["flash";"display"],"MovieClip" -> [" extends Sprite #if !flash_strict implements Dynamic #end"]
-			| ["flash";"errors"], "Error" -> [" #if !flash_strict implements Dynamic #end"]
-			| _ -> ext
-		) in
-		p "%s" (String.concat "" (List.rev ext));
-		p " {\n";
-		let sort l =
-			let a = Array.of_list (List.filter (fun f -> has_class_field_flag f CfPublic && not (List.memq f c.cl_overrides)) l) in
-			let name = function "new" -> "" | n -> n in
-			Array.sort (fun f1 f2 ->
-				match f1.cf_kind, f2.cf_kind with
-				| Var _, Var _ | Method _ , Method _ -> compare (name f1.cf_name) (name f2.cf_name)
-				| Var _, _ -> -1
-				| _ -> 1
-			) a;
-			Array.to_list a
-		in
-		List.iter (print_field false) (sort (match c.cl_constructor with None -> c.cl_ordered_fields | Some f -> f :: c.cl_ordered_fields));
-		List.iter (print_field true) (sort c.cl_ordered_statics);
-		p "}\n";
-	| TEnumDecl e ->
-		print_meta e.e_meta;
-		p "extern enum %s {\n" (stype (TEnum(e,List.map snd e.e_params)));
-		List.iter (fun n ->
-			let c = PMap.find n e.e_constrs in
-			p "\t%s" c.ef_name;
-			(match follow c.ef_type with
-			| TFun (args,_) -> p "(%s)" (String.concat ", " (List.map sparam (List.map (fun (a,o,t) -> a,(if o then Some (Ident "null") else None),t) args)))
-			| _ -> ());
-			p ";\n";
-		) e.e_names;
-		p "}\n"
-	| TTypeDecl t ->
-		print_meta t.t_meta;
-		p "typedef %s = " (stype (TType (t,List.map snd t.t_params)));
-		p "%s" (stype t.t_type);
-		p "\n";
-	| TAbstractDecl a ->
-		print_meta a.a_meta;
-		Option.may (fun c -> try print_meta [Meta.get Meta.Require c.cl_meta] with Not_found -> ()) a.a_impl;
-		p "extern ";
-		let is_enum = Meta.has Meta.Enum a.a_meta in
-		if is_enum then p "enum ";
-		p "abstract %s" (stype (TAbstract (a,List.map snd a.a_params)));
-		if not (Meta.has Meta.CoreType a.a_meta) then p "(%s)" (stype a.a_this);
-		p " {\n";
-		Option.may (fun c ->
-			let fields = c.cl_ordered_statics in
-			let fields =
-				if is_enum then
-					let sort l =
-						let a = Array.of_list l in
-						Array.sort (fun a b -> compare a.cf_name b.cf_name) a;
-						Array.to_list a
-					in
-					sort fields
-				else
-					fields
-			in
-
-			List.iter (fun f ->
-				let static = not (Meta.has Meta.Impl f.cf_meta) in
-				if not static && is_enum && Meta.has Meta.Enum f.cf_meta then begin
-					p "\tvar %s;\n" f.cf_name;
-				end else
-					print_field static f
-			) fields
-		) a.a_impl;
-		p "}\n";
-	);
-	IO.close_out ch
-
-let generate_hx com =
-	List.iter (generate_type com) com.types
-

+ 1 - 1
src/codegen/swfLoader.ml

@@ -269,7 +269,7 @@ let build_class com c file =
 							match v with
 							| None -> None
 							| Some v ->
-								(* add for --gen-hx-classes generation *)
+								(* add for -D gen-hx-classes generation *)
 								meta := (Meta.DefParam,[String aname;v]) :: !meta;
 								Some (EConst v,pos)
 					in

+ 21 - 19
src/compiler/main.ml

@@ -695,23 +695,6 @@ try
 		("Services",["--json"],[],Arg.String (fun file ->
 			json_out := Some file
 		),"<file>","generate JSON types description");
-		("Services",["--gen-hx-classes"],[], Arg.Unit (fun() ->
-			force_typing := true;
-			pre_compilation := (fun() ->
-				List.iter (fun (_,_,extract) ->
-					Hashtbl.iter (fun n _ -> classes := n :: !classes) (extract())
-				) com.swf_libs;
-				List.iter (fun (_,std,_,all_files,_) ->
-					if not std then
-						List.iter (fun path -> if path <> (["java";"lang"],"String") then classes := path :: !classes) (all_files())
-				) com.java_libs;
-				List.iter (fun (_,std,all_files,_) ->
-					if not std then
-						List.iter (fun path -> classes := path :: !classes) (all_files())
-				) com.net_libs;
-			) :: !pre_compilation;
-			xml_out := Some "hx"
-		),"","generate hx headers for all input classes");
 		("Optimization",["--no-output"],[], Arg.Unit (fun() -> no_output := true),"","compiles but does not generate any file");
 		("Debug",["--times"],[], Arg.Unit (fun() -> measure_times := true),"","measure compilation times");
 		("Optimization",["--no-inline"],[], define Define.NoInline, "","disable inlining");
@@ -798,8 +781,27 @@ try
 			with Not_found ->
 				raise (Arg.Bad new_msg));
 		arg_delays := [];
-		if com.platform = Globals.Cpp && not (Define.defined com.defines DisableUnicodeStrings) && not (Define.defined com.defines HxcppSmartStings) then
+		if com.platform = Globals.Cpp && not (Define.defined com.defines DisableUnicodeStrings) && not (Define.defined com.defines HxcppSmartStings) then begin
 			Define.define com.defines HxcppSmartStings;
+		end;
+		if Define.raw_defined com.defines "gen_hx_classes" then begin
+			(* TODO: this is something we're gonna remove once we have something nicer for generating flash externs *)
+			force_typing := true;
+			pre_compilation := (fun() ->
+				List.iter (fun (_,_,extract) ->
+					Hashtbl.iter (fun n _ -> classes := n :: !classes) (extract())
+				) com.swf_libs;
+				List.iter (fun (_,std,_,all_files,_) ->
+					if not std then
+						List.iter (fun path -> if path <> (["java";"lang"],"String") then classes := path :: !classes) (all_files())
+				) com.java_libs;
+				List.iter (fun (_,std,all_files,_) ->
+					if not std then
+						List.iter (fun path -> classes := path :: !classes) (all_files())
+				) com.net_libs;
+			) :: !pre_compilation;
+			xml_out := Some "hx"
+		end;
 	in
 	process_ref := process;
 	process ctx.com.args;
@@ -955,7 +957,7 @@ try
 		begin match !xml_out with
 			| None -> ()
 			| Some "hx" ->
-				Genxml.generate_hx com
+				Genhxold.generate com
 			| Some file ->
 				Common.log com ("Generating xml: " ^ file);
 				Path.mkdir_from_path file;

+ 302 - 0
src/generators/genhxold.ml

@@ -0,0 +1,302 @@
+(*
+	The Haxe Compiler
+	Copyright (C) 2005-2019  Haxe Foundation
+
+	This program is free software; you can redistribute it and/or
+	modify it under the terms of the GNU General Public License
+	as published by the Free Software Foundation; either version 2
+	of the License, or (at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *)
+
+open Globals
+open Ast
+open Type
+open Common
+open ExtString
+
+let rec create_dir acc = function
+	| [] -> ()
+	| d :: l ->
+		let path = acc ^ "/" ^ d in
+		(try Unix.mkdir path 0o777 with _ -> ());
+		create_dir path l
+
+
+let conv_path p =
+	match List.rev (fst p) with
+	| x :: l when starts_with x '_' -> List.rev (("priv" ^ x) :: l), snd p
+	| _ -> p
+
+let get_real_path meta path =
+	try
+		let real_path = match Meta.get Meta.RealPath meta with
+			| (_,[(EConst(String s),_)],_) ->
+				s
+			| _ -> raise Not_found
+		in
+		match List.rev (String.nsplit real_path ".") with
+			| name :: pack ->
+				(List.rev pack), name
+			| _ -> raise Not_found
+	with | Not_found ->
+		path
+
+let generate_type com t =
+	let base_path = "hxclasses" in
+	match t with TClassDecl { cl_kind = KAbstractImpl _ } -> () | _ ->
+	let pack, name =
+		let info = t_infos t in
+		get_real_path info.mt_meta info.mt_path
+	in
+	create_dir "." (base_path :: pack);
+	match pack, name with
+	| ["flash";"net"], "NetStreamPlayTransitions"
+	| ["flash";"filters"], "BitmapFilterQuality"
+	| ["flash";"display"], ("BitmapDataChannel" | "GraphicsPathCommand")  -> ()
+	| _ ->
+	let f = open_out_bin (base_path ^ "/" ^ (match pack with [] -> "" | l -> String.concat "/" l ^ "/") ^ name ^ ".hx") in
+	let ch = IO.output_channel f in
+	let p fmt = IO.printf ch fmt in
+	if pack <> [] then IO.printf ch "package %s;\n\n" (String.concat "." pack);
+	let rec notnull t =
+		match t with
+		| TMono r ->
+			(match !r with
+			| None -> t
+			| Some t -> notnull t)
+		| TLazy f ->
+			notnull (lazy_type f)
+		| TAbstract ({ a_path = [],"Null" },[t]) ->
+			t
+		| _ ->
+			t
+	in
+	let rec path meta p tl =
+		let p = conv_path (get_real_path meta p) in
+		(if fst p = pack then snd p else s_type_path p) ^ (match tl with [] -> "" | _ -> "<" ^ String.concat "," (List.map stype tl) ^ ">")
+	and stype t =
+		match t with
+		| TMono r ->
+			(match !r with
+			| None -> "Unknown"
+			| Some t -> stype t)
+		| TInst ({ cl_kind = KTypeParameter _ } as c,tl) ->
+			path [] ([],snd c.cl_path) tl
+		| TInst (c,tl) ->
+			path c.cl_meta c.cl_path tl
+		| TEnum (e,tl) ->
+			path e.e_meta e.e_path tl
+		| TType (t,tl) ->
+			path t.t_meta t.t_path tl
+		| TAbstract (a,tl) ->
+			path a.a_meta a.a_path tl
+		| TAnon a ->
+			let fields = PMap.fold (fun f acc -> (f.cf_name ^ " : " ^ stype f.cf_type) :: acc) a.a_fields [] in
+			"{" ^ String.concat ", " fields ^ "}"
+		| TLazy f ->
+			stype (lazy_type f)
+		| TDynamic t2 ->
+			if t == t2 then "Dynamic" else "Dynamic<" ^ stype t2 ^ ">"
+		| TFun ([],ret) ->
+			"Void -> " ^ ftype ret
+		| TFun (args,ret) ->
+			String.concat " -> " (List.map (fun (_,_,t) -> ftype t) args) ^ " -> " ^ ftype ret
+	and ftype t =
+		match t with
+		| TMono r ->
+			(match !r with
+			| None -> stype t
+			| Some t -> ftype t)
+		| TLazy f ->
+			ftype (lazy_type f)
+		| TFun _ ->
+			"(" ^ stype t ^ ")"
+		| _ ->
+			stype t
+	in
+	let sparam (n,v,t) =
+		match v with
+		| None ->
+			n ^ " : " ^ stype t
+		| Some (Ident "null") ->
+			if is_nullable (notnull t) then
+				"?" ^ n ^ " : " ^ stype (notnull t)
+			else
+				(* we have not found a default value stored in metadata, let's generate it *)
+				n ^ " : " ^ stype t ^ " = " ^ (match follow t with
+					| TAbstract ({ a_path = [],("Int"|"Float"|"UInt") },_) -> "0"
+					| TAbstract ({ a_path = [],"Bool" },_) -> "false"
+					| _ -> "null")
+		| Some v ->
+			n ^ " : " ^ stype t ^ " = " ^ (match s_constant v with "nan" -> "0./*NaN*/" | v -> v)
+	in
+	let print_meta ml =
+		List.iter (fun (m,pl,_) ->
+			match m with
+			| Meta.DefParam | Meta.CoreApi | Meta.Used | Meta.MaybeUsed | Meta.FlatEnum | Meta.Value | Meta.DirectlyUsed | Meta.Enum | Meta.Impl -> ()
+			| _ ->
+			match pl with
+			| [] -> p "@%s " (Meta.to_string m)
+			| l -> p "@%s(%s) " (Meta.to_string m) (String.concat "," (List.map Ast.s_expr pl))
+		) ml
+	in
+	let access is_read a = s_access is_read a in
+	let rec print_field stat f =
+		p "\t";
+		print_meta f.cf_meta;
+		if stat then p "static ";
+		let name = try (match Meta.get Meta.RealPath f.cf_meta with
+				| (Meta.RealPath, [EConst( String s ), _], _) ->
+					s
+				| _ ->
+					raise Not_found)
+			with Not_found ->
+				f.cf_name
+		in
+		(match f.cf_kind with
+		| Var v ->
+			if has_class_field_flag f CfFinal then
+				p "final %s" name
+			else begin
+				p "var %s" name;
+				if v.v_read <> AccNormal || v.v_write <> AccNormal then p "(%s,%s)" (access true v.v_read) (access false v.v_write);
+			end;
+			p " : %s" (stype f.cf_type);
+		| Method m ->
+			let params, ret = (match follow f.cf_type with
+				| TFun (args,ret) ->
+					List.map (fun (a,o,t) ->
+						let rec loop = function
+							| [] -> Ident "null"
+							| (Meta.DefParam,[(EConst (String p),_);(EConst v,_)],_) :: _ when p = a ->
+								(match v with
+								| Float "1.#QNAN" -> Float "0./*NaN*/"
+								| Float "4294967295." -> Int "0xFFFFFFFF"
+								| Int "16777215" -> Int "0xFFFFFF"
+								| Float x ->
+									(try
+										let f = float_of_string x in
+										let s = string_of_int (int_of_float f) in
+										if s ^ "." = x then Int s else v
+									with _ ->
+										v)
+								| _ -> v)
+							| _ :: l -> loop l
+						in
+						a,(if o then Some (loop f.cf_meta) else None ),t
+					) args, ret
+				| _ ->
+					assert false
+			) in
+			let tparams = (match f.cf_params with [] -> "" | l -> "<" ^ String.concat "," (List.map fst l) ^ ">") in
+			p "function %s%s(%s) : %s" name tparams (String.concat ", " (List.map sparam params)) (stype ret);
+		);
+		p ";\n";
+		if Meta.has Meta.Overload f.cf_meta then List.iter (fun f -> print_field stat f) f.cf_overloads
+	in
+	(match t with
+	| TClassDecl c ->
+		print_meta c.cl_meta;
+		let finalmod = if c.cl_final then "final " else "" in
+		p "extern %s%s %s" finalmod (if c.cl_interface then "interface" else "class") (stype (TInst (c,List.map snd c.cl_params)));
+		let ext = (match c.cl_super with
+		| None -> []
+		| Some (c,pl) -> [" extends " ^ stype (TInst (c,pl))]
+		) in
+		let ext = List.fold_left (fun acc (i,pl) -> ((if c.cl_interface then " extends " else " implements ") ^ stype (TInst (i,pl))) :: acc) ext c.cl_implements in
+		let ext = (match c.cl_dynamic with
+			| None -> ext
+			| Some t ->
+				(match c.cl_path with
+				| ["flash";"errors"], _ -> ext
+				| _ when t == t_dynamic -> " implements Dynamic" :: ext
+				| _ -> (" implements Dynamic<" ^ stype t ^ ">") :: ext)
+		) in
+		let ext = (match c.cl_path with
+			| ["flash";"utils"], "ByteArray" -> " implements ArrayAccess<Int>" :: ext
+			| ["flash";"utils"], "Dictionary" -> [" implements ArrayAccess<Dynamic>"]
+			| ["flash";"xml"], "XML" -> [" implements Dynamic<XMLList>"]
+			| ["flash";"xml"], "XMLList" -> [" implements ArrayAccess<XML>"]
+			| ["flash";"display"],"MovieClip" -> [" extends Sprite #if !flash_strict implements Dynamic #end"]
+			| ["flash";"errors"], "Error" -> [" #if !flash_strict implements Dynamic #end"]
+			| _ -> ext
+		) in
+		p "%s" (String.concat "" (List.rev ext));
+		p " {\n";
+		let sort l =
+			let a = Array.of_list (List.filter (fun f -> has_class_field_flag f CfPublic && not (List.memq f c.cl_overrides)) l) in
+			let name = function "new" -> "" | n -> n in
+			Array.sort (fun f1 f2 ->
+				match f1.cf_kind, f2.cf_kind with
+				| Var _, Var _ | Method _ , Method _ -> compare (name f1.cf_name) (name f2.cf_name)
+				| Var _, _ -> -1
+				| _ -> 1
+			) a;
+			Array.to_list a
+		in
+		List.iter (print_field false) (sort (match c.cl_constructor with None -> c.cl_ordered_fields | Some f -> f :: c.cl_ordered_fields));
+		List.iter (print_field true) (sort c.cl_ordered_statics);
+		p "}\n";
+	| TEnumDecl e ->
+		print_meta e.e_meta;
+		p "extern enum %s {\n" (stype (TEnum(e,List.map snd e.e_params)));
+		List.iter (fun n ->
+			let c = PMap.find n e.e_constrs in
+			p "\t%s" c.ef_name;
+			(match follow c.ef_type with
+			| TFun (args,_) -> p "(%s)" (String.concat ", " (List.map sparam (List.map (fun (a,o,t) -> a,(if o then Some (Ident "null") else None),t) args)))
+			| _ -> ());
+			p ";\n";
+		) e.e_names;
+		p "}\n"
+	| TTypeDecl t ->
+		print_meta t.t_meta;
+		p "typedef %s = " (stype (TType (t,List.map snd t.t_params)));
+		p "%s" (stype t.t_type);
+		p "\n";
+	| TAbstractDecl a ->
+		print_meta a.a_meta;
+		Option.may (fun c -> try print_meta [Meta.get Meta.Require c.cl_meta] with Not_found -> ()) a.a_impl;
+		p "extern ";
+		let is_enum = Meta.has Meta.Enum a.a_meta in
+		if is_enum then p "enum ";
+		p "abstract %s" (stype (TAbstract (a,List.map snd a.a_params)));
+		if not (Meta.has Meta.CoreType a.a_meta) then p "(%s)" (stype a.a_this);
+		p " {\n";
+		Option.may (fun c ->
+			let fields = c.cl_ordered_statics in
+			let fields =
+				if is_enum then
+					let sort l =
+						let a = Array.of_list l in
+						Array.sort (fun a b -> compare a.cf_name b.cf_name) a;
+						Array.to_list a
+					in
+					sort fields
+				else
+					fields
+			in
+
+			List.iter (fun f ->
+				let static = not (Meta.has Meta.Impl f.cf_meta) in
+				if not static && is_enum && Meta.has Meta.Enum f.cf_meta then begin
+					p "\tvar %s;\n" f.cf_name;
+				end else
+					print_field static f
+			) fields
+		) a.a_impl;
+		p "}\n";
+	);
+	IO.close_out ch
+
+let generate com =
+	List.iter (generate_type com) com.types